Skip to main content

Try it Live

Run FeeMarket examples in the interactive playground

FeeMarket Utilities

Validation and conversion utilities.

Validation

validateTxFeeParams

validateTxFeeParams(params: TxFeeParams | BlobTxFeeParams): string[]
Validate transaction fee parameters. Returns empty array if valid, array of error messages if invalid. Parameters:
  • params - Transaction or blob transaction fee parameters
Returns: Array of validation error messages (empty if valid) Validates: Regular tx (TxFeeParams):
  • maxFeePerGas >= 0
  • maxPriorityFeePerGas >= 0
  • maxPriorityFeePerGas <= maxFeePerGas
  • baseFee >= 0
Blob tx (BlobTxFeeParams), additionally:
  • maxFeePerBlobGas >= 0
  • blobBaseFee >= 0
  • 1 <= blobCount <= 6
Examples:
import * as FeeMarket from './FeeMarket.js';

// Valid parameters
const params1 = {
  maxFeePerGas: 2_000_000_000n,
  maxPriorityFeePerGas: 1_000_000_000n,
  baseFee: 800_000_000n
};

const errors1 = FeeMarket.validateTxFeeParams(params1);
// errors1 === []

// Invalid: priority fee exceeds max fee
const params2 = {
  maxFeePerGas: 1_000_000_000n,
  maxPriorityFeePerGas: 2_000_000_000n, // Too high
  baseFee: 800_000_000n
};

const errors2 = FeeMarket.validateTxFeeParams(params2);
// errors2 === ["maxPriorityFeePerGas cannot exceed maxFeePerGas"]

// Invalid: negative values
const params3 = {
  maxFeePerGas: -1n,                     // Negative
  maxPriorityFeePerGas: 1_000_000_000n,
  baseFee: 800_000_000n
};

const errors3 = FeeMarket.validateTxFeeParams(params3);
// errors3 === ["maxFeePerGas must be non-negative"]

// Blob tx: invalid blob count
const params4 = {
  maxFeePerGas: 2_000_000_000n,
  maxPriorityFeePerGas: 1_000_000_000n,
  baseFee: 800_000_000n,
  maxFeePerBlobGas: 10_000_000n,
  blobBaseFee: 5_000_000n,
  blobCount: 10n // Too many (max is 6)
};

const errors4 = FeeMarket.validateTxFeeParams(params4);
// errors4 === ["blobCount must be between 1 and 6"]

// Multiple errors
const params5 = {
  maxFeePerGas: 1_000_000_000n,
  maxPriorityFeePerGas: 2_000_000_000n, // Exceeds maxFee
  baseFee: -1n                          // Negative
};

const errors5 = FeeMarket.validateTxFeeParams(params5);
// errors5.length === 2
// errors5[0] === "maxPriorityFeePerGas cannot exceed maxFeePerGas"
// errors5[1] === "baseFee must be non-negative"
Usage Pattern:
import { ValidationError } from 'tevm/errors'

function buildAndValidateTx(params: FeeMarket.TxFeeParams) {
  const errors = FeeMarket.validateTxFeeParams(params);

  if (errors.length > 0) {
    throw new ValidationError(`Invalid transaction parameters: ${errors.join(', ')}`, {
      value: params,
      expected: "Valid fee parameters",
      code: "INVALID_TX_FEE_PARAMS"
    });
  }

  // Safe to proceed
  const fee = FeeMarket.calculateTxFee(params);
  return fee;
}

validateState

validateState(state: State): string[]
Validate block fee market state. Returns empty array if valid, array of error messages if invalid. Parameters:
  • state - Block fee market state
Returns: Array of validation error messages (empty if valid) Validates:
  • gasUsed >= 0
  • gasLimit > 0
  • gasUsed <= gasLimit
  • baseFee >= MIN_BASE_FEE (7 wei)
  • excessBlobGas >= 0
  • blobGasUsed >= 0
  • blobGasUsed <= MAX_BLOB_GAS_PER_BLOCK (786432)
Examples:
import * as FeeMarket from './FeeMarket.js';

// Valid state
const state1: FeeMarket.State = {
  gasUsed: 15_000_000n,
  gasLimit: 30_000_000n,
  baseFee: 1_000_000_000n,
  excessBlobGas: 0n,
  blobGasUsed: 393216n
};

const errors1 = FeeMarket.validateState(state1);
// errors1 === []

// Invalid: gas used exceeds limit
const state2: FeeMarket.State = {
  gasUsed: 40_000_000n,    // Exceeds limit
  gasLimit: 30_000_000n,
  baseFee: 1_000_000_000n,
  excessBlobGas: 0n,
  blobGasUsed: 0n
};

const errors2 = FeeMarket.validateState(state2);
// errors2 === ["gasUsed cannot exceed gasLimit"]

// Invalid: base fee below minimum
const state3: FeeMarket.State = {
  gasUsed: 15_000_000n,
  gasLimit: 30_000_000n,
  baseFee: 5n,              // Below MIN_BASE_FEE (7)
  excessBlobGas: 0n,
  blobGasUsed: 0n
};

const errors3 = FeeMarket.validateState(state3);
// errors3 === ["baseFee must be at least 7"]

// Invalid: blob gas exceeds maximum
const state4: FeeMarket.State = {
  gasUsed: 15_000_000n,
  gasLimit: 30_000_000n,
  baseFee: 1_000_000_000n,
  excessBlobGas: 0n,
  blobGasUsed: 1_000_000n   // Exceeds MAX (786432)
};

const errors4 = FeeMarket.validateState(state4);
// errors4 === ["blobGasUsed cannot exceed 786432"]

// Multiple errors
const state5: FeeMarket.State = {
  gasUsed: -1n,             // Negative
  gasLimit: 0n,             // Not positive
  baseFee: 1_000_000_000n,
  excessBlobGas: -100n,     // Negative
  blobGasUsed: 0n
};

const errors5 = FeeMarket.validateState(state5);
// errors5.length === 3
// errors5[0] === "gasUsed must be non-negative"
// errors5[1] === "gasLimit must be positive"
// errors5[2] === "excessBlobGas must be non-negative"
Usage Pattern:
import { ValidationError } from 'tevm/errors'

function processBlock(state: FeeMarket.State) {
  const errors = FeeMarket.validateState(state);

  if (errors.length > 0) {
    throw new ValidationError(`Invalid block state: ${errors.join(', ')}`, {
      value: state,
      expected: "Valid block fee market state",
      code: "INVALID_BLOCK_STATE"
    });
  }

  // Safe to proceed
  const nextState = FeeMarket.nextState(state);
  return nextState;
}

Conversion

weiToGwei

weiToGwei(wei: bigint): string
Convert wei to gwei for human-readable display. Parameters:
  • wei - Amount in wei
Returns: String formatted to 9 decimal places Examples:
import * as FeeMarket from './FeeMarket.js';

// Exact gwei
const gwei1 = FeeMarket.weiToGwei(1_000_000_000n);
// gwei1 === "1.000000000"

// Fractional gwei
const gwei2 = FeeMarket.weiToGwei(1_234_567_890n);
// gwei2 === "1.234567890"

// Small amount
const gwei3 = FeeMarket.weiToGwei(123n);
// gwei3 === "0.000000123"

// Large amount
const gwei4 = FeeMarket.weiToGwei(50_000_000_000n);
// gwei4 === "50.000000000"

// Base fee example
const baseFee = 1_500_000_000n;
console.log(`Base fee: ${FeeMarket.weiToGwei(baseFee)} gwei`);
// "Base fee: 1.500000000 gwei"
Display Usage:
const state: FeeMarket.State = { /* ... */ };

console.log(`Base fee: ${FeeMarket.weiToGwei(state.baseFee)} gwei`);

const blobFee = FeeMarket.State.getBlobBaseFee.call(state);
console.log(`Blob fee: ${FeeMarket.weiToGwei(blobFee)} wei/gas`);
// Note: blob fees are per gas, not per gwei
Precision: 9 decimal places (1 gwei = 10^9 wei). All wei values represented.

gweiToWei

gweiToWei(gwei: number): bigint
Convert gwei to wei. Parameters:
  • gwei - Amount in gwei (JavaScript number)
Returns: Amount in wei (bigint) Examples:
import * as FeeMarket from './FeeMarket.js';

// Exact gwei
const wei1 = FeeMarket.gweiToWei(1);
// wei1 === 1_000_000_000n

// Fractional gwei
const wei2 = FeeMarket.gweiToWei(1.5);
// wei2 === 1_500_000_000n

const wei3 = FeeMarket.gweiToWei(0.123456789);
// wei3 === 123_456_789n

// Large amount
const wei4 = FeeMarket.gweiToWei(100);
// wei4 === 100_000_000_000n

// Set transaction fee
const maxFeePerGas = FeeMarket.gweiToWei(2); // 2 gwei
const maxPriorityFeePerGas = FeeMarket.gweiToWei(1); // 1 gwei
Precision: Floors fractional wei (rounds down).
const wei = FeeMarket.gweiToWei(1.9999999999);
// wei === 1_999_999_999n (last digit floored)
Usage:
// Build transaction from gwei inputs
function buildTxFromGwei(
  maxFeeGwei: number,
  priorityFeeGwei: number,
  baseFeeGwei: number
): FeeMarket.TxFeeParams {
  return {
    maxFeePerGas: FeeMarket.gweiToWei(maxFeeGwei),
    maxPriorityFeePerGas: FeeMarket.gweiToWei(priorityFeeGwei),
    baseFee: FeeMarket.gweiToWei(baseFeeGwei)
  };
}

const params = buildTxFromGwei(2, 1, 0.8);
// params.maxFeePerGas === 2_000_000_000n
// params.maxPriorityFeePerGas === 1_000_000_000n
// params.baseFee === 800_000_000n

Combined Usage

Validate and Display

function displayFeeInfo(params: FeeMarket.TxFeeParams) {
  // Validate
  const errors = FeeMarket.validateTxFeeParams(params);
  if (errors.length > 0) {
    console.error('Invalid parameters:', errors.join(', '));
    return;
  }

  // Calculate
  const fee = FeeMarket.calculateTxFee(params);

  // Display
  console.log(`Max fee: ${FeeMarket.weiToGwei(params.maxFeePerGas)} gwei`);
  console.log(`Priority fee: ${FeeMarket.weiToGwei(params.maxPriorityFeePerGas)} gwei`);
  console.log(`Base fee: ${FeeMarket.weiToGwei(params.baseFee)} gwei`);
  console.log(`Effective price: ${FeeMarket.weiToGwei(fee.effectiveGasPrice)} gwei`);
  console.log(`Actual priority: ${FeeMarket.weiToGwei(fee.priorityFee)} gwei`);
}

State Validation Pipeline

function processBlockSafely(state: FeeMarket.State) {
  // Validate current state
  const currentErrors = FeeMarket.validateState(state);
  if (currentErrors.length > 0) {
    throw new Error(`Current state invalid: ${currentErrors.join(', ')}`);
  }

  // Calculate next state
  const nextState = FeeMarket.nextState(state);

  // Validate next state
  const nextErrors = FeeMarket.validateState(nextState);
  if (nextErrors.length > 0) {
    throw new Error(`Next state invalid: ${nextErrors.join(', ')}`);
  }

  // Display transition
  console.log('Current base fee:', FeeMarket.weiToGwei(state.baseFee), 'gwei');
  console.log('Next base fee:', FeeMarket.weiToGwei(nextState.baseFee), 'gwei');

  return nextState;
}

User Input Validation

function buildTxFromUserInput(
  maxFeeGwei: number,
  priorityFeeGwei: number,
  currentBaseFeeWei: bigint
): FeeMarket.TxFeeParams {
  const params: FeeMarket.TxFeeParams = {
    maxFeePerGas: FeeMarket.gweiToWei(maxFeeGwei),
    maxPriorityFeePerGas: FeeMarket.gweiToWei(priorityFeeGwei),
    baseFee: currentBaseFeeWei
  };

  const errors = FeeMarket.validateTxFeeParams(params);
  if (errors.length > 0) {
    throw new Error(`Invalid fee parameters: ${errors.join(', ')}`);
  }

  // Check if transaction can be included
  if (!FeeMarket.canIncludeTx(params)) {
    throw new Error(
      `Max fee (${maxFeeGwei} gwei) below current base fee ` +
      `(${FeeMarket.weiToGwei(currentBaseFeeWei)} gwei)`
    );
  }

  return params;
}

Implementation

Locations:
  • BrandedFeeMarket/validateTxFeeParams.js
  • BrandedFeeMarket/validateState.js
  • BrandedFeeMarket/weiToGwei.js
  • BrandedFeeMarket/gweiToWei.js
See branded-feemarket.mdx for implementation details.

References