Estimating EIP-1559 Transaction Gas on Polygon with ethers.js
Polygon Mainnet was upgraded to EIP-1559 on Jan 18th 2022.
Pre-EIP1559 we could estimate the gasPrice
from getFeeData()
that is available on the provider
object. Eg:
const feeData = await provider.getFeeData();
const tx = await yourContract.yourMethod(yourArguments, {gasPrice: feeData.gasPrice});
await tx.wait();
console.log(tx.hash);
However, the introduction of EIP-1559 deprecates gasPrice
and the gas for a transaction is dictated by 3 new parameters.
baseFee, maxPriorityFeePerGas
and maxFeePerGas
Of these, we need to send only maxPriorityFeePerGas
and maxFeePerGas
with our transaction. This is because maxFeePerGas
is the the sum of maxPriorityFeePerGas
and baseFee
. maxPriorityFeePerGas
is seperately included as is the amount that is directly forwarded to the miner as a “tip” in return for a higher priority while executing all the txs included that block.
So evidently, in order to send an EIP-1559 compatible transaction, we have to change how we estimate gas before sending a transaction using ethers.js.
If you use the values for maxPriorityFeePerGas
and maxFeePerGas
from provider.getFeeData()
and while sending a transaction on Polygon, you’ll recieve an error that says
“error”:{“code”:-32000,”message”:”transaction underpriced”}}
This error persists even if you 5x or 10x both the params. That means we have to deal with it differently.
So instead of sourcing our maxPriorityFeePerGas
and maxFeePerGas
from provider.getFeeData()
, let us source our values from Polygon’s gas station end point:
https://gasstation-mainnet.matic.network/v2
An example response looks like this:
{
"safeLow": {
"maxPriorityFee": 30.102290831615385,
"maxFee": 50.15799883361538
},
"standard": {
"maxPriorityFee": 30.52003085923077,
"maxFee": 50.57573886123077
},
"fast": {
"maxPriorityFee": 31.700968178846153,
"maxFee": 51.756676180846156
},
"estimatedBaseFee": 20.055708002,
"blockTime": 2,
"blockNumber": 37822302
}
Using these values in our code looks a little like this:
const resp = await fetch('https://gasstation-mainnet.matic.network/v2')
const data = await resp.json()
const maxFeePerGas = ethers.utils.parseUnits(${Math.ceil(data.fast.maxFee)}`,'gwei',)const maxFeePerGas = ethers.utils.parseUnits(${Math.ceil(data.fast.maxFee)}`,'gwei',)
const maxPriorityFeePerGas = ethers.utils.parseUnits(${Math.ceil(data.fast.maxPriorityFeePerGas)}`,'gwei',)const maxFeePerGas = ethers.utils.parseUnits(${Math.ceil(data.fast.maxFee)}`,'gwei',)const tx = await yourContract.yourMethod(yourArguments, { maxFeePerGas, maxPriorityFeePerGas })
await tx.wait();
console.log(tx.hash);
And the transaction goes through!
Hope this helped! If you have any question regarding this you find me on Twitter @0xamogh! Have a nice day! 😄