抢币机器人,我们也可以称之为:抢跑交易。这类机器人通常有两个类型,第一种是抢中心化交易所的机器人。当币安或者火币有新币上线的时候,这种机器人会按照设定好的价格快速买入。由于使用的是机器人,比人工速度快,买入的价格低,进而获利较大。
不过今天我们分享的是第二种机器人:链上抢币机器人,也叫夹子。这种机器人,会在开盘的前几个区块买入代币,从而用低价获得大量代币。而在代币价格上涨时,又卖出,实现低买高卖的目的。
这种链上夹子机器人,大多以抢跑区块的方式实现,可以最大限度的降低自己的损失,从而获利。具体怎么实现呢?今天就给大家分享一下这类机器人的合约源码。
一、抢跑原理
链上机器人通过调高gas或其他方法将自己的交易安插在其他交易之前,来攫取价值。什么意思?在用户的交易被矿工打包进坊区块链之前,大部分交易会汇集到交易内存池中,矿工在这里寻找费用高的交易优先打包出块,实现利益最大化。通常来说,gas费越高的交易,越容易被打包。这种时候,机器人就会通过调高自己的Gas费来实现抢跑,进而达到提前交易的目的。
二、实现路径
在了解了原理之后,接下来就要进行实践了。我们以机器人抢跑购买NFT为例,整个过程共分为三个步骤:
- 搭建本地测试链,请提前安装好 foundry
- 用remix进行NFT合约的部署和铸造
- 通过etherjs脚本监听mempool并进行抢跑
1、启动测试链
在安装好 foundry 之后,在命令行输入 anvil –chain-id 1234 -b 10 搭建本地测试链,chain-id 为 1234,每 10 秒产出一个区块。搭建成功后,它会在显示一些测试账户的地址和私钥,每个账户有 10000 ETH。你可以使用它们进行测试。
当然,如果你不想用本地测试链,完全可以使用币安测试链、火币测试链进行测试,这都无关紧要。主要是有这么一个链。
2. 将Remix连接到测试链: 打开 Remix 的部署页面,打开左上角的Environment
下拉菜单,选Foundry Provider
即可将 Remix 连接到测试链。
3. 部署NFT合约: 在 Remix 上部署一个简单的 freemint(免费铸造)NFT合约。它有一个mint()
,用于免费铸造NFT。
// SPDX-License-Identifier: MIT
// By 0xAA
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// 我们尝试frontrun一笔Free mint交易
contract FreeMint is ERC721 {
uint256 public totalSupply;
// 构造函数,初始化NFT合集的名称、代号
constructor() ERC721("Free Mint NFT", "FreeMint"){}
// 铸造函数
function mint() external {
_mint(msg.sender, totalSupply); // mint
totalSupply++;
}
}
4. 部署ethers.js抢跑脚本: 简单来说,frontrun.js
脚本监听了测试链mempool
中的未决交易,筛选出调用了mint()
的交易,然后复制它并调高gas
进行抢跑。
// provider.on("pending", listener)
import { ethers, utils } from "ethers";
// 1. 创建provider
var url = "http://127.0.0.1:8545";
const provider = new ethers.providers.WebSocketProvider(url);
let network = provider.getNetwork()
network.then(res => console.log(`[${(new Date).toLocaleTimeString()}] 连接到 chain ID ${res.chainId}`));
// 2. 创建interface对象,用于解码交易详情。
const iface = new utils.Interface([
"function mint() external",
])
// 3. 创建钱包,用于发送抢跑交易
const privateKey = '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a'
const wallet = new ethers.Wallet(privateKey, provider)
const main = async () => {
// 4. 监听pending的mint交易,获取交易详情,然后解码。
console.log("\n4. 监听pending交易,获取txHash,并输出交易详情。")
provider.on("pending", async (txHash) => {
if (txHash) {
// 获取tx详情
let tx = await provider.getTransaction(txHash);
if (tx) {
// filter pendingTx.data
if (tx.data.indexOf(iface.getSighash("mint")) !== -1 && tx.from != wallet.address ) {
// 打印txHash
console.log(`\n[${(new Date).toLocaleTimeString()}] 监听Pending交易: ${txHash} \r`);
// 打印解码的交易详情
let parsedTx = iface.parseTransaction(tx)
console.log("pending交易详情解码:")
console.log(parsedTx);
// Input data解码
console.log("raw transaction")
console.log(tx);
// 构建抢跑tx
const txFrontrun = {
to: tx.to,
value: tx.value,
maxPriorityFeePerGas: tx.maxPriorityFeePerGas * 1.2,
maxFeePerGas: tx.maxFeePerGas * 1.2,
gasLimit: tx.gasLimit * 2,
data: tx.data
}
// 发送抢跑交易
var txResponse = await wallet.sendTransaction(txFrontrun)
console.log(`正在frontrun交易`)
await txResponse.wait()
console.log(`frontrun 交易成功`)
}
}
}
});
provider._websocket.on("error", async () => {
console.log(`Unable to connect to ${ep.subdomain} retrying in 3s...`);
setTimeout(init, 3000);
});
provider._websocket.on("close", async (code) => {
console.log(
`Connection lost with code ${code}! Attempting reconnect in 3s...`
);
provider._websocket.terminate();
setTimeout(init, 3000);
});
};
main()
5. 调用mint()
函数: 在 Remix 的部署页面调用 Freemint 合约的mint()
函数,进行 NFT 铸造。
6. 脚本监听到交易并进行抢跑 我们可以在终端看到 frontrun.js 脚本成功监听到了交易,并进行了抢跑。如果你调用 NFT 合约的 ownerOf() 函数查看 tokenId 为 0 的持有者是抢跑脚本中的钱包地址,证明抢跑成功!
三、预防措施
现在,我们已经理解了链上抢跑机器人的实现方法和路径,那么,如果说我们自己遇到了这种机器人,应该如何预防呢?一般来说,我们没法消除它,但是可以通过减少交易顺序或时间的重要性,减少被抢先交易的收益。比如说使用暗池,用户发出的交易将不进入公开的mempool,而是直接到矿工手里。
最后,如果您开发这种夹子机器人,可以联系我,电报:@dapp165,微信:btc6540