Hardhat Testing – How to Fund Contract with ERC20 Tokens in Hardhat Test

hardhattesting

I have a contract I'm testing using hardhat.

What is a good approach to fund that contract with an arbitrary ERC20 token (WETH in this case)?

I am testing using a hardhat mainnet fork, my approach is to impersonate an account which has lots of that token and send from that account to my contract; This is not working, seems like I am not successful in impersonating that account. Also, it seems like there might be a better way.

MyTest.js

const { expect } = require("chai");
const { ethers } = require("hardhat");

const IERC20_SOURCE = "@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20";

const WETH_WHALE = "0xF04a5cC80B1E94C69B48f5ee68a08CD2F09A7c3E";
const WETH_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";


describe("Test Contract", async () => {

  let contractToTest, wethContract;
  let admin;

  beforeEach(async () => {
        ([admin] = await ethers.getSigners());

        // Deploy contract
        const MyContract = await ethers.getContractFactory("MyContract");
        contractToTest = await MyContract.deploy();
        await contractToTest.deployed();
       
        // ~~~~~~~~~~~~~ HERE LIES THE ISSUE ~~~~~~~~~~~~

        // Send some ERC20 to my contract
        // by trying to impersonate a whale and sending stuff from their accounts
        await hre.network.provider.request({
            method: "hardhat_impersonateAccount",
            params: [WETH_WHALE],
        });
        const signer = await ethers.provider.getSigner(WETH_WHALE);
        signer.address = signer._address;
        wethContract = await hre.ethers.getContractAt(IERC20_SOURCE, WETH_ADDRESS, signer);
        wethContract = wethContract.connect(signer);

        console.log("Signer WETH balance", await wethContract.balanceOf(signer.address))
        // Signer WETH balance BigNumber { value: "480881976480357719815777" }

        // ~~~~~~~~~~~~~~~ ERROR AFTER THIS LINE :
        await wethContract.transfer(contractToTest.address, ethers.utils.parseEther("10"));
        //  InvalidInputError: sender doesn't have enough funds to send tx. 
        // The max upfront cost is: 3311216806566865328 and the sender's account only has: 0

        // WE DON'T GET HERE: 
        // check that contractToTest actually holds the 10 WETH
        expect(await wethContract.balanceOf(contractToTest.address)).to.equal(
            ethers.utils.parseEther("10"), 
            "Contract to test should hold 10 WETH!");
  });

});

hardhat.config.js


require("@nomiclabs/hardhat-waffle");
require('dotenv').config();
require("@nomiclabs/hardhat-ethers");

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
const { ALCHEMY_MAINNET_URL, PRIVATE_KEY } = process.env;
module.exports = {
  solidity: "0.6.12",
  defaultNetwork: "hardhat",
  networks: {
      hardhat: {
        forking: {
          url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_MAINNET_URL}`,
          // accounts: [`0x${PRIVATE_KEY}`]
        }
      }
  },
};


Best Answer

I think your problem is not that you did not send tokens into the contract, but that you do not have enough gas in the contract to cover the transaction cost. When deploying, send some value with this transaction so your contract can pay for their own transactions.

Related Topic