- EIP-8037 state gas support (#3406). Gas is now split into regular gas and state gas tracked via a reservoir. State gas draws from the reservoir first and spills into regular gas when exhausted. This affects gas accounting across the entire stack.
Gas::spent()andrecord_cost()deprecated. Usetotal_gas_spent(),record_regular_cost(),record_state_cost().- New
Gas::new_with_regular_gas_and_reservoir(limit, reservoir)constructor for creating child frame gas with reservoir. ResultGas::new()deprecated (takes 3 params now). UseResultGas::new_with_state_gas(total_gas_spent, refunded, floor_gas, state_gas_spent).ResultGas::spent()/used()deprecated. Usetotal_gas_spent()/tx_gas_used(). New accessors:state_gas_spent(),block_regular_gas_used(),block_state_gas_used().ExecutionResult::gas_used()deprecated, usegas().tx_gas_used().InitialAndFloorGas::initial_gasfield renamed toinitial_total_gas. New fields added:initial_state_gas(state gas portion) andeip7702_reservoir_refund(refund for existing EIP-7702 authorities).CallInputsgainedreservoir: u64field for propagating state gas from parent to child frames.Interpreter::cleartakes 7 params (was 6),EthFrame::cleartakes 11 (was 10) — both gained reservoir parameter.HostandCfgtraits gained required methodis_amsterdam_eip8037_enabled() -> bool. Must be implemented on any custom types.Handler::pre_executionandapply_eip7702_auth_listgained&mut InitialAndFloorGasparam to write back state gas and refund info.Handler::first_frame_inputgained&InitialAndFloorGasparam to compute the reservoir for the first frame.validate_initial_tx_gastakes 5 params (was 3) — addedis_amsterdam_eip8037_enabledandtx_gas_limit_cap.create_init_frametakes 2 params (was 3), gainedCTX: ContextTrgeneric. Reservoir is set byfirst_frame_inputafter creation.
PrecompileErrorrestructured (#3496, #3502). All specific error variants removed (OutOfGas,Blake2*,Bn254*,Bls12381*,Kzg*,Secp256k1*,Other, etc.).PrecompileErroris now only for fatal/unrecoverable errors with two variants:Fatal(String)andFatalAny(AnyError). Non-fatal failures (OOG, invalid input) are now expressed viaPrecompileStatus::HaltinPrecompileOutput.PrecompileError::other(),other_static(),is_oog()removed.
PrecompileOutputfields changed:gas_refundedandrevertedremoved, new fieldsstatus: PrecompileStatus,state_gas_used,reservoir.PrecompileOutput::new(gas_used, bytes, reservoir)— added reservoir param.PrecompileOutput::new_reverted()/reverted()removed, usePrecompileOutput::revert()instead.PrecompileFnsignature changed fromfn(&[u8], u64)tofn(&[u8], u64, u64)— added reservoir param.Precompile::execute()also gainedreservoir: u64param.
EVMError::CustomAny(AnyError)variant added (#3502). Update exhaustive matches.EVMErroralso lostUnwindSafe/RefUnwindSafeauto traits.SELFDESTRUCT_LOG_TOPICconstant removed fromrevm-primitives(#3438).StateBuilder::with_background_transition_mergeremoved (was a no-op) (#3510). Simply remove any calls.CfgEnv::set_specdeprecated (#3550). Use thespecfield directly.MemoryGas::record_new_lenandmemory_gasfunction removed (#3534).- Inspector
frame_startandframe_endmethods added with default impls (#3518). Hooks into frame lifecycle; no action needed unless you want to use them.
Bytecode flattened from enum to struct (#3375)
Bytecode is no longer an enum with LegacyRaw, LegacyAnalyzed, Eip7702 variants. It is now an opaque struct wrapping Arc<BytecodeInner> (size reduced from 16 to 8 bytes).
- Pattern matching on
Bytecodevariants is no longer possible. Use accessor methods instead:bytecode.kind()returnsBytecodeKind(LegacyAnalyzedorEip7702).bytecode.is_legacy(),bytecode.is_eip7702()for type checks.bytecode.eip7702_address()instead of matchingBytecode::Eip7702(...).bytecode.legacy_jump_table()instead of matchingBytecode::LegacyAnalyzed(...).
- Constructors:
Bytecode::new_legacy(raw_bytes)— replacesBytecode::LegacyRaw(...)(analysis happens on creation).Bytecode::new_analyzed(bytecode, original_len, jump_table)— replacesBytecode::LegacyAnalyzed(Arc::new(...)).Bytecode::new_eip7702(address)— replacesBytecode::Eip7702(Arc::new(...)).Bytecode::new_raw(bytes)— auto-detects EIP-7702 delegation.
LegacyAnalyzedBytecode,LegacyRawBytecode,Eip7702Bytecodestructs are no longer publicly exported.JumpTable::from_bytesandJumpTable::from_bytes_arcremoved (Arc is now internal to Bytecode).- The
legacymodule is removed from public API.
ExecutionResult: new ResultGas struct replaces gas_used/gas_refunded (#3413)
All three ExecutionResult variants now use a gas: ResultGas field instead of separate gas_used: u64 / gas_refunded: u64:
// Before:
ExecutionResult::Success { reason, gas_used, gas_refunded, logs, output }
ExecutionResult::Revert { gas_used, output }
ExecutionResult::Halt { reason, gas_used }
// After:
ExecutionResult::Success { reason, gas: ResultGas, logs, output }
ExecutionResult::Revert { gas: ResultGas, logs, output }
ExecutionResult::Halt { reason, gas: ResultGas, logs }ResultGas provides:
used()— equivalent to oldgas_used(accounts for EIP-7623 floor).remaining()—limit - spent.inner_refunded()— raw refund value.final_refunded()— 0 when floor gas is active, otherwise equals refunded.spent_sub_refunded()—spent - refunded.- Construct with
ResultGas::new(limit, spent, refunded, floor_gas, intrinsic_gas).
The convenience method ExecutionResult::gas_used() still works (delegates to gas().used()).
ExecutionResult::Revert and Halt now carry logs (#3424)
This is only relevant for revm variant ( Tempo ), ethereum does not contains logs on Halt or Revert.
Both Revert and Halt variants gained a logs: Vec<Log> field containing logs emitted before the revert/halt:
// Before:
ExecutionResult::Revert { gas, output }
ExecutionResult::Halt { reason, gas }
// After:
ExecutionResult::Revert { gas, logs, output }
ExecutionResult::Halt { reason, gas, logs }logs()andinto_logs()now return logs from all variants, not justSuccess.
EIP-161 state clear moved into journal finalize (#3444)
Pre-EIP-161 normalization is now handled by JournalInner::finalize() instead of the database layer.
CacheState::has_state_clearfield removed.CacheState::set_state_clear_flag()removed.State::set_state_clear_flag()removed.StateBuilder::without_state_clear()removed.CacheState::new()now takes no parameters (wasnew(has_state_clear: bool)).CacheAccount::touch_create_pre_eip161()removed.AccountStatus::on_touched_created_pre_eip161()removed.
// Before:
CacheState::new(true)
state_builder.without_state_clear()
// After:
CacheState::new()
// (no replacement needed — journal handles it)JournalInner.spec replaced by JournalInner.cfg (#3395)
JournalInner's spec field is replaced by a cfg: JournalCfg struct that bundles spec with EIP-7708 config:
- Access spec via
journal.inner.cfg.specinstead ofjournal.inner.spec. JournalInneralso gained aselfdestructed_addressesfield.JournalCheckpointgained aselfdestructed_i: usizefield.
Handler::execution_result signature changed (#3413)
// Before:
fn execution_result(&mut self, evm, result) -> Result<ExecutionResult, Error>
// After:
fn execution_result(&mut self, evm, result, result_gas: ResultGas) -> Result<ExecutionResult, Error>Also, post_execution::output() now takes a ResultGas parameter instead of computing gas internally.
EthPrecompiles and EthInstructions no longer implement Default (#3434)
// Before:
EthPrecompiles::default()
EthInstructions::default()
EthInstructions::new_mainnet() // deprecated
// After:
EthPrecompiles::new(spec)
EthInstructions::new_mainnet_with_spec(spec)Fixed-bytes hashmaps from alloy-core (#3358)
HashMap<Address, _> / HashSet<Address> replaced with AddressMap<_> / AddressSet throughout the codebase. Similarly HashMap<B256, _> → B256Map<_> and HashMap<U256, _> → U256Map<_>.
Affected trait signatures:
DatabaseCommit::commit():HashMap<Address, Account>→AddressMap<Account>.JournalTr::warm_access_list():HashMap<Address, HashSet<StorageKey>>→AddressMap<HashSet<StorageKey>>.JournalTr::warm_precompiles():HashSet<Address>→AddressSet.JournalTr::precompile_addresses(): returns&AddressSet.
Import these types from revm::primitives (re-exported from alloy-core).
BlockHashCache replaces BTreeMap for block hashes (#3299)
State::block_hashes changed from BTreeMap<u64, B256> to BlockHashCache (O(1) ring buffer, 256 entries).
// Before:
state.block_hashes.get(&block_num)
StateBuilder::default().with_block_hashes(btree_map)
// After:
state.block_hashes.get(block_num)
StateBuilder::default().with_block_hashes(block_hash_cache)apply_auth_list gains refund_per_auth parameter (#3366)
// Before:
apply_auth_list(context, auth_list, journal)
// After:
apply_auth_list(context, auth_list, journal, refund_per_auth)Use gas_params.tx_eip7702_auth_refund() for the default value (12500).
EIP-7843: SLOTNUM opcode (#3340)
- New opcode
SLOTNUM(0x4B) gated behindAMSTERDAM. BlockEnvhas a newslot_num: u64field (default0). Include when constructingBlockEnvliterals.Hosttrait gainedfn slot_num(&self) -> U256.Blocktrait gainedfn slot_num(&self) -> u64with default returning0.
- When Amsterdam is active and value is non-zero, ETH transfers (CALL, CREATE, SELFDESTRUCT, tx value) emit EIP-7708 logs.
Cfgtrait gainedis_eip7708_disabled()andis_eip7708_delayed_burn_disabled().JournalTrtrait gainedset_eip7708_config().- Tests that check exact log counts on Amsterdam+ specs need updating.
EIP-8024: DUPN, SWAPN, EXCHANGE opcodes (#3223)
- New opcodes at
0xE6–0xE8gated behindAMSTERDAM, each with 1-byte immediates. - New
InstructionResult::InvalidImmediateEncodingvariant — update exhaustive matches.
JournalTr::caller_accounting_journal_entry()andnonce_bump_journal_entry()(#3367).EthInstructions::new_mainnet()— usenew_mainnet_with_spec(spec)(#3434).ItemOrResult::map_frame— usemap_item(#3320).
- Default hardfork updated to Osaka (Ethereum) and Jovian (Optimism) (#3326).
ContextErrorhandling extracted intotake_errorhelper (#3312).BlockHashCacheincorrectly returning zero for block 0 fixed (#3319).ResultGas::final_refunded()corrected when floor gas is active (#3450).- EIP-161 state clear fix for empty Loaded/Changed accounts (#3421).
CacheState::clear()andTransitionState::clear()added (#3390).calc_linear_cost_u32renamed tocalc_linear_cost(#3318).
- BAL (EIP-7928) support added to Database implementations.
GasParamsis new struct where you can set dynamic opcode gas params. Initialized and can be found in cfg.- Gas calculation functions moved from
revm-interpreterto be part of gas params. - Gas constants moved from
revm_interpreter::gas torevm_context_interface::cfg::gas
- Gas calculation functions moved from
CreateInputsstruct fields made private with accessor pattern.- Use
CreateInputs::created_address()getter (now cached).
- Use
Host::selfdestructsignature changed to support OOG on cold load for target account.- Inspector
logfunction renamed:Inspector::logrenamed tologandlog_full.log_fulldefault impl callslog.log_fullhasInterpreterinput whilelogdoes not.logis called in places where Interpreter is not found.
PrecompileError::Othernow containsCow<'static, str>instead of&'static str.- Allows setting both
&'static str(no perf penalty) andStringif needed.
- Allows setting both
JournaledAccountstruct added for tracking account changes.JournalTrfunctions that fetch account now return a ref.- New function
load_account_mutreturnsJournaledAccount.
JournalTr::load_account_codedeprecated, renamed toJournalTr::load_account_with_code.JournalTr::warm_account_and_storageandJournalTr::warm_accountremoved.- Access list is now separate from the main Journal EvmState.
- Use
JournalTr::warm_access_listto import access list.
- Declarative macros
tri!,gas_or_fail!,otry!removed fromrevm-interpreter. MemoryGasAPI signature changes.- Removed deprecated methods including
into_plain_state,regenerate_hash. State.bal_statefield added (breaks struct literal constructors).DatabaseCommitExt::drain_balancesandincrement_balancesadded.- First precompile error now bubbles up with detailed error messages.
- New
PrecompileErrorvariants added.
- New
No breaking changes
No breaking changes
- Additionally to v99 version:
Host::selfdestructfunction got changed to support oog on cold load for target account.
(yanked version)
- Added support for transmitting Logs set from precompiles.
Inspector::logfunction got renamed tologandlog_fulllog_fulldefault impl will calllog- difference is that
log_fullhasInterpreterinput whilelogdoes not andlogwill be called in places where Interpreter is not found.
PrecompileErrornow containsOtherasCow<'static, str>- It allows setting both
&'static strthat is without perf penalty andStringif needed.
- It allows setting both
No breaking changes.
No breaking changes.
No breaking changes.
- Cfg added
memory_limit()function JournaledAccounthave been added that wraps account changes, touching and creating journal entry.- Past function that fetches account now return a ref and new function
load_account_mutnow returnJournaledAccount JournalEntrytype is added toJournalTrso JournaledAccount can create it.
- Past function that fetches account now return a ref and new function
JournalTr::load_account_codeis deprecated/renamed toJournalTr::load_account_with_codeJournalTr::warm_account_and_storageandJournalTr::warm_accountare removed as access list is now separate from the main Journal EvmState. Function that imports access list to the Journal isJournalTr::warm_access_list
No breaking changes
No breaking changes
No breaking changes
No breaking changes
No breaking changes
- Removal of some deprecated functions.
into_plain_state,regenerate_hashwere deprecated few releases ago.
No breaking changes
ContextTr,EvmTrgainedall_mut()andall()functions.InspectorEvmTrgotall_inspectorandall_mut_inspectorfunctions.- For custom Evm, you only need to implement
all_*functions.
InspectorFramegot changed to allow CustomFrame to be added.- If there is no need for inspection
fn eth_framecan return None.
- If there is no need for inspection
kzg-rsfeature and library removed. Default KZG implementation is now c-kzg.- for no-std variant, arkworks lib is used.
- Opcodes that load account/storage will not load item if there is not enough gas for cold load.
- This is in preparation for BAL.
- Journal functions for loading now have skip_cold_load bool.
libsecp256k1parity library is deprecated and removed.JumpTableinternal representation changed fromBitVectoBytes. No changes in API.SpecIdenum gained newAmsterdamvariant andOpSpecIdgainedJovianvariant.SELFDESTRUCTconstant renamed toSELFDESTRUCT_REFUND.FrameStack::pushandFrameStack::end_initmarked asunsafeas it can cause UB.- First precompile error is now bubble up with detailed error messages. New
PrecompileErrorvariants added. - Batch execution errors now include transaction index.
CallInputnow contains bytecode that is going to be executed (Previously it had address).- This allows skipping double bytecode fetching.
InvalidTransactionenum gainedStr(Cow<'static, str>)variant for custom error messages.calc_excess_blob_gasandcalc_excess_blob_gasremoves as they are unused and not accurate for Prague.
PrecompileWithAddressis renamed toPrecompileand it became a struct.PrecompilecontainsPrecompileId,Addressand function.- The reason is adding
PrecompileIdas it is needed for fusaka hardfork
Forward compatible version.
SystemCallEvmfunctions got renamed and old ones are deprecated. Renaming is done to align it with other API calls.transact_system_call_finalizeis nowsystem_call.transact_system_callis nowsystem_call_one.
ExtBytecode::regenerate_hashgot deprecated in support forget_or_calculate_hashorcalculate_hash.- Precompiles:
- Bn128 renamed to Bn254. ethereum/EIPs#10029 (comment)
InstructionResultnow starts from 1 (previous 0) for perf purposes.- In
JournalInnerpreviousprecompiles,warm_coinbase_addressandwarm_preloaded_addressespub fields are now moved towarm_addressesto encapsulate addresses that are warm by default. All access list account are all loaded from database.
ContextTrgainedHostsupertrait.- Previously Host was implemented for any T that has ContextTr, this restricts specializations. #2732
Hostis moved torevm-context-interface- If you custom struct that implement
ContextTryou would need to manually implementHosttrait, in most cases no action needed.
- In
revm-interpreter, fncast_slice_to_u256was removed andpush_slicefn is added toStackTrait. PrecompileOutputnow contains revert flag.- It is safe to put to false.
- In
kzgandblake2modules few internal functions were made private or removed.
- Inspector fn
step_endis now called even if Inspectorstepsets the action. Previously this was not the case.- #2687
- this additionally fixes panic bug where
bytecode.opcode()would panic instep_end
- Removal of
EvmData.- It got flattened and ctx/inspector fields moved directly to Evm, additional layering didn't have purpose.
- Merging of
Handler'svalidate_tx_against_stateanddeduct_callerinto one functionvalidate_against_state_and_deduct_caller- If you dont override those functions there is no action. If you do please look at
pre_execution::validate_against_state_and_deduct_callerfunction orOpHandlerfor examples of migration.
- If you dont override those functions there is no action. If you do please look at
- Breaking changed for EOF to support eof-devnet1.
SharedMemoryis not longer Rc<RefCell<>> and internally uses Rc<RefCell<Vec>> buffer.- No action if you dont use it inside Interpreter.
- In
JournalExtfnlast_journal_mut()is renamed tojournal_mut() - EOF is disabled from Osaka and not accessible.
No breaking changes
- No code breaking changes
- alloy-primitives bumped to v1.0.0 and we had a major bump because of it.