EEVM.Interpreter (eevm v0.1.0)

Copy Markdown View Source

The EVM interpreter — fetches, decodes, and dispatches opcodes in a loop.

This is the core opcode-execution engine. It is invoked by EEVM.Handler (the transaction-level pipeline) and by system contracts that need to evaluate bytecode against an existing world state.

Execution ends when a terminating opcode is reached (STOP, RETURN, REVERT, INVALID), the program counter advances past the end of the bytecode (implicit STOP), or gas runs out before the opcode can execute. INVALID (0xFE) is special-cased: its "base" gas cost is set to the entire remaining gas, draining it completely before the opcode runs.

Opcode dispatch is data-driven via the frame's per-hardfork EEVM.Interpreter.InstructionTable (built from EEVM.Interpreter.Instructions.Registry); opcode modules own their semantics, and the interpreter only orchestrates.

Summary

Functions

Applies the transaction-end steps to a halted top-level state: deletes the accounts that SELFDESTRUCTed and touched empty accounts (EIP-161), then settles the refund counter into frame.gas and resets the counter to 0.

Creates a MachineState from bytecode and options, then runs the execution loop.

The main execution loop. Runs the active frame until it halts.

Functions

finalize(state, initial_gas, authorization_refund \\ 0)

Applies the transaction-end steps to a halted top-level state: deletes the accounts that SELFDESTRUCTed and touched empty accounts (EIP-161), then settles the refund counter into frame.gas and resets the counter to 0.

The refund is capped at a fraction of the gas used by the whole transaction: 1/5 from London (EIP-3529), 1/2 before. When env.tx.gas_limit is set, gas used counts from it and so includes intrinsic gas; otherwise it counts from initial_gas. The execution refund counts only when execution succeeded; authorization_refund (EIP-7702) always counts. From Prague the gas charged after the refund is floored at the EIP-7623 calldata cost.

run/2 calls this itself. Callers that charge more gas after execution ends, such as the code deposit of a CREATE transaction, call run_loop/1, charge that gas, then call this, so the cap counts it.

run(code, opts \\ [])

Creates a MachineState from bytecode and options, then runs the execution loop.

Options

  • :gas — initial gas limit (default: 1_000_000)
  • :value — ETH value sent with the call, in wei
  • :code — contract bytecode (usually the same as the first argument)
  • :calldata — ABI-encoded input data for the call
  • :caller — address of the account initiating this call
  • :origin — address of the original transaction signer
  • :authorization_refund — EIP-7702 refund earned before execution; it is added to the refund counter even when execution fails

Returns the final MachineState after execution completes, with the transaction-end steps of finalize/3 applied.

run_loop(state)

The main execution loop. Runs the active frame until it halts.

Any status but :running means the frame has already halted, and the state is returned as-is. It runs one frame: CALL and CREATE run each child frame in a nested call and merge the result into the parent (EEVM.Interpreter.Journal). It is public for those callers and the transaction handler; it is not part of the public API — use run/2.