Wault Finance漏洞分析
攻击信息:
攻击交易:
0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670e
攻击合约:
0x886358f9296de461d12e791bc9ef6f5a03410c64
流程分析:
第一步:
首先通过闪电贷借出16839004个WUSD,调用WUSDMaster合约的redeem函数发送USDT和WEX到攻击合约中。成本大于是 0.015 USDT/WEX。
第二步:
通过闪电贷借入40000000USDT,把其中的23000000usdt换成WEX,算了一下成本,0.044 USDT/WEX。
第三步:
多次通过抵押,拉高wex的价格。
最后一次的价格算出来,1.44 USDT/WEX.
第四步:
把WEX换成USDT。这时后价格为 0.041 USDT/WEX
第五步:
还闪电贷。
第六步:
最后获利,跨链。
代码分析:
1 function redeem(uint256 amount) external nonReentrant { 2 uint256 usdtTransferAmount = amount * (1000 - wexPermille - treasuryPermille) / 1000; 3 uint256 usdtTreasuryAmount = amount * treasuryPermille / 1000; 4 uint256 wexTransferAmount = wex.balanceOf(address(this)) * amount / wusd.totalSupply(); 5 wusd.burn(msg.sender, amount); 6 usdt.safeTransfer(treasury, usdtTreasuryAmount); 7 usdt.safeTransfer(msg.sender, usdtTransferAmount); 8 wex.safeTransfer(msg.sender, wexTransferAmount); 9 10 emit Redeem(msg.sender, amount); 11 }
首先通过调用redeem函数,攻击者可以拿到当前最便宜的wex,然后用闪电贷,借出大量的资金,因为攻击者后面要砸盘,所以说,他用一部分来拉盘(这里指23000000那一笔),然后一部分用来重复抵押换取wex(%10用于把usdt换取wex)这一部分用来填补之前通过闪电贷借出wusd获得的wex和usdt。(相当于帮用户高位接盘)
1 function stake(uint256 amount) external nonReentrant { 2 require(amount <= maxStakeAmount, 'amount too high'); 3 usdt.safeTransferFrom(msg.sender, address(this), amount); 4 if(feePermille > 0) { 5 uint256 feeAmount = amount * feePermille / 1000; 6 usdt.safeTransfer(treasury, feeAmount); 7 amount = amount - feeAmount; 8 } 9 uint256 wexAmount = amount * wexPermille / 1000; 10 usdt.approve(address(wswapRouter), wexAmount); 11 wswapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 12 wexAmount, 13 0, 14 swapPath, 15 address(this), 16 block.timestamp 17 ); 18 wusd.mint(msg.sender, amount); 19 20 emit Stake(msg.sender, amount); 21 }