0

I've been writing unit tests for a contract using Hardhat + Ethers + Typescript, let's call it ContractA. This ContractA has a hardcoded address of a deployed ERC20 token in it like this TokenA = '0x...'. So in the tests I do:

ContractA = await ethers.getContractFactory("ContractA");
contractA = await upgrades.deployProxy(ContractA);

and then I proceed to test some functions, which work normally.

But when I try to test a particular function in ContractA that uses the hardcoded ERC20 address like this:

function buyExtra(address Owner, uint256 count) public whenNotPaused {
...
IERC20Upgradeable(TokenA).safeTransferFrom(msg.sender, address(this), count);
...
}

it doesn't work, and I received the error Error: VM Exception while processing transaction: revert Address: call to non-contract.

PS: I think I understand the reason, that is because the hardcoded address given in ContractA is the address of the ERC20 token in Rinkeby. As such, it does not exist in the test environment.

So what should I do? Is it possible to deploy the ERC20 contract in the test environment with the exact the same address it has in Rinkeby? Is this what I need to do? Btw, I don't have the ERC20 contract in my project.

1 Answer 1

1

You should be passing deployment information into the contract, e.g. through the constructor. Then you have some flexibility in migrations and tests.

  • If rinkeby, address = hardcoded
  • If elsewere, deploy a stub and use that address

(For example).

An alternative way to go is to try forking the public chain and then testing against that.

Hope it helps

UPDATE

import "./IERC20.sol";

contract X {

  IERC20 token;

  constructor(address _token) {
     token = IERC20(_token);
  }
}

Sketched on a phone. No warranty ;-)

2
  • thanks a lot! I'll modify my contracts so I can pass the token address in the constructor. After that, in the tests, how will it work? I only need to deploy an ERC20 mock contract and pass its address?
    – afm
    Commented Mar 20, 2021 at 17:19
  • Sounds right. Then IERC20 token = IERC20(thatAddress); Commented Mar 24, 2021 at 4:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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