Skip to main content

Try it Live

Run Hardfork examples in the interactive playground
New to hardforks? Read the Fundamentals guide for an introduction to Ethereum protocol upgrades, activation mechanisms, and feature timeline.
Ethereum hardforks are protocol upgrades that change EVM behavior, gas costs, or add features. This module provides type-safe hardfork identification, version comparison, and feature detection.
import { Hardfork } from 'tevm';

const fork = Hardfork("cancun");
if (Hardfork.hasEIP4844(fork)) {
  // Blob transactions available
}

Hardfork Type

Hardforks are represented as branded strings:
type BrandedHardfork = string & { __tag: "Hardfork" };

Core Operations

Version Comparison:
Hardfork.isAtLeast(current, target)  // current >= target
Hardfork.isBefore(current, target)    // current < target
Hardfork.compare(a, b)                // -1, 0, 1
Feature Detection:
Hardfork.hasEIP1559(fork)   // EIP-1559 base fee (London+)
Hardfork.hasEIP3855(fork)   // PUSH0 opcode (Shanghai+)
Hardfork.hasEIP4844(fork)   // Blob transactions (Cancun+)
Hardfork.isPostMerge(fork)  // Proof of Stake (Merge+)
String Parsing:
Hardfork("cancun")        // Case-insensitive
Hardfork("paris")         // Alias → MERGE
Hardfork.toString(fork)              // Normalized name

API Methods

Constructors

Comparison Methods

Feature Detection

Collection Operations

  • allNames() - Get all hardfork names (chronological order)
  • allIds() - Get all hardfork IDs (chronological order)
  • range(start, end) - Get hardforks between two versions (inclusive)
  • min(forks) - Find earliest hardfork in array
  • max(forks) - Find latest hardfork in array

Constants

All hardfork constants available:
FRONTIER, HOMESTEAD, DAO, TANGERINE_WHISTLE, SPURIOUS_DRAGON
BYZANTIUM, CONSTANTINOPLE, PETERSBURG, ISTANBUL, MUIR_GLACIER
BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE
SHANGHAI, CANCUN, PRAGUE, OSAKA

Hardfork.DEFAULT  // PRAGUE

Quick Examples

Version Gating

import { Hardfork, CANCUN, LONDON } from 'tevm';

const fork = Hardfork("cancun");

// Check minimum version
if (Hardfork.isAtLeast(fork, LONDON)) {
  // EIP-1559 available
}

// Feature-based check
if (Hardfork.hasEIP4844(fork)) {
  // Use blob transactions
}

Network Configuration

import { InvalidFormatError } from 'tevm/errors'

function getNetworkCapabilities(hardfork: string) {
  const fork = Hardfork(hardfork);
  if (!fork) {
    throw new InvalidFormatError("Invalid hardfork", {
      value: hardfork,
      expected: "Valid hardfork name (e.g., 'cancun', 'london')",
      code: "INVALID_HARDFORK"
    })
  }

  return {
    consensus: Hardfork.isPostMerge(fork) ? "PoS" : "PoW",
    eip1559: Hardfork.hasEIP1559(fork),
    push0: Hardfork.hasEIP3855(fork),
    blobs: Hardfork.hasEIP4844(fork),
    transientStorage: Hardfork.hasEIP1153(fork),
  };
}

Upgrade Path

import { BERLIN, CANCUN, range } from 'tevm';

// Get all hardforks between two versions
const upgradePath = range(BERLIN, CANCUN);
// [BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE, SHANGHAI, CANCUN]

console.log(`${upgradePath.length} hardforks to upgrade through`);

Additional Documentation

Tree-Shaking

Import only what you need for optimal bundle size:
// Import specific features
import { hasEIP4844, isAtLeast, fromString } from 'tevm/Hardfork'

// Or import constants only
import { CANCUN, LONDON, BERLIN } from 'tevm/Hardfork'

// Selective imports reduce bundle size
const fork = fromString(userInput)
if (hasEIP4844(fork)) {
  // Blob logic
}
Each comparison method, feature detector, and utility is independently exported. Import only the hardfork detection logic your application needs.

Performance

All operations are O(1):
  • Comparisons: Simple array index lookups (~10-20ns)
  • Feature detection: Single comparison + branch (~15-30ns)
  • String parsing: Hash table lookup (~50-100ns)
  • String conversion: Array index (~20-40ns)
No WASM implementation - pure TypeScript is optimal for these operations. WASM overhead (1-2μs) would make operations 10-100x slower.

Implementation

  • Type: Branded string (string & { __tag: "Hardfork" })
  • Storage: Chronologically ordered array
  • Comparison: Array index comparison
  • Parsing: Hash table with lowercase keys
  • Aliases: “paris” → MERGE, “constantinoplefix” → PETERSBURG

Best Practices

  1. Use feature detection over version checks
    // Good - explicit about requirements
    if (Hardfork.hasEIP4844(fork)) { /* ... */ }
    
    // Less clear - couples to version
    if (Hardfork.isAtLeast(fork, CANCUN)) { /* ... */ }
    
  2. Validate user input
    import { InvalidFormatError } from 'tevm/errors'
    
    const fork = Hardfork(userInput);
    if (!fork) {
      throw new InvalidFormatError("Invalid hardfork", {
        value: userInput,
        expected: "Valid hardfork name",
        code: "INVALID_HARDFORK"
      })
    }
    
  3. Normalize for storage
    const normalized = Hardfork.toString(fork);
    
  4. Use convenience forms for readability
    if (fork.supportsBlobs()) { /* ... */ }
    
  • Network - Chain ID and network configuration
  • Transaction - Transaction type selection based on hardfork
  • Block - Block structure changes per hardfork