What
ArcBlockAssembler::assemble_block (crates/evm/src/assembler.rs:85-90) reads the system
accounting slot that carries nextBaseFee from the state provider when the bundle state has no
change for it:
if value.is_none() {
value = input
.state_provider
.storage(SYSTEM_ACCOUNTING_ADDRESS, slot)
.unwrap_or(None)
}
storage() returns ProviderResult<Option<U256>>. unwrap_or(None) collapses a provider
error (database/trie read failure, closed transaction, etc.) into "slot not set", so block
assembly carries on, logs Gas value not found for block number: … and leaves extra_data empty.
Impact
extra_data is not optional for Arc blocks: validate_extra_data_base_fee
(crates/evm/src/executor.rs:267) rejects any block whose extra_data does not decode to the
computed nextBaseFee. So a transient provider failure on the proposer does not fail the build —
it produces a block that every validator rejects, and the only trace is a misleading
"Gas value not found" warning, while the real I/O error is dropped. Under a sustained storage
problem the node keeps proposing invalid blocks round after round instead of surfacing the error.
Suggested fix
Propagate the error instead of masking it:
value = input
.state_provider
.storage(SYSTEM_ACCOUNTING_ADDRESS, slot)
.map_err(BlockExecutionError::other)?;
(assemble_block already returns Result<_, BlockExecutionError>.) The "slot genuinely absent"
path (Ok(None)) keeps its current warning. A unit test can drive the mapping with an Err from a
provider mock and assert the assembler returns the error rather than a block with empty
extra_data.
Environment: main @ 2a3e8ab, reth v2.2.0.
(Opening as an issue first per CONTRIBUTING.md; happy to be assigned and submit the fix + test.)
What
ArcBlockAssembler::assemble_block(crates/evm/src/assembler.rs:85-90) reads the systemaccounting slot that carries
nextBaseFeefrom the state provider when the bundle state has nochange for it:
storage()returnsProviderResult<Option<U256>>.unwrap_or(None)collapses a providererror (database/trie read failure, closed transaction, etc.) into "slot not set", so block
assembly carries on, logs
Gas value not found for block number: …and leavesextra_dataempty.Impact
extra_datais not optional for Arc blocks:validate_extra_data_base_fee(
crates/evm/src/executor.rs:267) rejects any block whoseextra_datadoes not decode to thecomputed
nextBaseFee. So a transient provider failure on the proposer does not fail the build —it produces a block that every validator rejects, and the only trace is a misleading
"Gas value not found" warning, while the real I/O error is dropped. Under a sustained storage
problem the node keeps proposing invalid blocks round after round instead of surfacing the error.
Suggested fix
Propagate the error instead of masking it:
value = input .state_provider .storage(SYSTEM_ACCOUNTING_ADDRESS, slot) .map_err(BlockExecutionError::other)?;(
assemble_blockalready returnsResult<_, BlockExecutionError>.) The "slot genuinely absent"path (
Ok(None)) keeps its current warning. A unit test can drive the mapping with anErrfrom aprovider mock and assert the assembler returns the error rather than a block with empty
extra_data.Environment: main @
2a3e8ab, reth v2.2.0.(Opening as an issue first per CONTRIBUTING.md; happy to be assigned and submit the fix + test.)