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
Fee Market Calculations
Transaction fee calculations and state transitions.
calculateTxFee
calculateTxFee(params: TxFeeParams): TxFee
Calculate EIP-1559 transaction fee breakdown.
Parameters:
params.maxFeePerGas - Maximum fee per gas (wei)
params.maxPriorityFeePerGas - Maximum priority fee/tip (wei)
params.baseFee - Current block base fee (wei)
Returns: TxFee with effectiveGasPrice, priorityFee, baseFee
Formula:
effectiveGasPrice = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
priorityFee = effectiveGasPrice - baseFee
Examples:
import * as FeeMarket from './FeeMarket.js';
// Full tip paid
const fee1 = FeeMarket.calculateTxFee({
maxFeePerGas: 2_000_000_000n, // 2 gwei max
maxPriorityFeePerGas: 1_000_000_000n, // 1 gwei tip
baseFee: 800_000_000n // 0.8 gwei base
});
// fee1.effectiveGasPrice === 1_800_000_000n (0.8 + 1.0)
// fee1.priorityFee === 1_000_000_000n (full tip)
// fee1.baseFee === 800_000_000n
// Tip capped by maxFee
const fee2 = FeeMarket.calculateTxFee({
maxFeePerGas: 2_000_000_000n,
maxPriorityFeePerGas: 1_500_000_000n, // Want 1.5 gwei tip
baseFee: 1_800_000_000n // 1.8 gwei base
});
// fee2.effectiveGasPrice === 2_000_000_000n (capped at maxFee)
// fee2.priorityFee === 200_000_000n (reduced tip: 2.0 - 1.8)
// fee2.baseFee === 1_800_000_000n
// No tip paid
const fee3 = FeeMarket.calculateTxFee({
maxFeePerGas: 1_000_000_000n,
maxPriorityFeePerGas: 100_000_000n,
baseFee: 1_000_000_000n // maxFee === baseFee
});
// fee3.effectiveGasPrice === 1_000_000_000n
// fee3.priorityFee === 0n (no tip)
Total Cost:
const fee = FeeMarket.calculateTxFee(params);
const gasUsed = 21_000n; // Standard transfer
const totalCost = fee.effectiveGasPrice * gasUsed;
// totalCost in wei
const breakdown = {
baseFee: fee.baseFee * gasUsed,
priorityFee: fee.priorityFee * gasUsed,
total: totalCost
};
calculateBlobTxFee
calculateBlobTxFee(params: BlobTxFeeParams): BlobTxFee
Calculate blob transaction fee (EIP-4844). Combines regular gas fee with blob gas fee.
Parameters:
params.maxFeePerGas - Maximum fee per gas (wei)
params.maxPriorityFeePerGas - Maximum priority fee (wei)
params.baseFee - Current block base fee (wei)
params.maxFeePerBlobGas - Maximum blob gas fee (wei)
params.blobBaseFee - Current blob base fee (wei)
params.blobCount - Number of blobs (1-6)
Returns: BlobTxFee extending TxFee with blobGasPrice, totalBlobFee
Formula:
// Regular gas (from calculateTxFee)
effectiveGasPrice = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
priorityFee = effectiveGasPrice - baseFee
// Blob gas
blobGasPrice = min(maxFeePerBlobGas, blobBaseFee)
totalBlobFee = blobGasPrice * BLOB_GAS_PER_BLOB * blobCount
Examples:
import * as FeeMarket from './FeeMarket.js';
// Standard blob transaction
const fee1 = FeeMarket.calculateBlobTxFee({
maxFeePerGas: 2_000_000_000n,
maxPriorityFeePerGas: 1_000_000_000n,
baseFee: 800_000_000n,
maxFeePerBlobGas: 10_000_000n, // 10 wei/gas
blobBaseFee: 5_000_000n, // 5 wei/gas
blobCount: 3n
});
// fee1.effectiveGasPrice === 1_800_000_000n
// fee1.priorityFee === 1_000_000_000n
// fee1.blobGasPrice === 5_000_000n (below maxFee)
// fee1.totalBlobFee === 1_966_080_000_000n (3 * 131072 * 5)
// Blob fee capped
const fee2 = FeeMarket.calculateBlobTxFee({
maxFeePerGas: 2_000_000_000n,
maxPriorityFeePerGas: 1_000_000_000n,
baseFee: 800_000_000n,
maxFeePerBlobGas: 3_000_000n, // Lower max
blobBaseFee: 5_000_000n, // Higher actual
blobCount: 1n
});
// fee2.blobGasPrice === 3_000_000n (capped at maxFee)
// fee2.totalBlobFee === 393_216_000_000n (1 * 131072 * 3)
Total Cost:
const fee = FeeMarket.calculateBlobTxFee(params);
const gasUsed = 100_000n; // Execution gas
const executionCost = fee.effectiveGasPrice * gasUsed;
const blobCost = fee.totalBlobFee;
const totalCost = executionCost + blobCost;
console.log(`Execution: ${FeeMarket.weiToGwei(executionCost)} gwei`);
console.log(`Blobs: ${FeeMarket.weiToGwei(blobCost)} gwei`);
console.log(`Total: ${FeeMarket.weiToGwei(totalCost)} gwei`);
canIncludeTx
canIncludeTx(params: TxFeeParams | BlobTxFeeParams): boolean
Check if transaction meets minimum fee requirements for inclusion.
Parameters:
params - Transaction or blob transaction fee parameters
Returns: true if transaction can be included
Validation:
- Regular tx:
maxFeePerGas >= baseFee
- Blob tx: Above +
maxFeePerBlobGas >= blobBaseFee
Examples:
import * as FeeMarket from './FeeMarket.js';
// Can include
const canInclude1 = FeeMarket.canIncludeTx({
maxFeePerGas: 2_000_000_000n,
maxPriorityFeePerGas: 1_000_000_000n,
baseFee: 1_000_000_000n
});
// canInclude1 === true (2 gwei >= 1 gwei)
// Cannot include
const canInclude2 = FeeMarket.canIncludeTx({
maxFeePerGas: 800_000_000n, // Too low
maxPriorityFeePerGas: 100_000_000n,
baseFee: 1_000_000_000n
});
// canInclude2 === false (0.8 gwei < 1 gwei)
// Blob transaction
const canInclude3 = FeeMarket.canIncludeTx({
maxFeePerGas: 2_000_000_000n,
maxPriorityFeePerGas: 1_000_000_000n,
baseFee: 1_000_000_000n,
maxFeePerBlobGas: 10_000_000n,
blobBaseFee: 5_000_000n,
blobCount: 3n
});
// canInclude3 === true (both gas and blob fees sufficient)
// Blob fee too low
const canInclude4 = FeeMarket.canIncludeTx({
maxFeePerGas: 2_000_000_000n,
maxPriorityFeePerGas: 1_000_000_000n,
baseFee: 1_000_000_000n,
maxFeePerBlobGas: 3_000_000n, // Too low
blobBaseFee: 5_000_000n,
blobCount: 3n
});
// canInclude4 === false (blob fee insufficient)
Usage:
const params = buildTxParams();
if (!FeeMarket.canIncludeTx(params)) {
// Increase fees
params.maxFeePerGas = baseFee + 1_000_000_000n; // Add 1 gwei buffer
if ('maxFeePerBlobGas' in params) {
params.maxFeePerBlobGas = blobBaseFee * 2n; // 2x buffer
}
}
nextState
nextState(state: State): State
Calculate next block’s complete fee market state.
Parameters:
state - Current block state
Returns: Next block’s state with updated fees and reset usage
Updates:
baseFee - Calculated via BaseFee
excessBlobGas - Calculated via calculateExcessBlobGas
gasUsed - Reset to 0
blobGasUsed - Reset to 0
gasLimit - Unchanged
Examples:
import * as FeeMarket from './FeeMarket.js';
const currentState: FeeMarket.State = {
gasUsed: 25_000_000n, // 83% full (above target)
gasLimit: 30_000_000n,
baseFee: 1_000_000_000n,
excessBlobGas: 0n,
blobGasUsed: 524288n // 4 blobs (above target)
};
const nextState = FeeMarket.nextState(currentState);
// nextState.gasUsed === 0n (reset)
// nextState.baseFee > 1_000_000_000n (increased, above gas target)
// nextState.excessBlobGas === 131072n (1 blob excess accumulated)
// nextState.blobGasUsed === 0n (reset)
// nextState.gasLimit === 30_000_000n (unchanged)
State method:
const nextState = FeeMarket.State.next.call(currentState);
// Same result
Multi-block projection:
let state = currentState;
// Simulate 10 blocks with constant usage
const blobGasUsed = 524288n; // 4 blobs per block
const gasUsed = 25_000_000n; // 83% full
for (let i = 0; i < 10; i++) {
state = FeeMarket.nextState({
...state,
gasUsed,
blobGasUsed
});
console.log(`Block ${i + 1}:`);
console.log(` Base fee: ${FeeMarket.weiToGwei(state.baseFee)} gwei`);
console.log(` Excess blob gas: ${state.excessBlobGas}`);
}
// Fees compound over blocks
projectBaseFees
projectBaseFees(
initialState: State,
blocks: number,
avgGasUsed: bigint,
avgBlobGasUsed?: bigint
): bigint[]
Project future base fees over multiple blocks with constant utilization.
Parameters:
initialState - Starting state
blocks - Number of blocks to project
avgGasUsed - Average gas used per block
avgBlobGasUsed - Average blob gas per block (optional, default 0)
Returns: Array of projected base fees (length = blocks)
Examples:
import * as FeeMarket from './FeeMarket.js';
const state: FeeMarket.State = {
gasUsed: 0n,
gasLimit: 30_000_000n,
baseFee: 1_000_000_000n, // 1 gwei
excessBlobGas: 0n,
blobGasUsed: 0n
};
// High utilization: fees rise
const risingFees = FeeMarket.projectBaseFees(
state,
10, // 10 blocks
25_000_000n, // 83% full (above target)
524288n // 4 blobs (above target)
);
// risingFees[0] > 1 gwei
// risingFees[9] >> risingFees[0] (compounding)
// At target: fees stable
const stableFees = FeeMarket.projectBaseFees(
state,
10,
15_000_000n, // 50% full (at target)
393216n // 3 blobs (at target)
);
// stableFees[i] ≈ 1 gwei for all i
// Low utilization: fees fall
const fallingFees = FeeMarket.projectBaseFees(
state,
10,
7_500_000n, // 25% full (below target)
131072n // 1 blob (below target)
);
// fallingFees[9] < fallingFees[0]
Projection Analysis:
const projection = FeeMarket.projectBaseFees(state, 20, avgGasUsed);
// Find peak fee
const peakFee = projection.reduce((max, fee) => fee > max ? fee : max, 0n);
const peakIndex = projection.indexOf(peakFee);
console.log(`Peak: ${FeeMarket.weiToGwei(peakFee)} gwei at block ${peakIndex + 1}`);
// Calculate trend
const firstFee = projection[0];
const lastFee = projection[projection.length - 1];
const change = Number((lastFee - firstFee) * 100n / firstFee);
console.log(`Trend: ${change.toFixed(1)}% over ${projection.length} blocks`);
Setting Transaction Fees:
// Project worst case over 5 blocks
const projection = FeeMarket.projectBaseFees(
state,
5,
28_000_000n // Assume high utilization
);
// Set maxFee to cover worst case + buffer
const maxProjectedFee = projection[projection.length - 1];
const maxFeePerGas = maxProjectedFee + 500_000_000n; // +0.5 gwei buffer
console.log(`Set maxFee to ${FeeMarket.weiToGwei(maxFeePerGas)} gwei`);
State Convenience Methods
State namespace provides this:-bound convenience methods:
const state: FeeMarket.State = { /* ... */ };
// Calculate next state
const next = FeeMarket.State.next.call(state);
// Get current blob base fee
const blobFee = FeeMarket.State.getBlobBaseFee.call(state);
// Get gas target
const gasTarget = FeeMarket.State.getGasTarget.call(state);
// Check utilization
const aboveGas = FeeMarket.State.isAboveGasTarget.call(state);
const aboveBlob = FeeMarket.State.isAboveBlobGasTarget.call(state);
See types.mdx and FeeMarket.js for details.
Implementation
Locations:
BrandedFeeMarket/calculateTxFee.js
BrandedFeeMarket/calculateBlobTxFee.js
BrandedFeeMarket/canIncludeTx.js
BrandedFeeMarket/nextState.js
BrandedFeeMarket/projectBaseFees.js
See branded-feemarket.mdx for implementation details.
References