DEV Community

Cover image for How to Fork Mainnet for Testing
Dmitry Zakharov
Dmitry Zakharov

Posted on

30 2 2 2 2

How to Fork Mainnet for Testing

Intro

One of the most exciting features of DeFi is interoperability, which allows constructing protocols using deployed smart contracts as base blocks for your protocol (e.g., Yearn Strategies). As a matter of fact, interoperability is one of the reasons why DeFi protocols are referred to as legos. Just like Lego blocks, you have to find the right way to fit two DeFi protocols together for specific use cases.
Developers have two options for testing smart contracts that integrate with at least one existing protocol: creating a mock that implements all necessary functions of an already deployed smart contract or using mainnet forking for tests. Mocks can mask very dangerous problems because they usually copy only the needed function from real contracts, which can lead to incorrect mock work. That's why we strongly recommend using mocks only if it is crucial. In all other cases, you can use mainnet forking.

Mainnet forking in hardhat

In this article, we will discuss how to set up your hardhat project for mainnet forking. First of all, you must have an Infura or Alchemy API key to use a RPC node to fork the state of the specific block. After getting an API key from one of the RPC providers, you need to change your config file like this:

const CHAIN_IDS = {
  hardhat: 31337, // chain ID for hardhat testing
};
module.exports = {
  networks: {
    hardhat: {
      chainId: CHAIN_IDS.hardhat,
      forking: {
        // Using Alchemy
        url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}`, // url to RPC node, ${ALCHEMY_KEY} - must be your API key
        // Using Infura
        // url: `https://mainnet.infura.io/v3/${INFURA_KEY}`, // ${INFURA_KEY} - must be your API key
        blockNumber: 12821000, // a specific block number with which you want to work
      },
    },
    ... // you can also add more necessary information to your config
  }
}
Enter fullscreen mode Exit fullscreen mode

After adding this to your hardhat.config.js file, you can use all necessary information from the specific block. For example, you can impersonate an address and use some tokens from a random address to test your function (it is very useful when you need a rare NFT to test one of your functions), or you can call any function from any contract only by adding a needed interface to your project. Some tips for working with a mainnet fork in a hardhat test are presented in the example below.

// Function which allows to convert any address to the signer, which can sign transactions in a test
const impersonateAddress = async (address) => {
  const hre = require('hardhat');
  await hre.network.provider.request({
    method: 'hardhat_impersonateAccount',
    params: [address],
  });
  const signer = await ethers.provider.getSigner(address);
  signer.address = signer._address;
  return signer;
};
// Function to increase time in mainnet fork
async function increaseTime(value) {
  if (!ethers.BigNumber.isBigNumber(value)) {
    value = ethers.BigNumber.from(value);
  }
  await ethers.provider.send('evm_increaseTime', [value.toNumber()]);
  await ethers.provider.send('evm_mine');
}
// Construction to get any contract as an object by its interface and address in blockchain
// It is necessary to note that you must add an interface to your project
const WETH = await ethers.getContractAt('IWETH', wethAddress);
Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

đź‘‹ Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay