Ethereum Gas Price : How ? & Estimate

Arun Jangra
DataX Journal
Published in
5 min readMar 24, 2023

EIP 1559 and Gas Price estimation

How Gas Fee is calculated ?

Gas fee in ETH is handled by algorithm defined in EIP 1559. Gas fee is handled on the basis of the fee target in a block. To demonstrate this we can assume two blocks :

Block 1 & block 2

Each block’s max gas amount : 30 M gas
Each block’s target gas amount : 15 M gas

Now,

In Block 1 :
Total used gas : 22 M gas

In Block 2 :
Total used gas : 10M gas

Here the mechanics is defined as :

Less space left for gas -----> Higher demand -----> High gas fee

More space left for gas -----> Less demand -----> Low gas fee

From this we can understand that :
Gas fee will be lower in Block 2 and It will be higher in Block 1

What is EIP 1559 ?

It is an Ethereum Improvement proposal which proposes a new fee market mechanism that would make the fee system more predictable and efficient. Under this proposal, each block would have a “base fee” that is algorithmically determined based on the current network usage. Users would then be able to add a “tip” to incentivize miners to prioritize their transactions.

Post EIP 1559, Ethereum used a bidding method for calculating the gas fees where users bid for limited block space by paying higher fees. This can result in high and unpredictable fees during times of network congestion.

Here let me demonstrate how EIP 1559 works using a very simple code :

pragma solidity ^0.8.0;

contract EIP1559Demonstration {
uint256 public counter;

function increment() public payable {

// Getting the current base fee and the maximum tip amount
(uint256 baseFee, uint256 maxTip) = getFeeAndTip();

// Calculating the total fee for the transaction
uint256 totalFee = baseFee + msg.value;
if (totalFee > baseFee + maxTip) {
totalFee = baseFee + maxTip;
}

// Incrementing the counter and pay the fee to the miner
counter++;
(bool success, ) = block.coinbase.call{value: totalFee}("");
require(success, "Failed to pay fee to miner");
}

function getFeeAndTip() public view returns (uint256 baseFee, uint256 maxTip) {
// Getting the current block number
uint256 blockNumber = block.number;

// Calculate the base fee using the EIP 1559 formula
uint256 baseFeePerGas = block.basefee;
baseFee = tx.gasprice * (blockNumber - tx.blockNumber) * baseFeePerGas;

// Setting the maximum tip to twice the base fee
maxTip = baseFee * 2;
}
}

In this contract, there is a counter variable that can be incremented by calling the increment() function. The function takes a payment in Ether and uses the EIP 1559 fee market mechanism to calculate the transaction fee and pay it to the miner.

The getFeeAndTip() function calculates the current base fee using the block.basefee variable, which represents the current base fee per gas for the block. It then sets the maximum tip to twice the base fee. The increment() function calculates the total fee for the transaction by adding the base fee and the payment amount and then capping it at the maximum tip.

Finally, the increment() function increments the counter variable and pays the total fee to the miner using the block.coinbase variable, which represents the address of the miner who mined the current block.

Can we calculate estimated gas price from the previous blocks’ data ?

YES

Now we can also use our mechanism to calculate the fee which can be used for custom fees in our own DAPP (decentralised application). So let’s write some code and after that explanation will be provided.

We will be using getFeeHistory to get the data of the previous blocks and then we will use that data to get the estimated gas fee for a transaction to be included.

We will use this logic to get the estimated gas fees :

Top 1 %ile of the transactions to get slow gas fee
Top 50 %ile of the transactions to get average gas fee
Top 99 %ile of the transactions to get fast gas fee

Utils

formatResult.ts

export const formatResult = (
result: any,
historicalBlocks: number
) => {
// getting blocknumber
let blockNum = Number(result.oldestBlock);

const formattedBlocks = [];

for (let loopInd = 0; loopInd < historicalBlocks; loopInd++) {
formattedBlocks.push({
block_number: blockNum,
baseFeePerGas: Number(result.baseFeePerGas[loopInd]),
gasUsedRatio: Number(result.gasUsedRatio[loopInd]),
priorityFeePerGasPercentiles: result.reward[loopInd].map((x: number) =>
Number(x)
),
});
blockNum += 1;
}

return formattedBlocks;
};

calcAverage.ts

export const calcAverage = (arr: number[]) => {
// sum of elements in array
const sum = arr.reduce((a, v) => a + v);
return Math.round(sum / arr.length);
};

Root

Index.ts

import Web3 from "web3";
import * as dotenv from "dotenv";
import { formatResult } from "./utils/formatResult";
import { calcAverage } from "./utils/calcAverage";
dotenv.config();

const ETH_RPC: string = process.env.ETH_RPC || "";
const web3 = new Web3(ETH_RPC);

// Historical Blocks : Defines how many older blocks we want to get.
const historicalBlocks = 20;

/*
getFeeHistory : This function is required to get the fee history of the previous blocks
getFeeHistory(arg1, arg2, arg3)

* arg 1 : historical blocks
* arg 2 : type of blocks to retrieve ("pending in our case")
* arg 3 : array of numbers defining the percentile of the priority fee of the blocks we want to fetch

For Eg :
In our case 1,50,99
represents priority fee in the 1 percentile of transactions, 50 percentile of the transactions and 99 percentile of transactions
*/

web3.eth
.getFeeHistory(historicalBlocks, "pending", [1, 50, 99])
.then((result) => {
const res = formatResult(result, historicalBlocks);

const slow = calcAverage(
res.map((block) => block.priorityFeePerGasPercentiles[0])
);
const average = calcAverage(
res.map((block) => block.priorityFeePerGasPercentiles[1])
);
const fast = calcAverage(
res.map((block) => block.priorityFeePerGasPercentiles[2])
);

// Getting the latest block
web3.eth.getBlock("pending").then((block) => {
const baseFeeOfLatestBlock = Number(block.baseFeePerGas);
console.log(`Gas Estimation (Block Number : ${Number(block.number)}) :
slow 🐌 : ${slow + baseFeeOfLatestBlock}
average 🚩 : ${average + baseFeeOfLatestBlock}
fast ⚡ : ${fast + baseFeeOfLatestBlock}`);
});
});

Output :

Gas Estimation (Block Number : 8710534) :
slow 🐌 : 160758582325
average 🚩 : 161582842530
fast ⚡ : 455478648655

For more details check the github readme

Github : https://github.com/Arun89-crypto/GasEstimatorEth

You can check more about Ethereum and London Fork on Alchemy and Ethereum official website.

Thank You :)

Keep learning 🧠 & Buidling 🏗️

--

--