I would like to thank Toni Wahrstaetter, Marius Vanderwijden and Parithosh Jayanthi for the discussion that led to this report
This post works out what Hegota needs to change to keep scaling the gas limit after Glamsterdam. The starting point is a single observation: the 21,000-gas ETH transfer bounds both dimensions of the slot.
- On the execution side, the Glamsterdam repricings pushed costs as far as the transfer cap permits, fixing worst-case execution at 100 Mgas/s.
- On the bandwidth side, a block full of transfers is itself a data payload (envelopes, signatures, and BAL entries) that no pricing instrument can touch without charging more than 21k.
We therefore use the transfer-full block as the anchor block. We derive its bandwidth performance, find the PTC deadline that maximizes the gas limit, compare it against the adversarial calldata + SLOAD block, and then ask what this implies for state growth, history, and memory.
Key findings
-
The 21k ETH transfer anchors both sides of the slot. It freezes worst-case execution at 100 Mgas/s and sets an irreducible byte density of ~0.0105 B/gas (221 B per transfer, worst-case) that no pricing instrument can undercut. The anchor block propagates at ~214 Mgas/s, so it is execution-bound, and solving both ceilings at a symmetric 25% buffer gives ~422M with the PTC deadline at ~6.4s. We treat the 25% buffer as a guideline, not a hard floor, and relax it slightly to land on round numbers: we recommend 450M at $D = 6$s, which runs the anchor block at a ~25% worst-case execution buffer and a ~11% propagation buffer.
-
Hegota’s repricing job is to bring every priced composition down to the transfer line. Since we cannot reprice the transfer without touching the 21k cap, so the goal is to make it the worst case by construction. Glamsterdam pricing fails this: the mixed calldata +
SLOADblock sits at ~2.2× the line and pins the system at ~302M, ~120M below the anchor optimum. The solution is to raise the calldata floor again (64 → 96) plus coverage of BAL bytes, or introduce a single uniform calldata rate (~94) — trading mechanism complexity against incidence breadth. -
Below the transfer line, only further optimizations move the optimum. Pricing can equalize compositions at the line but cannot go beneath it. Each 10% improvement in the propagation time per kb increases the gas limit by roughly +14–18M, up to a max of 618M. In parallel, improvements in the execution time of ETH transfers would allow higher execution anchors, thus permitting higher limits without changing the PTC deadline.
Background
Glamsterdam ships ePBS (EIP-7732), BALs (EIP-7928), and the repricing bundle, including the data-pricing EIPs 7976 (calldata floor 64/64, standard 4/16) and 7981 (access-list bytes at the floor rate). The repricings targeted a worst-case execution performance of 100 Mgas/s. This target cannot be raised further: doing so would require repricing the gas cost of an ETH transfer to go above its 21,000, which would break functionality in some hardware wallets. So for Hegota, the 100 Mgas/s execution anchor is frozen, and additional scale has to come from the optimizations (both in execution and propagation), changes in the PTC deadline, and (separately) from making overpriced compute operations cheaper. That last option is analyzed in parallel and only enters this report through one interaction noted later.
The assumptions used throughout:
| Parameter | Value | Notes |
|---|---|---|
| Execution anchor R | 100 Mgas/s | Frozen by the 21k transfer cap |
| Slot end T_3 | 12 s | |
| Beacon-block attestation deadline T_1 | 3 s | Earliest payload propagation start under ePBS; 2s vs 3s still open |
| Safety buffers | 25% on both the execution and propagation windows | Guideline, not a hard floor; the recommended 450M/6s point runs ~25% execution / ~11% propagation |
| Propagation model | t = 569 + 0.443 \cdot \text{KB} ms (p90, MEV-boost) | From Toni’s worst-case block-size analysis; snappy-compressed size, measured after release (p_{90} - \min). Transfer block treated as incompressible (post-snappy ≈ raw) |
Cold SLOAD |
3,000 | Preliminary EIP-8038 numbers; unchanged in Hegota |
Cold account access (BALANCE) |
3,000 | Preliminary EIP-8038 numbers; unchanged in Hegota |
Cold SSTORE |
13,000 | Preliminary EIP-8038 numbers; unchanged in Hegota |
| Calldata pricing | 64/64 floor, 4/16 standard | EIP-7976/7981 |
| State creation | CPSB = 1530, fixed |
Latest EIP-8037 spec (150M reference, 120 GiB/yr) |
A map of the resources
It helps to organize the resources by the kind of constraint that bounds them, since that determines how each one responds to a higher gas limit:
| Resource | Constraint type | What happens at a higher limit (Glamsterdam pricing) | Hegota action |
|---|---|---|---|
| Execution | Per-slot, after D | Worst-case execution time grows with G; traded against propagation via D | No upward repricing (by assumption) |
| Bandwidth | Per-slot, before D | Worst-case payload grows with G; BAL bytes are unpriced | Fork change (this report’s core) |
| State growth | Cumulative (disk) | Growth rate grows with G because CPSB is fixed |
Re-derive CPSB (fork item) |
| History | Cumulative (disk + serving) | Grows with G | Expiry prerequisite; LOGDATA review |
| Memory | Per-transaction (RAM) | Does not grow with G (bounded per tx by EIP-7825) | None |
The next sections cover the per-slot trade-off (which sets the gas limit), and we return to the cumulative resources at the end.
The transfer block as the anchor block
How many bytes does a transfer carry?
A transfer writes no storage and runs no opcodes, but it still ships bytes: its envelope and signature, plus the records EIP-7928 keeps for it in the BAL.
A type-2 transfer’s envelope is ~110 B realistically: the signature (r, s at 32 B each, plus y_parity) is ~65 B and the 20-byte recipient address ~21 B once RLP-framed, leaving ~25 B for the nonce, the two fee fields, gas limit, value, chain id, and the empty access list. We round up to 130 B in the table as a worst-case envelope across current transaction types.
For the BAL, a transfer touches two accounts (sender: balance + nonce; recipient: balance). Because RLP encodes balances minimal-length (≤ 11 B, bounded by total ETH supply, not 32) and nonces in 1–2 B, the worst-case marginal contribution is ~91 B.
| Scenario | Construction | B per transfer | \beta_t (bytes/gas) |
|---|---|---|---|
| Worst-case accounting | 130 envelope + 91 BAL | 221 | 0.01052 |
The propagation model is calibrated on post-snappy bytes, so we map this raw 221 B onto the wire by treating the transfer block as incompressible (post-snappy ≈ raw). This is worst-case-safe — signatures are random bytes snappy cannot touch — and is the report’s single most consequential assumption: any real compression only loosens the bound and raises the achievable gas limit. Measuring the compressed marginal byte slope on real encoded blocks is the most consequential data task this report identifies.
Where should the PTC deadline go?
The deadline D splits the slot into a propagation window, from $T_1 = 3$s to D, and an execution window, from D to 12s. Holding the 25% buffer guideline on both, a gas limit L is feasible when the anchor block can both propagate and execute in time:
The first ceiling falls as D moves later; the second rises. The optimum is the crossover:
| Scenario | D^* (s) | L^* | Payload at L^* |
|---|---|---|---|
| Worst-case accounting (221 B) | 6.38 | 422M | 4.44 MB |
The transfer-anchored optimum, holding the 25% guideline on both windows, is ~422M at $D \approx 6.4$s. The 25% buffer is a guideline rather than a hard floor, so we relax it slightly to recommend round operating numbers — 450M at $D = 6$s, moving the deadline slightly earlier to trade propagation headroom for a higher limit. The execution buffer holds at ~25%; the propagation buffer absorbs the shift, dropping from 25% to ~11% — the anchor block then uses ~89% of the propagation window instead of 75%:
| Operating point | Execution buffer | Propagation buffer |
|---|---|---|
| 422M @ 6.38s (symmetric optimum) | 25% | 25% |
| 450M @ 6s (recommended) | ~25% | ~11% |
The residual uncertainty is in the propagation fit (the p90 percentile and Toni’s tail-emphasized versus conservative \sqrt{n\cdot\text{size}} weighting) and the post-snappy compression assumption. Propagation improvements (below) would restore the symmetric 25% buffer at 450M, or push the limit higher.
The adversarial block
The transfer block is not the worst case
The transfer block anchors the slot, but it is not the densest block we can build — its \beta_t \approx 0.0105 B/gas is a floor, not a ceiling. Since we cannot price the transfer block without touching the 21k cap, our goal is to make it the worst case by construction: every composition the protocol prices should carry at most \beta_t bytes per gas. Any priced block above \beta_t binds the slot before the transfer block does and pulls L^* below 422M, so we check each one.
A single-resource block’s byte density is its per-operation byte footprint over its gas cost, \beta = b/c:
- 1/F for calldata at the floor
- 32/c for a cold
SLOAD(32-byte BAL key) - 20/c for a cold account access such as
BALANCE(20-byte address) - 64/c for a cold
SSTORE(32-byte key + 32-byte value in the BAL)
The mixed block adds the densest cheap calldata it can — the 16 gas/byte standard rate, up to the share that still stays under the 7976 floor — and fills the rest with cold SLOADs:
Evaluating the menu at the assumed prices for Glamsterdam (cold SLOAD 3,000, cold account access 3,000, cold SSTORE 13,000, calldata floor F = 64), we get:
| Block | Construction | \beta (B/gas) | × transfer line |
|---|---|---|---|
| ETH transfer (anchor) | 221 B / 21,000 gas | 0.01052 | 1.00× |
Cold SSTORE |
64 B / 13,000 | 0.00492 | 0.47× |
Cold BALANCE |
20 B addr / 3,000 | 0.00667 | 0.63× |
Cold SLOAD |
32 B key / 3,000 | 0.01067 | 1.01× |
| Calldata at floor | 1/F, F = 64 | 0.01563 | 1.49× |
Mixed 25% calldata@16 + 75% SLOAD |
\beta(64, 3000) | 0.02363 | 2.25× |
Key observations:
-
Only cold
SLOADrivals the transfer line. A coldBALANCEwrites only its 20-byte address to the BAL at 3,000 gas (0.63×), and a coldSSTOREwrites a 64-byte key+value at 13,000 gas (0.47×) — both comfortably under. The 32-byte storage key paid for by coldSLOAD’s 3,000 gas is the byte-densest thing state access can add per gas, which is why the adversarial blocks are built from coldSLOAD. -
Cold
SLOADsits essentially on the line. At 3,000 gas its 32-byte key gives 0.01067 B/gas, 1% above \beta_t; the line is reached exactly at c = 3{,}041. -
Two priced blocks exceed the line: pure calldata (1.49×) and the mixed block (2.25×). Both overshoot for the same root cause — calldata priced below the transfer line — but, as we show next, they need different fixes.
The smallest lever: re-raise the calldata floor
The pure-calldata block is over the line for a one-line reason: the EIP-7976 floor of 64 gas/byte implies 1/64 = 0.0156 B/gas, 49% above \beta_t. The fix is a single constant — raise the floor to
This is Hegota’s easiest data pricing change. However, this still does not fix the mixed block. Raising F shrinks the cheap calldata share (from 16/64 = 25\% to 16/96 = 16.7\%) but the cold-SLOAD remainder keeps adding bytes to the BAL, resulting in an overall byte density of \beta(96, 3000) = 0.0193 B/gas. This is still 1.84× above the line.
In fact, with the F \to \infty, the byte density tends to 32/c, which is the SLOAD block density itself. This means that no finite calldata floor brings the mixed block down enough.
Three ways to tame the mixed block
The remaining bottleneck is the mixed block, at 1.84× the line. We have three options. The first two price the BAL bytes the calldata floor cannot see, layered on top of the 64 → 96 floor bump just derived; the third leaves the BAL unpriced and instead removes the dual-rate calldata structure the mixed block exploits.
Option 1: BAL bytes in the floor. The obvious solution is to start including the BAL bytes in the floor calculation. This proposal from Toni extends the 7623-style floor to every payload byte, including the BAL bytes. Every priced byte then yields at most 1/96 bytes per gas, with no SLOAD change at all. The cost is a new gas-accounting mechanism that keeps a runtime floor accumulator touching every cold-access path. This acts on the floor side only, so normal users and the 21k transfer are untouched.
Option 2: An intrinsic data surcharge. Alternatively, we can add an explicit data component to every BAL-contributing operation (cold access, cold storage, etc.). This is constants-only, the simplest mechanism on top of the floor. But pricing the BAL bytes this way is a de-facto state-access repricing. Bringing the mixed block to the line requires raising cold-state-access costs substantially, which sits awkwardly with the frozen-anchor rationale even though it is execution-safe. In addition, this further misprices the pure-opcode blocks, which are already under the line.
Option 3: A uniform calldata price, no BAL pricing. The mixed block works because calldata has two rates — the cheap 16 gas/byte standard rate, ridden up to the floor share, and the floor above it. If we give calldata a single rate p, this bottleneck disappears. Every calldata byte costs p, so the calldata block is bounded at 1/p and mixing it into a state block only dilutes the density. The worst case then reverts to the densest unpriced state op, which is the cold SLOAD at 32/c. So p only needs to stop pure calldata from beating SLOAD:
This is barely under the floor’s 96: dropping the floor changes who pays, not the rate. A floor of 96 bites only data-heavy transactions, while a uniform 94 charges every calldata byte the floor rate. This is a ~6× rise on the 16 standard rate. In exchange, it is the simplest mechanism (one rate, no BAL accounting, no max()).
The choice is between mechanism complexity and incidence breadth. Option 1 has the smallest impact on users — it only affects blocks that exceed the calldata floor — but it introduces a new gas-accounting mechanism. Options 2 and 3 are both constants-only changes, but they affect every user of BAL-affecting operations (option 2) or every user of calldata (option 3). Option 3 is cleaner and more defensible then option 2, since the operations that produce BAL bytes already have the correct price for both their execution and their bandwidth cost. The mixed block only exploits the dual-rate structure of calldata, so removing that is a direct fix without needing to touch the BAL bytes at all.
What if propagation gets faster?
Pricing can equalize compositions at the transfer line but cannot go below it. Past that point, only the propagation model itself can move, through mempool-based payload reconstruction (most payload bytes already sit in peers’ mempools), gossip and topology improvements, or erasure-coded dissemination. Re-running the central crossover with an x\% better slope:
| Slope improvement | D^* (s) | L^* |
|---|---|---|
| — (0.443 ms/KB) | 6.38 | 422M |
| −10% | 6.19 | 436M |
| −20% | 6.00 | 450M |
| −30% | 5.79 | 466M |
| −40% | 5.56 | 483M |
| −50% | 5.32 | 501M |
| Overhead halved (569 → 285 ms) only | 6.12 | 441M |
The pattern is roughly +14–18M of gas limit per 10% of slope improvement, with the deadline drifting earlier in step; a −20% slope reaches the round 450M at $D = 6.0$s — restoring the symmetric 25% buffer at the recommended limit — and −50% reaches ~501M at $D \approx 5.3$s. Halving the fixed overhead (569 → 285 ms) is worth about one slope-decile on its own (~+19M). Note that transfer-heavy payloads are the least compressible shape (signatures are random bytes), so compression-based improvements help the adversarial tail more than the anchor block itself.
The hard ceiling of this whole framing is execution: as D approaches T_1 plus the fixed overhead, the execution window saturates at ~8.2s, i.e. 618M at 75% of 100 Mgas/s. Going beyond that requires raising real execution throughput, which is what the parallel analysis on repricing overpriced compute operations addresses. That work couples back to this report in one place: cheaper execution pushes more transactions onto the calldata floor, so floor incidence at F = 96 should be evaluated against post-repricing execution costs.
Implications for the other resources
State growth: re-derive CPSB
The latest EIP-8037 spec fixes CPSB = 1530, derived at a 150M reference limit for a 120 GiB/yr target, and explicitly defers re-derivation to a subsequent fork. Left at 1,530, the target-rate growth at a 450M limit would be ~360 GiB/yr. Using the spec’s own derivation at the new limits, we get:
| Operating point | CPSB |
New slot (64 B) | New account (120 B) | 24 KiB deploy |
|---|---|---|---|---|
| 450M | ~4,600 | 294k | 551k | 113M state-gas |
| 501M (p2p stretch) | ~5,110 | 327k | 613k | 126M state-gas |
The transfer is untouched either way, since only new-account creation pays state gas, in the separate dimension with the reservoir model.
There is also the question of how real demand will respond to the higher block limit and increased CPSB. The final value will likely be different once we observe how users adapt to the Glamsterdam fork.
History: No need to repricing, but expiry becomes more important
Measured geth history (headers, bodies, and receipts) grew at ~525 MiB/day — about 180 GiB/yr — at the 36M limit over May 2024–May 2025 (more info here). Scaling that linearly to 450M gives ~2.2 TiB/yr. This already includes logs, which live in receipts, but the measurement window predates BALs, so the figure omits them. BALs (EIP-7928) are a second history channel of comparable size — ~41% of a transfer block’s bytes, and dominant for the state-access-heavy compositions — but EIP-7928 permits pruning stored BALs to their hash root, so their durable contribution depends on the retention window.
At these history growth rates, rolling history expiry (EIP-4444-family) therefore becomes more important for validators. However, this growth rate is still manageable, and thus there is no need for repricing it.
Memory: nothing to do
Worst-case EVM memory is a per-transaction quantity: quadratic expansion cost against the EIP-7825 cap bounds a single frame at ~3–4 MB, and memory is freed between sequentially executed transactions. A higher block limit adds transactions per block, not concurrent memory. This only changes if the 7825 cap is raised or linear-memory pricing (EIP-7923/7686) ships without a compensating limit.
Compute: downward repricings
The flip side of freezing the 100 Mgas/s anchor is that most operations are now overpriced relative to it: their worst-case client runtime sits below their current gas cost, so they consume more of the block’s gas budget than the time they actually take. Taking current client performance results, we could reprice ~62 EVM operations and precompiles, with 36 of them falling below 1 gas at the anchor rate. These are the cheap, high-frequency arithmetic, bitwise, stack, and memory ops.
This overpricing is throughput left on the table. On mainnet traffic, ~12.4% of block gas is effectively wasted today on operations charged above their fair runtime cost. Repricing downward with integer rounding (max(⌈exact⌉, 1)) cuts that to ~2.6%.
A 10% gain is nice, but it very likely does not compensate the cost of repricing 62 operations. Therefore, the recomendation here is to no change copute costs in Hegota.
What Hegota actually ships
| # | Item | Type |
|---|---|---|
| 1 | Gas limit → ~450M, $D = 6$s | Validator coordination, gated on 2–5 |
| 2 | Calldata floor 64 → 96 | One constant (7976/7981) |
| 3 | Mixed-block fix: BAL floor pair, intrinsic surcharge, or uniform calldata price (~94) | The one open mechanism decision |
| 4 | CPSB re-derivation: 1,530 → ~4,600 (~5,110 at p2p stretch) |
One constant, per the 8037 spec’s process |
| 5 | p2p slope/overhead improvements | Non-fork track: +14–18M per 10% slope, up to ~501M |
Limitations
-
All propagation numbers inherit Toni’s p90 MEV-boost fit (569 + 0.443 \cdot \text{KB} ms, snappy-compressed size, measured after release as p_{90} - \min) and the $T_1 = 3$s assumption; both are choices, not givens. Toni’s conservative \sqrt{n\cdot\text{size}} weighting gives a steeper slope (and the Local / higher-percentile fits steeper still), each of which pulls the optimum down; the crossovers move ~51M per second of T_1 and proportionally with the slope.
-
The per-transfer byte figure is derived from the confirmed RLP minimal-length encoding, so framing overhead is resolved; but Toni’s propagation model is calibrated on post-snappy bytes and we assume the transfer block is incompressible (post-snappy ≈ raw 221 B). Real wire compression and the
block_access_indexwidth’s growth with transaction count remain unmodeled and move every headline number — compression in particular only loosens the bound and raises L^*. -
The crossover model treats propagation and execution as strictly serial with hard 25% buffers; pipelining or overlapping validation would shift the optimum outward.
-
The 8037 figures follow the live spec (
CPSB = 1530); the local EIPs repo still carries the older auto-scaling draft, whose numbers do not apply. -
History projections scale today’s measured history growth (headers, bodies, receipts) linearly with the gas limit; the observed 30M→36M scaling is close to linear, but composition shifts (blob adoption, real BAL sizes) will move them.