-
-
Save k1rill-fedoseev/8537cc9a3f1753b0d579e1af662834bb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: CC0-1.0 | |
pragma solidity 0.8.15; | |
import "forge-std/Test.sol"; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; | |
import "../../src/interfaces/ILegacyERC20.sol"; | |
interface IUniversalRouter { | |
function execute(bytes calldata commands, bytes[] calldata inputs) external payable; | |
} | |
interface IInventoryMinter { | |
function getOrder0() external view returns (bytes32, IRouter.LimitOrder memory); | |
function getOrder1() external view returns (bytes32, IRouter.LimitOrder memory); | |
} | |
interface IRouter { | |
struct LimitOrder { | |
uint256 salt; | |
address makerAsset; | |
address takerAsset; | |
address maker; | |
address receiver; | |
address allowedSender; | |
uint256 makingAmount; | |
uint256 takingAmount; | |
uint256 offsets; | |
bytes interactions; | |
} | |
function fillOrderTo( | |
LimitOrder calldata order_, | |
bytes calldata signature, | |
bytes calldata interaction, | |
uint256 makingAmount, | |
uint256 takingAmount, | |
uint256 skipPermitAndThresholdAmount, | |
address target | |
) external payable returns(uint256 actualMakingAmount, uint256 actualTakingAmount, bytes32 orderHash); | |
} | |
contract VerifyGnosisSafeTx_Gov31 is Test { | |
address constant bob = address(0xB0B195aEFA3650A6908f15CdaC7D92F8a5791B0B); | |
address constant usdcMainnet = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); | |
address constant usdtMainnet = address(0xdAC17F958D2ee523a2206206994597C13D831ec7); | |
address constant usdcBNB = address(0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d); | |
address constant usdtBNB = address(0x55d398326f99059fF775485246999027B3197955); | |
address constant router = address(0x1111111254EEB25477B68fb85Ed929f73A960582); | |
address constant uniswapRouterMainnet = address(0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B); | |
address constant nftPositionsMainnet = address(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); | |
address constant uniswapRouterBNB = address(0x5Dc88340E1c5c6366864Ee415d6034cadd1A9897); | |
address constant nftPositionsBNB = address(0x7b8A01B39D58278b5DE7e48c8449c9f4F5170613); | |
function testBNB() external { | |
vm.createSelectFork("https://rpc.ankr.com/bsc"); | |
address from = address(0xd4a3D9Ca00fa1fD8833D560F9217458E61c446d8); | |
address to = address(0x40A2aCCbd92BCA938b02010E17A5b8929b49130D); | |
bytes memory data = hex"8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002f600b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002442966c6800000000000000000000000000000000000000000000d3c21bcecceda100000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000ef655f7cee3d430302bc7d3d491af295cb4040100000000000000000000000000000000000000000001a784379d99db42000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000525b4e120ddc602ff055aa86803acd7d71f0c7530000000000000000000000000000000000000000000016e988a40bd4b1a0000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000525b4e120ddc602ff055aa86803acd7d71f0c75300000000000000000000000000000000000000000001909aaef98e0690600000000ef655f7cee3d430302bc7d3d491af295cb40401000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041249c58b00525b4e120ddc602ff055aa86803acd7d71f0c753000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041249c58b00000000000000000000"; | |
uint256 supply = IERC20(bob).totalSupply(); | |
uint256 govBalanceBob = IERC20(bob).balanceOf(from); | |
uint256 govBalanceUsdc = IERC20(usdcBNB).balanceOf(from); | |
uint256 govBalanceUsdt = IERC20(usdtBNB).balanceOf(from); | |
uint256 govBalancePositions = IERC20(nftPositionsBNB).balanceOf(from); | |
prankDelegate(from).delegatecall(to, data); | |
assertEq(IERC20(bob).totalSupply(), supply - 1_000_000 ether); | |
assertEq(IERC20(bob).balanceOf(from), govBalanceBob - 4_891_800 ether); | |
assertEq(IERC20(usdcBNB).balanceOf(from), govBalanceUsdc - 108_200 ether); | |
assertEq(IERC20(usdtBNB).balanceOf(from), govBalanceUsdt); | |
assertEq(IERC20(nftPositionsBNB).balanceOf(from), govBalancePositions + 2); | |
checkUniswapInventory(uniswapRouterBNB, usdcBNB, 100); | |
checkUniswapInventory(uniswapRouterBNB, usdtBNB, 100); | |
(, IRouter.LimitOrder memory order0) = IInventoryMinter(0x0eF655F7Cee3D430302BC7D3d491aF295CB40401).getOrder0(); | |
checkLimitOrderFilling(order0); | |
(, IRouter.LimitOrder memory order1) = IInventoryMinter(0x0eF655F7Cee3D430302BC7D3d491aF295CB40401).getOrder1(); | |
checkLimitOrderFilling(order1); | |
(, IRouter.LimitOrder memory order2) = IInventoryMinter(0x525b4E120dDC602fF055Aa86803acD7D71F0c753).getOrder0(); | |
checkLimitOrderFilling(order2); | |
(, IRouter.LimitOrder memory order3) = IInventoryMinter(0x525b4E120dDC602fF055Aa86803acD7D71F0c753).getOrder1(); | |
checkLimitOrderFilling(order3); | |
} | |
function testMainnet() external { | |
vm.createSelectFork("https://rpc.ankr.com/eth"); | |
address from = address(0xd4a3D9Ca00fa1fD8833D560F9217458E61c446d8); | |
address to = address(0x40A2aCCbd92BCA938b02010E17A5b8929b49130D); | |
bytes memory data = hex"8d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000033600b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000cdad0ad4dd1f614a6502043ef546e447b25ffb9900000000000000000000000000000000000000000001a7836772e5547324000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000cdad0ad4dd1f614a6502043ef546e447b25ffb990000000000000000000000000000000000000000000000000000000000e4e1c000cdad0ad4dd1f614a6502043ef546e447b25ffb99000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041249c58b00a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000015729ac1795fa02448a55d206005dc1914144a9f00000000000000000000000000000000000000000000000000000008e452fb4f0015729ac1795fa02448a55d206005dc1914144a9f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044cce7ec13000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000008e452fb4f00b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002442966c6800000000000000000000000000000000000000000001a784379d99db4200000000000000000000000000"; | |
uint256 supply = IERC20(bob).totalSupply(); | |
uint256 govBalanceBob = IERC20(bob).balanceOf(from); | |
uint256 govBalanceUsdc = IERC20(usdcMainnet).balanceOf(from); | |
uint256 govBalanceUsdt = IERC20(usdtMainnet).balanceOf(from); | |
uint256 govBalancePositions = IERC20(nftPositionsMainnet).balanceOf(from); | |
prankDelegate(from).delegatecall(to, data); | |
assertEq(IERC20(bob).totalSupply(), supply - 2_000_000 ether); | |
assertEq(IERC20(bob).balanceOf(from), govBalanceBob - 1_999_985 ether - 1_961_810 ether); | |
assertEq(IERC20(usdcMainnet).balanceOf(from), govBalanceUsdc - 38_190.381903 * 1e6); | |
assertEq(IERC20(usdtMainnet).balanceOf(from), govBalanceUsdt - 15 * 1e6); | |
assertEq(IERC20(nftPositionsMainnet).balanceOf(from), govBalancePositions + 1); | |
checkUniswapInventory(uniswapRouterMainnet, usdcMainnet, 100); | |
checkUniswapInventory(uniswapRouterMainnet, usdtMainnet, 100); | |
(, IRouter.LimitOrder memory order0) = IInventoryMinter(0xCDAD0ad4DD1F614a6502043Ef546e447b25Ffb99).getOrder0(); | |
checkLimitOrderFilling(order0); | |
(, IRouter.LimitOrder memory order1) = IInventoryMinter(0xCDAD0ad4DD1F614a6502043Ef546e447b25Ffb99).getOrder1(); | |
checkLimitOrderFilling(order1); | |
} | |
function prankDelegate(address _target) internal returns (Delegator) { | |
vm.etch(_target, type(Delegator).runtimeCode); | |
return Delegator(payable(_target)); | |
} | |
function checkUniswapInventory(address _router, address _token, uint24 _fee) internal { | |
uint256 amountIn = 10_000 * 10 ** IERC20Metadata(_token).decimals(); | |
uint256 amountOut = 10_000 ether; | |
deal(_token, address(this), amountIn); | |
deal(bob, address(this), 0); | |
ILegacyERC20(_token).transfer(address(_router), amountIn); | |
bytes[] memory inputs = new bytes[](1); | |
inputs[0] = abi.encode(address(this), amountIn, amountOut * 999 / 1000, abi.encodePacked(_token, _fee, bob), false); | |
IUniversalRouter(_router).execute( | |
hex"00", | |
inputs | |
); | |
assertApproxEqAbs(IERC20(bob).balanceOf(address(this)), amountOut, 10 ether); | |
} | |
function checkLimitOrderFilling(IRouter.LimitOrder memory _order) internal { | |
if (_order.makerAsset == address(0) || _order.makingAmount < 10 ** (IERC20Metadata(_order.makerAsset).decimals() - 3)) { | |
return; | |
} | |
deal(_order.takerAsset, address(this), 10 ** IERC20Metadata(_order.takerAsset).decimals()); | |
IERC20(_order.takerAsset).approve(router, 10 ** IERC20Metadata(_order.takerAsset).decimals()); | |
(uint256 actualMakingAmount, uint256 actualTakingAmount, ) = IRouter(router).fillOrderTo( | |
_order, | |
"", | |
"", | |
10 ** IERC20Metadata(_order.makerAsset).decimals(), | |
0, | |
10 ** IERC20Metadata(_order.takerAsset).decimals(), | |
address(this) | |
); | |
assertEq(actualMakingAmount, 10 ** IERC20Metadata(_order.makerAsset).decimals()); | |
assertEq(actualTakingAmount, 10 ** IERC20Metadata(_order.takerAsset).decimals()); | |
console2.log(_order.makerAsset, _order.takerAsset); | |
console2.log(_order.makingAmount, _order.takingAmount); | |
} | |
} | |
contract Delegator { | |
function delegatecall(address dest, bytes memory cd) external payable virtual { | |
assembly { | |
let result := delegatecall(gas(), dest, add(cd, 32), mload(cd), 0, 0) | |
returndatacopy(0, 0, returndatasize()) | |
switch result | |
case 0 { revert(0, returndatasize()) } | |
default { return(0, returndatasize()) } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment