I've been trying to debug this for the past 2 days, it has driven me insane. I'm getting this error when testing my contract: Error: Transaction reverted: function call to a non-contract account. It's the simplest contract and simplest function call. It of course works on remix.

Here's the error for npx hardhat.test:

    1) Should not throw error

  0 passing (2s)
  1 failing

  1) Factory
       Should not throw error:
     Error: Transaction reverted: function call to a non-contract account
      at Factory.newToken (contracts/Factory.sol:13)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
      at HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1070:23)
      at HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:369:16)
      at EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1373:18)
      at HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:99:18)
      at EthersProviderWrapper.send (node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)

Please somebody help.

Here's my setup: Factory.sol:

// @unsupported: ovm
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "hardhat/console.sol";

contract Factory  {

    function newToken() public {
        uint x = IERC20(0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa).balanceOf(address(this));




const fs = require('fs');

module.exports = async ({
}) => {
  const { deploy, log, get } = deployments
  const { deployer } = await getNamedAccounts()
  const chainId = await getChainId()
  const factory = await deploy('Factory', {
    from: deployer,
    args: [],
    log: true


module.exports.tags = ['all', 'factory']


const { expect } = require('chai')

describe('Factory', async function () {
  let factory

  beforeEach(async () => {
    await deployments.fixture(['mocks', 'factory'])
    const Factory = await deployments.get('Factory')
    factory = await ethers.getContractAt('Factory', Factory.address)


  it("Should not throw error", async function () {
    await factory.newToken();



 * @type import('hardhat/config').HardhatUserConfig


const MAINNET_RPC_URL = process.env.MAINNET_RPC_URL || process.env.ALCHEMY_MAINNET_RPC_URL || "https://eth-mainnet.alchemyapi.io/v2/your-api-key"
const RINKEBY_RPC_URL = process.env.RINKEBY_RPC_URL || "https://eth-rinkeby.alchemyapi.io/v2/your-api-key"
const KOVAN_RPC_URL = process.env.KOVAN_RPC_URL 
const MNEMONIC = process.env.MNEMONIC 
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || "Your etherscan API key"
// optional
const PRIVATE_KEY = process.env.PRIVATE_KEY || "your private key"

module.exports = {
    defaultNetwork: "hardhat",
    networks: {
        hardhat: {
            // // If you want to do some forking, uncomment this
            // forking: {
            //   url: MAINNET_RPC_URL
            // }
        localhost: {
        kovan: {
            url: KOVAN_RPC_URL,
            // accounts: [PRIVATE_KEY],
            accounts: {
                mnemonic: MNEMONIC,
            saveDeployments: true,
        rinkeby: {
            url: RINKEBY_RPC_URL,
            // accounts: [PRIVATE_KEY],
            accounts: {
                mnemonic: MNEMONIC,
            saveDeployments: true,
        ganache: {
            url: 'http://localhost:8545',
            accounts: {
                mnemonic: MNEMONIC,
    etherscan: {
        // Your API key for Etherscan
        // Obtain one at https://etherscan.io/
        apiKey: ETHERSCAN_API_KEY
    namedAccounts: {
        deployer: {
            default: 0, // here this will by default take the first account as deployer
            1: 0 // similarly on mainnet it will take the first account as deployer. Note though that depending on how hardhat network are configured, the account 0 on one network can be different than on another
        feeCollector: {
            default: 1
    paths: {
        deploy: 'deploy',
        deployments: 'client/packages/contracts/src/deployments',
        artifacts: 'client/packages/contracts/src/deployments/artifacts',
        imports: 'imports'
    solidity: {
        compilers: [
                version: "0.6.6"
                version: "0.6.12",
                settings: {
                  optimizer: {
                    enabled: true,
                    runs: 200
                version: "0.4.24"

    mocha: {
        timeout: 100000


  "name": "chainlink-hardhat-box",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "test": "hardhat test",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  "license": "MIT",
  "devDependencies": {
    "@nomiclabs/hardhat-ethers": "^2.0.1",
    "@nomiclabs/hardhat-etherscan": "^2.1.1",
    "@nomiclabs/hardhat-waffle": "^2.0.1",
    "@nomiclabs/hardhat-web3": "^2.0.0",
    "chai": "^4.2.0",
    "ethereum-waffle": "^3.2.1",
    "ethers": "^5.0.24",
    "hardhat": "^2.0.6",
    "hardhat-deploy": "^0.7.0-beta.39"
  "dependencies": {
    "@chainlink/contracts": "0.1.6",
    "@chainlink/test-helpers": "0.0.5",
    "@chainlink/token": "^1.1.0",
    "@nomiclabs/hardhat-truffle5": "^2.0.0",
    "@openzeppelin/contracts": "3.4.0",
    "@openzeppelin/contracts-upgradeable": "3.4.0",
    "@openzeppelin/hardhat-upgrades": "^1.6.0",
    "@uniswap/v2-periphery": "1.1.0-beta.0",
    "dotenv": "6.2.0",
    "eslint": "^6.0.0"
  "mocha": {
    "timeout": 10000000

It means, the interface is trying to call a contract that doesn't exist.


The following line in your contract is triggering the error.

uint x = IERC20(0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa).balanceOf(address(this));

Looking at your hardhat config, you using a fresh local development network where 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa is likely an empty account, since I couldn't see any other logic that deploys an ERC20 at that address.

I guessed that you meant to do a mainnet fork (docs). But the address 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa is not an ERC20 contract on ethereum mainnet, are you sure this address is correct? If you put a valid ERC20 contract address, you will not get this error.


I had similar issue. After a bit research, I found out that the contract I am calling doesn't exist. I was using local hardhat network. But after redeployment, everything is working fine. Local hardhat network do not persist data if you shutdown the node. It stores every transaction and block in memory. As soon as you shutdown the node, all the block and transaction which has been mined is lost. So you need to start the node again and deploy the contracts again to be able to work.


In my case, I was forking from a block where the contract I was trying to access to was not yet created. Hope this helps somebody else!


I had the same issue and I think followed the same tutorial as you from Jame Bachini. You need to follow his steps where he forks the network using his alchemy node and then open a new terminal window and npx hardhat run --network localhost and your tests should run fine.

To ensure nothing is wrong with your codebase, backstop it against his repo linked here: https://github.com/jamesbachini/myVault

Original video: https://www.youtube.com/watch?v=R91Uhw07W3U&t=224s

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.