Documentation Index Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Try it Live Run FeeMarket examples in the interactive playground
Conceptual Guide - For API reference and method documentation, see FeeMarket API .
Ethereum has two independent fee markets: EIP-1559 for transaction execution (gas) and EIP-4844 for blob data availability. This guide explains how both work using Tevm.
What is EIP-1559?
EIP-1559 replaced the legacy gas price auction with a predictable base fee that adjusts based on network demand:
Base Fee : Minimum fee per gas, adjusted each block based on utilization
Priority Fee : Optional tip to validators for faster inclusion
Fee Burn : Base fee is burned (destroyed), reducing ETH supply
Why EIP-1559 Exists
Before EIP-1559 (Legacy):
Users bid gas prices in blind auction
Unpredictable fees (overpay or wait forever)
Validators keep all fees
After EIP-1559:
Base fee calculated algorithmically
Predictable costs: base_fee + priority_fee
Base fee burned (deflationary pressure)
Only tips go to validators
Base Fee Mechanics
The base fee targets 50% block utilization and adjusts ±12.5% per block:
Target: 15M gas (50% of 30M limit)
Block utilization → Next block adjustment:
├─ < 15M gas (under target) → Base fee decreases by 12.5%
├─ = 15M gas (at target) → Base fee unchanged
└─ > 15M gas (above target) → Base fee increases by 12.5%
Calculating Next Base Fee
import * as FeeMarket from 'tevm' ;
// Block with 50% utilization (at target)
const nextFee1 = FeeMarket . BaseFee (
15_000_000 n , // gas used (50% of limit)
30_000_000 n , // gas limit
1_000_000_000 n // current base fee (1 gwei)
);
console . log ( nextFee1 ); // 1_000_000_000n (unchanged)
// Block with 100% utilization (over target)
const nextFee2 = FeeMarket . BaseFee (
30_000_000 n , // gas used (100% of limit)
30_000_000 n , // gas limit
1_000_000_000 n // current base fee (1 gwei)
);
console . log ( nextFee2 ); // 1_125_000_000n (increased by 12.5%)
// Block with 0% utilization (under target)
const nextFee3 = FeeMarket . BaseFee (
0 n , // gas used (0% of limit)
30_000_000 n , // gas limit
1_000_000_000 n // current base fee (1 gwei)
);
console . log ( nextFee3 ); // 875_000_000n (decreased by 12.5%)
// Adjustment based on gas used vs target
const gasTarget = gasLimit / 2 n ; // 50% utilization target
const gasUsedDelta = gasUsed - gasTarget ;
if ( gasUsedDelta === 0 n ) {
// At target: no change
nextBaseFee = currentBaseFee ;
} else if ( gasUsedDelta > 0 n ) {
// Over target: increase
const increase = ( currentBaseFee * gasUsedDelta ) / gasTarget / 8 n ;
nextBaseFee = currentBaseFee + Math . max ( increase , 1 n );
} else {
// Under target: decrease
const decrease = ( currentBaseFee * Math . abs ( gasUsedDelta )) / gasTarget / 8 n ;
nextBaseFee = currentBaseFee - decrease ;
}
// Minimum base fee is 7 wei
nextBaseFee = Math . max ( nextBaseFee , 7 n );
The /8n factor gives 12.5% max adjustment per block.
Priority Fee (Tip)
Priority fee (tip) incentivizes validators to include your transaction:
import * as FeeMarket from 'tevm' ;
const txFee = FeeMarket . calculateTxFee ({
maxFeePerGas: 2_000_000_000 n , // Max you'll pay (2 gwei)
maxPriorityFeePerGas: 500_000_000 n , // Max tip (0.5 gwei)
baseFee: 1_000_000_000 n // Current base fee (1 gwei)
});
console . log ( txFee . effectiveGasPrice ); // 1_500_000_000n (1.5 gwei)
console . log ( txFee . priorityFee ); // 500_000_000n (0.5 gwei tip)
console . log ( txFee . baseFee ); // 1_000_000_000n (1 gwei burned)
How Effective Gas Price is Calculated
// Effective gas price is the minimum of:
// 1. maxFeePerGas (user's max)
// 2. baseFee + maxPriorityFeePerGas (base + tip)
effectiveGasPrice = Math . min (
maxFeePerGas ,
baseFee + maxPriorityFeePerGas
);
// Priority fee paid is the remainder after base fee
priorityFeePaid = effectiveGasPrice - baseFee ;
Example scenarios:
// Scenario 1: Normal operation (tip fully paid)
maxFeePerGas = 2_000_000_000 n ; // 2 gwei
maxPriorityFeePerGas = 500_000_000 n ; // 0.5 gwei
baseFee = 1_000_000_000 n ; // 1 gwei
effectiveGasPrice = Math . min ( 2_000_000_000 n , 1_000_000_000 n + 500_000_000 n );
// = 1_500_000_000n (1.5 gwei)
priorityFeePaid = 1_500_000_000 n - 1_000_000_000 n ;
// = 500_000_000n (full 0.5 gwei tip)
// Scenario 2: Tip reduced by maxFee cap
maxFeePerGas = 1_200_000_000 n ; // 1.2 gwei
maxPriorityFeePerGas = 500_000_000 n ; // 0.5 gwei
baseFee = 1_000_000_000 n ; // 1 gwei
effectiveGasPrice = Math . min ( 1_200_000_000 n , 1_000_000_000 n + 500_000_000 n );
// = 1_200_000_000n (capped at maxFee)
priorityFeePaid = 1_200_000_000 n - 1_000_000_000 n ;
// = 200_000_000n (only 0.2 gwei tip, rest capped)
// Scenario 3: Transaction rejected (base fee too high)
maxFeePerGas = 1_000_000_000 n ; // 1 gwei
maxPriorityFeePerGas = 500_000_000 n ; // 0.5 gwei
baseFee = 1_500_000_000 n ; // 1.5 gwei
// Transaction REJECTED: maxFeePerGas < baseFee
// effectiveGasPrice would be 1_000_000_000n, but baseFee is 1_500_000_000n
maxFeePerGas vs maxPriorityFeePerGas
Understanding the two fee parameters:
// maxFeePerGas: Absolute maximum you'll pay per gas
// - Protects you from overpaying if base fee spikes
// - Must be >= baseFee for transaction to be included
// - Set this based on urgency and budget
// maxPriorityFeePerGas: Maximum tip to validator
// - Incentivizes faster inclusion
// - Actual tip may be less if maxFee caps it
// - Set this based on how quickly you need inclusion
Setting Fees for Different Urgency Levels
import * as FeeMarket from 'tevm' ;
// Current network state
const currentBaseFee = 1_000_000_000 n ; // 1 gwei
// Low urgency: can wait, minimal tip
const lowUrgency = {
maxFeePerGas: currentBaseFee + 500_000_000 n , // 1.5 gwei (50% buffer)
maxPriorityFeePerGas: 100_000_000 n // 0.1 gwei tip
};
// Standard urgency: normal inclusion time
const standard = {
maxFeePerGas: currentBaseFee * 2 n , // 2 gwei (100% buffer)
maxPriorityFeePerGas: 1_000_000_000 n // 1 gwei tip
};
// High urgency: next block inclusion
const highUrgency = {
maxFeePerGas: currentBaseFee * 3 n , // 3 gwei (200% buffer)
maxPriorityFeePerGas: 2_000_000_000 n // 2 gwei tip
};
// Calculate what you'll actually pay for each
const lowFee = FeeMarket . calculateTxFee ({
... lowUrgency ,
baseFee: currentBaseFee
});
const standardFee = FeeMarket . calculateTxFee ({
... standard ,
baseFee: currentBaseFee
});
const highFee = FeeMarket . calculateTxFee ({
... highUrgency ,
baseFee: currentBaseFee
});
console . log ( 'Low urgency:' , lowFee . effectiveGasPrice ); // 1_100_000_000n
console . log ( 'Standard:' , standardFee . effectiveGasPrice ); // 2_000_000_000n
console . log ( 'High urgency:' , highFee . effectiveGasPrice ); // 3_000_000_000n
Complete Example: Estimating Transaction Cost
Calculate total cost for a token transfer:
import * as FeeMarket from 'tevm' ;
// Current network conditions
const currentBaseFee = 1_200_000_000 n ; // 1.2 gwei
const gasLimit = 30_000_000 n ;
const gasUsed = 21_000_000 n ; // 70% utilization (above target)
// Project next block's base fee
const nextBaseFee = FeeMarket . BaseFee (
gasUsed ,
gasLimit ,
currentBaseFee
);
console . log ( `Next base fee: ${ nextBaseFee } wei` ); // ~1.35 gwei (increased)
// Set fees with buffer for potential spike
const maxFeePerGas = nextBaseFee * 2 n ; // 2.7 gwei buffer
const maxPriorityFeePerGas = 1_000_000_000 n ; // 1 gwei tip
// Calculate effective fee
const txFee = FeeMarket . calculateTxFee ({
maxFeePerGas ,
maxPriorityFeePerGas ,
baseFee: nextBaseFee
});
console . log ( `Effective gas price: ${ txFee . effectiveGasPrice } ` );
// 2_350_000_000n (1.35 base + 1.0 tip)
// Total cost for 21,000 gas transfer
const gasUsedForTransfer = 21_000 n ;
const totalCost = txFee . effectiveGasPrice * gasUsedForTransfer ;
const ethCost = totalCost / 1_000_000_000_000_000_000 n ; // Convert wei to ETH
console . log ( `Total cost: ${ totalCost } wei` );
// 49_350_000_000_000 wei
console . log ( `Total cost: ${ ethCost } ETH` );
// ~0.000049 ETH
Handling Fee Spikes
Protect against sudden base fee increases:
import * as FeeMarket from 'tevm' ;
// Project base fees for next 5 blocks assuming high utilization
const currentBaseFee = 1_000_000_000 n ;
const gasLimit = 30_000_000 n ;
const highUtilization = 25_000_000 n ; // 83% full blocks
const projections = FeeMarket . projectBaseFees ({
baseFee: currentBaseFee ,
gasLimit ,
blocks: 5 ,
gasUsedPerBlock: highUtilization
});
console . log ( 'Base fee projections:' );
projections . forEach (( fee , i ) => {
const gwei = Number ( fee ) / 1_000_000_000 ;
console . log ( `Block + ${ i } : ${ gwei . toFixed ( 2 ) } gwei` );
});
// Block +0: 1.00 gwei (current)
// Block +1: 1.11 gwei
// Block +2: 1.23 gwei
// Block +3: 1.36 gwei
// Block +4: 1.51 gwei
// Set maxFee based on worst-case projection
const maxProjected = projections [ projections . length - 1 ];
const maxFeePerGas = maxProjected + 1_000_000_000 n ; // Add 1 gwei buffer
console . log ( `Safe maxFeePerGas: ${ maxFeePerGas } ` );
// Covers spike up to ~2.51 gwei
EIP-4844 Blob Gas
EIP-4844 introduced a separate fee market for blob data (layer 2 data availability):
import * as FeeMarket from 'tevm' ;
// Blob gas operates independently from regular gas
const BLOB_GAS_PER_BLOB = 131_072 n ; // Each blob costs this much blob gas
const TARGET_BLOB_GAS = 393_216 n ; // Target: 3 blobs per block
const MAX_BLOBS = 6 n ; // Max: 6 blobs per block
// Calculate blob base fee from excess blob gas
const excessBlobGas = 262_144 n ; // 2 blobs above target
const blobBaseFee = FeeMarket . BlobBaseFee ( excessBlobGas );
console . log ( `Blob base fee: ${ blobBaseFee } wei per blob gas` );
Blob Fee Mechanics
Unlike EIP-1559’s ±12.5% adjustment, blob fees use exponential pricing :
// Blob base fee formula (simplified):
// blobBaseFee = MIN_BLOB_BASE_FEE * e^(excessBlobGas / TARGET_BLOB_GAS)
// Examples at different utilization levels:
const scenarios = [
{ blobs: 0 , excessBlobGas: 0 n },
{ blobs: 3 , excessBlobGas: 0 n }, // At target
{ blobs: 4 , excessBlobGas: 131_072 n }, // 1 over target
{ blobs: 6 , excessBlobGas: 393_216 n } // 3 over target (max)
];
scenarios . forEach (({ blobs , excessBlobGas }) => {
const fee = FeeMarket . BlobBaseFee ( excessBlobGas );
console . log ( ` ${ blobs } blobs: ${ fee } wei/gas` );
});
// 0 blobs: 1 wei/gas (minimum)
// 3 blobs: 1 wei/gas (at target)
// 4 blobs: ~1.1 wei/gas
// 6 blobs: ~1.4 wei/gas
Complete Blob Transaction Example
import * as FeeMarket from 'tevm' ;
// Current blob market state
const parentExcessBlobGas = 131_072 n ; // 1 blob above target
const parentBlobGasUsed = 262_144 n ; // 2 blobs used in parent
// Calculate next block's blob base fee
const excessBlobGas = FeeMarket . calculateExcessBlobGas (
parentExcessBlobGas ,
parentBlobGasUsed
);
const blobBaseFee = FeeMarket . BlobBaseFee ( excessBlobGas );
console . log ( `Excess blob gas: ${ excessBlobGas } ` );
console . log ( `Blob base fee: ${ blobBaseFee } wei/gas` );
// Your transaction: 3 blobs
const blobCount = 3 n ;
const totalBlobGas = blobCount * 131_072 n ; // 393,216 blob gas
// Calculate blob fee cost
const blobFee = FeeMarket . calculateBlobTxFee ({
maxFeePerBlobGas: 100 n , // Your max (100 wei/gas)
blobBaseFee: blobBaseFee , // Current blob base fee
blobGasUsed: totalBlobGas // Total blob gas for your blobs
});
console . log ( `Blob fee: ${ blobFee . blobFee } wei` );
console . log ( `Blobs: ${ blobFee . blobsCount } ` );
// Total blob cost
const totalBlobCost = blobBaseFee * totalBlobGas ;
console . log ( `Total blob cost: ${ totalBlobCost } wei` );
Visual Fee Calculation
EIP-1559 Transaction Fee Breakdown
User Transaction Parameters:
├─ maxFeePerGas: 2.0 gwei
└─ maxPriorityFeePerGas: 1.0 gwei
Network State:
└─ baseFee: 1.0 gwei
Calculation:
├─ effectiveGasPrice = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
│ = min(2.0, 1.0 + 1.0) = 2.0 gwei
│
├─ User pays: 2.0 gwei × 21,000 gas = 42,000 gwei = 0.000042 ETH
│
└─ Fee distribution:
├─ Burned: 1.0 gwei × 21,000 = 21,000 gwei (base fee)
└─ To validator: 1.0 gwei × 21,000 = 21,000 gwei (priority fee)
Base Fee Adjustment Visualization
Block Sequence (30M gas limit, 15M target):
Block N: gasUsed = 15M, baseFee = 1.0 gwei → No change
├─ At target (50% full)
└─ Next baseFee = 1.0 gwei
Block N+1: gasUsed = 30M, baseFee = 1.0 gwei → Increase
├─ Over target (100% full)
└─ Next baseFee = 1.125 gwei (+12.5%)
Block N+2: gasUsed = 30M, baseFee = 1.125 gwei → Increase
├─ Over target (100% full)
└─ Next baseFee = 1.265625 gwei (+12.5%)
Block N+3: gasUsed = 5M, baseFee = 1.265625 gwei → Decrease
├─ Under target (16.7% full)
└─ Next baseFee = 1.107... gwei (-12.5%)
Blob Gas Market Visualization
Blob Market (131,072 gas per blob, 3 blob target, 6 max):
Target: ▓▓▓ (3 blobs = 393,216 gas)
Max: ▓▓▓▓▓▓ (6 blobs = 786,432 gas)
Utilization → Blob Base Fee:
├─ 0 blobs: 1 wei/gas (under target)
├─ 1 blob: 1 wei/gas (under target)
├─ 2 blobs: 1 wei/gas (under target)
├─ 3 blobs: 1 wei/gas (at target)
├─ 4 blobs: ~1.1 wei/gas (over target)
├─ 5 blobs: ~1.3 wei/gas (over target)
└─ 6 blobs: ~1.4 wei/gas (at max)
Sustained high usage → exponential growth:
├─ +10 blocks at 6 blobs: ~2 wei/gas
├─ +50 blocks at 6 blobs: ~100 wei/gas
└─ +100 blocks at 6 blobs: ~10,000 wei/gas
Resources
Next Steps