Preserving censorship resistance for BAL data in EIP-7999

EIP-7999 separates data from EVM execution gas and treats data as an unconditional resource under FOCIL: a builder may not omit an inclusion-list transaction merely because the block’s data resource is full. This works because each IL is limited to 8 KiB of serialized transactions. EIP-8279, which can be incorporated in EIP-7999, specifies a single data resource consisting of both calldata and EIP-7928 BAL data. The existing IL size bound is then no longer sufficient. This post proposes a simple way to preserve unconditional data CR without executing omitted transactions.

The problem

The original censorship-resistance design for calldata in EIP-7999 relied on each of the sixteen ILs being limited to 8 KiB, meaning that all ILs together could contain at most 128 KiB of serialized transactions. This bound is sufficient when the data resource covers only transaction content, but not once it also covers BAL data generated during execution. A very small transaction can read thousands of distinct storage slots or call an existing factory that generates and deploys a large contract. The final runtime code does not need to appear in the transaction: short initcode can construct it during execution, while EIP-7928 records the full deployed bytecode in the BAL. Under the proposed EIP-7954, each deployed contract is limited to 64 KiB of runtime code, with a separate 128 KiB initcode limit. The 64 KiB limit applies per deployed contract, however, not per transaction: one transaction can deploy multiple contracts and produce other BAL entries. A small IL transaction can therefore consume much more data than its serialized size indicates.

Cold storage reads show when this becomes relevant even without contract creation. Under the proposed EIP-8038 gas schedule, a cold SLOAD costs 2,100 execution gas and adds a 32-byte storage key to the BAL. As an example, a uniform price of 16 data gas per byte and a 60M data-gas limit would correspond to 3,750,000 bytes, or 3.576 MiB, of metered transaction-attributable data. After reserving the maximum 128 KiB of transaction content for the ILs, a block filled with distinct cold reads would then exhaust the remaining data capacity at approximately:


(3,750,000 - 16 × 8,192) × 2,100 / 32 ≈ 237M execution gas

This ignores transaction and loop overhead, so the practical threshold would be somewhat higher. Contract creation creates issues at lower gas limits because a compact transaction can generate a large amount of runtime bytecode. Actual BAL usage cannot safely determine CR eligibility, because validators would then have to execute transactions omitted from the block, and the result could also depend on transaction ordering and state.

Simple solution

A recent post outlined various designs for EVM gas accounting in EIP-7999. We note here that the designs that enforce a transaction data byte limit allow for the most trivial solution. The transaction’s worst-case data consumption is then known before execution and the block’s transaction data capacity can be divided among the sixteen ILs:


IL_DATA_BYTE_LIMIT = BLOCK_TRANSACTION_DATA_BYTE_LIMIT // IL_COMMITTEE_SIZE

Under the previously specified limit, this gives each IL 234,375 bytes, or approximately 228.9 KiB. An IL is valid only if it satisfies the existing 8 KiB serialized-size limit and the sum of its transactions’ data_byte_limit values does not exceed this allowance. Any capacity not actually consumed by IL transactions remains available for normal block building.

The rule operates on declared limits rather than actual consumption, and since fees are ultimately charged on consumed bytes, declaring far more data than a transaction uses is nearly free. However, the data allowance binds before the serialized-size limit only if the IL’s transactions declare, on average, more than roughly 29 data bytes per serialized byte (in the hypothetical block limit above), whereas ordinary transactions declare within a small multiple of their serialized size. An includer would therefore have to admit several conspicuously padded transactions or a single extreme outlier, and includers remain free to simply pass over such transactions.

Every transaction admitted to a valid IL consequently receives unconditional data CR, subject to the existing conditional execution-gas requirement. A 229 KiB allowance comfortably covers any single-contract deployment permitted by EIP-7954’s proposed 64 KiB runtime-code limit, together with substantial additional BAL data. It does not literally cover every conceivable transaction since a transaction could deploy several large contracts or otherwise generate more than 229 KiB, but such unusually data-heavy operations could be split across transactions or included normally without an IL guarantee. In practice, the rule should preserve CR for essentially all ordinary transactions.

1 Like