说明
这也是一个典型的代币通缩类型的漏洞,之前前面也分析了多个代币通缩类型的漏洞,漏洞合约完全是一样的,本篇文章就简单分析下腺管漏洞合约。
基本信息
漏洞合约:https://bscscan.com/address/0xd3d4b46db01c006fb165879f343fc13174a1ceeb
攻击交易:https://bscscan.com/tx/0x9fe19093a62a7037d04617b3ac4fbf5cb2d75d8cb6057e7e1b3c75cbbd5a5adc
漏洞函数
balanceOf
1 | uint256 private _tTotal; |
burn
1 | function burn(uint256 _value) public { |
漏洞位置和之前没有任何的区别。所以就不作过多的分析,直接看攻击过程。
攻击分析
flashloan
通过aave3闪电贷获得200000个BUSD。

executeOperation
aave3闪电贷的回调函数。
BUSDToBIGFI
将闪电贷得到的BUSD全部兑换为BIGFI,得到BIGFI代币的数量是5869494994603961621184

burn
调用BIGFI中的burn()函数,用于修改_tTotal。
实际攻击,调用burn()得到的数量是20999908387035301038233370。
需要分析,是如何计算得到这个20999908387035301038233370值的。
在了解到具体的计算方法之前,需要了解到balanceOf()的计算方法。
中间的换算公式也非常的简单,在没有调用burn之前,计算balanceOf的公式如下:
$$
old_balanceOf[account] = \frac{r_owned[account]}{\frac{r_total}{r_total}}
= \frac{r_ownwd[account] \times t_total}{r_total}
$$
当调用burn之后,会执行_tTotal = _tTotal.sub(_value);,此时公式就变成:
$$
new_balanceOf[account] = \frac{r_ownwd[account] \times (t_total - _value)}{r_total}
$$
如果需要new_balanceOf[account]=1,需要计算此时的_value是多少,得到此时的t_total是:
$$
_value = t_total - \frac{t_total}{old_balanceOf[account]}
$$
代入到实际的计算公式,得到:
$$
burn_value = BIGFI.totalSupply() - \frac{BIGFI.totalSupply()}{BIGFI.balanceOf(address(Pair))}
$$
所以对应此时的攻击代码就是:
1 | uint256 burnAmount = BIGFI.totalSupply() - 2 * (BIGFI.totalSupply() / BIGFI.balanceOf(address(Pair))); |
sync
由于通过burn方法,修改了BIGFI.balanceOf(pair)的值,需要通过sync将更新后的值复写到Pair中。

此时在Pair中的BIGFI的数量已经成功变为了1
swap
由于此时在Pair合约中的两种代币的数量差距非常大,其中的BIGFI的数量只有1,此时攻击者通过swap将BIGFI兑换成为了USDT就可以大量获利。
最终攻击者通过兑换,获得了230466095832979875922923的BUSD。

最后就是完成闪电贷的还款。
获利分析
攻击者通过swap()获得了230466095832979875922923数量的BUSD,除去闪电贷的还款200160000000000000000000。最终攻击者获得了:
1 | 230466095832979875922923 - 200160000000000000000000 = 30306095832979875922923 |
所以攻击者最终获利是30306数量BUSD。