Skip to main content

On Wednesday the Ethereum Foundation postponed the Glamsterdam upgrade on the Hoodi testnet, four days before it was due. The coverage settled on a number within hours: 13. Thirteen real-world smart contracts that a security firm had flagged as potentially affected by the gas changes, names withheld while responsible disclosure runs its course.

Thirteen is a number you can hold in your head. It is also the wrong number, by more than four orders of magnitude, and the right one has been sitting in a public Ethereum Foundation repository since August.

It is 191,792.

TL;DR

  • The Ethereum Foundation’s own repricing-impact repository replayed 929,731,274 mainnet transactions under EIP-8037 and publishes 191,792 affected contract addresses. Press coverage of the delay reported 13.
  • “Affected” there is a strict definition: the transaction succeeded before the repricing and fails after it, and no gas-limit increase can rescue it. That cohort is 2,687,652 transactions for EIP-8037 and 3,036,537 for EIP-8038.
  • EIP-8037 documented the breakage itself. Its Security Considerations contain a section titled “gas_left can increase” and a section naming the ERC-4337 EntryPoint by name. The dataset’s top three affected contracts are EntryPoint v0.6, v0.7 and v0.8, together 59.3% of the whole cohort.
  • The data is complete. The index is not: only 2,453 of 191,792 affected contracts (1.279%) carry a searchable name. Typing “vrf” into the Foundation’s own affected-contracts page returns zero results.
  • Chainlink’s VRFCoordinatorV2_5, the contract that delivers verifiable randomness to games on Ethereum mainnet, is in the affected set. It appears as a 42-character hex string with no label, reachable only if you already know the address.

What the Foundation actually said

Start with the primary notice rather than the write-ups. The Ethereum Foundation Protocol Cluster published “Glamsterdam on Hoodi Postponed” on 22 October 2026. The upgrade had been scheduled for 26 October 2026 at 17:42:48 UTC, epoch 132,352. A new activation date has not been set.

The stated reason, verbatim: core developers decided on ACDE #248 to delay the fork “to allow for further investigation of interactions of EIP-8037 with mainnet smart contracts”. The rollback also removes the Amsterdam execution-layer and Gloas consensus-layer activations, and it removes the gas-limit schedule that would have taken Hoodi to 200M at the same epoch.

Read that notice end to end and three words never appear: the security firm’s name, “griefing”, and “13”. The Foundation named one EIP and one category of problem. Everything else in the coverage was supplied downstream.

What EIP-8037 does to a storage slot

EIP-8037 is “State Creation Gas Cost Increase”, status Last Call, last-call deadline 1 November 2026. Its purpose is unglamorous and sound: a Geth node’s state was around 390 GiB in January 2026, the jump from a 30M to a 60M gas limit more than tripled daily state growth from roughly 105 MiB to roughly 326 MiB, and at 200M the EIP’s own extrapolation puts annual growth near 387 GiB. Nodes start degrading around 650 GiB. The arithmetic runs out in under a year.

So the EIP makes new state expensive. It defines a cost per state byte, CPSB, at 1530, and charges by bytes created. A new storage slot is 64 state bytes. Do the multiplication yourself:

64 × 1530 = 97,920

Against today’s GAS_STORAGE_SET of 20,000, that is 4.896 times dearer. A new account is 120 state bytes, which the EIP spells out in its own text as 183,600 gas, against 21,000 to send ether to a fresh address.

The part that matters for breakage is not the price, though. It is the reservoir. A transaction has one gas limit, so EIP-8037 splits it in two at the start: gas_left for execution, and a state_gas_reservoir for the overflow. State charges draw from the reservoir first and from gas_left only when the reservoir is empty. Two budgets, one number on the outside.

One figure circulating in the coverage puts the new worst case at 110,020 gas. It does not reconcile with the published parameters: from the EIP’s own table, a new slot with a cold access is 97,920 + 2,100 = 100,020, against 22,100 today. I did not read the security firm’s original note, so I report the discrepancy rather than resolve it.

The count nobody ran

The Ethereum Foundation has a repository called ethereum/repricing-impact, created on 30 June 2026. Its description: “Analyzes the gas and contract-failure impact of EVM gas repricings using historical mainnet replay data.” It has zero stars.

It is not a sketch. It replayed 4,000,000 mainnet blocks, numbers 21,319,986 to 25,319,985, covering 3 December 2024 to 15 June 2026, and partitions all 929,731,274 transactions in that window under each candidate gas schedule. The partition it uses is the honest one:

Group Meaning EIP-8037 EIP-8038
g1 No change 616,171,141 370,866,136
g2 Succeeds with changes 121,934,542 456,656,332
g3 Fixable with gas-limit increase 174,473,898 84,708,228
g4 Potentially broken 2,687,652 3,036,537
af Already failing 14,464,041 14,464,041

Group g4 is defined in the repository’s schema as baseline_success = true AND schedule_success = false AND min_multiplier_to_succeed IS NULL. In English: it worked before, it fails after, and raising the gas limit does not save it. That last clause is what separates g4 from g3’s 174 million transactions, which merely need more gas. A contract counts as affected if it shows up in any g4 transaction as the entry point, the out-of-gas halt site, or the non-OOG revert site.

On that definition the published counts are 191,792 contracts for EIP-8037 and 17,937 for EIP-8038.

And the set is internally consistent, which is how you know it is real rather than an estimate. The repository ships one JSON file per affected contract. I pulled the directory listings through the Git trees API: 41,377 individual shards for EIP-8037, plus a collapsed aggregate covering 150,415 freshly-deployed accounts that run out of gas inside their own constructors. 41,377 + 150,415 = 191,792, to the unit. For EIP-8038 there are 17,937 shards and no collapsed class, matching its count exactly.

There is a small, telling crack in that consistency, and it is in the prose rather than the data. The repository’s own design note describing this dataset says “~102k of ~118k affected contracts are freshly-deployed accounts”. The published JSON it describes says 150,415 of 191,792. The document explaining the index is stale against the index by 73,792 contracts, which is itself a fair summary of the week.

What those collapsed deployments die on is worth one line, because it is not where you would guess. The aggregate breaks the halts down by opcode: 111,819 halt on RETURN, 38,710 on SSTORE, 14 on CREATE2. Halting on RETURN means the wallet’s constructor ran to completion and then could not afford to write its own code to disk. The contract was built and could not be filed.

The delay names one EIP. The data names two.

The Foundation’s notice cites EIP-8037 alone. The published analysis covers two schedules, and they do not break the same contracts.

Taking the per-contract shard lists as sets: 41,377 addresses under EIP-8037, 17,937 under EIP-8038, a union of 49,901, and an overlap of only 9,413. Fewer than one in five of the affected addresses is hit by both. There are 8,524 contracts that only EIP-8038 touches, and they are not covered by an investigation scoped to its sibling.

The asymmetry gets sharper when you read the second EIP. EIP-8038, “State-Access Gas Cost Update”, also Last Call to 1 November, raises cold-account access costs and adds explicit write surcharges. Its entire Security Considerations section is two sentences: changing the cost of state access “could impact the usability of certain applications”, and “more analysis is needed”. No reservoir discussion, no gasleft() warning, no named protocol.

And yet EIP-8038 has the larger potentially-broken cohort: 3,036,537 transactions against EIP-8037’s 2,687,652. The EIP that documented its own failure mode in detail is the one that got the delay. The one with the thinner warning and the bigger measured blast radius did not come up.

The EIP already wrote down the break

Here is the part that reframes the week. The mechanism everyone is now investigating is in EIP-8037’s own Security Considerations, under a heading that says it plainly: “gas_left can increase”.

The text explains that refills credit gas_left before the reservoir, so a frame’s remaining gas can be higher after an operation than before it. Then this sentence: “A contract measuring work as the difference between two GAS reads then gets a negative value. This reverts under checked arithmetic and wraps under unchecked arithmetic.”

Wraps. An unchecked subtraction that goes negative becomes an enormous positive number, and any logic branching on it takes the wrong branch. The EIP then states the scope: a negative result requires the reservoir to be empty, and “that is the case for every transaction with tx.gas up to TX_MAX_GAS_LIMIT“. That is not an exotic corner. That is ordinary transactions.

The EIP goes further and names the pattern as common: “Returning state-gas on a merge extends this across a call boundary, which no call does today. Metering a sub-call this way is the more common pattern.”

And then it names a victim outright, in a section headed “Interaction with ERC-4337 bundles”: the GAS opcode cannot observe the reservoir, so “bundling protocols that meter sub-call consumption via gasleft() deltas (e.g., the ERC-4337 EntryPoint) therefore cannot accurately attribute state-gas usage”. Bundlers, it says, MUST account for state gas explicitly rather than relying on gasleft() differences.

The dataset names the same victim the EIP did

Now sort the published affected list by how many potentially-broken transactions entered through each contract. The top three, under EIP-8037:

Contract g4 transactions entered
ERC-4337 EntryPoint v0.7 834,298
ERC-4337 EntryPoint v0.6 451,253
ERC-4337 EntryPoint v0.8 307,305

Together: 1,592,856 transactions, 59.3% of the entire g4 cohort. Under EIP-8038, EntryPoint v0.7 alone accounts for 969,142. The collapsed 150,415 deploy-time failures are, by the repository’s own explainer, “mostly ERC-4337 smart-account wallets created via CREATE2 inside EntryPoint handleOps“.

So the sequence is not discovery. The EIP named the mechanism and named the contract family. The Foundation’s replay counted it, down to the transaction. The only missing step, for two months, was somebody reading either one.

The catalogue has 191,792 drawers and 2,453 labels

The repository publishes a search page where you look up a contract and see exactly how it breaks. The data behind it is complete. The way in is not.

The schema states the rule without flinching: “Unlabeled affected contracts still get a shard file but are omitted from index.contracts (they are only reachable by pasting the raw address).” The search box reads only that index, and matches your text against each entry’s label and owner project.

That index holds 2,453 entries out of 191,792 affected contracts. 1.279%. For EIP-8038 it is 2,417 of 17,937, a healthier 13.475%, but the asymmetry is the point: the bigger the blast radius, the thinner the index gets.

I ran the page’s own matching logic against its own index, locally, over the published JSON. Searching vrf returns 0 results. Searching random returns 0. Searching coordinator returns 0. Searching chainlink returns 6: the LINK token, an EACAggregatorProxy, and four price-feed addresses.

To be fair to the engineering, which is careful: a lookup that misses a shard is not told it is safe. The front end falls back to the collapsed aggregate first, and its comments explicitly require that network failures stay visible so they “cannot be misreported as evidence that a contract was unaffected”. The gap is not honesty. It is that you must already know the address.

The randomness coordinator is in there

I checked the one address class this blog cares about, and I checked it the right way round: pull the affected address list, then identify what the addresses are, rather than guessing a name and searching for it.

Three Chainlink randomness addresses on Ethereum mainnet, and one deliberate control:

Address What it is In the EIP-8037 affected set?
0x271682deb8c4e0901d1a1550ad2e64d568e69909 VRFCoordinatorV2 1.0.0 No
0x5a861794b927983406fce1d062e00b9368d97df6 VRFV2Wrapper 1.0.0 No
0xd7f86b4b8cae7d942340ff628f82735b7a20893a VRFCoordinatorV2_5 Yes
0x5fbdb2315678afecb367f032d93f642f64180aa3 junk control address No

The first two identified themselves: calling typeAndVersion() against a public mainnet node returns those exact strings. The third reverts on that call, so I did not take my own memory for it. Blockscout’s verified-source record names it VRFCoordinatorV2_5, 24,094 bytes of verified code. The junk control returning “no” is what tells you the lookup method discriminates rather than answering yes to everything.

The coordinator’s shard is real and specific. Six distinct failure clusters. Nine out-of-gas halts and nine non-OOG reverts in the window. The largest cluster, seven transactions, halts on SSTORE at call depth 8, with a bottleneck the dataset classes as FractionalGas and a pattern it classes as storage_heavy; the drivers behind it are 9 cold account accesses, 29 SLOADs and one SSTORE at the median. A worked example is transaction 0x370bfecbc607faa85a76fcde569cbf3f3cebcfb28d038e60475f0a3ec806c6ae at block 23,467,089.

And its label field contains its own address. Confidence: low. Category: null. Owner project: null.

One honest note on that shard, because it looked like an error and was not. The entry selector is 0xa9059cbb, which the dataset renders as func_2093253501(bytes) rather than the ERC-20 transfer(address,uint256) everyone knows. I assumed a decoding bug and went to prove it. Both strings hash to 0xa9059cbb. It is a genuine four-byte collision, and the dataset picked the other pre-image. Nothing is wrong except my first instinct.

What this does and does not mean for a draw

Be precise here, because the easy version of this paragraph is false.

Satoshie’s draws settle on Base, and the coordinator we use is a different deployment at a different address. Base does not run Glamsterdam, Glamsterdam is not scheduled on Ethereum mainnet, the Hoodi rehearsal has no date, and the nine halts in that shard are nine transactions out of a four-million-block window. Nobody’s raffle is broken this morning. Anyone telling you otherwise is selling something.

What is true is narrower and more durable. An on-chain draw is a callback with a bounded gas allowance, executed inside somebody else’s frame. Its correctness depends on the gas schedule staying where it was when the contract was written, and on nothing in the stack between the entry point and the callback metering its work by subtracting one gasleft() reading from another. A repricing is the one upgrade class that can invalidate a deployed contract without anybody touching it, and the contract cannot be redeployed into the past.

That is why the index matters more than the thirteen. The right question after Wednesday was never “which thirteen”. It was “is the thing that decides who wins on the list, and can anyone find it there”. The answer, for mainnet randomness, is yes and no respectively.

Four posts this is not

This blog has been near this material four times, and none of them is this.

The June post on Glamsterdam argued the upgrade makes on-chain gaming dramatically cheaper. That claim was about the gas limit rising. This is the opposite vector inside the same fork: a state-creation repricing that makes a new storage slot 4.9 times dearer, and the Hoodi rollback took the 200M limit with it.

The September post covered the previous Glamsterdam rehearsal and argued a testnet cannot price an attack because test ether is free. Its subject was ePBS and the builder auction. This one does not touch consensus: the rehearsal was cancelled over execution-layer gas accounting, which a testnet replays perfectly well.

The October post on paying a winner is the closest neighbour and the one most likely to be confused with this. It measured what it costs to push a payout to a smart account rather than a plain key, on Base, today. It owns the recipient side of ERC-4337. This owns the accounting side: not what the wallet costs to pay, but that the EntryPoint paying it measures sub-calls with a subtraction that EIP-8037 can make go negative.

The callback-headroom measurement counted how much of the requested callback gas Base draws actually consume, and found one with 115 gas spare. That is headroom under a fixed schedule. This is the schedule itself moving underneath contracts that already shipped.

Why it matters if you are the one betting

The reason to care about an index, rather than a count, is that an index is what turns a disclosure into something you can act on.

Satoshie’s position has always been that the parts of a game you have to take on faith should be as few as possible: the odds are in the contract before you enter, the randomness arrives with a verifiable proof, the payout is escrowed on-chain, and none of it depends on believing an operator. That claim is about the contract. It is not a claim about the EVM underneath it, and this week is a clean demonstration of the difference.

Nobody on this list did anything wrong. The affected contracts are correct code, deployed under one gas schedule, measured against a different one. The Foundation did the expensive, unglamorous work of replaying 929 million transactions and published every address it found. The EIP authors documented the failure mode in their own Security Considerations before anybody flagged it. The process worked. The communication did not: the number that reached the public was 13, and the number on the shelf was 191,792.

If you run a contract on Ethereum mainnet, you can check it this morning, and you do not need anybody’s disclosure timeline to do it. That is the actual difference between an open system and a closed one. A casino tells you when it is ready to tell you. A public replay dataset tells you now, if you can find the drawer.

Six honest limits

  • The data is 130 days old. The replay window ends 15 June 2026, the aggregates were generated on 24 August 2026, and the repository’s last push was 25 August. The security report that triggered the delay came on 13 October. Nothing in this published dataset reflects it.
  • Both EIPs are Last Call, not final. Parameters can still change before 1 November 2026, and CPSB at 1530 is the value as published today. Every gas figure here moves if that value moves.
  • “Potentially broken” is a replay classification, not a confirmed exploit. It means a historical transaction that succeeded would fail under the new schedule. It does not mean funds are at risk, and the repository is careful to say so.
  • I did not read the security firm’s original note. The “13 real-world examples” figure and the 110,020 gas figure both reached me through press summaries. The 13 could be a count of distinct patterns rather than contracts, which would make it a different measurement from mine rather than a contradiction of it.
  • The nine coordinator events are a small sample. Nine halts across four million blocks is not a pattern, and I have not established what those transactions were doing eight frames deep. The finding is that the contract is in the set at all, not that it fails often.
  • Satoshie is not exempt from any of this. We run on Base, which inherits execution-layer changes from Ethereum on its own schedule. Our draws are callbacks with gas limits like everyone else’s. A future repricing is a risk to our contracts exactly as it is to the 191,792, and saying otherwise would be the sort of claim this blog exists to pick apart.

Three questions worth asking

  1. If the Foundation’s own replay has named 191,792 affected addresses since August, what is the 13 a count of, and who decided that was the publishable figure?
  2. Why does the index covering 191,792 contracts carry 2,453 names, when the same repository already resolves labels for tokens, exchanges and price feeds? Labelling is the cheapest part of the pipeline and the only part a user touches.
  3. If a repricing can invalidate deployed, correct code, what is the obligation on a protocol upgrade to notify the contracts it breaks, and who holds it when the contract’s author is gone?

Run it yourself

None of this needed an API key, a node, or permission. The affected address list comes from the Git trees API on ethereum/repricing-impact, the counts come from site/data/eip-8037/affected/index.json, the EIP text comes from the raw file in the ethereum/EIPs repository, the contract identities come from eth_call against a public mainnet RPC and Blockscout’s verified-source record, and the postponement notice comes from the Ethereum Foundation’s own blog feed. Every figure above is reproducible by anyone who wants to check me, and I would rather be checked than believed.

The catalogue is public. Someone just has to open the drawers.

📷 Photo by Ilya Semenov on Unsplash

Valentina Ní Críonna

Author Valentina Ní Críonna

More posts by Valentina Ní Críonna