Ethereum Virtual Machine (EVM): Dealing with Nonce Headache

in Programming & Devlast year (edited)

Working on a web3 project is fun until you start dealing with bugs here. If you've been there, you'll agree that there's no magic to it. It's Either you seek help from senior engineers or hunt for solutions yourself. In my case, I did the latter.

You may want to ask; 'What type of bug was I dealing with?. Well, Truth be told, it wasn't really a bug. It was just me seeking better approaches to improve my app performance then I ended up discovering a fantastic tool/library for developing front-end web3 projects. What do I mean?

In my app, I created a function that returned an instance of an EVM smart contract. Inside this function, I declared the followings;

  • A new provider using the jsonRpcProvider
  • A new signer using the Wallet signer(This requires the wallet private key, and the provider)
  • And a contract instance which takes in (contract address, contract abi, and signer)

check the example code below;


 // conract address
  const contractAddress= "0xc65...";

  // node url
  const rpcUrl = "https://testnet.......";

  //provider
  const  provider= new ethers.providers.JsonRpcProvider(rpcUrl);


  // Signer
  const  walletSigner= new ethers.Wallet(pk, provider);

  const mycontract= new ethers.Contract(
    contractAddress,
    contractAbi,
    walletSigner
  );


The problem


With the code above, I was able to communicate with contract functions. However, with the way my code ought to be written, I needed to keep listening to the contract states. And just in case you don't know, spam calling an EVM contract functions leads to your app lagging and it's not even a good coding practice.

In fact, I faced an issue where contract functions were being called just before the previous call is resolved. This led to “nonce too low” Error. What does this mean?

Each time we initiate a transaction on the blockchain, each of those transactions ought to have a unique position which is known as Nonce. Nonce prevents double-spending. That is, a wallet's nonce increases as it initiates a new transaction.

So, “nonce too low” error simply means that the transaction expected a higher nonce number from the one generated by the tnx. So why was this happening in my case?

Don't forget that my code was constantly listening to the contract states. So, my code didn't have the logic to await for the previous call to resolve before sending a new one.

To solve this error, I came across an amazing tool that manages nonce each time a transaction is initiated.

The nonce manager

The nonce manager is one of those packages that are under the experimental category of Etherjs project. Experimental packages are those tools that are not ready to be included in the base library. I understood the risk of using unofficially released packages before using the nonce manager for my app.

With the help of the nonce manager, let's rewrite my function.

//import NonceManger from etherjs
import { NonceManager } from "@ethersproject/experimental";

// conract address
  const contractAddress= "0xc65...";

  // node url
  const rpcUrl = "https://testnet.......";

  //provider
  const  provider= new ethers.providers.JsonRpcProvider(rpcUrl);

  // Signer
  const  walletSigner= new ethers.Wallet(pk, provider);

const managedSigner = new NonceManager(walletSigner);

  const mycontract= new ethers.Contract(
    contractAddress,
    contractAbi,
    walletSigner
  );

I add the manager const managedSigner = new NonceManager(walletSigner);, then, passed the walletSigner as a parameter. Now, I do not have to worry about the nonce too low error.

If anyone is interested in reading more on Nonce Manger, kindly check this page.


image.png

Sort:  


The rewards earned on this comment will go directly to the people sharing the post on Twitter as long as they are registered with @poshtoken. Sign up at https://hiveposh.com.

Thanks for your contribution to the STEMsocial community. Feel free to join us on discord to get to know the rest of us!

Please consider delegating to the @stemsocial account (85% of the curation rewards are returned).

You may also include @stemsocial as a beneficiary of the rewards of this post to get a stronger support. 
 

Well done @rufans! You successfully guessed the match result and unlocked your badge!
Click on the badge to view your board. Click here to check your ranking.

Thank you to our sponsors. Please consider supporting them.

Check out the last post from @hivebuzz:

HiveBuzz World Cup Contest - Quarterfinals - Recap of Day 1
The Hive Gamification Proposal Renewal
Well done @rufans! You successfully guessed the match result and unlocked your badge!
Click on the badge to view your board. Click here to check your ranking.

Thank you to our sponsors. Please consider supporting them.

Check out the last post from @hivebuzz:

HiveBuzz World Cup Contest - Quarterfinals - Recap of Day 2
HiveBuzz World Cup Contest - Quarterfinals - Recap of Day 1
The Hive Gamification Proposal Renewal