ethers.js: Polygon transactions are stuck/transaction underpriced error
Ethers Version
5.6.1
Search Terms
polygon maxPriorityFeePerGas maxFeePerGas
Describe the Problem
There is a harcoded (1.5 gwei) maxPriorityFeePerGas (and maxFeePerGas) in index.ts.
This value is used in populateTransaction.
In case of Polygon, this will either result in a transaction stuck in the mempool, or in case og e.g an Alchemy endpoint, “transaction underpriced” error.
Code Snippet
signer.populateTransaction(txParams)
signer.sendTransaction(txParams)
Where txParams don't contain maxPriorityFeePerGas/maxFeePerGas, and is a type 2 transaction.
(Legacy transactions pass as they use gasPrice only)
Contract ABI
No response
Errors
processing response error (body="{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"transaction underpriced\"},\"id\":64}", error={"code":-32000}, requestBody="{\"method\":\"eth_sendRawTransaction\",\"params\":[\"0x02f873818981c98459682f0084596898e882520894c54c244200d657650087455869f1ad168537d3b387038d7ea4c6800080c080a07cb6e05c60a2cb7ffc83349bc52ade79afaf9fdb911c64d57aed421caa1ecbcfa05f30023a4d21dd2eab6ea619c8dbb4820ce40c71841baacf8e82cbde7e87602a\"],\"id\":64,\"jsonrpc\":\"2.0\"}", requestMethod="POST",
Environment
No response
Environment (Other)
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 28
- Comments: 49 (4 by maintainers)
Commits related to this issue
- set custom gas price when creating NFT Polygon increased it's minimum gas price from 30 Gwei to 1Gwei to curb spam. Other blockchains might change their default gas price as well so we should get th... — committed to atilatech/arthouse-api by ademidun 2 years ago
- Added basic Gas Station support via a NetworkPlugin (#2828). — committed to ethers-io/ethers.js by ricmoo a year ago
- Added new exports for FallbackProviderOptions and FetchUrlFeeDataNetworkPlugin (#2828, #4160). — committed to ethers-io/ethers.js by ricmoo a year ago
- [Snyk] Upgrade ethers from 5.7.2 to 6.8.0 (#175) <p>This PR was automatically created by Snyk using the credentials of a real user.</p><br /><h3>Snyk has created this PR to upgrade ethers from 5.7.... — committed to Woodpile37/EIPs by Woodpile37 8 months ago
- [Snyk] Upgrade ethers from 5.7.2 to 6.8.0 (#201) <p>This PR was automatically created by Snyk using the credentials of a real user.</p><br /><h3>Snyk has created this PR to upgrade ethers from 5.7.... — committed to Woodpile37/EIPs by Woodpile37 8 months ago
- Use Polygon gas oracle (#2965) ### Description After investigating #2959, I found the following this is a known problem with Polygon, explanation here https://github.com/ethers-io/ethers.js/is... — committed to hyperlane-xyz/hyperlane-monorepo by tkporter 7 months ago
- Use Polygon gas oracle (#2965) After investigating #2959, I found the following this is a known problem with Polygon, explanation here https://github.com/ethers-io/ethers.js/issues/2828#issuecomment... — committed to hyperlane-xyz/hyperlane-monorepo by tkporter 7 months ago
- Use Polygon gas oracle (#2965) After investigating #2959, I found the following this is a known problem with Polygon, explanation here https://github.com/ethers-io/ethers.js/issues/2828#issuecomment... — committed to hyperlane-xyz/hyperlane-monorepo by tkporter 7 months ago
- Added basic Gas Station support via a NetworkPlugin (#2828). — committed to Woodpile37/ethers.js by ricmoo a year ago
- Added new exports for FallbackProviderOptions and FetchUrlFeeDataNetworkPlugin (#2828, #4160). — committed to Woodpile37/ethers.js by ricmoo a year ago
- Added basic Gas Station support via a NetworkPlugin (#2828). — committed to Woodpile37/ethers.js by ricmoo a year ago
- Added new exports for FallbackProviderOptions and FetchUrlFeeDataNetworkPlugin (#2828, #4160). — committed to Woodpile37/ethers.js by ricmoo a year ago
My current workaround:
And my current workaround:
I removed
gasLimit
from the options as it never worked;Yeah I was reading this thread like “oh yay a solution” and then “wtf is mulDiv?”
After some significant googling, I found that it’s an old timey method that just means (a * b) / c. He’s using it to calculate 10% higher than the given number.
But after getting it to work, I found that I didn’t need to go 10% higher. I included the 10% higher code in a comment, in case anyone needs it.
I adapted and cleaned up the code, and here is what I ended up with.
Provided I didn’t make any mistakes in converting to ES, this should be a full working snippet. If not, let me know.
Honestly I don’t know how I would have ever solved this if not for stumbling upon this particular thread. So thanks for your efforts, and your help.
I’m so sick of this constantly changing. What worked 5 months ago didn’t work a month ago and what worked 5 days ago doesn’t work today. What is changing?
Ok so as much as I can tell maxFeePerGas and maxPriorityFeePerGas are estimated completely wrong by the ethers on mainnet polygon. gasPrice gets closer, but is still dramatically underpriced. So now I’m just back to using gasPrice again.
@jschiarizzi It’s official: https://docs.polygon.technology/docs/develop/tools/polygon-gas-station
So, basically Polygon wanted to keep “backwards compatibility” with Geth by using EIP-1559 but without actually using EIP-1559.
The purpose of EIP-1559 is to stabilize fee pricing and make it highly predictable (for example; I’ve not had a single tx take more than 2 blocks on Ethereum since it was added, and almost all are in the next block). But that involves setting a reasonable floating baseFee and a fixed priorityFee.
Polygon wants their prices to remain “looking low”, so they effective hard coded the baseFee, and a floating priorityFee (notice this is backwards).
This results in mimicking the old pre-EIP-1559 behaviour, creating a bidding war for priorityFee during congestion (which per-EIP-1559 txs did, creating a bidding war for gasPrice during congestion). The only viable solution Ethereum had that worked back then was a gas station; a separate service which would track the mempool and store stats on when a tx enters the mempool and when it was mined, map this duration against its gasPrice, and generate histograms that map gasPrice to wait times. These histograms over short periods of time could then be used to pick a gas price that would get a tx included within a reasonable time. During congestion ramp up, the prices would possibly lag and would result in slower transactions and during ramp down would cause overpayment for a transaction. It’s a terrible solution, it the best possible solution at the same time. 😃
So, the only really way to probably “solve” this is to find/host a Gas Station for Polygon.
FYI. I have a gas station implementation you can adapt; but with proper EIP-1559 networks, it is no longer necessary, so I don’t maintain it much anymore. Basically, change the gasPrice property to maxPriorityFeePerGas and run it against a local Polygon node; it has to be a local Polygon node you sync, since the mempool is busy.
I’d also be welcome to developers convincing Polygon to correctly use the specification, and that you prefer predicable correct pricing rather than chaotic “perceived” cheaper pricing. 😉
Or get Polygon to add gas tracking to their node and provide a gas station API on their node. If anyone has any Polygon contacts. 😃
@Benjythebee seems like you could then just call
provider.getGasPrice()
directlyWhat was the fix?
Just completed minting 1000 nfts yesterday on polygon RELIABLY - finally. Here’s my code to get around this very frustrating gas pricing issue on Polygon/Mumbai:
it irks me that the maxPriorityFeePerGas is so high. I know I saw random transactions I had with default gas paying 1.5gwei but I havent been able to re-achieve this reliably.
Note that I had to include a gasLimit at a 10% premium for improved reliability. the ethers getFeeData did NOT work. it was always underpriced.
But the code is demonstrably reliable in sending the tx and getting it included in the block within a few seconds each time. I added a check to retry the tx later if the maxFeePerGas exceeds 50gwei in production.
Hope that helps someone.
Update. SO the nonce was pending with a previous accepted tx. So, the maxFeePerGas value from the gasstation is getting accepted. However, if I wait for the transaction to confirm, it never returns. If i submit another TX, it gets a REPLACEMENT_UNDERPRICED error. I then have to go to metamask, and send a 0Matic transaction with the SAME NONCE at the fast price to clear the pending tx. GREAT. YAY.
So as a part of all this pricing business, I have TX with an accepted price and a hash, that doesnt confirm within any reasonable timeframe, hence still blocking all other TX. Looking up the TX in polygonscan - i get this: Status: Pending This txn hash was found in our secondary node and should be picked up by our indexer in a short while. for a tx made 5 minutes ago.
trying a different RPC to see if there’s any improvement.
I’m updating this info so maybe it helps others? But I sure could use some feedback from the more experienced Polygoner’s out there who have figured this out. If there is such a state…
Meanwhile, more 0 matic transfers to reset Tx.
Update: after maybe 15min? explorer shows this: Sorry, We are unable to locate this TxnHash Sooo… the accepted fee wasn’t good enough???
Update #2: so it seems now we’re cooking with gas 😃 So a number of issues:
So… my batcher is finally chugging await and logging successful tx now. YAY but what a week from HELL. I cannot say I would recommend Polygon, or the support that is available to help. Thanks to the community here for the gas pricing info
NEXT STOP: anyone have any experience setting default gas for the provider, versus per tx. when using an sdk - direct access to setting the gas for a tx is sometimes not available - ie Rarible API or Opensea perhaps. I’m told Web3 has Web3Ethereum that can be supplied with gas option - does this work for maxFeeForGas? Is there an ETHERS equivalent?
I’ve updated @robertu7’s answer to make it work with ethers 6.6.3 and the new Polygon gas station URLs:
My current workaround
Why don’t they just fix their node software to respect the minimum priority gwei rate. Running a full node will recommend lower rates…
For your interest @robertu7 I pulled what you did into a new wallet subclass that one day may or may not get sent back into the main lib. It’s tuned for our use cases with Polygon but I can’t see why it can’t be generalized with the help of some interfaces: