eot - EVM Opcode Table
EVM opcodes library with fork-aware gas costs, static metadata, and bytecode analysis.
Overview
eot provides a single OpCode(u8) type backed by a static [Option<OpCodeInfo>; 256] lookup table for O(1) opcode lookups with zero heap allocation. Every opcode carries its name, stack I/O, gas cost, group, introduction fork, EIP reference, immediate size, and termination flag.
Fork-specific gas costs (EIP-150, EIP-1884, EIP-2929) are resolved at query time via OpCode::gas_cost(fork), so there's no need for per-fork enum types. A DynamicGasCalculator handles warm/cold access, memory expansion, and complex call pricing for more precise analysis.
Quick start
use ;
// O(1) lookup
let add = ADD;
assert_eq!;
assert!;
// Parse from byte
let op = new.unwrap;
assert_eq!;
assert_eq!;
// Parse from string
let op: OpCode = "KECCAK256".parse.unwrap;
assert_eq!;
// Gas cost evolution
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!; // cold access
Features
- 149 opcodes from Frontier through Prague with full metadata
- Zero-allocation lookups via a static 256-element array
- Fork-aware gas costs encoding EIP-150, EIP-1884, EIP-2929 repricing
- Dynamic gas calculator for warm/cold access, memory expansion, call pricing
- Sequence analysis with optimization suggestions
- Fork comparison to see what changed between any two forks
- Validation of the opcode table against known historical facts
- Optional serde support behind the
serdefeature flag
Supported forks
| Fork | Date | Key changes |
|---|---|---|
| Frontier | Jul 2015 | Base set (130+ opcodes) |
| Homestead | Mar 2016 | DELEGATECALL |
| Tangerine Whistle | Oct 2016 | EIP-150 gas repricing |
| Spurious Dragon | Nov 2016 | EIP-161/170 |
| Byzantium | Oct 2017 | REVERT, RETURNDATASIZE, RETURNDATACOPY, STATICCALL |
| Constantinople | Feb 2019 | SHL, SHR, SAR, CREATE2, EXTCODEHASH |
| Petersburg | Feb 2019 | Reverted EIP-1283 |
| Istanbul | Dec 2019 | CHAINID, SELFBALANCE, EIP-1884 repricing |
| Berlin | Apr 2021 | EIP-2929 warm/cold access costs |
| London | Aug 2021 | BASEFEE (EIP-1559) |
| Paris | Sep 2022 | DIFFICULTY becomes PREVRANDAO |
| Shanghai | Apr 2023 | PUSH0 (EIP-3855) |
| Cancun | Mar 2024 | TLOAD, TSTORE, MCOPY, BLOBHASH, BLOBBASEFEE |
| Prague | May 2025 | — |
| Fusaka | Dec 2025 | EOF (EIP-7692), CLZ, RJUMP, CALLF, DUPN, SWAPN, EXTCALL, +13 more |
Gas analysis
use ;
use Fork;
let calc = new;
let mut ctx = new;
// Cold SLOAD
let cold = calc.calculate_gas_cost.unwrap;
// Warm the slot, then re-read
let key = ;
let addr = ctx.current_address;
ctx.mark_storage_accessed;
let warm = calc.calculate_gas_cost.unwrap;
assert!;
Architecture
src/
lib.rs OpCode, OpCodeInfo, Fork, Group, OPCODE_TABLE, gas_cost_for_fork()
gas.rs Gas constants, GasCostCategory, GasAnalysis
gas/calculator.rs DynamicGasCalculator (warm/cold, memory, calls)
gas/context.rs ExecutionContext, Address/StorageKey types
gas/analysis.rs GasAnalyzer, GasComparator, GasOptimizationAdvisor
validation.rs Static table validation
The entire opcode table is a single static [Option<OpCodeInfo>; 256] initialized at compile time. No HashMap, no heap allocation, no per-fork enum duplication.
Contributing
- Adding an opcode or fork: edit the
opcodes!invocation insrc/lib.rsand add the fork variant to theForkenum. Runcargo ttto verify. - Fixing gas costs: update
gas_cost_for_fork()insrc/lib.rsfor historical changes, or thebase_gasin the opcode table for base costs. - Adding analysis features: extend
gas/analysis.rsorgas/calculator.rs.