Overview
Scroll is an EVM-compatible zkEVM L2 that posts its state roots to Ethereum. A follower node participates in the public mempool of transactions but doesn't participate in block building consensus — it tracks what's happening without being a sequencer.
This project wires up the modular reth stack to build exactly that: a node that syncs L1 state blazingly fast, then runs rollup sync in the background to track Scroll's state progression.
Why reth
reth (Paradigm's Rust Ethereum execution client) is designed for extensibility — it exposes its database, p2p layer, and execution pipeline as composable crates. Instead of forking a monolithic client, you can assemble exactly what you need.
For a follower node, this means:
- Using
reth's existing L1 sync pipeline as-is - Plugging in Scroll-specific rollup logic at the engine layer
- Reusing
alloy's type primitives and RPC client throughout
Architecture
L1 Ethereum
│
▼
reth L1 sync ──────────────────────► local chain state (MDBX)
│
▼
Rollup sync task (background)
│ - reads L1 ScrollChain contract events
│ - decodes batch commitments and state roots
▼
Scroll L2 state tracker
The rollup sync task runs as a background tokio task, querying the ScrollChain contract on L1 for CommitBatch and FinalizeBatch events, then correlating them against the local L1 chain state.
What's implemented
- Blazing fast L1 state sync via reth's pipeline
- Background rollup sync tracking batch commitment and finalization
- Monitoring public mempool transactions on Scroll L2
What I learned
Navigating the reth codebase is itself a skill — it's ~500k LOC and moves fast. The key insight is that reth's provider abstraction (DatabaseProvider, BlockchainProvider) separates read/write concerns cleanly, and almost everything you need is behind one of those traits.
The hardest part was the rollup sync: Scroll's batch format evolved across versions, so decoding calldata from commitBatch transactions required handling multiple encoding formats.