Glamsterdam, the next Ethereum upgrade after Fusaka, has two headline changes. The consensus-layer half is ePBS, EIP-7732, which restructures how blocks get built and has absorbed most of the attention. The execution-layer half is EIP-7928, Block-Level Access Lists, and it is arguably the more practical change for anyone whose job is consuming Ethereum data rather than producing blocks. It is also further along than most people realize: Geth 1.17.4 already constructs and verifies BALs during block execution and serves them over the new eth/71 wire protocol, ahead of the fork activating anywhere public.
Most coverage of BALs frames them as parallel-execution plumbing, which is true but incomplete. This post explains what a BAL actually contains, why the protocol wants one in every block, and then the part that matters if you index, trace, or analyze chain state: BALs put a consensus-verified state diff inside every block, and that quietly replaces a whole category of expensive re-execution work.
What EIP-7928 actually adds
Under EIP-7928, every block carries a companion structure that lists every address touched during the block’s execution and, per address, exactly what happened to it. Storage slots that were written appear with their post-execution values. Slots that were only read appear in a separate read list. Balance changes, nonce changes, and deployed or modified contract code are recorded the same way. Each entry is keyed by a position in the block, so you do not just learn that a slot changed; you learn which transaction changed it and what the value was afterwards. Index 0 is reserved for pre-execution system calls, indices 1 through n are the transactions in order, and n+1 covers post-execution system calls.
The block header gains a new field, block_access_list_hash, the Keccak-256 hash of the RLP-encoded list. Every validating node rebuilds the list independently while executing the block and compares hashes; if the list a builder shipped does not match what execution actually touched, the entire block is invalid. That single rule is what separates BALs from the transaction access lists Ethereum has had since EIP-2930. Those are optional, unenforced hints that nothing checks and almost nothing uses. A BAL is consensus data: it is exactly as trustworthy as the block it arrives in.
The encoding is built for determinism. Addresses are sorted lexicographically and appear exactly once. A storage slot lives in either the write list or the read list for a given account, never both, and a write that leaves a slot at its previous value is recorded as a read. Two clients executing the same block must produce byte-identical lists, because a single byte of disagreement is a consensus failure.
Why Ethereum wants BALs
The EVM executes transactions one at a time, and the reason is informational, not architectural. Until a transaction runs, nobody knows which accounts and slots it will touch, so the client has to assume the worst: every transaction might depend on the one before it. Serial execution is the only safe schedule when dependencies are unknown.
BALs remove that unknown. Once the access set of every transaction is declared up front and enforced by consensus, a client can load all the state a block needs from disk in parallel before executing anything, run transactions with disjoint access sets concurrently, keep ordering only where sets actually collide, and split state-root computation across cores. Client research prototypes have measured block-processing times dropping by roughly forty percent with BAL-driven prefetching alone, before any parallel EVM work.
Two things are worth keeping straight. First, EIP-7928 does not itself switch on a parallel EVM; it removes the information barrier that made one impossible, which is why “groundwork” is the honest framing. Second, the payoff is not hypothetical future speed. BALs are the foundation of the new snap/2 sync protocol (EIP-8189, also in Geth 1.17.4), and they enable executionless state updates: a node, or your indexer, can apply a block’s state changes without running a single opcode of it. That matters directly for the next section, and it matters for the protocol because Glamsterdam devnets are simultaneously pushing the gas limit toward 200 million; serial execution was the bottleneck standing in the way.
What a BAL gives you as a data consumer
Today, if you want to know what a block actually did to state, you have two options, and both are expensive. You can re-execute it: debug_traceBlockByNumber with the prestate tracer in diff mode, or trace_replayBlockTransactions with the stateDiff option. Trace calls sit at the heavy end of every provider’s price sheet, billed at multiples of a normal read, they are slow, and they require a node that still has the state in question. Or you can maintain your own full copy of state and apply every block yourself, which means operating what is effectively a custom client.
With BALs, the block answers the question itself. Every storage write with its post-value, every balance, nonce, and code change, attributed to a specific transaction index, plus the complete set of slots that were read; all of it verified by every node on the network as a condition of the block being valid at all.
Concretely, that turns several workloads from trace pipelines into parsing jobs. Tracking balances for an arbitrary set of addresses no longer needs an archive query per block; the deltas arrive in the BAL. Watching specific storage slots, a Uniswap pool’s reserves, an oracle’s latest answer, a lending market’s utilization, becomes a filter over the write list with per-transaction granularity. Contract deployments and code changes are enumerated for you. And the read set is a dataset that simply did not exist before: you can see which transactions touched the same state without executing anything, which is raw material for contention analysis, bundle-conflict prediction, and protocol research. If you keep your own mirror of the slots you care about, updating it means parsing tens of kilobytes per block instead of re-running the EVM over it.
What BALs do not replace
A BAL records post-values only. If you need the value a slot held before the block, you get it from your own running index of the previous block, or from an archive node; the BAL alone gives you deltas only when you already know the prior value. There are no call trees, no internal call arguments, no revert reasons, and no gas breakdowns, so debug_traceBlock keeps its job for forensics and simulation. And there are no event logs. Logs live in receipts and remain the semantic layer: the BAL tells you slot 8 of a pool contract now holds a new value; the Sync event tells you that was a swap. Raw state and meaning are different products, and BALs only ship the first one.
Availability has a boundary worth knowing too. The spec requires execution clients to retain BALs for at least the weak subjectivity period, a few months of history, with retrieval via the Engine API and consensus-layer sidecars. Deep historical backfill is not guaranteed by the protocol, so analysis over years of old blocks stays in archive-and-trace territory.
The cost of shipping a diff in every block
None of this is free: blocks get bigger. Research measurements put the average BAL around 72 KiB compressed at a 60 million gas limit, with storage writes and reads accounting for roughly two thirds of that, and the consensus layer caps the structure at 8 MiB. The size scales with the gas limit, and the gas limit is exactly what Glamsterdam intends to raise.
Where you read blocks from starts to matter accordingly. If your pipeline pulls every full block plus its BAL across the public internet, you are paying the growth twice, once in transfer time and once in billing, since large responses are exactly what per-megabyte surcharges meter. If your code runs on the same host as the node, the block and its BAL cross a local socket instead of the internet, and the size stops being your problem. This is the same conclusion the bandwidth math always reaches for full-block consumers, but BALs raise the stakes: the most valuable new dataset on the chain is also the one that makes blocks heavier.
How to prepare
EIP-7928 is not live on mainnet. As of July 2026, Glamsterdam is in its final devnet phase, with the public testnets (Holesky and Hoodi) forking next and mainnet targeted for the second half of 2026. Specifics can still shift before activation, so treat slot-level details as devnet-current rather than final.
You can experiment today. The ethPandaOps Glamsterdam devnets run BAL-producing clients, and Geth 1.17.4 or later builds and validates the lists. The plumbing currently rides the Engine API, where ExecutionPayloadV4 carries the blockAccessList field and historical payload bodies include BALs; a public eth_ JSON-RPC method for fetching a block’s BAL is still being specified in the execution-apis repository. In practice that means early BAL consumers read them from a node they control, not from a gateway; the public RPC surface will lag the fork.
The preparation that pays off regardless is structural. A BAL maps naturally onto address, field, transaction index, and post-value, which is a straightforward wide table in any store you already run. If you design your ingestion around per-block diffs now, using trace-based diffs as the backend, then when the fork lands you swap the expensive backend for BAL parsing and keep the schema. On BLAZED.sh the deployment shape is already what BALs reward: your container or script runs on the same host as a fully synced node, reads full blocks over the local socket at no metered transfer, and has archive access for the pre-values a BAL does not carry. The docs cover deploying a container next to the chain in a few minutes.
FAQ
Is EIP-7928 live on Ethereum mainnet?
No. As of July 2026 it is running on Glamsterdam devnets, with public testnets next and mainnet activation targeted for the second half of 2026. Geth 1.17.4 ships BAL support ahead of activation, and details of the encoding can still change before the fork is scheduled.
Do BALs replace debug_traceBlock?
For state diffs, largely yes: the writes, balances, nonces, and code changes that diff-mode tracing reconstructs by re-execution ship inside the block instead, already verified. For call trees, internal calls, revert reasons, and gas attribution, no; execution tracing remains the only source.
Do BALs include event logs?
No. Logs stay in transaction receipts and are queried the same way as today. BALs describe raw state effects; logs describe what those effects meant. An indexer that decodes events will keep doing so and use the BAL for the state side.
How big is a BAL?
Research measurements average around 72 KiB compressed per block at a 60 million gas limit, with a consensus-enforced maximum of 8 MiB. The realistic size grows with the gas limit, which Glamsterdam plans to raise substantially.
Conclusion
Block-Level Access Lists make every Ethereum block self-describing about state. The protocol wants that so clients can prefetch, execute, and hash in parallel; you should want it because a consensus-verified state diff in every block eliminates the re-execution tax that tracing-based pipelines have always paid. The work between now and the fork is mostly schema work, and the one architectural decision that compounds with BALs is the same one that ePBS is forcing on the latency side: put your code next to the node, because the chain is about to produce more data per block and reward the consumers who do not move it across the internet to use it.