Lesson 21 — Custom payload builder — sequencer-mode block production
Question
Custom PayloadBuilder = sequencer-mode block production. Reth-as-sequencer (centralised L2) needs this. Read the customisation pattern.
Principle (minimum model)
- PayloadBuilder trait.
build_payload(attrs) -> Payload. Called by sequencer to mint a block. - Standard impl. Takes mempool txs; orders by gas price; builds block. Used by Eth nodes.
- Custom impl. Override to add: bundle txs from MEV searcher, drain pending fills (CLOB), system txs (L1 messages), priority queue (payment rail).
- Wire via NodeBuilder.
NodeBuilder::payload_builder(YourBuilder::default()). - Hot path. Called every 12 seconds (or your block time). Performance matters.
- Tests. Build a payload; assert it contains expected txs + system txs.
- Production examples. op-rbuilder (Flashbots) for OP Stack sequencers; Tempo's validators build blocks with its own payload builder (
tempoxyz/tempocrates/payload). - Sequencer mode = centralised. Trade-off: faster blocks vs decentralisation. Production L2s pick the trade-off explicitly.
Worked example + steps
Custom payload builder — sequencer-mode block production
For Ethereum mainnet, blocks are produced by validators running the consensus client and pulling proposed payloads from the execution client. For an L2 or any centralized-sequencer chain, the block-production model is different: the sequencer is the block producer, full stop. The payload builder is the component that knows how.
1. The trait surface
PayloadBuilder (and friends) is the slot in reth's NodeBuilder for "how to build a block." It takes:
- A parent block (where we're building from)
- Current chain state
- A pool of pending transactions
- A timestamp / slot
...and returns a built block (the "payload"). On mainnet, the validator's consensus client triggers this via the Engine API. On a sequencer L2, the sequencer triggers it directly.
2. Three production-relevant builders
The reth ecosystem has multiple payload builders to study:
| Builder | Where | Use case |
|---|---|---|
| Default Ethereum builder | crates/ethereum/payload/ (EthereumPayloadBuilder) | Mainnet validators |
| OP payload builder | rust/op-reth/crates/payload/ in ethereum-optimism/optimism (reth's crates/optimism/payload/ until Feb 2026) | OP Stack sequencer |
| op-rbuilder | flashbots/rbuilder | High-perf external block builder for OP Stack |
The first two are inside reth. op-rbuilder is a separate repo, more aggressive about MEV and ordering policy, and is the production builder several OP Stack chains use.
3. What an L2 builder does differently
Sequencer-mode block production typically:
- Force-includes deposit txs at the top of the block (from a known L1 oracle queue)
- Sorts the rest of the block by either FIFO (first-come-first-serve) or priority-fee
- Updates the L1 block oracle storage slot as the first state write
- Caps the block at the L2 gas limit (not the mainnet limit)
- Tags the block with the sequencer's signature (some L2s commit to sequencer identity)
Notice that several of these are not in the executor — they're in the builder. Why? Because the builder controls what goes into a block; the executor only runs what's in a block.
4. The MEV question
A sequencer that orders transactions can extract MEV in ways a validator can't (it has no consensus competitor inside its block).
Three positions a sequencer can take:
| Position | What it means | Examples |
|---|---|---|
| MEV-blind | Strict FIFO, no peeking into tx semantics | Some smaller L2s claim this |
| MEV-aware, public | Public order flow, builder accepts MEV-share-style bids | OP Stack with op-rbuilder |
| MEV-extracting | Sequencer runs internal searchers | (Often opaque; centralized chains can do whatever they want) |
The choice ends up in the payload builder's source code, gated by feature flags or external builder integrations. Reading a chain's payload builder is reading its MEV policy.
5. op-rbuilder — the production-grade reference
flashbots/rbuilder is the external builder Paradigm built for OP Stack. Worth studying because:
- It implements bundle merging (private order flow + public mempool)
- It supports sealing strategies (greedy, parallelizable algorithms)
- It exposes a builder API other parties can submit bundles to
- It's the closest thing in the open-source world to a "real" production block builder
Tempo does not use op-rbuilder (no rbuilder crate in its Cargo.toml); it ships its own builder in crates/payload/builder/.
6. For Tempo specifically
What the code in tempoxyz/tempo shows:
- A payment-aware payload builder (
crates/payload/builder/src/lib.rs): non-payment txs are capped by a separategeneral_gas_limit, so payment txs keep reserved block space — the "payment lanes" in the README. - Pool ordering by tip:
TempoTipOrdering(crates/transaction-pool/src/ordering.rs) orders by effective coinbase tip. - Pool admission checks: an
AddressFilterchecks senders and every direct call target, and a separate 2D-nonce sub-pool (tt_2d_pool.rs) handles Tempo transactions. - No sequencer: blocks come from a validator set running Simplex consensus (via Commonware,
crates/consensus/), and the testnet has a public RPC.
There is no merchant-authorization filter or per-merchant rate limiter in the builder or pool. Each component above is one trait impl wired into the node.
7. Practice
Open op-reth's rust/op-reth/crates/payload/ (in ethereum-optimism/optimism) and:
- Find the
PayloadBuildertrait impl - Trace how deposit txs get included at the top of the block
- Identify where the block gas cap is enforced
- Find the function that signs/seals the built block
Then read op-rbuilder's README for the "external builder" model.
Final check: in one sentence, what does the payload builder decide that the executor does not? If your answer doesn't include the word "ordering" or "selection," go back and re-read section 3.
Summary (3 lines)
- Custom PayloadBuilder = sequencer-mode block production. Override
build_payload. - Customisations: MEV bundles, CLOB fills, system txs, priority queue. Hot path; performance matters.
- Production: op-rbuilder (OP Stack sequencers, centralised; trade-off accepted) + Tempo's payload builder (L1 validators).