Skip to content

feat(core): record used state during execution#112

Open
MavenRain wants to merge 1 commit into
flashbots:mainfrom
MavenRain:feat/used-state-inspector
Open

feat(core): record used state during execution#112
MavenRain wants to merge 1 commit into
flashbots:mainfrom
MavenRain:feat/used-state-inspector

Conversation

@MavenRain

@MavenRain MavenRain commented Jul 8, 2026

Copy link
Copy Markdown

Motivation

Closes the design in #50: builders need to know the state each order reads
and writes so they can detect conflicts between orders and parallelize
block construction across orders that touch disjoint state.

Solution

Adds a UsedStateInspector (a revm Inspector) that records, per
execution:

  • first read and last write of each storage slot (SLOAD / SSTORE)
  • first balance read of each account (BALANCE / SELFBALANCE)
  • wei sent/received per account via internal value-bearing calls
  • created and self-destructed contracts

The signer nonce is modelled as a read/write of slot zero of the signer so
two transactions from the same signer are detected as conflicting.

Executable::execute attaches the inspector by default, and the resulting
UsedStateTrace is exposed via ExecutionResult::used_state(). For a
bundle the trace is aggregated over the transactions kept in the bundle
(reverted/discarded transactions are not folded in, since their state is
rolled back). This follows the "state trace inspector by default" cut
agreed in the issue thread; further inspector modularity can be layered on
later.

The implementation mirrors the used-state inspector already proven in rbuilder.

Note

This change was written with AI assistance (Claude), reviewed by me.

Add a UsedStateInspector EVM inspector that records the storage slots,
account balances and contract lifecycle changes an execution reads and
writes, exposed as a UsedStateTrace on ExecutionResult.

Executing a transaction or a bundle now attaches the inspector by
default, so builders can read ExecutionResult::used_state() to detect
conflicts between orders and parallelize block construction across orders
that do not touch the same state.

The signer nonce is modelled as a read and write of slot zero of the
signer account so two transactions from the same signer are detected as
conflicting. For a bundle the trace is the aggregate over the
transactions kept in the bundle.

Refs flashbots#50

Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
Copilot AI review requested due to automatic review settings July 8, 2026 03:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an EVM inspector to record “used state” (storage slot reads/writes, balance reads, value transfers, and contract create/selfdestruct events) during execution, and exposes that trace on ExecutionResult so downstream builders can detect conflicts and parallelize non-overlapping work.

Changes:

  • Introduces UsedStateInspector + UsedStateTrace and a SlotKey type to record accessed state during EVM execution.
  • Attaches the inspector by default when executing a transaction or bundle, and aggregates traces across kept bundle transactions.
  • Extends ExecutionResult with used_state() and adds tests validating nonce modeling + bundle aggregation.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
crates/core/src/payload/used_state.rs New inspector + trace structures for tracking touched storage/balances/transfers/lifecycle events.
crates/core/src/payload/mod.rs Wires the new used_state module and re-exports the public types.
crates/core/src/payload/exec.rs Attaches the inspector by default, stores the trace on ExecutionResult, and adds tests for nonce/bundle aggregation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +21 to +29
interpreter::{
CallInputs,
CallOutcome,
CreateInputs,
CreateOutcome,
Interpreter,
interpreter_types::Jumps,
},
},
Comment on lines +80 to +83
self
.written_slot_values
.extend(other.written_slot_values.clone());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants