# Erigon / EIP-7928: pinned Amsterdam conformance review

Review date: 2026-10-27. **One conditional spec difference retained, with known design history; no new strong BAL-construction candidate identified.** The retained difference is a fixed 10 MiB decoder limit in addition to the specified gas-derived item limit. It matters only when a permitted block can produce a larger BAL. No client, fixture, node, RPC, transaction, or network experiment was run. This is a public-source review, not an execution result or a claim of race freedom.

## Scope and pins

The bounded item is Erigon's implementation of EIP-7928, with Reth as the comparison implementation. The broader goal's other client/EIP reviews are outside this item. Repository code was read from shallow clones or raw.githubusercontent.com; GitHub blob links below identify exact locations, rather than HTML pages used to read code.

| Source | Head pinned from the named commit API | Commit time (UTC) |
|---|---|---|
| erigontech/erigon `main` | [`f32a39d1e5f87a9ec3a9ce2858171c74acc3c242`](https://api.github.com/repos/erigontech/erigon/commits/main) | 2026-10-27T16:04:32Z |
| ethereum/execution-specs `forks/bogota` | [`7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b`](https://api.github.com/repos/ethereum/execution-specs/commits/forks/bogota) | 2026-10-27T17:40:55Z |
| paradigmxyz/reth `main` | [`e0378eb691aa2770bb96fd4ecec2f4445a2a3e7c`](https://api.github.com/repos/paradigmxyz/reth/commits/main) | 2026-10-27T12:11:23Z |
| ethereum/EIPs `master` | [`d4c575521d99ec881a444ab3af604e684b5f0743`](https://api.github.com/repos/ethereum/EIPs/commits/master) | 2026-10-27T16:04:29Z |
| ethereum/consensus-specs `master` | [`8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2`](https://api.github.com/repos/ethereum/consensus-specs/commits/master) | 2026-10-27T16:28:12Z |

The Erigon and Reth clone HEADs matched their API pins. All `E`, `S`, and `R` code citations below use those pins, not moving branches. Auxiliary EIP and consensus citations also use the pins above.

**Fork/spec version.** The pinned [Glamsterdam meta EIP](https://eips.ethereum.org/EIPS/eip-7773) schedules 2780, 7688, 7708, 7732, 7778, 7843, **7928**, 7954, 7976, 7981, 7997, 8024, 8037, 8038, 8045, 8061, 8246, and 8282. It lists networking and informational EIPs separately. Source: [EIPS/eip-7773.md#L21-L55](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7773.md#L21-L55). This inventory establishes context; it does not claim a version review of the other EIPs.

For this item, the current EIP-7928 prose is [the published EIP](https://eips.ethereum.org/EIPS/eip-7928), pinned as [EIPS/eip-7928.md#L1-L18](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7928.md#L1-L18). The EIPs head above is also the latest commit returned for that file, titled “Update EIP-7928: specify BAL integer encoding.” The executable reference is the Amsterdam package at the pinned `forks/bogota` head, specifically `block_access_lists.py`, `fork.py`, and `blocks.py`. Do not substitute Bogota's BAL module for Amsterdam's. The tests' recorded EIP reference is still `f834f0004aa5110a5f1ac0d6b80e3dc4b842d040`, not the newer EIPs head: [tests/amsterdam/eip7928_block_level_access_lists/spec.py#L14-L17](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip7928_block_level_access_lists/spec.py#L14-L17). That revision distinction is preserved here.

**Not live on mainnet.** The meta EIP has no Mainnet activation timestamp: [EIPS/eip-7773.md#L62-L70](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7773.md#L62-L70). Erigon's pinned mainnet chainspec contains no `amsterdamTime`: [execution/chain/spec/chainspecs/mainnet.json#L1-L52](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/chain/spec/chainspecs/mainnet.json#L1-L52); its EIP-7928 gate maps to Amsterdam: [execution/chain/chain_config.go#L137-L152](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/chain/chain_config.go#L137-L152). C1 concerns the new Amsterdam BAL payload path. No candidate in currently active Ethereum-mainnet execution logic is disclosed in this report.

## C1 — A canonical BAL larger than 10 MiB is rejected before its gas-derived item bound is considered

**Status:** retained spec-conformance difference; known intentional limit in a merged PR, rather than a newly discovered implementation mechanism. **Severity: valid block rejected.** Conditional on a sufficiently large permitted block gas limit; no such payload was executed in this review.

### 1. Specification, verbatim

[EIP-7928, Block Access List Size Constraint](https://eips.ethereum.org/EIPS/eip-7928#block-access-list-size-constraint):

> The block access list is constrained by the block gas limit rather than a fixed maximum number of items.

The rule is `bal_items <= block_gas_limit // ITEM_COST`, where items count addresses and storage keys, and `ITEM_COST = 2000`. The executable reference is:

[src/ethereum/forks/amsterdam/block_access_lists.py#L887-L892](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L887-L892)

```python
    if bal_items > block_gas_limit // GasCosts.BLOCK_ACCESS_LIST_ITEM:
        raise BlockAccessListGasLimitExceededError(
            f"Block access list exceeds gas limit, {bal_items} items "
            f"exceeds limit of "
            f"{block_gas_limit // GasCosts.BLOCK_ACCESS_LIST_ITEM}."
        )
```

Counting is in [src/ethereum/forks/amsterdam/block_access_lists.py#L871-L885](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L871-L885), and the constant is in [src/ethereum/forks/amsterdam/vm/gas.py#L138-L140](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L138-L140). No encoded-BAL byte bound is applied in this function or in the BAL construction/validation flow at [src/ethereum/forks/amsterdam/fork.py#L831-L850](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L831-L850).

The separate execution-block RLP size rule is applied to `rlp.encode(block)` at [src/ethereum/forks/amsterdam/fork.py#L291-L296](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L291-L296). `Block` contains header, transactions, ommers and withdrawals, not the BAL sidecar: [src/ethereum/forks/amsterdam/blocks.py#L299-L323](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/blocks.py#L299-L323). Thus the RLP block-size rule does not itself supply this missing BAL byte constraint.

### 2. Erigon implementation at the pin, verbatim

[execution/types/block_access_list.go#L191-L194](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L191-L194)

```go
const maxBlockAccessListBytes = 10 * 1024 * 1024

// EIP-7928: bal_items <= block_gas_limit / BalItemCost
const BalItemCost = 2000
```

[execution/types/block_access_list.go#L817-L821](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L817-L821)

```go
func decodeBlockAccessListBytes(data []byte, budget *blockAccessListDecodeBudget) (BlockAccessList, error) {
	if len(data) > maxBlockAccessListBytes {
		return nil, fmt.Errorf("block access list RLP exceeds maximum size (%d bytes)", len(data))
	}
	stream := rlp.NewStream(bytes.NewReader(data), 0)
```

This function is reached by `DecodeBlockAccessListSidecarForBlock` through the sidecar decoder: [execution/types/block_access_list.go#L65-L81](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L65-L81). In the Gloas-version Engine path, the error is converted to `INVALID` before execution:

[execution/engineapi/engine_server.go#L397-L405](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/engineapi/engine_server.go#L397-L405)

```go
		balBytes := *req.BlockAccessList
		blockAccessList, blockAccessListErr = types.DecodeBlockAccessListSidecarForBlock(balBytes, header.GasLimit, len(req.Transactions))
		if blockAccessListErr != nil && !errors.Is(blockAccessListErr, types.ErrInvalidBlockAccessList) {
			e.logger.Debug("[NewPayload] failed to decode blockAccessList", "err", blockAccessListErr, "raw", hex.EncodeToString(balBytes))
			return &engine_types.PayloadStatus{
				Status:          engine_types.InvalidStatus,
				ValidationError: engine_types.NewStringifiedErrorFromString(fmt.Sprintf("%v: decode failed: %v", types.ErrInvalidBlockAccessList, blockAccessListErr)),
			}, nil
		}
```

The byte-limit error is not wrapped as `ErrInvalidBlockAccessList`, so it takes exactly that early branch. The item budget is independently seeded from `gasLimit / BalItemCost`: [execution/types/block_access_list.go#L65-L71](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L65-L71). Later correct item checks do not undo the earlier rejection.

### 3. Divergent condition, in words only

An otherwise valid Amsterdam block has a canonical, correctly committed BAL whose encoded length exceeds 10,485,760 bytes, while its addresses plus unique storage keys remain within the block's gas-derived allowance. Submit its execution payload through the new Engine method. The reference executes it and checks the resulting hash and item count; Erigon returns `INVALID` at BAL decoding.

A concrete **static construction**, not an executed reproducer: a chain with an allowed parent and child gas limit of two billion, a funded transaction sender, and a small existing contract that reads storage keys. Include one hundred ordinary transactions, each reading four thousand distinct keys, with disjoint ranges across transactions. Choose keys whose minimal integer representation occupies 32 bytes; the slots may all hold zero. Each key alone then occupies 33 RLP bytes. Four hundred thousand such read keys require at least **13,200,000 bytes**, already greater than 10,485,760, before account and list overhead. They consume 400,000 storage items plus the small address/system-access set, below the **1,000,000-item** allowance. These are arithmetic lower bounds, not measurements of a generated BAL.

The cold storage read cost is 2,100; the per-transaction execution cap is 16,777,216: [src/ethereum/forks/amsterdam/vm/gas.py#L74-L80](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L74-L80) and [src/ethereum/forks/amsterdam/vm/gas.py#L151-L154](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L151-L154). Four thousand reads cost 8.4 million for the reads themselves, leaving room for a compact loop and intrinsic costs within a twelve-million transaction budget. One hundred such budgets total 1.2 billion, below the illustrative block limit. Small transaction calldata and loop bytecode need not make the execution block itself large. Parent/child gas-limit adjustment must also be satisfied; the reference allows equal sufficiently large parent/child limits in [src/ethereum/forks/amsterdam/fork.py#L1147-L1155](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L1147-L1155). This is **not** an assertion that current mainnet or a particular devnet has that gas limit.

Minimal-integer key encoding is specified in [EIP-7928, RLP Encoding](https://eips.ethereum.org/EIPS/eip-7928#rlp-encoding). The numeric size and allowance calculations above were checked locally with integer arithmetic; no client code was run.

### 4. Same rule in Reth at its pinned head

Reth's payload path decodes a supplied BAL and then enforces the gas-derived item limit, agreeing with the reference on the rule under review:

[crates/engine/tree/src/tree/payload_validator.rs#L577-L584](https://github.com/paradigmxyz/reth/blob/e0378eb691aa2770bb96fd4ecec2f4445a2a3e7c/crates/engine/tree/src/tree/payload_validator.rs#L577-L584)

```rust
        if let Some(decoded_bal) = decoded_bal.as_deref() {
            // Reject oversized BAL sidecars before executing the block.
            ensure_ok!(decoded_bal
                .as_bal()
                .validate_gas_limit(input.gas_limit())
                .map_err(ConsensusError::from));
        }

```

Its decode call is [crates/engine/tree/src/tree/payload_validator.rs#L2041-L2049](https://github.com/paradigmxyz/reth/blob/e0378eb691aa2770bb96fd4ecec2f4445a2a3e7c/crates/engine/tree/src/tree/payload_validator.rs#L2041-L2049). This delegates to `DecodedBal::from_rlp_bytes`; it does not introduce Erigon's 10 MiB BAL-specific check at this call site.

The dependency must be followed to substantiate that comparison: Reth's pinned [Cargo.lock#L253-L257](https://github.com/paradigmxyz/reth/blob/e0378eb691aa2770bb96fd4ecec2f4445a2a3e7c/Cargo.lock#L253-L257) resolves `alloy-eip7928` **0.4.11**, whose published crate records source commit `c66a2fab30d24e2a2a584e2a48019faa5f6938af` in `alloy-rs/eips`. The source downloaded from that exact raw GitHub commit matches the crate's inspected `block_access_list.rs`. It decodes to a vector-backed BAL and rejects trailing bytes, with no fixed 10 MiB check on this path: [crates/eip7928/src/block_access_list.rs#L56-L69](https://github.com/alloy-rs/eips/blob/c66a2fab30d24e2a2a584e2a48019faa5f6938af/crates/eip7928/src/block_access_list.rs#L56-L69) and [crates/eip7928/src/block_access_list.rs#L735-L753](https://github.com/alloy-rs/eips/blob/c66a2fab30d24e2a2a584e2a48019faa5f6938af/crates/eip7928/src/block_access_list.rs#L735-L753). Its bound is:

[crates/eip7928/src/block_access_list.rs#L407-L413](https://github.com/alloy-rs/eips/blob/c66a2fab30d24e2a2a584e2a48019faa5f6938af/crates/eip7928/src/block_access_list.rs#L407-L413)

```rust
        pub fn validate_gas_limit(&self, gas_limit: u64) -> Result<(), BlockAccessListGasError> {
            let items = self.total_bal_items();
            if items > gas_limit / crate::constants::ITEM_COST as u64 {
                return Err(BlockAccessListGasError::new(items, gas_limit));
            }
            Ok(())
        }
```

This comparison concerns BAL validation, not every transport restriction in Reth. Its default authenticated RPC construction permits 128 MiB requests at [crates/rpc/rpc-builder/src/auth.rs#L334-L346](https://github.com/paradigmxyz/reth/blob/e0378eb691aa2770bb96fd4ecec2f4445a2a3e7c/crates/rpc/rpc-builder/src/auth.rs#L334-L346), so the illustrative roughly 13.2 MB BAL is not defeated simply by that request-body limit, even allowing JSON hex expansion. End-to-end import was not demonstrated.

### 5. Confidence and attempted disproof

**High confidence in the extra rejection rule and its spec difference; medium confidence in the complete unexecuted block construction.** The source-level rejection is unconditional above the stated byte count. The remaining uncertainty is end-to-end construction and propagation, not the decoder's behavior.

Disproof attempts:

- **Was the historical cap removed?** Yes, the older 4 MiB/list-count restrictions were changed, but the current source still imposes 10 MiB. This is not a report of the removed 4 MiB constant.
- **Does the execution-block size rule imply the same bound?** No: the reference `Block` excludes the BAL. A large read-only BAL can accompany a small block body, as the reference's block schema and validation call above show.
- **Could item/gas or transaction caps make the condition impossible?** The read-key lower-bound construction separates byte size from item count and divides reads across transactions. It fits the illustrative item allowance and per-transaction budget. It was not filled or executed, so exact transaction gas and final list length remain unmeasured.
- **Is 10 MiB a consensus-layer container limit?** The pinned Gloas definition is a progressive list, with no 10 MiB type parameter:

[specs/gloas/beacon-chain.md#L413-L420](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L413-L420)

```python
### New `BlockAccessList`

```python
class BlockAccessList(ProgressiveList[Byte]):
    """
    The serialized block access list of an execution payload.
    """
```
```

  PR #24684 explicitly justifies Erigon's limit using devp2p and CL gossip message limits and an incompletely checked relay-to-CL-to-EL path. That is substantial counterevidence to ordinary network reachability, and is why this report does not claim a currently propagatable devnet split. It does not add a BAL byte-size rejection to the EL reference transition. The discrepancy remains relevant to direct Engine validation, future high-gas settings, or acceptance via another transport.

### 6. Severity and known-check

**Valid block rejected**, conditional as described. A split between validators with different rules is a possible consequence if such a payload reaches them; no observed split is claimed. There is no wrong-gas or wrong-state finding here.

**Known:** [Erigon issue #24670](https://github.com/erigontech/erigon/issues/24670), **closed**, reports the original hardcoded 4 MiB failure on a high-gas shadow fork. [PR #24684](https://github.com/erigontech/erigon/pull/24684), **closed and merged 2026-10-15**, deliberately retains a 10 MiB input cap while replacing other fixed limits with gas-derived budgets. This report identifies the surviving boundary, not a newly unindexed root cause. No separate issue specifically acknowledging the retained 10 MiB check as an EL-spec violation was found by the queries below.

Queries covered both issues and PRs, open and closed, by omitting state/type filters: `repo:erigontech/erigon 7928`; `repo:erigontech/erigon "block access list"`; `repo:erigontech/erigon "block-level access"`; `repo:erigontech/erigon "BAL" "10 MiB"`; and `repo:erigontech/erigon "BAL" "10" "limit"`. The first two searches were read through page 2. Numerical matches to unrelated issue numbers were discarded. Search and result URLs are recorded below.

For external known-checks, [execution-specs tracker #3217](https://github.com/ethereum/execution-specs/issues/3217), **open**, and the Glamsterdam devnet trackers (including [#3518](https://github.com/ethereum/execution-specs/issues/3518), **closed**) were read. The targeted search `repo:ethereum/execution-specs "Test Release Tracker" "BAL" "size"` returned #3217; no specific 10 MiB boundary result was identified in the inspected tracker bodies or latest tracker comments. **Hive status: unverified** — the required [listing.jsonl](https://hive.ethpandaops.io/glamsterdam/listing.jsonl) returned HTTP 403 on direct retrieval and was also inaccessible through the web tool. No pass/fail result, affected build, or absence of a known Hive failure is inferred from that failure.

## Rules checked: no discrepancy identified at the pin

“Correct” below means the inspected source implements the stated rule; it is not certification of every execution path. The byte limit is excluded from this table because it is C1. No test file cited here was executed.

| Rule checked | Spec source | Erigon source and static result |
|---|---|---|
| Shared post-execution index; withdrawals precede dequeues | [src/ethereum/forks/amsterdam/fork.py#L831-L840](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L831-L840) | [execution/protocol/rules/merge/merge.go#L183-L204](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/rules/merge/merge.go#L183-L204) and [execution/exec/block_assembler.go#L415-L447](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/exec/block_assembler.go#L415-L447): one finalization context covers the withdrawal and syscall work; the BAL is built after it. |
| Slot restored to its index-start value by a later system call | [src/ethereum/forks/amsterdam/block_access_lists.py#L747-L776](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L747-L776) and [src/ethereum/forks/amsterdam/block_access_lists.py#L813-L824](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L813-L824) | [execution/state/intra_block_state.go#L3380-L3408](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/intra_block_state.go#L3380-L3408), [execution/state/versionedio.go#L3032-L3043](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3032-L3043), [execution/state/versionedio.go#L3148-L3164](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3148-L3164): repeated writes replace the recorded final value; net-zero final writes are suppressed against the first read or previous surviving write. See detailed disproof below. |
| Withdrawal credit fully forwarded away at the same post index | [src/ethereum/forks/amsterdam/block_access_lists.py#L784-L792](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L784-L792) | [execution/protocol/rules/merge/merge.go#L183-L204](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/rules/merge/merge.go#L183-L204), [execution/state/intra_block_state.go#L3177-L3195](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/intra_block_state.go#L3177-L3195), [execution/state/versionedio.go#L3053-L3087](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3053-L3087): one final balance per address reaches the builder; unchanged balances are omitted, addresses remain accessed. |
| Earlier-index changes survive a later no-op or restoration at another index | [src/ethereum/forks/amsterdam/block_access_lists.py#L516-L540](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L516-L540) and [src/ethereum/forks/amsterdam/block_access_lists.py#L813-L824](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L813-L824) | [execution/state/versionedio.go#L3032-L3043](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3032-L3043) and [execution/state/versionedio.go#L3148-L3164](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3148-L3164): a value different from the last surviving write appends at the current index; equality suppresses only the new no-op. It does not delete an earlier change. |
| Destroyed/recreated account's wiped storage still registers reads | [src/ethereum/forks/amsterdam/state_tracker.py#L252-L286](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/state_tracker.py#L252-L286) and [src/ethereum/forks/amsterdam/block_access_lists.py#L708-L724](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L708-L724) | [execution/state/read_paths.go#L365-L416](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/read_paths.go#L365-L416): the wiped-storage path explicitly records `SetStorage` with zero and the destructor version, in addition to the lifecycle dependency. BAL extraction visits storage reads at [execution/state/versionedio.go#L2734-L2745](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L2734-L2745). This addresses the historical #23407/#23541 mechanism. |
| Same-transaction destruction drops nonce/code writes; touched storage remains represented | [src/ethereum/forks/amsterdam/state_tracker.py#L494-L540](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/state_tracker.py#L494-L540) and [src/ethereum/forks/amsterdam/block_access_lists.py#L784-L824](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L784-L824) | [execution/state/versionedio.go#L1259-L1338](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L1259-L1338): finalize zeros same-transaction created/destroyed storage and snapshot suppresses destroyed-account nonce/code writes. The storage/no-op and read collectors above then determine read representation. EIP-8246 balance preservation is respected; no obsolete burn rule was imposed. |
| Maximum BAL nonce is uint64, including the maximum value | [src/ethereum/forks/amsterdam/block_access_lists.py#L104-L119](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L104-L119) | [execution/types/block_access_list.go#L609-L631](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L609-L631): `Uint64()` accepts a canonical 8-byte maximum, unlike a narrower/signed decoder. Index separately checked as uint32. Sender/CREATE overflow prevention occurs before target access at [execution/protocol/txn_executor.go#L257-L271](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/txn_executor.go#L257-L271) and [execution/vm/evm.go#L618-L637](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/vm/evm.go#L618-L637); a BAL post-nonce maximum is distinct from permitting another increment. |
| Zero-value and self transfers: touched address retained, net-zero balance omitted | [src/ethereum/forks/amsterdam/state_tracker.py#L606-L660](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/state_tracker.py#L606-L660) and [src/ethereum/forks/amsterdam/block_access_lists.py#L784-L792](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L784-L792) | [execution/protocol/misc/eip7708.go#L53-L68](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/misc/eip7708.go#L53-L68), [execution/state/intra_block_state.go#L1123-L1129](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/intra_block_state.go#L1123-L1129), [execution/state/versionedio.go#L3053-L3087](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3053-L3087) and [execution/state/versionedio.go#L2856-L2862](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L2856-L2862): transfer touches and typed/access-only reads feed the BAL; balance filtering removes no-ops. |
| Coinbase with zero fee versus genuinely unaccessed coinbase | [src/ethereum/forks/amsterdam/block_access_lists.py#L784-L792](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L784-L792) plus [EIP-7928 normative edge cases](https://eips.ethereum.org/EIPS/eip-7928#edge-cases-normative) | [execution/protocol/txn_executor.go#L753-L769](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/txn_executor.go#L753-L769) still calls fee accounting for a zero tip; [execution/state/intra_block_state.go#L1123-L1129](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/intra_block_state.go#L1123-L1129) touches it without inventing a balance delta. Empty Ethereum PoS blocks have no block reward entries, [execution/protocol/rules/merge/merge.go#L148-L155](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/rules/merge/merge.go#L148-L155). |
| Non-minimal RLP scalars rejected, not silently normalized | [EIP-7928 RLP encoding](https://eips.ethereum.org/EIPS/eip-7928#rlp-encoding); the executable BAL shape uses numeric slots/values | [execution/types/block_access_list.go#L529-L546](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L529-L546), [execution/types/block_access_list.go#L569-L586](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L569-L586), [execution/types/block_access_list.go#L609-L631](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L609-L631), [execution/types/block_access_list.go#L956-L963](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L956-L963) use canonical `Uint64`/`ReadUint256`; [execution/rlp/decode.go#L1027-L1060](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/rlp/decode.go#L1027-L1060) rejects leading-zero uint256 input. Historical fix #21879 is present. |
| Deterministic address/slot/index ordering and uniqueness | [src/ethereum/forks/amsterdam/block_access_lists.py#L625-L687](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L625-L687) | [execution/state/versionedio.go#L2866-L2901](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L2866-L2901) sorts addresses; [execution/types/block_access_list.go#L429-L461](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L429-L461) normalizes fields. Received lists are validated rather than repaired: [execution/types/block_access_list.go#L973-L992](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L973-L992) and [execution/types/block_access_list.go#L1058-L1143](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L1058-L1143). |
| Reject duplicate indexes, empty slot-change lists, overlapping read/write slots, and indexes above n+1 | [src/ethereum/forks/amsterdam/block_access_lists.py#L625-L687](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L625-L687); [EIP-7928 ordering and uniqueness](https://eips.ethereum.org/EIPS/eip-7928#ordering-uniqueness-and-determinism) | [execution/types/block_access_list.go#L1005-L1040](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L1005-L1040) bounds indexes, [execution/types/block_access_list.go#L1058-L1143](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L1058-L1143) checks overlap and strict ordering. Decode with a block budget also checks early, [execution/types/block_access_list.go#L896-L913](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L896-L913). |
| Header commits to canonical BAL, including an actually empty BAL | [src/ethereum/forks/amsterdam/blocks.py#L251-L261](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/blocks.py#L251-L261), [src/ethereum/forks/amsterdam/block_access_lists.py#L850-L856](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L850-L856), [src/ethereum/forks/amsterdam/fork.py#L349-L358](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L349-L358) | [execution/types/block_access_list.go#L966-L970](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L966-L970) uses the empty constant at [common/empty/empty_hashes.go#L49-L50](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/common/empty/empty_hashes.go#L49-L50): `1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347`. [execution/bal/process.go#L85-L112](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/bal/process.go#L85-L112) checks supplied bytes and computed hash against the header, including when a stored sidecar is absent. An empty transaction list does not imply an empty BAL: system accesses still count. |
| First Amsterdam block requires BAL header field; pre-fork block forbids it | [src/ethereum/forks/amsterdam/fork.py#L165-L186](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L165-L186), [src/ethereum/forks/amsterdam/blocks.py#L251-L261](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/blocks.py#L251-L261) and [tests/amsterdam/eip7928_block_level_access_lists/test_fork_transition.py#L171-L217](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip7928_block_level_access_lists/test_fork_transition.py#L171-L217) | [execution/protocol/rules/merge/merge.go#L391-L409](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/rules/merge/merge.go#L391-L409) gates presence using the current header time, without waiting for an Amsterdam parent. [execution/chain/chain_config.go#L137-L152](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/chain/chain_config.go#L137-L152) supplies the Amsterdam EIP gate. Builder records BAL on that block at [execution/exec/block_assembler.go#L126-L139](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/exec/block_assembler.go#L126-L139). |
| Item limit: count addresses plus distinct slots, floor division, equality allowed | [src/ethereum/forks/amsterdam/block_access_lists.py#L859-L892](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L859-L892) | [execution/types/block_access_list.go#L1042-L1056](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L1042-L1056) rejects only `items > maxItems`; prior validation excludes duplicated/overlapping keys. Header-aware decode consumes the same item budget at [execution/types/block_access_list.go#L65-L71](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L65-L71) and [execution/types/block_access_list.go#L201-L209](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/types/block_access_list.go#L201-L209). C1 is the separate byte limit. |
| Pre-state gas checks occur before recording SSTORE slot access | [EIP-7928 gas-validation rule](https://eips.ethereum.org/EIPS/eip-7928#gas-validation-before-state-access) | [execution/vm/operations_acl.go#L35-L99](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/vm/operations_acl.go#L35-L99) checks the stipend sentry and warm/cold access cost before `GetState`; insufficient access gas returns before the slot read. CALL stateless checks similarly precede stateful lookup at [execution/vm/operations_acl.go#L323-L363](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/vm/operations_acl.go#L323-L363). This is a targeted ordering check, not a full gas audit. |
| Index mapping and parallel publication determinism mechanisms | [src/ethereum/forks/amsterdam/fork.py#L831-L834](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L831-L834) and [src/ethereum/forks/amsterdam/block_access_lists.py#L625-L687](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L625-L687) | [execution/state/versionmap.go#L2032-L2034](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionmap.go#L2032-L2034) maps internal index -1 to BAL 0 and final index n to BAL n+1. [execution/stagedsync/exec3_parallel.go#L3548-L3584](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/stagedsync/exec3_parallel.go#L3548-L3584) replaces attempt IO and removes dropped writes; [execution/stagedsync/exec3_parallel.go#L671-L680](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/stagedsync/exec3_parallel.go#L671-L680) feeds the builder in index order. Finalize syscalls share one recorder at [execution/stagedsync/exec3_parallel.go#L3787-L3842](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/stagedsync/exec3_parallel.go#L3787-L3842). Race freedom and reorg correctness remain unproven by inspection. |

## Disproof of the strongest construction suspicions

### Shared n+1 index: why Geth #35776 is not evidence against Erigon

The inspected [Geth issue #35776](https://github.com/ethereum/go-ethereum/issues/35776), **open**, describes independently built system-call BALs whose merge retains a restored slot as a write. The pinned reference now explicitly caches the state at index start and removes restored changes: [src/ethereum/forks/amsterdam/block_access_lists.py#L727-L792](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L727-L792) and [src/ethereum/forks/amsterdam/block_access_lists.py#L813-L824](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/block_access_lists.py#L813-L824). The reference has targeted cases at [tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_cross_index.py#L537-L560](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_cross_index.py#L537-L560) and [tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_cross_index.py#L860-L897](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_cross_index.py#L860-L897).

I traced both Erigon paths rather than assuming its write-set `Merge` has the same defect:

- **Builder:** finalization sets the final transaction index once, executes engine finalization, and only then obtains the final write snapshot and records it: [execution/exec/block_assembler.go#L415-L447](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/exec/block_assembler.go#L415-L447). `FinalizeBlockExecution` closes over the same state for every syscall: [execution/protocol/block_exec.go#L303-L328](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/block_exec.go#L303-L328).
- **Validator:** finalization instantiates one state object, uses it for all system calls, and records one resulting read/write set: [execution/stagedsync/exec3_parallel.go#L3787-L3842](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/stagedsync/exec3_parallel.go#L3787-L3842). Withdrawal credit happens before request system calls in Merge finalization at [execution/protocol/rules/merge/merge.go#L183-L204](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/rules/merge/merge.go#L183-L204).
- **No per-call IO reset:** the system-call helper and EVM reset preserve that state recorder: [execution/protocol/block_exec.go#L222-L275](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/block_exec.go#L222-L275) and [execution/vm/evm.go#L169-L184](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/vm/evm.go#L169-L184). Repeated storage and balance writes overwrite the current index's final value in place: [execution/state/intra_block_state.go#L3177-L3195](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/intra_block_state.go#L3177-L3195) and [execution/state/intra_block_state.go#L3384-L3408](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/intra_block_state.go#L3384-L3408).
- **Final filtering:** storage compares a final value to the first read if there was no earlier block write, or the last surviving earlier-index write otherwise. Balances compare against the tracked prior balance and initial baseline: [execution/state/versionedio.go#L3032-L3118](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3032-L3118) and [execution/state/versionedio.go#L3148-L3164](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/state/versionedio.go#L3148-L3164). Restoring at index n+1 therefore does not leave an independently accumulated intermediate write in these paths. The touched/read entry remains.

This refutes the proposed transplant of Geth's mechanism for the requested slot-restoration and forwarded-withdrawal cases. It is a static argument, not a passing result for those reference fixtures. I did not infer equivalence for arbitrary system-contract lifecycle programs or every speculative schedule.

### Destroy/recreate and zero rewards

[Issue #23407](https://github.com/erigontech/erigon/issues/23407), **closed**, and [PR #23541](https://github.com/erigontech/erigon/pull/23541), **closed**, describe the missing wiped-slot read that survives a reverted `SSTORE`. The explicit `SetStorage` in the current read path, cited in the table, defeats that historical mechanism. It is not relabeled as a new candidate.

[PR #25392](https://github.com/erigontech/erigon/pull/25392), **open, unmerged**, proposes skipping zero block rewards in AuRa/Merge finalization. The Ethereum PoS engine already returns an empty reward list unless wrapping AuRa: [execution/protocol/rules/merge/merge.go#L148-L155](https://github.com/erigontech/erigon/blob/f32a39d1e5f87a9ec3a9ce2858171c74acc3c242/execution/protocol/rules/merge/merge.go#L148-L155). Consequently, the PR's presence does not demonstrate an Ethereum Amsterdam empty-block coinbase bug. Zero **transaction fees** are different: fee accounting does access coinbase and its BAL address is required. No candidate retained.

## Known bugs and public test evidence

| Item | Public status inspected | Treatment in this review |
|---|---|---|
| [#21651](https://github.com/erigontech/erigon/issues/21651), nondeterministic parallel BAL on devnet-5 | Closed | Known historical report. Its symptoms are not proof that the mechanism persists at this pin. No new deterministic trigger established here. |
| [#22254](https://github.com/erigontech/erigon/issues/22254), builder wrong state root during ePBS reorg | Closed | Known historical report. No reorg or network replay was performed; no recurrence asserted. |
| [#24670](https://github.com/erigontech/erigon/issues/24670) / [#24684](https://github.com/erigontech/erigon/pull/24684), BAL size | Closed / closed and merged | C1 distinguishes the current 10 MiB design from the old 4 MiB failure. |
| [#21879](https://github.com/erigontech/erigon/pull/21879), non-canonical integer decode | Closed | Current canonical scalar readers inspected; no new candidate. |
| [#21574](https://github.com/erigontech/erigon/pull/21574), no-op storage writes after an earlier change | Closed | Current last-write equality suppression inspected. Its claimed test results are author-reported history, not rerun evidence here. |
| [#23407](https://github.com/erigontech/erigon/issues/23407) / [#23541](https://github.com/erigontech/erigon/pull/23541), wiped-slot reads | Closed / closed | Specific missing-read path now explicitly records storage. |
| [#25392](https://github.com/erigontech/erigon/pull/25392), zero rewards | Open, unmerged | Disproved as an Ethereum PoS reward-list trigger; not a retained candidate. |
| [Execution-specs #3217](https://github.com/ethereum/execution-specs/issues/3217), tests@v21.0.0 | Open | Tracker marks nonce-boundary, destroyed/recreated storage-read, non-minimal scalar, zero-tip coinbase, and system-phase-access coverage as included. The final consume-engine/rlp sweep remains unchecked; this is not “all clients pass.” |
| [Execution-specs #3518](https://github.com/ethereum/execution-specs/issues/3518), glamsterdam-devnet@v8.1.4 | Closed | Release includes #3475 (storage reads), #3482 (nonce boundary), and #3486 (scalar encoding). Publication/coverage is not an Erigon pass result. |
| [Hive Glamsterdam listing](https://hive.ethpandaops.io/glamsterdam/listing.jsonl) | Could not retrieve: HTTP 403; web access also failed | Public Hive result cross-check incomplete. No result fabricated. |

Additional searches for the shared-index suspicion were `repo:erigontech/erigon "BAL" "same index"`, `repo:erigontech/erigon "BAL" "netting"`, and `repo:erigontech/erigon "7928" "35776"`. No matching surviving Erigon mechanism was established; source tracing above is the reason it was dropped, not search absence. Broad search counts were 133 for `7928`, 174 for `"block access list"`, and 21 for `"block-level access"` at retrieval. These mutable search counts are included only to explain pagination/coverage, not as stable protocol facts.

## URLs read and access limitations

Pinned file citations throughout this report are the source locations read. Code was obtained from the following public clone/raw endpoints, with commit equality checked for the two client clones:

- https://github.com/erigontech/erigon (shallow clone, main at the Erigon pin).
- https://github.com/paradigmxyz/reth (shallow clone, main at the Reth pin).
- `https://raw.githubusercontent.com/ethereum/execution-specs/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/{block_access_lists.py,fork.py,blocks.py,state_tracker.py,vm/gas.py}` and the cited EIP-7928 tests.
- `https://raw.githubusercontent.com/ethereum/EIPs/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/{eip-7928.md,eip-7773.md}`; also the published [EIP-7928](https://eips.ethereum.org/EIPS/eip-7928), [EIP-7773](https://eips.ethereum.org/EIPS/eip-7773), and [EIP-7934](https://eips.ethereum.org/EIPS/eip-7934).
- `https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/{beacon-chain.md,p2p-interface.md}`. Only the container definition is used to support C1; no full consensus-client review was attempted.
- [Alloy crate 0.4.11](https://crates.io/api/v1/crates/alloy-eip7928/0.4.11/download) and [matching raw source](https://raw.githubusercontent.com/alloy-rs/eips/c66a2fab30d24e2a2a584e2a48019faa5f6938af/crates/eip7928/src/block_access_list.rs).
- Commit API URLs in the pin table; recursive repository-tree APIs at those pins; [EIP-7928 file history API](https://api.github.com/repos/ethereum/EIPs/commits?path=EIPS/eip-7928.md&per_page=1).

Issue/PR content was read through the GitHub public API. Human-facing issue/PR links above identify the same records. Main known-check query URLs:

- [Search: `repo:erigontech/erigon 7928`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%207928&per_page=100&page=1).
- [Search: `repo:erigontech/erigon 7928`; page 2](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%207928&per_page=100&page=2).
- [Search: `repo:erigontech/erigon "block access list"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22block%20access%20list%22&per_page=100&page=1).
- [Search: `repo:erigontech/erigon "block access list"`; page 2](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22block%20access%20list%22&per_page=100&page=2).
- [Search: `repo:erigontech/erigon "block-level access"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22block-level%20access%22&per_page=100&page=1).
- [Search: `repo:erigontech/erigon "BAL" "10 MiB"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22BAL%22%20%2210%20MiB%22&per_page=100&page=1).
- [Search: `repo:erigontech/erigon "BAL" "10" "limit"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22BAL%22%20%2210%22%20%22limit%22&per_page=100&page=1).
- [Search: `repo:erigontech/erigon "BAL" "same index"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22BAL%22%20%22same%20index%22&per_page=100&page=1).
- [Search: `repo:erigontech/erigon "BAL" "netting"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%22BAL%22%20%22netting%22&per_page=100&page=1).
- [Search: `repo:erigontech/erigon "7928" "35776"`; page 1](https://api.github.com/search/issues?q=repo%3Aerigontech%2Ferigon%20%227928%22%20%2235776%22&per_page=100&page=1).
- [Search: `repo:ethereum/execution-specs "Test Release Tracker"`; page 1](https://api.github.com/search/issues?q=repo%3Aethereum%2Fexecution-specs%20%22Test%20Release%20Tracker%22&per_page=100&page=1).
- [Search: `repo:ethereum/execution-specs "Test Release Tracker" "BAL" "size"`; page 1](https://api.github.com/search/issues?q=repo%3Aethereum%2Fexecution-specs%20%22Test%20Release%20Tracker%22%20%22BAL%22%20%22size%22&per_page=100&page=1).

Tracker bodies read included #2915, #3001, #3034, #3043, #3049, #3123, #3132, #3147, #3167, #3217, #3295, #3311, #3452, #3479 and #3518 in `ethereum/execution-specs`; comments were additionally read for #3217 and #3518 and for Erigon #24670/#24684. No matching C1 test verdict was identified. The required Hive URL was attempted without success, as recorded above.

**Review limitations:** public source only, no test execution; no network/node probing; no latest-build Hive verdict; targeted rather than exhaustive concurrency proof; C1's large-block construction is an analytical condition, not a measured fixture. Other rules in the table had no surviving difference established by this inspection.
