Multichain Testing with Foundry
One of the powerful features offered by Foundry, a blazingly fast development
framework for Ethereum smart contracts, is its ability to run tests against
multiple chains within a single project. This can be achieved using two key
functions: vm.createFork
and vm.selectFork
.
To begin, you need to set up your test file accordingly. By utilizing these functions in combination, you gain flexibility in running tests across different networks seamlessly.
Suppose you have two test files:
VaultL1.t.sol
that test your vault strategy against Uniswap V3 contract on Ethereum mainnet.VaultL2.t.sol
that test your vault strategy against random lending protocol on Polygon zkEVM.
On VaultL1.t.sol
you need to select Ethereum network and fork it:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {Test} from "forge-std/Test.sol";
contract VaultL1Test is Test {
string ETH_RPC_URL = vm.envString("ETH_RPC_URL");
function setUp() public {
uint256 mainnetFork = vm.createFork(ETH_RPC_URL);
vm.selectFork(mainnetFork);
// your setup code here
}
// your tests here
}
Then on the VaultL2.t.sol
do the same thing:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {Test} from "forge-std/Test.sol";
contract VaultL2Test is Test {
string ZKEVM_RPC_URL = vm.envString("ZKEVM_RPC_URL");
function setUp() public {
uint256 zkEvmFork = vm.createFork(ZKEVM_RPC_URL);
vm.selectFork(zkEvmFork);
// your setup code here
}
// your tests here
}
Last step, create .env
in the root directory with the following content:
ETH_RPC_URL="add ethereum rpc url here"
ZKEVM_RPC_URL="add polygon zkevm rpc url here"
With this setup complete, when executing forge test
, the correct network will
automatically be selected according to what has been specified within your test
file. Thus allowing you to conveniently validate that your code interacts
flawlessly across various chains without having separate projects.
This capability provided by Foundry simplifies cross-chain testing procedures while maintaining organization and efficiency during development iterations.
You can check how it used in my recent project here:
L1Escrow.t.sol and L2Dai.t.sol.
That’s it. Follow me on 𝕏
TAGS
*post-tags*
- [1]