-
-
Save k1rill-fedoseev/c7ca38a4a0a1d1980c905e430fa86685 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 "../../src/interfaces/ILegacyERC20.sol"; | |
import "../../src/BobVault.sol"; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; | |
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; | |
contract VerifyGnosisSafeTx is Test { | |
address constant bob = address(0xB0B195aEFA3650A6908f15CdaC7D92F8a5791B0B); | |
address constant usdcMainnet = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); | |
address constant usdtMainnet = address(0xdAC17F958D2ee523a2206206994597C13D831ec7); | |
address constant usdcOptimism = address(0x7F5c764cBc14f9669B88837ca1490cCa17c31607); | |
address constant usdtOptimism = address(0x94b008aA00579c1307B0EF2c499aD98a8ce58e58); | |
address constant usdcBNB = address(0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d); | |
address constant usdtBNB = address(0x55d398326f99059fF775485246999027B3197955); | |
address constant usdcArbitrum = address(0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8); | |
address constant usdtArbitrum = address(0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9); | |
address constant uniswapRouter = address(0xE592427A0AEce92De3Edee1F18E0157C05861564); | |
address constant kyberswapRouter = address(0xC1e7dFE73E1598E3910EF4C7845B68A9Ab6F4c83); | |
address constant bobVaultMainnet = address(0x15729Ac1795Fa02448a55D206005dC1914144a9F); | |
address constant bobVaultOptimism = address(0x8aEb89D5C689C2cf373Fe8b56c7A0cD5BDc74CE6); | |
address constant bobVaultBNB = address(0x61a57F1C82DA40e632C075D7812Af375Db23367c); | |
address constant bobVaultArbitrum = address(0x72e6B59D4a90ab232e55D4BB7ed2dD17494D62fB); | |
function testMainnet() external { | |
vm.createSelectFork("https://rpc.ankr.com/eth"); | |
address from = address(0xd4a3D9Ca00fa1fD8833D560F9217458E61c446d8); | |
address to = address(0x40A2aCCbd92BCA938b02010E17A5b8929b49130D); | |
bytes memory data = hex"8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008a100b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f1900000000000000000000000015729ac1795fa02448a55d206005dc1914144a9f000000000000000000000000000000000000000000027b46536c66c8e300000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f19000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000034f086f3b33b683290c2a00b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a80000000000000000000000000000000000000000000000000000000000000001002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000841c49584a000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000010c6c21c15a4936b7e64002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4ea540632000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000000000008fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc89bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc89dfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2761800000000000000000000000000000000000000000001a784379d99c3f93ed1a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000000000000000006553f100002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000841c49584a000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000f4270ad40df2b08be65608f4517e8002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4ea540632000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000437630000000000000000000000000000000000000000000000000000000000043765fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a784379d99c3f93ed1a200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000000000000000006553f10000000000000000000000000000000000000000000000000000000000000000"; | |
uint256 supply = IERC20(bob).totalSupply(); | |
uint256 govBalance = IERC20(bob).balanceOf(from); | |
prankDelegate(from).delegatecall(to, data); | |
assertApproxEqAbs(IERC20(bob).totalSupply(), supply + 3_000_000 ether + 4_000_000 ether, 1 gwei); | |
assertEq(IERC20(bob).balanceOf(from), govBalance); | |
checkUniswapInventory(usdcMainnet, 100); | |
checkUniswapInventory(usdcMainnet, 500); | |
checkKyberswapInventory(usdcMainnet, 8); | |
checkKyberswapInventory(usdtMainnet, 8); | |
checkBobVaultInventory(bobVaultMainnet, usdcMainnet); | |
checkBobVaultInventory(bobVaultMainnet, usdtMainnet); | |
} | |
function testOptimism() external { | |
vm.createSelectFork("https://rpc.ankr.com/optimism"); | |
address from = address(0x14fc6a1a996A2EB889cF86e5c8cD17323bC85290); | |
address to = address(0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B); | |
bytes memory data = hex"8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003c400b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f190000000000000000000000008aeb89d5c689c2cf373fe8b56c7a0cd5bdc74ce60000000000000000000000000000000000000000000422ca8b0a00a42500000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f1900000000000000000000000014fc6a1a996a2eb889cf86e5c8cd17323bc8529000000000000000000000000000000000000000000001a784379d99db41ffffaf00c36442b4a4522e871399cd717abdd847ab11fe880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008413ead5620000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000f4270ad40df2b08be65608f4517e800c36442b4a4522e871399cd717abdd847ab11fe8800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164883164560000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000437630000000000000000000000000000000000000000000000000000000000043765000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a784379d99db420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014fc6a1a996a2eb889cf86e5c8cd17323bc85290000000000000000000000000000000000000000000000000000000006553f10000000000000000000000000000000000000000000000000000000000"; | |
uint256 supply = IERC20(bob).totalSupply(); | |
uint256 govBalance = IERC20(bob).balanceOf(from); | |
prankDelegate(from).delegatecall(to, data); | |
assertApproxEqAbs(IERC20(bob).totalSupply(), supply + 5_000_000 ether + 2_000_000 ether, 1 gwei); | |
assertEq(IERC20(bob).balanceOf(from), govBalance); | |
checkUniswapInventory(usdcOptimism, 100); | |
checkUniswapInventory(usdcOptimism, 500); | |
checkBobVaultInventory(bobVaultOptimism, usdcOptimism); | |
checkBobVaultInventory(bobVaultOptimism, usdtOptimism); | |
} | |
function testBNB() external { | |
vm.createSelectFork("https://rpc.ankr.com/bsc"); | |
address from = address(0xd4a3D9Ca00fa1fD8833D560F9217458E61c446d8); | |
address to = address(0x40A2aCCbd92BCA938b02010E17A5b8929b49130D); | |
bytes memory data = hex"8d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080800b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f1900000000000000000000000061a57f1c82da40e632c075d7812af375db23367c0000000000000000000000000000000000000000000422ca8b0a00a42500000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f19000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000034f086f3b33b6840000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000001869c008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000001869c002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000841c49584a00000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000001000346d6ff11672ae55ad010002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4ea54063200000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000008ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a784379d99db41fe795b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000000000000000006553f100002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000841c49584a0000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000001000346d6ff11672ae55ad010002b1c7b41f6a8f2b2bc45c3233a5d5fb3cd6dc9a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a4ea5406320000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000008ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a784379d99db41fe795b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000000000000000006553f100000000000000000000000000000000000000000000000000"; | |
uint256 supply = IERC20(bob).totalSupply(); | |
uint256 govBalance = IERC20(bob).balanceOf(from); | |
prankDelegate(from).delegatecall(to, data); | |
assertApproxEqAbs(IERC20(bob).totalSupply(), supply + 5_000_000 ether + 4_000_000 ether, 1 gwei); | |
assertEq(IERC20(bob).balanceOf(from), govBalance); | |
checkKyberswapInventory(usdcBNB, 8); | |
checkKyberswapInventory(usdtBNB, 8); | |
checkBobVaultInventory(bobVaultBNB, usdcBNB); | |
checkBobVaultInventory(bobVaultBNB, usdtBNB); | |
} | |
function testArbitrum() external { | |
vm.createSelectFork("https://rpc.ankr.com/arbitrum"); | |
address from = address(0xd4a3D9Ca00fa1fD8833D560F9217458E61c446d8); | |
address to = address(0x40A2aCCbd92BCA938b02010E17A5b8929b49130D); | |
bytes memory data = hex"8d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000045d00b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f1900000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb0000000000000000000000000000000000000000000422ca8b0a00a42500000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004440c10f19000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d800000000000000000000000000000000000000000001a784379d99db41290c7900b0b195aefa3650a6908f15cdac7d92f8a5791b0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00c36442b4a4522e871399cd717abdd847ab11fe880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008413ead562000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000010c6c21c15a4936b7e6400c36442b4a4522e871399cd717abdd847ab11fe880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016488316456000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000000000000000064fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc89bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc89d00000000000000000000000000000000000000000001a784379d99db42000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d4a3d9ca00fa1fd8833d560f9217458e61c446d8000000000000000000000000000000000000000000000000000000006553f100000000"; | |
uint256 supply = IERC20(bob).totalSupply(); | |
uint256 govBalance = IERC20(bob).balanceOf(from); | |
prankDelegate(from).delegatecall(to, data); | |
assertApproxEqAbs(IERC20(bob).totalSupply(), supply + 5_000_000 ether + 2_000_000 ether, 1 gwei); | |
assertEq(IERC20(bob).balanceOf(from), govBalance); | |
checkUniswapInventory(usdcArbitrum, 100); | |
checkBobVaultInventory(bobVaultArbitrum, usdcArbitrum); | |
checkBobVaultInventory(bobVaultArbitrum, usdtArbitrum); | |
} | |
function prankDelegate(address _target) internal returns (Delegator) { | |
vm.etch(_target, type(Delegator).runtimeCode); | |
return Delegator(payable(_target)); | |
} | |
function checkUniswapInventory(address _token, uint24 _fee) internal { | |
uint256 amountIn = 10_000 * 10 ** IERC20Metadata(_token).decimals(); | |
uint256 amountOut = 10_000 ether; | |
deal(_token, address(this), amountIn); | |
ILegacyERC20(_token).approve(address(uniswapRouter), amountIn); | |
uint256 realAmountOut = ISwapRouter(uniswapRouter).exactInput( | |
ISwapRouter.ExactInputParams({ | |
path: abi.encodePacked(_token, _fee, bob), | |
recipient: address(this), | |
deadline: block.timestamp, | |
amountIn: amountIn, | |
amountOutMinimum: 0 | |
}) | |
); | |
assertApproxEqAbs(realAmountOut, amountOut, 10 ether); | |
} | |
function checkKyberswapInventory(address _token, uint24 _fee) internal { | |
uint256 amountIn = 10_000 * 10 ** IERC20Metadata(_token).decimals(); | |
uint256 amountOut = 10_000 ether; | |
deal(_token, address(this), amountIn); | |
ILegacyERC20(_token).approve(address(kyberswapRouter), amountIn); | |
uint256 realAmountOut = IKyberSwapRouter(kyberswapRouter).swapExactInput( | |
ISwapRouter.ExactInputParams({ | |
path: abi.encodePacked(_token, _fee, bob), | |
recipient: address(this), | |
deadline: block.timestamp, | |
amountIn: amountIn, | |
amountOutMinimum: 0 | |
}) | |
); | |
assertApproxEqAbs(realAmountOut, amountOut, 10 ether); | |
} | |
function checkBobVaultInventory(address _vault, address _token) internal { | |
uint256 amountIn = 10_000 * 10 ** IERC20Metadata(_token).decimals(); | |
uint256 amountOut = 10_000 ether; | |
deal(_token, address(this), amountIn); | |
ILegacyERC20(_token).approve(address(_vault), amountIn); | |
uint256 realAmountOut = BobVault(_vault).buy(_token, amountIn); | |
assertApproxEqAbs(realAmountOut, amountOut, 10 ether); | |
} | |
} | |
interface IKyberSwapRouter { | |
function swapExactInput(ISwapRouter.ExactInputParams memory params) external returns (uint256 amountOut); | |
} | |
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