Summary
Add optional step-by-step execution tracing that logs each opcode execution with stack, memory, gas, and storage state. Essential for debugging test failures and comparing execution traces against reference implementations.
Specification
Trace entry per step:
%TraceStep{
pc: non_neg_integer(),
op: atom(), # e.g., :ADD, :SSTORE
gas_remaining: non_neg_integer(),
gas_cost: non_neg_integer(),
stack: [non_neg_integer()],
memory_size: non_neg_integer(),
depth: non_neg_integer(), # call depth
return_data: binary(),
error: atom() | nil
}
Output Format
Compatible with evm --json trace format for easy diffing against geth/revm traces.
Implementation Guide
- Create
lib/eevm/tracer.ex — trace collector (functional, no GenServer)
- Add optional
tracer field to MachineState — nil (disabled) or %Tracer{}
- Hook into
Executor.step/1 — before each opcode, record trace entry if tracer enabled
- Add
EEVM.execute/3 variant that accepts trace options
- JSON output —
Tracer.to_json/1 for geth-compatible format
- Tests: trace a simple program, verify gas costs per step, verify stack states
Acceptance Criteria
Reference
- geth
--json trace format
- revm
TracerEip3155
Summary
Add optional step-by-step execution tracing that logs each opcode execution with stack, memory, gas, and storage state. Essential for debugging test failures and comparing execution traces against reference implementations.
Specification
Trace entry per step:
Output Format
Compatible with
evm --jsontrace format for easy diffing against geth/revm traces.Implementation Guide
lib/eevm/tracer.ex— trace collector (functional, no GenServer)tracerfield to MachineState —nil(disabled) or%Tracer{}Executor.step/1— before each opcode, record trace entry if tracer enabledEEVM.execute/3variant that accepts trace optionsTracer.to_json/1for geth-compatible formatAcceptance Criteria
Reference
--jsontrace formatTracerEip3155