Sequencer-Defined Metering
Table of Contents
- Overview
- Activation
- Payload Schema (Version 1)
- Transaction Classification
- Gas Refund Semantics
- Canonical Gas
- Settlement
- Producer and Verifier
- Receipt Extension
- Backwards Compatibility
- Security Considerations
Overview
Sequencer-Defined Metering (SDM) is the version-1 post-exec payload schema. It lets the sequencer attach per-transaction gas refunds to a block. Each refund lowers the gas a transaction is charged for and rebalances the fees it already paid.
Refund data is carried by a post-exec transaction (0x7D) appended to the block as its final
transaction. The post-exec envelope and structural rules are specified in post-exec.md; this
document specifies the version-1 payload and how clients apply the included refunds.
Activation
SDM activates with the Lagoon network upgrade and is gated by the Lagoon activation timestamp. When SDM is active for a block, the block MAY contain a post-exec transaction; when SDM is inactive, the block MUST NOT contain a post-exec transaction (see post-exec.md § Block-Level Structural Rules).
Before the Lagoon activation timestamp, every block MUST be produced and validated with SDM inactive, identically to a chain that has never specified SDM.
Payload Schema (Version 1)
When version = 1, the post-exec payload is RLP-encoded as:
[version, blockNumber, gasRefundEntries]
| Field | Type | Description |
|---|---|---|
version | uint8 | MUST be 1. |
blockNumber | uint64 | The L2 block number containing this payload (see post-exec.md § Block Number). |
gasRefundEntries | list<SDMGasEntry> | Non-zero per-transaction gas refunds. |
SDMGasEntry
Each entry in gasRefundEntries is an RLP list of two fields:
| Field | Type | Description |
|---|---|---|
index | uint64 | Transaction index within the block (zero-based). |
gasRefund | uint64 | Gas refund for the transaction at index. |
Validity Rules
A version-1 payload is invalid if any of the following hold:
gasRefundEntriesis empty.- Any
SDMGasEntryhasgasRefund == 0. - Entries are not ordered by strictly increasing
index. - Any entry's
indexdoes not refer to a standard Ethereum transaction in the block.
The envelope-level rules in post-exec.md § Block-Level Structural Rules apply in addition to the rules above. As long as SDM is the only active payload schema: if the sequencer assigns no gas refunds, the block has no post-exec transaction.
Transaction Classification
Every transaction in the block is classified as exactly one of:
| Kind | Source | May have refund? |
|---|---|---|
| A standard Ethereum transaction. | Yes | |
Deposit | A deposited transaction (type 0x7E). | No |
PostExec | The post-exec transaction (type 0x7D). | No |
Deposits buy gas on L1 and have no L2-side gas-price to refund. The post-exec transaction carries SDM data only; it charges no fees, consumes no gas and is not executed as code.
Gas Refund Semantics
For each standard Ethereum transaction at index i, define refund(i) as:
- the
gasRefundvalue in the payload entry whoseindex == i, if one exists; otherwise 0.
The refund value is sequencer-defined block data. Clients use the included value directly when executing and validating the block.
Refund policy. The sequencer chooses refunds with a refund policy. A refund policy is not a consensus rule: consensus constrains
refund(i)only through the validity rules andrefund(i) <= evmGasUsed(i). Verifiers do not run the policy, and a block whose refunds differ from it is still valid.
Canonical Gas
Canonical gas is the gas a standard Ethereum transaction is accounted for under SDM: the gas the EVM
reports minus the SDM refund applied to it. It is the value written to receipts and summed into the block's
cumulativeGasUsed and gasUsed, as distinct from evmGasUsed (the raw gas the EVM reports before any SDM
adjustment). It is unrelated to the "canonical chain" sense of canonical used elsewhere in these specs.
For each standard Ethereum transaction at index i:
evmGasUsed(i)is the gas used reported by the EVM, before any SDM adjustment: gas spent minus the EIP-3529-capped refund, but at least the EIP-7623 floor.refund(i)MUST be less than or equal toevmGasUsed(i).canonicalGasUsed(i) = evmGasUsed(i) - refund(i).
If refund(i) > evmGasUsed(i) for any transaction, the entire block is invalid. A verifier MUST NOT clamp the
refund, skip the offending entry, or otherwise apply the rest of the payload. Unlike the
validity rules, this bound cannot be checked by decoding the payload alone: evmGasUsed(i) is
known only once transaction i has executed, so the check is made then, before its settlement.
The receipt of transaction i reports canonicalGasUsed(i) as its gas-used field. The block's cumulativeGasUsed
and gasUsed are computed using canonicalGasUsed for standard Ethereum transactions and evmGasUsed for Deposit
transactions. The post-exec transaction contributes zero gas (see post-exec.md § Receipt).
Block Gas Limit
The block gas limit bounds pre-refund gas, not canonical gas. Before executing transaction i, a verifier MUST check
gasLimit(i) <= blockGasLimit - sum(evmGasUsed(j) for every transaction j < i in the block)
where evmGasUsed(j) is the gas used reported by the EVM for transaction j before any SDM adjustment, for
Deposit and standard Ethereum transactions alike. A transaction that fails this check invalidates the block.
Because evmGasUsed(j) >= canonicalGasUsed(j), this check implies the usual check against the block's canonical
gasUsed, and the two are identical when a block carries no refunds. SDM refunds therefore lower the gas the
header reports, but they cannot admit more execution into a block than its gas limit allows.
Settlement
Because the EVM initially charges fees using evmGasUsed(i), SDM applies a balance settlement for every standard
Ethereum transaction with refund(i) > 0.
Per-Recipient Deltas
Let r = refund(i), p be the transaction's EIP-1559 effective gas price, b be the block's base fee, and let
operatorFee(g) be the operator fee charged by the L1Block precompile for gas usage g at the active spec
(post-Isthmus).
| Recipient | Adjustment | Amount |
|---|---|---|
Sender (tx.from) | credit | r * p + (operatorFee(evmGasUsed) - operatorFee(canonicalGasUsed)) |
| Block beneficiary | debit | r * (p - b) |
| Base fee vault | debit | r * b |
| Operator fee vault (post-Isthmus) | debit | operatorFee(evmGasUsed) - operatorFee(canonicalGasUsed) |
The sender credit equals the sum of the recipient debits: r * (p - b) + r * b = r * p. This identity relies on
p >= b, which holds for every transaction that can be included: an EIP-1559 transaction has
p = b + min(maxPriorityFeePerGas, maxFeePerGas - b) >= b, and a legacy transaction must have gasPrice >= b to
be included. Hence p - b >= 0, so the beneficiary debit is never negative; at the boundary p = b (e.g. a legacy
transaction whose gas price equals the base fee) the priority tip — and therefore the beneficiary debit — is zero.
The L1 fee vault is not adjusted: L1 cost is independent of L2 gas usage.
Application Rules
Settlement is applied after the transaction's EVM frame finishes and before the transaction state delta is committed. It is atomic with the transaction and does not produce a separate receipt.
If any debit would underflow, the block is invalid. For any payload that respects refund(i) <= evmGasUsed(i),
this cannot occur, because each recipient was just paid the corresponding amount by the EVM in the same
transaction; an underflow therefore indicates a malformed or adversarial payload rather than a reachable state of
honest execution.
The converse does not hold: the underflow check is no substitute for the refund(i) <= evmGasUsed(i) bound. The
debited balances include fees accumulated over earlier transactions and blocks, so a refund that exceeds the bound
would typically settle with no underflow, transferring those accumulated fees to the sender. The bound is
enforced separately, as specified in Canonical Gas.
Producer and Verifier
Under SDM:
- The sequencer executes the block, chooses the non-zero
gasRefundEntries, and appends a post-exec transaction if and only if the entry list is non-empty. - A verifier enforces the post-exec envelope rules and the SDM validity rules, then applies the
refunds from the payload when computing canonical gas, settlement, receipts, and block gas usage. As it executes
each standard Ethereum transaction, it also enforces
refund(i) <= evmGasUsed(i); a violation invalidates the block (see Canonical Gas).
A sequencer MAY guard against a refund policy that produces a refund above evmGasUsed(i), for example by
dropping that refund before building the payload. Such a safeguard is producer behavior, not a consensus rule:
verifiers judge only the payload the sequencer actually includes.
Receipt Extension
The post-exec transaction's own receipt carries no SDM-specific fields (see post-exec.md § Receipt).
The JSON-RPC receipts returned for standard Ethereum transactions are extended with a single additional field:
| Field | Type | Description |
|---|---|---|
opGasRefund | Quantity (uint64) or null | The SDM gas refund credited to the transaction, or null when SDM was inactive for the block or the transaction had no refund. |
The value is sourced from the embedded post-exec payload's gasRefundEntries for the transaction's index.
opGasRefund is not part of the receipt's RLP encoding and is not committed to the receipts trie. Because it is
an additional JSON-RPC field outside the consensus receipt, existing receipt tooling that ignores unknown fields
(e.g. cast receipt) is unaffected; only consumers that opt in observe it.
Backwards Compatibility
Before the Lagoon activation timestamp, blocks are produced and validated identically to a chain that has never specified SDM: no post-exec transactions appear, no canonical-gas adjustment is performed, and no settlement runs.
From the Lagoon activation timestamp, two changes become observable:
- A
0x7Dtransaction may appear at the end of any block produced after activation, exposed through the same transaction-list interfaces used today. - The receipts of standard Ethereum transactions in such blocks gain the
opGasRefundfield; clients that ignore unknown fields are unaffected.
Mempool and transaction-pool interfaces are unchanged: post-exec transactions are not user-submittable and do not propagate over the public transaction-gossip protocol.
Security Considerations
Sequencer-defined amounts. Refund amounts are part of the sequencer's block data. The only consensus-defined
constraints are on their encoding, their target transaction (standard Ethereum transactions only), and the application bounds
(refund(i) <= evmGasUsed(i) and no settlement underflow); otherwise the sequencer has complete freedom to
allocate refunds according to arbitrary policy.
Cross-block replay. The post-exec transaction's blockNumber field anchors each payload to its containing
block. A payload from one block re-injected into another fails the envelope blockNumber check.
Excessive refunds. A refund above evmGasUsed(i) invalidates the block. This bound, not the settlement underflow
check, is what stops a payload from paying senders out of fees accumulated in the fee vaults.
Settlement underflow. Any settlement debit underflow invalidates the block.
Block resource limit. Refunds do not free block capacity. The block gas limit applies to
pre-refund evmGasUsed, so a sequencer cannot use refunds to fit more execution or calldata into a block than the
gas limit allows. This also preserves the resource bound of the EIP-7623 floor, which is part of evmGasUsed.