1

This week at a talking by our friend Patrick Collins during the Chainlink Spring 2022 Hackathon schedule, I took knowledge of the possibility of moving ahead of time on the blockchain during tests:

  async moveTime(amount: number) {
    console.log("Moving blocks...");
    await network.provider.send("evm_increaseTime", [amount]);

    console.log(`Moved forward in time ${amount} seconds`);
  }

So I'm trying to use it on my tests but, from the moment I started to use it, my tests started to have this exception:

Error: nonce has already been used [ See: https://links.ethers.org/v5-errors-NONCE_EXPIRED ] (error={"name":"InvalidInputError","code":-32000,"_isProviderError":true}, method="sendTransaction", transaction="0x02f872827a69148459682f008461277a0a8401bad45894532323de74bab864b7005d910e5bd8562d038b9b8084478c7d5fc001a0e987896b237af1c098617321e8356a5dd903b834f7fe9e4188f6b5858530d263a06fce96280dc21b5d41909353ae33897f4155a3742d1deefac0f77575d9ec9151", code=NONCE_EXPIRED, version=providers/5.6.1)

I've found out a similar post with this kind of error at NONCE_EXPIRED error with ethers.js on local hardhat node and have followed the instructions about doing the snapshot but it didn't solve the problem:

before(async function () {
    const accounts = waffle.provider.getWallets();

    ....
    this.loadFixture = waffle.createFixtureLoader(accounts);

    snapshot = await waffle.provider.send("evm_snapshot", []);
  });

  after(async function () {
    await waffle.provider.send("evm_revert", [snapshot]);
  });

Anyone else faced this kind of problem and succeded solving it?

IMPORTANT: The error does not happen in all execution, only when I run the tests few seconds after a previous execution.

Regards,

1 Answer 1

1

I've found out the cause of problem I reported above. In my case specifically, the problem was not related to the JSON-RPC methods evm_increaseTime and the solution was not snapshoting the blockchain.

The problem is that in some of my tests when asserting for events emitted and reverted conditions I've done it in a wrong way.

On the contrary of regular assertions, where we pass the value being asserted to expect function:

expect(BigNumber.from(100)).to.be.within(BigNumber.from(99), BigNumber.from(101));

And, of course, if it's remote call we make use of await in order to not pass a Promise but the actual value returned:

expect(await token.balanceOf(wallet.address)).to.equal(993);

To assert emitted events and revertions, we can** pass the Promise to expect and we have to use await for the expect function:

await expect(token.transfer(walletTo.address, 7))
  .to.emit(token, 'Transfer')
  .withArgs(wallet.address, walletTo.address, 7);


await expect(token.transfer(walletTo.address, 1007))
  .to.be.revertedWith('Insufficient funds');

There is even a note in the Waffle documentation about this:

You must await the expect in order for the matcher to execute properly. Failing to await will cause the assertion to pass whether or not the event is actually emitted!

After going throughout all my testing code and repairing all occurrences of this mistake, it is working just fine.

** My tests work well when I pass the Promise returned by contract's function calling to expectfunction, as well as when I make use of await before the function calling and pass the receipt itself in spite of the Promise.

Your Answer

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

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