I have the following code:
const Contract = artifacts.require('./Market.sol');
module.exports = async function(callback) {
let instance = await Contract.deployed();
for(var i = 0; i <=200; i++){
await instance.createListing(i, 4, {from: address, gas: 5000000, gasPrice: 2000000000})}
}
This works on Truffle and Ganache, works on Ropsten via Infura (executed via truffle exec script.js --network ropsten
).
However, when I'm deploying the contract on mainnet and running truffle exec script.js --network live
, it works for the first 2-3 iterations, and then I'm getting:
UnhandledPromiseRejectionWarning: Error: nonce too low
I tried reinstalling MetaMask, but the issue is still there. What could be the reason of this, and is there a way to add a chunk of code in the script or truffle.js that could help to deal with it?
Best Answer
If you're using Truffle with Infura directly (which it sounds like you are, although it's unclear why you mention MetaMask), you need to be aware that Infura is running on a server farm. If you submit a transaction, the node that receives it first may not be the same node that handles the next transaction, or that handles the
eth_getTransactionCount
call that gets the nonce for the next transaction.On Ropsten, transactions will propagate quickly, and will quickly be mined, but this isn't always true on mainnet, so you need some kind of client-side nonce management.
MetaMask handles this using some special nonce-tracking middleware. It's rather disappointing that Truffle's
HDWalletProvider
doesn't use this middleware, sinceHDWalletProvider
already re-uses several pieces of MetaMask middleware, and I'm half tempted to raise a pull request to include it.In any case, here's a
truffle.js
that implements this via a slightly hacky workaround: