Transaction-scoped accumulators that survive nested call frames.
Fields
touched_addresses— EIP-161 cleanup set; empty accounts touched during the transaction are deleted on commit.accessed_addresses/accessed_storage_keys— EIP-2929 access lists powering cold/warm gas pricing.created_addresses— EIP-6780 set of contracts created in this tx; only these can be fully deleted bySELFDESTRUCTpost-Cancun. An address joins the set before its initcode runs, so aSELFDESTRUCTduring init deletes it, and leaves the set if that creation fails.selfdestructed_addresses— accounts whoseSELFDESTRUCTdeletes them (all of them pre-Cancun, only those increated_addressesunder EIP-6780). They stay in the database until the transaction ends, thenEEVM.Interpreter.finalize/3deletes them with their storage.original_storage— per-tx snapshot of the first-observed value of each storage slot, keyed by{address, key}, used by EIP-2200SSTOREaccounting.transient_storage— EIP-1153 per-tx store keyed by{address, slot}, passed into every child frame and cleared at tx end.logs— emitted log entries, newest first so LOG and frame merges prepend;EEVM.logs/1and the transaction result reverse them into emission order.program_cache— what is known of every code blob run so far, keyed by the code: its decoded program once a frame has decoded it (EEVM.Interpreter.InstructionTable.decode/3), else its JUMPDEST map once a frame has jumped in it (EEVM.Interpreter.InstructionTable.jumpdests/1). A contract called many times is analysed once.
The first eight fields revert together when a child frame fails (see
EEVM.Interpreter.Journal); program_cache is a cache and survives.
Stack, memory, pc, and gas are not substate — they belong to the
per-frame execution context.
Summary
Functions
Builds a substate, taking each field from the option of the same name and defaulting to an empty set, map, or list.
Types
@type log_entry() :: %{ address: non_neg_integer(), data: binary(), topics: [non_neg_integer()] }
@type t() :: %EEVM.Interpreter.MachineState.Substate{ accessed_addresses: MapSet.t(non_neg_integer()), accessed_storage_keys: MapSet.t({non_neg_integer(), non_neg_integer()}), created_addresses: MapSet.t(non_neg_integer()), logs: [log_entry()], original_storage: %{ required({non_neg_integer(), non_neg_integer()}) => non_neg_integer() }, program_cache: %{ required(binary()) => EEVM.Interpreter.InstructionTable.program() | binary() }, selfdestructed_addresses: MapSet.t(non_neg_integer()), touched_addresses: MapSet.t(non_neg_integer()), transient_storage: %{ required({non_neg_integer(), non_neg_integer()}) => non_neg_integer() } }