REVM v104 — Release Notes
Date: March 3, 2026
Tag: v104
Amsterdam hardfork support (EIP-7708, EIP-7843, EIP-8024), ResultGas struct refactor, flatten Bytecode, logs added to Revert/Halt variants, BAL (Block Access List) support, O(1) block hash cache, various performance improvements and bug fixes.
Migration Guide: MIGRATION_GUIDE.md
Changelog: CHANGELOG.md
Breaking Changes
- Flatten Bytecode —
Bytecodeis now a struct wrappingArc<BytecodeInner>instead of an enum. Use accessor methods (kind(),is_legacy(),eip7702_address()) instead of pattern matching. (#3375) ResultGasstruct inExecutionResult— Separategas_used/gas_refundedfields replaced by aResultGasstruct with methodsused(),remaining(),inner_refunded(),final_refunded(),spent_sub_refunded(). (#3413)- Logs in Revert/Halt variants —
ExecutionResult::RevertandHaltnow carrylogs: Vec<Log>for logs emitted before failure. (#3424) - EIP-161 state clear moved into journal finalize — Removed
has_state_clearfield and related methods fromCacheState/State. (#3444) - Remove Default for EthPrecompiles and EthInstructions — Use
new(spec)constructors instead. (#3434) - Fixed-bytes hashmaps from alloy-core —
HashMap<Address, _>→AddressMap<_>,HashMap<B256, _>→B256Map<_>. (#3358)
Amsterdam Hardfork (New EIPs)
- EIP-7708: ETH transfers emit a log — When Amsterdam is active and value is non-zero, ETH transfers emit logs. Includes configuration options in Cfg. (#3334, #3395)
- EIP-7843: SLOTNUM opcode — New opcode
0x4B.BlockEnvgainsslot_num: u64field,Hosttrait gainsslot_num()method. (#3340) - EIP-8024: DUPN, SWAPN, EXCHANGE opcodes — New opcodes at
0xE6–0xE8with a newInvalidImmediateEncodinginstruction result variant. (#3223)
Features
- BAL (Block Access List) support — New example and
StateBuilder::with_bal_builder_ifhelper. (#3339, #3351) - aws-lc-rs backend for secp256r1 — Alternative precompile backend via feature flag. (#3451)
- Configurable EIP-7702 auth refund — New
GasParamsentry. (#3366) tx_access_list_costhelper — Added toGasParams. (#3349)clear()for CacheState and TransitionState — Convenience method. (#3390)BlockHashCachehelpers —iter()andlowest()methods. (#3352)- Storage getter on
BundleState— (#3321) - revme:
--jsonoutput flag for evmrunner. (#3428) - revme:
--omit-progressflag for statetest. (#3419) - revme: validate block gas in blockchain tests. (#3416)
Performance
- O(1) ring buffer block hash cache — Replaces
BTreeMap<u64, B256>. (#3299) - Zero-copy scalar conversion in BLS12-381 MSM precompile. (#3359)
- Cache trusted setup G2 for KZG precompile. (#3322)
- Elide jumps in JUMP opcode execution. (#3347)
- Reserve capacity in
merge_transitions,extend_state, andadd_transitions. (#3430, #3373) - Avoid unnecessary clone/prealloc in state operations. (#3387)
- Remove unnecessary
enveloped_txclone in op-revm. (#3455)
Bug Fixes
- Forward
storage_by_account_idinWrapDatabaseRef. (#3441) - Allow EIP-161 state clear for empty Loaded and Changed accounts. (#3421)
- Big-endian resize for modexp output padding. (#3432)
- Respect
is_fee_charge_disabledincalculate_caller_fee. (#3401) - Fix
storage_by_account_idcache bypass in CacheDB. (#3385) - Fix populated account if BAL pre-state was none. (#3357)
- Set
transition_idto account correctly. (#3353) - Use provided code hash when setting account code. (#3324)
- LOG/CREATE opcodes memory modification tracking. (#3328)
Dependencies
- Updated vulnerable dependencies: keccak, time, bytes (#3467)
- Bumped c-kzg 2.1.4 → 2.1.6 (#3448)
- Default hardfork updated to Osaka (Ethereum) / Jovian (Optimism) (#3326)
Full diff: v103...v104 (181 files changed, 4494 insertions, 1791 deletions)
All commits
- chore: remove outdated stack pop TODO by @joeybright53 in #3315
- perf: Use O(1) ring buffer cache for block hashes instead of BTreeMap by @malik672 in #3299
- refactor(bytecode): remove redundant clones in legacy analysis tests by @letmehateu in #3317
- Rename misleading calc_linear_cost_u32 function by @saylor-mik87786 in #3318
- fix(database): BlockHashCache incorrectly returns zero for block 0 by @bshastry in #3319
- chore: update default hardfork to Osaka (Ethereum) and Jovian (Optimism) by @zerosnacks in #3326
- feat: Implement EIP-8024 for Amsterdam by @frangio in #3223
- fix(bytecode): improve analyze_legacy padding for SWAPN/DUPN/EXCHANGE by @rakita in #3332
- fix: the LOG[0-4] CREATE CREATE2 opcode can modify memory by @mark0-cn in #3328
- feat(database): add storage getter to BundleState by @mattsse in #3321
- perf: cache trusted setup G2 by @lisenokdonbassenok in #3322
- fix: use provided code hash when setting account code by @Bashmunta in #3324
- fix(bytecode): improve analyze_legacy and stack tests by @rakita in #3335
- feat: Implement EIP-7708 ETH transfers emit a log by @rakita in #3334
- revm-handler: add ItemOrResult::map_item (alias map_frame) by @maximevtush in #3320
- fix(bytecode): add padding for final opcode missing immediates by @frangio in #3338
- feat: Implement EIP-7843 SLOTNUM opcode for Amsterdam by @rakita in #3340
- feat: add BAL (Block Access List) example by @mattsse in #3339
- perf: elide some jumps in jump by @DaniPopes in #3347
- feat(gas): add tx_access_list_cost helper to GasParams by @saylor-mik87786 in #3349
- feat(database): add StateBuilder::with_bal_builder_if by @mattsse in #3351
- feat(database): add iter and lowest helpers to BlockHashCache by @mattsse in #3352
- fix: set transition_id to account by @rakita in #3353
- refactor(handler): extract duplicate ContextError handling by @andrewshab3 in #3312
- perf: use fixed bytes hashmaps from alloy-core by @gakonst in #3358
- fix(bal): fix populated account if pre-state was none by @jsign in #3357
- perf(precompile): zero-copy scalar conversion in BLS12-381 MSM by @dizer-ti in #3359
- Deprecate
nonce_bump_journal_entryandcaller_accounting_journal_entryfunctions by @rakita in #3367 - docs: clarify gmp uses dynamic linking (no GPL implications) by @gakonst in #3383
- feat(database): add clear() to CacheState and TransitionState by @mattsse in #3390
- perf(state): avoid unnecessary clone, prealloc, and fix typo by @nkysg in #3387
- fix(db): use self.storage() in storage_by_account_id to avoid cache bypass by @RyanBGG in #3385
- feat(statetest-types): add slot_number support (EIP-7843) by @rakita in #3391
- fix(journal): emit EIP-7708 log for selfdestructed accounts with remaining balance by @rakita in #3394
- chore(scripts): update devnet test fixtures to bal@v5.1.0 by @rakita in #3392
- perf: reserve capacity in add_transitions by @DaniPopes in #3373
- feat(gas_params): add configurable EIP-7702 auth refund by @Himess in #3366
- refactor(interpreter): deduplicate slice range logic by @andrewshab3 in #3376
- feat(statetest-types): add BPO2ToAmsterdamAtTime15k fork spec by @rakita in #3397
- refactor!: flatten Bytecode by @DaniPopes in #3375
- impl Display and Error for TxEnvBuildError and DeriveTxTypeError by @Himess in #3409
- feat(cfg): add EIP-7708 configuration options by @rakita in #3395
- chore: remove unused deps by @cuiweixie in #3414
- refactor!: add ResultGas struct to ExecutionResult by @rakita in #3413
- refactor!: add logs to Revert and Halt variants of ExecutionResult by @rakita in #3424
- bench: add subcall benchmarks (1000-call variants) by @rakita in #3427
- chore: remove unused alloy-provider dev-dependency by @zeroprooff in #3423
- perf(database): add reserve calls in merge_transitions and extend_state by @gakonst in #3430
- feat(revme): add --omit-progress flag to statetest command by @bluebluesaku in #3419
- fix(handler): respect is_fee_charge_disabled in calculate_caller_fee by @bluebluesaku in #3401
- fix: add a test utility function to generate memory input opcodes by @silathdiir in #3280
- feat(revme): validate block gas used in blockchain tests by @rakita in #3416
- fix(precompile): use big-endian resize for modexp output padding by @Wollac in #3432
- refactor(handler): remove Default for EthPrecompiles and EthInstructions by @rakita in #3434
- fix(database): allow EIP161 state clear for empty Loaded and Changed accounts by @msheth-circle in #3421
- feat(revme): add --json output flag to evmrunner command by @bluebluesaku in #3428
- refactor(gas): simplify log2floor implementation by @rakita in #3440
- fix: forward storage_by_account_id in WrapDatabaseRef by @andrewshab3 in #3441
- chore: bump c-kzg from 2.1.4 to 2.1.6 by @rakita in #3448
- refactor: deduplicate CacheDB::basic by delegating to load_account by @andrewshab3 in #3447
- refactor: move EIP-161 state clear into journal finalize by @decofe in #3444
- docs(op-revm): fix operator fee field doc comments by @jackwener in #3457
- perf(op-revm): remove unnecessary enveloped_tx clone in reward_beneficiary by @jackwener in #3455
- feat(precompile): add aws-lc-rs as alternative backend for secp256r1 by @rakita in #3451
- fix(context): correct ResultGas::final_refunded() when floor gas is active by @rakita in #3450
- chore: update vulnerable dependencies by @rakita in #3467
- chore: release by @github-actions[bot] in #3316
- docs: add v104 migration guide by @rakita in #3468
- chore: bump revm to v35.0.0 for v104 release by @rakita in #3470
New Contributors
- @saylor-mik87786 made their first contribution in #3318
- @mark0-cn made their first contribution in #3328
- @lisenokdonbassenok made their first contribution in #3322
- @Bashmunta made their first contribution in #3324
- @andrewshab3 made their first contribution in #3312
- @jsign made their first contribution in #3357
- @dizer-ti made their first contribution in #3359
- @Himess made their first contribution in #3366
- @cuiweixie made their first contribution in #3414
- @bluebluesaku made their first contribution in #3419
- @msheth-circle made their first contribution in #3421
- @decofe made their first contribution in #3444
Full Changelog: v103...v104