# `EEVM.Interpreter.Journal`
[🔗](https://github.com/mw2000/eevm/blob/v0.1.0/lib/eevm/interpreter/journal.ex#L1)

Snapshot/commit semantics for nested EVM call frames.

When a child frame halts normally (`:stopped`), its mutations to the
parent's revertible fields are promoted; on any other halt they are
discarded and the parent observes the pre-call state.

Revertible fields (the `db` plus all of `substate`) participate in the
merge:

- `db` — the unified world database (accounts + storage)
- `substate.logs` — emitted log entries, newest first (child's ahead of parent's)
- `substate.accessed_addresses` — EIP-2929 access list
- `substate.accessed_storage_keys` — EIP-2929 access list
- `substate.created_addresses` — EIP-6780 set of contracts created in this tx
- `substate.selfdestructed_addresses` — accounts to delete when the tx ends
- `substate.touched_addresses` — EIP-161 cleanup set
- `frame.refund` — the gas refund counter. A child starts at 0, so on
  success its (possibly negative) counter is added to the parent's; on
  failure it is dropped.

The `tracer` and `substate.program_cache` are *not* revertible — trace
events and JUMPDEST analyses accumulate monotonically and are always
preserved across child boundaries regardless of the child's outcome.

## What this module does NOT cover

- Stack and memory: those are local to a frame and never propagate child
  → parent on success or failure.
- Gas accounting: returning the child's unused `child.gas` to the parent
  happens at the call site, not here, because the math depends on opcode-specific
  bookkeeping (e.g. CREATE's deposit cost).
- The `:db` override in CREATE: the success path replaces `child.db` with
  a post-deploy db that has the runtime code installed. Call sites apply
  that override after `merge_child_result/2`.

# `merge_child_result`

```elixir
@spec merge_child_result(
  EEVM.Interpreter.MachineState.t(),
  EEVM.Interpreter.MachineState.t()
) ::
  EEVM.Interpreter.MachineState.t()
```

Merge the result of a child frame back into its parent.

- On success (`status: :stopped`): the child's mutations to revertible
  fields are promoted into the parent. Logs are kept newest first, so the
  child's logs are prepended to the parent's in O(child) time, and the
  child's refund counter is added to the parent's.
- On any other halt: the parent's revertible fields are kept untouched.

In both cases the child's tracer state is propagated into the parent,
because tracing accumulates regardless of execution outcome.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
