Mainnet Forking in Foundry

Samarth SaxenaSamarth Saxena
3 min read

Introduction

When developing smart contracts, we often need to interact with contracts that have already been deployed. It would not be a smart decision to deploy the contract and test it on Mainnet using real ETH. But, thankfully for us, there is a solution and that is what we will be covering in this guide. We’ll keep it short and simple for now.

What is forking?

Forking in this context is very similar forking a GitHub repository. Just like you are able to get the entirety of the repo in your account and make changes to it without affecting the original repo, forking a blockchain makes its entire state up till the time of fork available to you for interaction locally without actually sending transactions to that chain. No changes are made to the state of the chain you fork from and all your interactions remain on your local blockchain node.

Forking any Network

The process of forking a chain is pretty simple in Foundry. All you need is an RPC URL for the network you want to fork. Mind you, if you use a public RPC, chances are that it won’t contain the entire state of the blockchain up till that time and calling functions on contracts may not work as you’d expect them to. Moreover, you may get rate limited. If you have a key from QuickNode, Infura or other providers, you should use that instead.

For this example, we’ll fork Ethereum Mainnet. Spin up a local blockchain node using Anvil like so:

anvil --fork-url mainnet_rpc_url

This might take more time than when we run just anvil, as it should, since we are connecting an RPC endpoint to our node for interacting with the state of the chain up till that point. All the transactions we perform after this will remain on our local anvil node, unless we specify that we want to send them to some other network.

Check if it worked

Let’s see if we were able to successfully fork Ethereum Mainnet

cast block-number

For a node started using just anvil, ie. without the fork-url option, we would have received 0 as the output. But in our case, you should see something like this:

This is the block number at which the fork was created. So our local node can query the state of the blockchain upto this block in the live chain.

For further checking, let’s try to see the balance of the account with the ENS name ben.eth, whose address is 0xcd2e72aebe2a203b84f46deec948e6465db51c75. Run this command in your terminal

cast balance 0x91364516d3cad16e1666261dbdbb39c881dbe9ee

If the result is 0, make sure you’ve followed all the steps correctly. If the result is 0 even after that, ben.eth’s wallet probably got hacked and drained. Unfortunate.

A glimpse of what can be

When you want to run tests on the forked blockchain, you’ll do so in the following manner:

function setUp() public {
        // vm is a variable included in the forge standard library that is used to manipulate the execution environment of our tests
        // create a fork of Ethereum mainnet using the specified RPC URL and store its id in mainnetFork 
        mainnetFork = vm.createFork(MAINNET_RPC_URL);
        //select the fork thus obtained, using its id
        vm.selectFork(mainnetFork);
        //.... calls on contracts which exist on the forked chains

}

Don’t worry, we’ll cover smart contract testing soon in this series. I added this snippet just to show you how what’s possible.

Conclusion

That’s it! You’ve successfully forked a live chain and called functions on it! In the next guide, we’ll learn how to verify smart contracts using Etherscan’s API via Foundry. Stay tuned till then. Thanks a lot for reading to the end. Bye for now👋👋

0
Subscribe to my newsletter

Read articles from Samarth Saxena directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Samarth Saxena
Samarth Saxena

I am a Web3 Developer and Technical Writer from India. I love to write about the things I learn and understand. I believe that being serious is not required as long as one is sincere. I thus tend to have fun in everything that I do.