55

Im trying to send a raw transaction using web3 to ropsten testnet and Im getting this error:

replacement transaction underpriced

where sometimes my tx works and sometimes I get this error.

my tx parameters:

const nonce = web3.eth.getTransactionCount(ethereumConfig.contract.account)
const block = web3.eth.getBlock("latest")
const gasLimit = block.gasLimit
const gasPrice = web3.eth.gasPrice.toNumber() * 1.40 

note I'm already adding 40% to gasPrice

2
  • 1
    Try to increase your gas price. Please let me know the result
    – Aniket
    Sep 28, 2017 at 10:48
  • 3
    I'm already increasing 40% Sep 29, 2017 at 12:54

5 Answers 5

53

I have been running into this issue as well. The network thinks you are trying to replace an existing unmined transaction. There are two ways to avoid this:

  1. Adding a gas price %10 higher than the existing unmined transaction's gas price.
  2. Increase your nonce to one higher than the unmined transaction.

I have also been getting this error:

"Transaction was not mined within 50 blocks, please make sure your transaction was properly send. Be aware that it might still be mined!"

In my case, I think the transaction is getting stuck in limbo somehow. It's not being mined by anyone, but it's not being removed from the pool of unmined transactions. Keep in mind that web3.eth.getTransactionCount(walletAddress) will only give you the last CONFIRMED nonce. So it won't take the unmined ones into account.

7
  • 3
    so if I do 2. option should do: nonce = web3.eth.getTransactionCount() + 1 ? Sep 29, 2017 at 12:46
  • 1
    I'm having the same problem, not coding but in a transacction I'm trying to send in myetherwallet. I think increasing the nonce will solve it, but how do I do that if I'm sending my transaction through Metamask? Dec 8, 2017 at 8:04
  • 3
    So if I have an unmined transaction sitting around, does it ever go away? I don't want to have to mess with the nonce myself!
    – sudo
    May 26, 2018 at 18:47
  • 1
    Why does the network thinks the transaction is new? doesn't it compare the data and see it's different?
    – shaharsol
    Jul 2, 2018 at 13:59
  • 1
    Is there another way to replace the unmined transaction in Quorum, since the gas price is always 0 in Quorum.
    – faizal
    Apr 19, 2020 at 17:25
23

Define the Goal

Do you want to:

  1. Send a new transaction, after all your previous transactions have completed, or...
  2. Replace a pending (unmined) transaction, with the new raw transaction.

Send a New Transaction

The error message implies that you're trying to replace a pending transaction. That's because the raw transaction you're trying to send has the same nonce as another transaction that you have pending.

Since replacing a transaction is not your goal, simply increase the nonce to be one higher than your last pending transaction. You may need to track this internally, rather than relying on web3.eth.getTransactionCount().

Replace a Pending Transaction

The 10% Minumum

Since your goal is to replace a transaction that is pending, you must try to convince the miners to use your new transaction. To do that, you must use a gas price that is 10% higher* than the gasPrice of the pending transaction.

const gasPrice = web3.eth.gasPrice.toNumber() * 1.40 

note I'm already adding 40% to gasPrice

The quoted code adds 40% to web3.eth.gasPrice. This may not be 10% higher than the pending transaction's gas price. web3.eth.gasPrice may vary over time, and/or you might have set any arbitrary gas price on the pending transaction.

* 10% isn't defined in the protocol, it's just how most nodes & miners implement it.

Determining the Minimum

If you have the hash of the pending transaction, you can determine the required gas price with something like:

replacement_price = web3.eth.getTransaction(pending_txn_hash).gasPrice * 1.101

Note that this is floating point math, which will have rounding errors, so I threw in an extra 10th of a percent to be sure it was over the minimum.

2
  • How does metamask knows in advance the required gas price increase ? I'm trying with + 30% and it is instantly rejected with the "replacement transaction underpriced" error
    – challet
    Jan 1, 2022 at 15:10
  • @challet Where are you getting the gas price of the pending transaction? My guess is you're not actually adding 30% more than the pending transaction. For example, you might be bumping 30% from the current estimated price for a new transaction.
    – carver
    Jun 20, 2022 at 20:50
3

I have seen this when calling the same contract method twice from JavaScript without waiting for the first call to finish by either await or calling a second time in the success callback.

My guess is that contract methods in web3js are not thread safe.

1
  • 1
    I just came to this post by executing similar scenario. However, both tx has been mined.
    – Gleichmut
    Dec 8, 2022 at 7:21
2

I'm using Ganache and MetaMask suddenly stopped handling transactions, it queued the first one and every subsequent call would return either nothing or "transaction underpriced". Here's how to solve it:

  1. In MetaMask, navigate to Settings/Advanced and click on Reset Account.
  2. Restart your browser.

If that doesn't help, try reinstalling MetaMask.

1

Double check your Gas price. Even I am also setup Gas Price but somehow did applied proper Gas Price as well. One of example below screen shot. enter image description here

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