本文深入探讨了加密领域中的抢跑交易(Front-Running)问题,解释了其在DeFi中的运作方式,包括通过操纵交易顺序、Gas价格等手段获利。文章还分析了Hacken在智能合约审计中发现的潜在抢跑漏洞案例,并提出了平台和用户应采取的预防措施,同时提及了白帽黑客利用MEV机器人进行反制。
更新于:2025 年 6 月 30 日
阅读时长:11 分钟
作者:Oleh Malanii
在传统金融中,抢先交易(front-running)是一种经纪人利用提前访问客户交易订单的优势为自己谋取利益的行为,几十年来一直损害着股票市场的可靠性。在华尔街,根据 SEC Rule 17(j)-1,抢先交易是非法的。
这种做法也进入了 DeFi 领域。它的运作方式不同,但逻辑相同:利用真实的交易来为自己谋取利益。加密货币中抢先交易的规模是巨大的。
自 2020 年 6 月以来,MEV 机器人已经在 Ethereum、BSC 和 Solana 上赚取了至少 $10 亿 的利润,通常是以牺牲散户投资者为代价的。除了资金安全之外,抢先交易还引发了市场公平性和透明度的问题。
然而,这种看似不道德的做法也可以用于有益的目的。例如,白帽黑客会抢先恶意交易,以追回黑客窃取的资产,但稍后会详细介绍。
在传统市场中,抢先交易涉及经纪人知道客户即将下达大额订单,迅速进行自己的交易,从预期的价格变动中获利。
在加密货币的背景下,抢先交易攻击采取了一种更复杂的形式。凭借对交易队列(或“mempool”)的了解,运行软件以批准网络上交易的验证者可以重新排序、包含或省略交易,从而使他们获得经济利益。
例如,如果矿工注意到特定加密货币代币的大量买入订单,他们可能会先插入自己的买入订单,然后验证较大的买入订单,随后获得套利。
加密货币中的抢先交易比初看之下更为深入。除了获得最大份额抢先交易收益的验证者之外,还有一个庞大的最大可提取价值 (MEV) 交易者网络,他们运营机器人从区块链的复杂性中获利。
根据 Ryan Zurrer 的说法,大约有 50 个团队积极参与 MEV,其中大约 10 个团队占据主导地位。最好的团队每月赚取“五位数到六位数”的利润,并在最佳市场条件下赚取了数百万美元。
在公共区块链中,所有人都可访问交易数据。而且由于没有 SEC 的网络安全规则来约束他们,因此大多数抢先交易活动都发生在 DEX 上。因此,DeFi 世界充满了精明的交易者,他们运营 MEV 抢先交易机器人,在链上寻找猎物。
在这种类型的攻击中,攻击者使用更高的 Gas 价格来保证他们的交易在即将发生的交易之前得到处理。在这里,抬高价格可确保优先处理。
在这种方法中,攻击者利用交易的绝对数量来发挥自己的优势。他们创建大量交易,所有交易都具有显着更高的 Gas 价格,称为“抑制集群”。结果如何?由于大量高优先级的交易,受害者的交易难以在同一区块中找到空间。
插入策略更为复杂,类似于三明治攻击——抢先和后运行(back-running)交易。在这里,攻击者将受害者的 TX 放在所谓的三明治中。第一个具有较高的 Gas 价格,第二个具有较低的 Gas 价格。这种攻击在去中心化交易所中尤为普遍,使攻击者能够利用大规模交易,通常被称为“巨鲸交易”,从而使他们能够获得可观的利润。
三明治攻击示例
在本节中,我们将介绍可能导致抢先交易攻击的智能合约漏洞。所有问题均已在 Hacken 智能合约审计期间得到解决。
Catgirl 是一个 NFT 市场,允许用户列出、购买、出售和取消订单。
以下函数允许用户通过 BNB 代币交换他们的 Catgirl NFT,并且由于在交换操作期间缺少最低输出值强制机制,因此目前容易受到潜在的抢先交易操纵。当发生非常大的交换交易时,恶意用户可能会介入并收取更高的Gas费用来抢占交易,导致买方以更高的价格购买。
每当执行该函数时,此漏洞使其容易受到抢先交易策略的影响,因为它缺乏适当的滑点检查。
function swapBNBForCatgirl(uint256 amount) private {
address[] memory path = new address[](2);
path[0] = pancakeRouter.WETH();
path[1] = address(uCatgirlToken);
pancakeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{
value: amount
}(0, path, address(this), block.timestamp);
}
幸运的是,他们解决了这个问题并引入了滑点检查。目前,交换函数在防止抢先交易攻击方面受到保护。
Diverse Solutions 作为一个staking池运营,利用修改后的自动做市商 (AMM) 机制。ARDM 和 XARDM 之间的汇率由 XARDM 的总供应量与交易所合约中持有的 ARDM 总量之比决定。
在 2023 年 4 月 24 日的第一次审计审核中,Hacken 审计团队检测到其代码中存在抢先交易漏洞。问题的核心在于 deposit() 函数,其中一个看似无辜的等式控制着份额的铸造。这里,我们有两个主要函数:deposit() 函数用于将你的 ARDM 代币交换为 xARDM 代币,withdraw() 函数用于将你的 xARDM 代币交换为 ARDM 代币。
function deposit(uint256 _amount) external nonReentrant onlyEOA whenDepositNotPaused {
require(_amount > 0, "AMOUNT ZERO");
uint256 totalARDM = ARDM.balanceOf(address(this);
uint256 totalxARDM = xARDM.totalSupply();
if (totalxARDM == 0 || totalARDM == 0) {
xARDM.mint(msg.sender, _amount);
emit Deposit(msg.sender, _amount, _amount);
} else {
// 此等式根据用户存入的金额以及金库中的总资产和总份额来计算用户应收到的份额数量。然而,在表面之下,存在一个关键缺陷。此缺陷允许恶意行为者操纵分母,从而导致对其他用户不利的结果。
uint256 mintAmount = (_amount * totalxARDM) / totalARDM;
xARDM.mint(msg.sender, mintAmount);
emit Deposit(msg.sender, _amount, mintAmount);
}
ARDM.transferFrom(msg.sender, address(this), _amount);
if (penaltyFeePaused == false) {
_userDeadline[msg.sender] = block.timestamp;
}
}
function withdraw(uint256 _amount) external nonReentrant onlyEOA whenWithdrawNotPaused {
require(_amount > 0, "AMOUNT ZERO");
uint256 totalARDM = ARDM.balanceOf(address(this));
uint256 totalxARDM = xARDM.totalSupply();
uint256 transferAmount = (_amount * totalARDM) / totalxARDM;
if (
penaltyFeePaused == false &&
_userDeadline[msg.sender] + penaltyDeadline > block.timestamp
) {
uint256 fee = (transferAmount * penaltyFee) / 100000000000000000000;
uint256 transferAmountMinusFee = transferAmount - fee;
xARDM.burnFrom(msg.sender, _amount);
ARDM.transfer(msg.sender, transferAmountMinusFee);
ARDM.transfer(treasuryAddress, fee);
emit PenaltyFeeSent(treasuryAddress, fee);
} else {
xARDM.burnFrom(msg.sender, _amount);
ARDM.transfer(msg.sender, transferAmount);
}
emit Withdraw(msg.sender, transferAmount, _amount);
}
报告中解释的攻击场景如下:
最初,攻击者通过进行首次存款并铸造少量份额 (XARDM)(相当于一个 wei)来启动staking池。此操作表示为 “deposit(1)”,它导致池的总资产为 1 ARDM,XARDM 的总供应量也为 1 的状态。
攻击者怀有恶意,预测另一用户的存款行为并决定抢先交易。受害者打算将大量资金(特别是 20,000 ARDM)存入池中。
为了操纵局势使自己受益,攻击者在受害者发起存款时迅速膨胀了份额计算的分母。攻击者执行命令“ardm.transfer(20,000e18)”,该命令将大量 ARDM 转移到池中。因此,池的总资产显着增加至 20,000e18 ARDM,而 XARDM 的总供应量保持为 1。
由于池的资产迅速膨胀,当最终处理受害者的存款交易时,他们收到的 XARDM 份额极少。此计算执行如下:(1 * 20,000e18) / (20,000e18 + 1),这导致受害者几乎没有 XARDM 份额。
最终,攻击者通过燃烧其 XARDM 份额来利用这种情况。此操作有效地授予他们对池中所有 ARDM 的所有权,使受害者没有份额,也没有池资产的股份。
在这种情况下,攻击者利用交易的时机和份额的计算来操纵池的状态,并剥夺受害者在本应拥有的的池股份,最终获得对所有存入的 ARDM 的控制权。
问题的解决
客户已成功解决抢先交易问题,并从审计中获得了足够的分数。
在上面的比较中,说明了重大变化。该函数现在仅考虑通过 deposit() 函数转移的 ARDM 量,而不是合约的 ARDM 总余额。客户端已采取措施来防止 ARDM 代币的外部转移,因为它们会影响 ARDM/xARDM 的价格比率并减轻相关风险。
随着 DeFi 生态系统的不断成熟,那些试图利用它的人的创造力也在不断提高。
防止抢先交易攻击需要托管交易的平台和进行交易的个人用户采取措施。让我们深入研究针对每项措施的策略:
在一个独特的加密货币事件中,一位黑客执行了一次 $6900 万 Curve Finance 的流动性池黑客攻击,但由于抢先交易,70% 的损失资金被返还。盗窃行为部分被白帽黑客(包括 Coffeebabe)运营的 MEV 机器人挫败。Coffeebabe.eth 成功拦截了黑客的交易,将救回的资金返还给了 Curve。
此事件强调了 MEV 机器人的潜力以及白帽社区在反击恶意活动方面的潜力,此次干预追回了 70% 的损失资产。这种动态体现了DeFi 安全众包解决方案的重要性。
在加密货币领域,抢先交易是一种操作,验证者和 MEV 机器人通过驱逐、抑制或插入来操纵真实交易以获取经济利益。
随着抢先交易者的策略不断发展,解决这些策略的策略也必须不断发展。
DeFi 平台负责实施最低滑点率、提交-揭示方案、批量交易、智能合约审计、速率限制、优先级 Gas 拍卖、链下订单中继、随机交易排序、时间锁定合约和滑动窗口。
用户可以通过保护隐私、使用 Layer 2 解决方案、发送非标准 Gas 价格、在非高峰时段执行交易、选择安全的 DEX,以及最重要的是,随时了解情况来保护其资产免受抢先交易风险的影响。
- 原文链接: hacken.io/discover/front...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!