本篇文章分析BNBSmartChain上的ERC314标准代币AIZPT的攻击事件。该攻击事件的根本原因是:AIZPT兑换BNB时,恒定乘积公式出现问题,导致可以获得更多的BNB。
昨天,从DeFiHackLabs的漏洞仓库中,了解到BNB Smart Chain上的ERC314标准代币AIZPT的攻击事件。
攻击Tx:https://bscscan.com/tx/0x5e694707337cca979d18f9e45f40e81d6ca341ed342f1377f563e779a746460d
目前找不到关于AIZPT代币的相关背景,猜测是一个土狗项目。
<br>
<br>
首先,攻击者通过PancakeSwap利用闪电贷服务借了8000 WBNB,然后兑换成8000 BNB。
<br>
随后,攻击者用8000 BNB调用AIZPT代币合约的buy
函数去swap,攻击者得到805,227,658个AIZPT代币。(buy
函数是通过receive()
回调函数内部进行调用的)
<br>
接着,攻击者大量调用sell
函数(由transfer内部调用),每次调用将一部分的AIZPT代币swap回BNB。
调用sell
函数swap成的BNB数量,会逐渐减少:2431 -> 1473 -> 960 -> 660 ……
但攻击者总共得到了8039个BNB,偿还8004.1个给闪电贷后,获利34.9个BNB。
<br>
在上述过程中,攻击者用8000 BNB购买成AIZPT代币,再将AIZPT代币出售回BNB,最终多了39个BNB。这其中到底发生了什么?让我们深入合约代码的buy
和sell
函数去看看
function buy() internal {
require(tradingEnable, 'Trading not enable');
// 用户发送的BNB数量
uint256 swapValue = msg.value;
// 根据恒定乘积公式,计算用户得到的AIZPT代币数量
uint256 token_amount = (swapValue * _balances[address(this)]) / (address(this).balance);
require(token_amount > 0, 'Buy amount too low');
// 用户获得1/2的AIZPT代币
uint256 user_amount = token_amount * 50 / 100;
uint256 fee_amount = token_amount - user_amount;
_transfer(address(this), msg.sender, user_amount);
// 另外的1/2则是发送到feeReceiver, 应该是项目方的地址
_transfer(address(this), feeReceiver, fee_amount);
emit Swap(msg.sender, swapValue, 0, 0, user_amount);
}
代码逻辑很简单,根据恒定乘积公式进行swap,然后转移代币。1/2的代币发送到项目方地址,这应该是项目方的盈利手段。
function sell(uint256 sell_amount) internal {
require(tradingEnable, 'Trading not enable');
// 根据恒定乘积公式,计算用户得到的BNB数量
uint256 ethAmount = (sell_amount * address(this).balance) / (_balances[address(this)] + sell_amount);
require(ethAmount > 0, 'Sell amount too low');
require(address(this).balance >= ethAmount, 'Insufficient ETH in reserves');
// 将输入的AIZPT代币分成两份
uint256 swap_amount = sell_amount * 50 / 100;
uint256 burn_amount = sell_amount - swap_amount;
// 一份转移回合约
_transfer(msg.sender, address(this), swap_amount);
// 一份进行销毁
_transfer(msg.sender, address(0), burn_amount);
// 发送BNB给用户
payable(msg.sender).transfer(ethAmount);
emit Swap(msg.sender, 0, sell_amount, ethAmount, 0);
}
在sell函数中,会把1/2的AIZPT代币销毁,但是发送给用户的BNB数量却是以所有的AIZPT代币数量进行计算的。这就是攻击发送的根本原因,AIZPT数量随着调用变少,恒定乘积公式将不再恒定。以至于后续用AIZPT兑换成的BNB将比预期更多,直至把池子掏空。
<br>
该攻击事件的根本原因是:AIZPT兑换BNB时,恒定乘积公式出现问题,导致可以获得更多的BNB。在对攻击事件分析时,当站在攻击者的角度,会发现更多的攻击细节和疑惑点:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!