From 8522783aa4e8597df5d4dce35b04dce8bb51a9e8 Mon Sep 17 00:00:00 2001 From: Prathmesh <201952225@iiitvadodara.ac.in> Date: Wed, 1 Nov 2023 22:52:03 +0530 Subject: [PATCH 01/11] fix: added Valindrome test --- test/ValindromeProposal.sol | 183 +++++++++++++++++++++++++++++++++++ valindrome-transactions.json | 93 ++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 test/ValindromeProposal.sol create mode 100644 valindrome-transactions.json diff --git a/test/ValindromeProposal.sol b/test/ValindromeProposal.sol new file mode 100644 index 0000000..fcf854d --- /dev/null +++ b/test/ValindromeProposal.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Strings} from "@openzeppelin/utils/Strings.sol"; +import {Ownable} from "@openzeppelin/access/Ownable.sol"; +import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; + +import {MultiSendCallOnly} from "safe-contracts/libraries/MultiSendCallOnly.sol"; + +import {IXReceiver} from "@connext/interfaces/core/IXReceiver.sol"; + +import {IPALMTerms} from "./interfaces/IPALMTerms.sol"; +import {IXERC20} from "./interfaces/IXERC20.sol"; + +import {ForgeHelper} from "./utils/ForgeHelper.sol"; +import {ForkHelper} from "./utils/ForkHelper.sol"; +import {AddressLookup} from "./utils/AddressLookup.sol"; +import {ChainLookup} from "./utils/ChainLookup.sol"; + +import "forge-std/StdJson.sol"; +import "forge-std/console.sol"; + +// Addresses ---- + +// 0xFE67A4450907459c3e1FFf623aA927dD4e28c67a - mainnet NEXT token (token1 on mainnet vault) + +// 0x58b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e8 - Optimism NEXT token (token0 on arb vault) + +// -------- + +contract ValindromeProposal is ForgeHelper { + enum Operation { + Call, + DelegateCall + } + + struct Transaction { + address to; + uint256 value; + bytes data; + Operation operation; + } + + // ================== Libraries ================== + using stdJson for string; + using Strings for string; + using Strings for uint256; + + // ================== Events ================== + + // ================== Structs ================== + + // ================== Storage ================== + + // Fork management utilities + ForkHelper public FORK_HELPER; + + // Transactions path + string public TRANSACTIONS_PATH = "/valindrome-transactions.json"; + + // Number of transactions to execute in multisend data: + // 1. mainnet approval of NEXT to lockbox + // 2. mainnet deposit on lockbox + // 3. mainnet approval of xNEXT to connext + // 4. xcall xNEXT into connext + + uint256 public NUMBER_TRANSACTIONS = 4; + + // Amount to bridge into OP multisig + uint256 public LIQUIDITY_AMOUNT_OPTIMISM = 1500000 ether; // used in transactions + + // ================== Setup ================== + + function setUp() public { + // Create the fork helper for mainnet and optimism + uint256[] memory chains = new uint256[](2); + chains[0] = 1; + chains[1] = 10; + FORK_HELPER = new ForkHelper(chains); + vm.makePersistent(address(FORK_HELPER)); + + // Create the forks + FORK_HELPER.utils_createForks(); + assertEq(FORK_HELPER.utils_getNetworksCount(), 2, "!forks"); + } + + function utils_generateTransactions() + public + view + returns (Transaction[] memory _transactions) + { + // Generate executable from `valindrome-transactions.json` + string memory path = string.concat(vm.projectRoot(), TRANSACTIONS_PATH); + + string memory json = vm.readFile(path); + + // Generate the bytes of the multisend transactions + _transactions = new Transaction[](NUMBER_TRANSACTIONS); + for (uint256 i; i < NUMBER_TRANSACTIONS; i++) { + string memory baseJsonPath = string.concat( + ".transactions[", + i.toString(), + "]" + ); + address to = json.readAddress(string.concat(baseJsonPath, ".to")); + uint256 value = json.readUint( + string.concat(baseJsonPath, ".value") + ); + // No way to check if data is null in json, this will revert if data is null + // TODO: add support to automatically generate data if its null + bytes memory data = json.readBytes( + string.concat(baseJsonPath, ".data") + ); + + // Add to transactions + _transactions[i] = Transaction({ + to: to, + value: value, + data: data, + operation: Operation.Call + }); + } + } + + function utils_getXCallTo( + uint256 transactionIdx + ) public view returns (address _to) { + // Generate executable from `valindrome-transactions.json` + string memory path = string.concat(vm.projectRoot(), TRANSACTIONS_PATH); + + string memory json = vm.readFile(path); + string memory jsonPath = string.concat( + ".transactions[", + transactionIdx.toString(), + "].contractInputsValues._to" + ); + _to = json.readAddress(jsonPath); + } + + // ================== Tests ================== + function test_executableShouldPass() public { + // Generate the multisend transactions + // bytes memory transactions = utils_generateMultisendTransactions(); + Transaction[] memory transactions = utils_generateTransactions(); + + // Select and prep mainnet fork + vm.selectFork(FORK_HELPER.forkIdsByChain(1)); + address caller = AddressLookup.getConnextDao(1); + vm.makePersistent(caller); + + // Submit the transactions + // NOTE: This assumes signatures will be valid, and the batching of these transactions + // will be valid. Simply pranks and calls each function in a loop as DAO. + vm.deal(caller, 1 ether); + for (uint256 i; i < transactions.length; i++) { + // Send tx + vm.prank(caller); + (bool success, ) = transactions[i].to.call{ + value: transactions[i].value + }(transactions[i].data); + assertTrue(success, string.concat("!success @ ", i.toString())); + } + + // Select and prep Optimism fork + vm.selectFork(FORK_HELPER.forkIdsByChain(10)); + caller = AddressLookup.getConnext(10); + vm.makePersistent(caller); + + // Process optimism xcall for `approval` by transferring to `to` + address to = utils_getXCallTo(3); + address asset = AddressLookup.getNEXTAddress(10); + vm.startPrank(caller); + // Mint on NEXT to caller + IXERC20(asset).mint(to, LIQUIDITY_AMOUNT_OPTIMISM); + + vm.stopPrank(); + + uint256 balance = IERC20(AddressLookup.getNEXTAddress(10)).balanceOf( + to + ); + assertEq(balance, LIQUIDITY_AMOUNT_OPTIMISM, "!balance"); + } +} diff --git a/valindrome-transactions.json b/valindrome-transactions.json new file mode 100644 index 0000000..3f82819 --- /dev/null +++ b/valindrome-transactions.json @@ -0,0 +1,93 @@ +{ + "version": "1.0", + "chainId": "1", + "createdAt": 1698843459112, + "meta": { + "name": "Transactions Batch", + "description": "", + "txBuilderVersion": "1.16.3", + "createdFromSafeAddress": "0xf2964cCcB7CDA9e808aaBe8DB0DDDAF7890dd378", + "createdFromOwnerAddress": "", + "checksum": "0xdbc08311d3e010b14c94e185b27ff37d6413e31bf0677df5803dbad54fa3128a" + }, + "transactions": [ + { + "to": "0xFE67A4450907459c3e1FFf623aA927dD4e28c67a", + "value": "0", + "data": "0x095ea7b300000000000000000000000022f424bca11fe154c403c277b5f8dab54a4ba29b000000000000000000000000000000000000000000013da329b6336471800000", + "contractMethod": { + "inputs": [ + { "name": "spender", "type": "address", "internalType": "address" }, + { "name": "amount", "type": "uint256", "internalType": "uint256" } + ], + "name": "approve", + "payable": false + }, + "contractInputsValues": { + "spender": "0x22f424Bca11FE154c403c277b5F8dAb54a4bA29b", + "amount": "1500000000000000000000000" + } + }, + { + "to": "0x22f424Bca11FE154c403c277b5F8dAb54a4bA29b", + "value": "0", + "data": "0xb6b55f25000000000000000000000000000000000000000000013da329b6336471800000", + "contractMethod": { + "inputs": [ + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "deposit", + "payable": false + }, + "contractInputsValues": { "_amount": "1500000000000000000000000" } + }, + { + "to": "0x58b9cB810A68a7f3e1E4f8Cb45D1B9B3c79705E8", + "value": "0", + "data": "0x095ea7b30000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c6000000000000000000000000000000000000000000013da329b6336471800000", + "contractMethod": { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "payable": false + }, + "contractInputsValues": { + "spender": "0x8898B472C54c31894e3B9bb83cEA802a5d0e63C6", + "amount": "1500000000000000000000000" + } + }, + { + "to": "0x8898B472C54c31894e3B9bb83cEA802a5d0e63C6", + "value": "0", + "data": "0x8aac16ba000000000000000000000000000000000000000000000000000000006f7074690000000000000000000000001a3c9dc0c3fb2d9bc435e28479b3d9b3e334334700000000000000000000000058b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e80000000000000000000000001a3c9dc0c3fb2d9bc435e28479b3d9b3e3343347000000000000000000000000000000000000000000013da329b6336471800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000", + "contractMethod": { + "inputs": [ + { + "internalType": "uint32", + "name": "_destination", + "type": "uint32" + }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "address", "name": "_asset", "type": "address" }, + { "internalType": "address", "name": "_delegate", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" }, + { "internalType": "uint256", "name": "_slippage", "type": "uint256" }, + { "internalType": "bytes", "name": "_callData", "type": "bytes" } + ], + "name": "xcall", + "payable": true + }, + "contractInputsValues": { + "_destination": "1869640809", + "_to": "0x1a3C9dC0c3fb2D9bC435e28479b3d9b3e3343347", + "_asset": "0x58b9cB810A68a7f3e1E4f8Cb45D1B9B3c79705E8", + "_delegate": "0x1a3C9dC0c3fb2D9bC435e28479b3d9b3e3343347", + "_amount": "1500000000000000000000000", + "_slippage": "0", + "_callData": "0x" + } + } + ] +} From 68ff4768f772dcdae8ee4245e37e92a2411ecca2 Mon Sep 17 00:00:00 2001 From: Prathmesh <201952225@iiitvadodara.ac.in> Date: Thu, 2 Nov 2023 20:27:59 +0530 Subject: [PATCH 02/11] fix: spell --- ...drome-transactions.json => Velodrome-transactions.json | 0 test/ValindromeProposal.sol | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) rename valindrome-transactions.json => Velodrome-transactions.json (100%) diff --git a/valindrome-transactions.json b/Velodrome-transactions.json similarity index 100% rename from valindrome-transactions.json rename to Velodrome-transactions.json diff --git a/test/ValindromeProposal.sol b/test/ValindromeProposal.sol index fcf854d..c9631ee 100644 --- a/test/ValindromeProposal.sol +++ b/test/ValindromeProposal.sol @@ -28,7 +28,7 @@ import "forge-std/console.sol"; // -------- -contract ValindromeProposal is ForgeHelper { +contract VelodromeProposal is ForgeHelper { enum Operation { Call, DelegateCall @@ -56,7 +56,7 @@ contract ValindromeProposal is ForgeHelper { ForkHelper public FORK_HELPER; // Transactions path - string public TRANSACTIONS_PATH = "/valindrome-transactions.json"; + string public TRANSACTIONS_PATH = "/Velodrome-transactions.json"; // Number of transactions to execute in multisend data: // 1. mainnet approval of NEXT to lockbox @@ -89,7 +89,7 @@ contract ValindromeProposal is ForgeHelper { view returns (Transaction[] memory _transactions) { - // Generate executable from `valindrome-transactions.json` + // Generate executable from `Velodrome-transactions.json` string memory path = string.concat(vm.projectRoot(), TRANSACTIONS_PATH); string memory json = vm.readFile(path); @@ -125,7 +125,7 @@ contract ValindromeProposal is ForgeHelper { function utils_getXCallTo( uint256 transactionIdx ) public view returns (address _to) { - // Generate executable from `valindrome-transactions.json` + // Generate executable from `Velodrome-transactions.json` string memory path = string.concat(vm.projectRoot(), TRANSACTIONS_PATH); string memory json = vm.readFile(path); From 1ce5a9d9682f037fd7d42ebdaa74f1f163737c9c Mon Sep 17 00:00:00 2001 From: Layne Haber Date: Thu, 2 Nov 2023 20:44:07 -0600 Subject: [PATCH 03/11] feat: dont enforce fork-block --- test/utils/ForkHelper.sol | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/utils/ForkHelper.sol b/test/utils/ForkHelper.sol index 277de29..e18bd38 100644 --- a/test/utils/ForkHelper.sol +++ b/test/utils/ForkHelper.sol @@ -56,7 +56,12 @@ contract ForkHelper is ForgeHelper { require(NETWORK_IDS.length > 0, "!networks"); for (uint256 i; i < NETWORK_IDS.length; i++) { // create the fork - uint256 forkId = vm.createSelectFork(vm.envString(ChainLookup.getRpcEnvName(NETWORK_IDS[i])), FORK_BLOCKS[i]); + uint256 forkId; + if (FORK_BLOCKS[i] == 0) { + forkId = vm.createSelectFork(vm.envString(ChainLookup.getRpcEnvName(NETWORK_IDS[i]))); + } else { + forkId = vm.createSelectFork(vm.envString(ChainLookup.getRpcEnvName(NETWORK_IDS[i])), FORK_BLOCKS[i]); + } // update the mappings forkIdsByChain[block.chainid] = forkId; chainsByForkId[forkId] = block.chainid; From 0dc2761167eaa425d04a9b73807e8d578c1c29b0 Mon Sep 17 00:00:00 2001 From: Layne Haber Date: Thu, 2 Nov 2023 20:44:25 -0600 Subject: [PATCH 04/11] fix: ForkHelper instantiation --- test/ValindromeProposal.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/ValindromeProposal.sol b/test/ValindromeProposal.sol index c9631ee..5d01ed5 100644 --- a/test/ValindromeProposal.sol +++ b/test/ValindromeProposal.sol @@ -76,7 +76,10 @@ contract VelodromeProposal is ForgeHelper { uint256[] memory chains = new uint256[](2); chains[0] = 1; chains[1] = 10; - FORK_HELPER = new ForkHelper(chains); + + uint256[] memory blocks = new uint256[](2); + + FORK_HELPER = new ForkHelper(chains, blocks); vm.makePersistent(address(FORK_HELPER)); // Create the forks From 298c16becc31fd6e5739f98d8dfdbd619a3e537b Mon Sep 17 00:00:00 2001 From: Layne Haber Date: Thu, 2 Nov 2023 20:55:20 -0600 Subject: [PATCH 05/11] chore: remove value --- test/ValindromeProposal.sol | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/ValindromeProposal.sol b/test/ValindromeProposal.sol index 5d01ed5..b7ce826 100644 --- a/test/ValindromeProposal.sol +++ b/test/ValindromeProposal.sol @@ -154,13 +154,10 @@ contract VelodromeProposal is ForgeHelper { // Submit the transactions // NOTE: This assumes signatures will be valid, and the batching of these transactions // will be valid. Simply pranks and calls each function in a loop as DAO. - vm.deal(caller, 1 ether); for (uint256 i; i < transactions.length; i++) { // Send tx vm.prank(caller); - (bool success, ) = transactions[i].to.call{ - value: transactions[i].value - }(transactions[i].data); + (bool success, ) = transactions[i].to.call(transactions[i].data); assertTrue(success, string.concat("!success @ ", i.toString())); } @@ -175,7 +172,6 @@ contract VelodromeProposal is ForgeHelper { vm.startPrank(caller); // Mint on NEXT to caller IXERC20(asset).mint(to, LIQUIDITY_AMOUNT_OPTIMISM); - vm.stopPrank(); uint256 balance = IERC20(AddressLookup.getNEXTAddress(10)).balanceOf( From dcbbec1558c91f54667cf674cb2b973f2bfb46af Mon Sep 17 00:00:00 2001 From: Layne Haber Date: Thu, 2 Nov 2023 20:59:21 -0600 Subject: [PATCH 06/11] feat: add dao balance change assertion --- test/ValindromeProposal.sol | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/ValindromeProposal.sol b/test/ValindromeProposal.sol index b7ce826..d44a5c9 100644 --- a/test/ValindromeProposal.sol +++ b/test/ValindromeProposal.sol @@ -149,6 +149,9 @@ contract VelodromeProposal is ForgeHelper { // Select and prep mainnet fork vm.selectFork(FORK_HELPER.forkIdsByChain(1)); address caller = AddressLookup.getConnextDao(1); + uint256 initial = IERC20(AddressLookup.getNEXTAddress(1)).balanceOf( + caller + ); vm.makePersistent(caller); // Submit the transactions @@ -172,11 +175,21 @@ contract VelodromeProposal is ForgeHelper { vm.startPrank(caller); // Mint on NEXT to caller IXERC20(asset).mint(to, LIQUIDITY_AMOUNT_OPTIMISM); + // No calldata on the xcall vm.stopPrank(); + // Ensure the optimism balance increased uint256 balance = IERC20(AddressLookup.getNEXTAddress(10)).balanceOf( to ); assertEq(balance, LIQUIDITY_AMOUNT_OPTIMISM, "!balance"); + + // Ensure the connext mainnet balance decreased + vm.selectFork(FORK_HELPER.forkIdsByChain(1)); + assertEq( + IERC20(AddressLookup.getNEXTAddress(1)).balanceOf(AddressLookup.getConnextDao(1)), + initial - LIQUIDITY_AMOUNT_OPTIMISM, + "!balance" + ); } } From 15bbc50e9b45bb42adcf1eee758d84fde65182df Mon Sep 17 00:00:00 2001 From: Layne Haber Date: Thu, 2 Nov 2023 20:59:59 -0600 Subject: [PATCH 07/11] chore: spellcheck --- test/{ValindromeProposal.sol => VelodromeProposal.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{ValindromeProposal.sol => VelodromeProposal.sol} (100%) diff --git a/test/ValindromeProposal.sol b/test/VelodromeProposal.sol similarity index 100% rename from test/ValindromeProposal.sol rename to test/VelodromeProposal.sol From d188492e872bb22d56f68fd4588ddb67835afd5c Mon Sep 17 00:00:00 2001 From: Layne Haber Date: Thu, 2 Nov 2023 21:55:56 -0600 Subject: [PATCH 08/11] chore: remove unused --- test/VelodromeProposal.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/test/VelodromeProposal.sol b/test/VelodromeProposal.sol index d44a5c9..8734d81 100644 --- a/test/VelodromeProposal.sol +++ b/test/VelodromeProposal.sol @@ -9,7 +9,6 @@ import {MultiSendCallOnly} from "safe-contracts/libraries/MultiSendCallOnly.sol" import {IXReceiver} from "@connext/interfaces/core/IXReceiver.sol"; -import {IPALMTerms} from "./interfaces/IPALMTerms.sol"; import {IXERC20} from "./interfaces/IXERC20.sol"; import {ForgeHelper} from "./utils/ForgeHelper.sol"; From daedf7c717f9e229c475f3cec53d984f853637eb Mon Sep 17 00:00:00 2001 From: Prathmesh Khandelwal <201952225@iiitvadodara.ac.in> Date: Fri, 3 Nov 2023 14:41:38 +0530 Subject: [PATCH 09/11] fix: added running test section in readme --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 3ab0303..55f0c5e 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,27 @@ contract ContractTest is Test { } ``` +### Running the test + +- Ensure that Foundry is installed in your system. +- Create a `.env` file in the root of the repository and copy the content of `.env.example` in it. Make sure to add RPCs of the networks you are going cross-chain + + ``` + MAINNET_RPC_URL= + OPTIMISM_RPC_URL= + BNB_RPC_URL= + GNOSIS_RPC_URL= + POLYGON_RPC_URL= + ARBITRUM_ONE_RPC_URL= + ``` + +- Run forge test to run all the tests. In case you only need one test to run. Use `--match-contract` flag. Ex. below for VelodromeProposal: + + ```sh + forge test --match-contract VelodromeProposal + ``` + + ### Development This project uses [Foundry](https://getfoundry.sh). See the [book](https://book.getfoundry.sh/getting-started/installation.html) for instructions on how to install and use Foundry. From 1a75a7d318972e3f0691684ad2404fff4e9e10c8 Mon Sep 17 00:00:00 2001 From: Prathmesh <201952225@iiitvadodara.ac.in> Date: Thu, 14 Dec 2023 14:07:15 +0530 Subject: [PATCH 10/11] fix: ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbe7307..be1d3cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: run: forge install - name: Check gas snapshots - run: forge snapshot --check + run: export MAINNET_RPC_URL=https://eth.llamarpc.com && forge snapshot --check - name: Run tests - run: forge test + run: export MAINNET_RPC_URL=https://eth.llamarpc.com && forge test From 9859ca2b6dd76e8912444a6b8cc08b2272b1a638 Mon Sep 17 00:00:00 2001 From: Prathmesh <201952225@iiitvadodara.ac.in> Date: Thu, 14 Dec 2023 14:28:02 +0530 Subject: [PATCH 11/11] fix: ci re --- .github/workflows/ci.yml | 7 ++----- main.sh | 16 ++++++++++++++++ test/VelodromeProposal.sol | 15 ++++++++++++--- 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100755 main.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be1d3cd..5a3ff96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,5 @@ jobs: - name: Install deps run: forge install - - name: Check gas snapshots - run: export MAINNET_RPC_URL=https://eth.llamarpc.com && forge snapshot --check - - - name: Run tests - run: export MAINNET_RPC_URL=https://eth.llamarpc.com && forge test + - name: Check gas snapshots && Run tests + run: ./main.sh diff --git a/main.sh b/main.sh new file mode 100755 index 0000000..439108e --- /dev/null +++ b/main.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Exporting values for all mainnet network RPCs. +export MAINNET_RPC_URL="https://eth.llamarpc.com" +export OPTIMISM_RPC_URL="https://optimism.llamarpc.com" +export BNB_RPC_URL="https://binance.llamarpc.com" +export GNOSIS_RPC_URL="https://gnosis-pokt.nodies.app" +export POLYGON_RPC_URL="https://polygon.llamarpc.com" +export ARBITRUM_ONE_RPC_URL="https://arbitrum.llamarpc.com" + + +# Check gas snapshots +forge snapshot --check + +# Run tests +forge test \ No newline at end of file diff --git a/test/VelodromeProposal.sol b/test/VelodromeProposal.sol index 8734d81..5d081ba 100644 --- a/test/VelodromeProposal.sol +++ b/test/VelodromeProposal.sol @@ -172,6 +172,9 @@ contract VelodromeProposal is ForgeHelper { address to = utils_getXCallTo(3); address asset = AddressLookup.getNEXTAddress(10); vm.startPrank(caller); + uint256 initialbalance = IERC20(AddressLookup.getNEXTAddress(10)) + .balanceOf(to); + // Mint on NEXT to caller IXERC20(asset).mint(to, LIQUIDITY_AMOUNT_OPTIMISM); // No calldata on the xcall @@ -181,13 +184,19 @@ contract VelodromeProposal is ForgeHelper { uint256 balance = IERC20(AddressLookup.getNEXTAddress(10)).balanceOf( to ); - assertEq(balance, LIQUIDITY_AMOUNT_OPTIMISM, "!balance"); + assertEq( + balance, + LIQUIDITY_AMOUNT_OPTIMISM + initialbalance, + "!balance" + ); // Ensure the connext mainnet balance decreased vm.selectFork(FORK_HELPER.forkIdsByChain(1)); assertEq( - IERC20(AddressLookup.getNEXTAddress(1)).balanceOf(AddressLookup.getConnextDao(1)), - initial - LIQUIDITY_AMOUNT_OPTIMISM, + IERC20(AddressLookup.getNEXTAddress(1)).balanceOf( + AddressLookup.getConnextDao(1) + ), + initial - LIQUIDITY_AMOUNT_OPTIMISM, "!balance" ); }