ZongZi Exploit Analysis
💰

ZongZi Exploit Analysis

Published
May 26, 2024
Author
daleewong

Intro

Lost : $223K
Time:2024-03-25

Detail

notion image
先标记下hacker 的合约
notion image
line4 zongzi 在pancake 里的 wbnb有 1500000000000000000000
notion image
闪电贷借wbnb 1904347826086956521739
notion image
把wbnb全部转到另一个合约,把它mark成hacker_contract2,真正的攻击过程都在这里
notion image
接下来就是一系列的兑换
op type
wbnb
zongzi
wbnb-zongzi
100000000000000000
224422567899502736268038175462
zongzi-wbnb
81203796500469234
224422567899502736268038175462
wbnb-zongzi
1904247826086956521739
1871659197312641953023279714603473
call 3 func
858377721424360720681539559296354
zongzi-wbnb
861167498663157296581
858377721424360720681539559296354
进来wbnb:1904347826086956521739
出去wbnb:2158209956815657765815
白白的多了,问题就处在那三个函数调用上面
notion image
function burnToHolder(uint256 amount,address _invitation) external { require(amount >= 0, "TeaFactory: insufficient funds"); address sender = _msgSender(); if(Invitation[sender] == address(0) && _invitation != address(0) && _invitation != sender){ Invitation[sender] = _invitation; InvitationList[_invitation].add(sender);//add hacker addr } if (!userList.contains(sender)) { userList.add(sender); } address[] memory path = new address[](2); path[0] = address(_burnToken); path[1] = uniswapRouter.WETH(); uint256 deserved = 0; deserved = uniswapRouter.getAmountsOut(amount, path)[path.length - 1]; require(payable(address(_burnToken)).balance>=deserved,'not enough balance'); _burnToken.zongziToholder(sender, amount, deserved);//burntoken is zongzi _BurnTokenToDead(sender,amount); burnFeeRewards(sender,deserved); }
问题出在这行上面,错误的用getAmountsOut计算了金额。忽略了swap会存在slippage。直接用
getAmountsOut计算出的deserved会比正常swap大。
deserved = uniswapRouter.getAmountsOut(amount, path)[path.length - 1];
notion image
最后转给bnb到hacker cotract2
function receiveRewards(address payable to) external { address addr = msg.sender; uint256 balance = balanceOf(addr); uint256 amount = balance.sub(burnAmount[addr]); //.sub(Rewards[addr]); require(amount > 0 ); Rewards[addr] = Rewards[addr].add(amount); historyRewards[addr] = historyRewards[addr].add(amount); to.transfer(amount.mul(10**9)); // pay hacker 1296.961254356 bnb _transfer(addr, address(this), balance); burnAmount[addr]=0; totalReceive = totalReceive.add(amount); emit ReceiveReward(addr, amount, totalReceive); }

End

错误的计算swap金额是此次被黑的元凶。还是要懂uniswap的原理再开发,千万不要用getAmountsOut计算