58

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

Ernane Luis
  • 825
  • 1
  • 10
  • 16

6 Answers6

56

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.

M1Reeder
  • 700
  • 6
  • 7
  • 3
    so if I do 2. option should do:

    nonce = web3.eth.getTransactionCount() + 1 ?

    – Ernane Luis Sep 29 '17 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? – Moisés Briseño Estrello Dec 08 '17 at 08: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 '18 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 02 '18 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 '20 at 17:25
  • This error is raised when replacing the nonce, even with a ~ +30% gas price – challet Jan 01 '22 at 15:08
  • @challet, in theory tx is not mined because of capacity of nodes is lower rather than current workload. E.g. if nodes mine 10 tx per hour and there is 20 tx comes to nodes every hour, nodes will mine those tx which gas fee is higher. It means if your tx has not been mined for a while, its gas fee is lower than the rest top 10 tx that has been mined in this example. – Gleichmut Dec 08 '22 at 07:14
  • Using EIP-1559, We need to increase (10% in my case) both max fee per gas & max priority fee per gas, Otherwise we will get underpriced error. – Reza Aslejeddian Dec 12 '23 at 05:48
24

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.

carver
  • 6,381
  • 21
  • 51
  • 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 01 '22 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 '22 at 20:50
4

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.

Aaron Digulla
  • 428
  • 4
  • 10
3

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.

2

It self-resolved for me by just chillin' for 5 minutes.

HankCa
  • 175
  • 8
2

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

David S Lee
  • 121
  • 3