Skip to content

Instantly share code, notes, and snippets.

@k1rill-fedoseev
Created April 23, 2023 06:09
Show Gist options
  • Save k1rill-fedoseev/8537cc9a3f1753b0d579e1af662834bb to your computer and use it in GitHub Desktop.
Save k1rill-fedoseev/8537cc9a3f1753b0d579e1af662834bb to your computer and use it in GitHub Desktop.
// 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