Skip to main content

Crate evm_fork_cache

Crate evm_fork_cache 

Source
Expand description

Forked EVM simulation engine for EVM search, MEV, and backtesting.

evm-fork-cache simulates EVM transactions against recent on-chain state without re-deriving that state on every call. It builds on revm, alloy, and foundry-fork-db to provide a lazy-loading state cache, immutable snapshots shareable across threads, per-simulation overlays, a freshness control plane, and the state-manipulation helpers a search loop needs (balance overrides, batched multicalls, Foundry-style bytecode etching, CREATE3 address derivation, and an extensible revert decoder).

§The state stack

Reads flow up; the fork DB lazily fetches misses from RPC. Writes and purges are applied directly to the cache (no RPC on the hot path).

EvmOverlay × N      isolated, Send simulations (cheap Arc clones)
     ▲ clone × N
EvmSnapshot         immutable, point-in-time, Send + Sync
     ▲ create_snapshot()
EvmCache            lazy RPC fetch + local state cache + targeted writes/purge
     ▲ lazy fetch
RPC provider

The entry point is cache::EvmCache: construct one over an RPC backend (see cache::EvmCacheBuilder), then snapshot it with cache::EvmCache::create_snapshot to fan out parallel simulations, each driving its own cache::EvmOverlay. EvmCache is !Send (it owns the mutable fork and blocks on RPC internally); EvmSnapshot is Send + Sync and EvmOverlay is Send, so the fan-out parallelizes safely.

§Modules

  • cache — the fork cache, snapshots, overlays, and on-disk persistence.
  • access_list / access_set — EIP-2930 access-list construction and EIP-2929 warm-slot tracking for gas estimation.
  • errors — structured simulation errors (errors::SimError) and an extensible revert-reason decoder you can teach your own custom Solidity error selectors.
  • freshness — the four-layer freshness model (classification, observation, policy, mechanism) and the optimistic verify-and-rerun execution loop with deferred validation.
  • state_update — the generic state-mutation vocabulary (StateUpdate / AccountPatch / PurgeScope, plus relative SlotDelta read-modify-write and masked SlotMasked writes) applied by EvmCache::apply_update / apply_updates / modify_slot, with a structured StateDiff output (Pillar B.1).
  • events — the event → state pipeline (Pillar B.2): EventDecoder / StateView / DecoderRegistry decode an on-chain Log into StateUpdates, and EventPipeline ingests, reorg-purges, and reconciles a block’s logs. Ships an ERC-20 Transfer decoder plus traits for external decoders.
  • reactive — default-enabled provider-neutral handler runtime for logs, blocks, and pending transaction signals. Pure handlers emit StateUpdates, invalidations, resync requests, speculative signals, and hooks; the runtime validates and applies canonical cache mutations, journals canonical block effects for depth-bounded reorg recovery, and includes a live AlloySubscriber (WebSocket) transport.
  • cold_start — default-enabled (reactive-gated) declarative warming of a working set of accounts/slots into the cache in one batched pass (EvmCache::run_cold_start + ColdStartPlanner), returning a structured ColdStartRunReport.
  • bundle — multi-transaction bundle execution over cumulative block state (EvmOverlay::simulate_bundle): ordered txs, an Atomic/AllowReverts revert policy, and coinbase/miner-payment accounting.
  • inspector — an Inspector that captures ERC20 Transfer events to reconstruct balance deltas from a simulation.
  • tracing — a call-frame Inspector (CallTracer building a CallTrace tree) plus InspectorStack for composing several inspectors over one pass, driven through EvmOverlay::call_raw_with_inspector.
  • multicall — batched read-only calls through Multicall3.
  • deploy / create3 — contract deployment and CREATE3 address math.
  • prefetch_registry — two-stage storage-slot pre-warming.

§Requirements

Any constructor or method that may touch RPC fetches missing state through a synchronous façade over an async provider (tokio::task::block_in_place), so it must run on a multi-thread tokio runtime:

#[tokio::main(flavor = "multi_thread")]
async fn main() { /* ... */ }

#[tokio::test(flavor = "multi_thread")]
async fn my_test() { /* ... */ }

Running on a current-thread runtime panics when a fetch is attempted. The offline examples and integration tests build the cache over a mocked provider and never reach the network, so they are exempt.

§Error handling

Simulation entry points that distinguish failure modes return errors::SimulationResult (Result<T, SimError>), where SimError separates a decoded Revert, an EVM Halt, and an unexpected host-side Other error (RPC, database, ABI encoding). The freshness loop never silently trusts stale data: a transient RPC failure surfaces as freshness::Validation::Unverified so callers can retry rather than act on unverified results.

§Maturity & stability

This crate is pre-1.0 and developed against a phased roadmap (see docs/ROADMAP.md). Until 1.0, breaking changes may land in minor releases; each is recorded in the crate CHANGELOG.md. MSRV is Rust 1.88 (edition 2024).

The examples/ directory has runnable, documented walkthroughs of each module — offline ones that need no network, plus a few that fork real chain state over RPC. See the crate README for the full list.

Re-exports§

pub use access_set::StorageAccessList;
pub use bundle::BundleOptions;
pub use bundle::BundleResult;
pub use bundle::BundleTx;
pub use bundle::RevertPolicy;
pub use bundle::TxOutcome;
pub use cache::CallSimulationResult;
pub use cache::EvmCache;
pub use cache::EvmCacheBuilder;
pub use cache::EvmOverlay;
pub use cache::EvmSnapshot;
pub use cache::TxConfig;
pub use cold_start::ColdStartCall;
pub use cold_start::ColdStartCallResult;
pub use cold_start::ColdStartConfig;
pub use cold_start::ColdStartError;
pub use cold_start::ColdStartPin;
pub use cold_start::ColdStartPlan;
pub use cold_start::ColdStartPlanner;
pub use cold_start::ColdStartResults;
pub use cold_start::ColdStartRoundSummary;
pub use cold_start::ColdStartRunReport;
pub use cold_start::ColdStartStep;
pub use cold_start::RoundOutcome;
pub use events::erc20::Erc20TransferDecoder;
pub use events::BlockDigest;
pub use events::DecoderRegistry;
pub use events::EventDecoder;
pub use events::EventPipeline;
pub use events::ReconcileReport;
pub use events::ReorgConfig;
pub use events::StateView;
pub use freshness::AlwaysVerify;
pub use freshness::BlockClock;
pub use freshness::FreshnessClock;
pub use freshness::FreshnessController;
pub use freshness::FreshnessParams;
pub use freshness::FreshnessPolicy;
pub use freshness::FreshnessRegistry;
pub use freshness::NeverVerify;
pub use freshness::ObservationDriven;
pub use freshness::SimRequest;
pub use freshness::SlotChange;
pub use freshness::SlotFetch;
pub use freshness::SlotOutcome;
pub use freshness::SpeculativeSim;
pub use freshness::Validation;
pub use freshness::Validity;
pub use freshness::WallClock;
pub use reactive::ReactiveConfig;
pub use reactive::ReactiveHandler;
pub use reactive::ReactiveRuntime;
pub use state_update::AccountChange;
pub use state_update::AccountPatch;
pub use state_update::PurgeRecord;
pub use state_update::PurgeScope;
pub use state_update::SkippedAccountPatch;
pub use state_update::SkippedBalanceDelta;
pub use state_update::SkippedDelta;
pub use state_update::SkippedMask;
pub use state_update::SlotDelta;
pub use state_update::StateDiff;
pub use state_update::StateUpdate;
pub use tracing::CallKind;
pub use tracing::CallStatus;
pub use tracing::CallTrace;
pub use tracing::CallTracer;
pub use tracing::InspectorStack;

Modules§

access_list
EIP-2930 access list builder with L2 profitability accounting.
access_set
Compact account/storage touch sets captured from EVM execution.
bundle
Multi-transaction bundle simulation over cumulative block state, plus coinbase / miner-payment accounting (Phase 6 Track A+B).
cache
cold_start
Protocol-neutral cold-start sync for EvmCache.
create3
CREATE3 deployment-address derivation.
deploy
Helpers for deploying Foundry artifacts into an EvmCache.
errors
Simulation error types and revert-reason decoding.
events
Event → state pipeline (Pillar B.2 — the reader half of the event pipeline).
freshness
Freshness control plane and the optimistic verify-and-rerun execution loop.
inspector
ERC20 Transfer-event capture for reconstructing balance deltas.
multicall
Multicall3 batching support for EvmCache.
prefetch_registry
Generalized storage prefetch registry for EVM cache pre-warming.
reactive
Protocol-neutral reactive runtime for cache state effects.
state_update
Targeted state-mutation vocabulary and the structured diff it produces (Pillar B.1 — the writer half of the event → state pipeline).
tracing
Call-frame tracing and a composing inspector seam.