EIP-8037: State Creation Gas Cost Increase

The fee structure will be redesigned to reflect actual storage costs over time.

How does this EIP interact with EIP-3155? Does this require any changes to traces?

Here’s a chart I made of the marginal cost for one million gas on Ethereum since base fees were introduced mid 2021. Log10-scaled, so this shows a massive change over time.

The primary effect of this EIP is to allow computation/communication gas to become cheaper in dollar terms and as a result unlocking more applications that are both storage-light and infeasible at current gas prices.

My biggest concern is that we will not see a noticeable difference in the composition of block transactions after the implementation of this proposal. And if the transactions stay mostly the same, we’ve added a chunk of complexity to Ethereum, to all future clients, and to an ecosystem of tooling, for no gain.

Here’s why I think no change is a likely outcome:

  • The transactions that use existing successful applications are likely to continue making up the bulk of transactions. These are already fairly storage optimized, since most successful applications generating transactions on Ethereum were born in a time when gas prices were 50x to 500x what they are now. Improvements would be small, and security/upgradability concerns make changing these apps impractical.

  • We’ve already had a massive price decrease for computation-heavy transactions (simply because the price for all transactions has crashed). We have not seen an emergence of these non-storage apps yet on ethereum, even though they are far more affordable today.

  • Other chains - BSC, Base, Monad - have had much much cheaper gas than even Ethereum today, and have not seen these computation heavy apps show up. In fact, what we’ve seen on BSC and Base is an increase in storage use per application user, rather than any growth of computation apps.

  • Gas prices in dollar terms on Ethereum have been trending down consistently over the last years. If this continues, even if we increased the proportional cost of storage, the absolute cost of storage would continue to decrease, and thus the financial incentive would still be in favor of storage heavy apps.

  • Most of the initial effect of making gas cheaper ends up enabling smaller and smaller arbs. These tiny arb transactions don’t really use any long-term storage anyway.

I certainly hope that there will be a new class of blockchain applications that look nothing like current ones. (After all, I built live video streaming over tx data recently.) But I think those apps may be waiting until changes beyond gas costs to happen.

My second concern is that this proposal uses max block size as the control variable for storage costs. However, Vitalik said yesterday that slot time reduction is the top of the roadmap. This proposal plays badly with decreased slot times, because this proposal removes control of storage per block from the voted on max block size. If slot times move from 12s to 8s, we’ll have a 50% increase in possible state growth with no validator control possible. Not having controls here would leave us worse off with this EIP in place.

Lastly, this proposal does not actually ensure that storage is paid for at a sustainable price vs its costs.

Block space has the property that it is created continuously, and can’t really be saved for the future. Because of this, auctioning it off and taking whatever is bid makes plenty of sense. Storage slots operate on completely different economics. Whenever a slot is used, it has a lifetime cost. If it’s not used, there is no cost. The ideal way to charge for storage looks nothing like the way to charge for block gas. However, this proposal keeps ethereum in a world where storage charges have no relation to storage costs, and go up and down 1000x for completely unrelated reasons.

I think it’s helpful to compare this proposal to some alternatives:

  1. Doing nothing: If block gas stays at 60M and then reduces proportionately as blocks get faster, storage space increases stay roughly the same. Validators keep have control over storage use. We don’t get the cheaper computation/communication gas though.

  2. One time price increase for opcodes around new storage use: Gets us more computation, while still giving validators control of ongoing storage rate increases. Still requires ecosystem tooling changes, but these changes are much simpler, and tooling already has support for hard fork opcode pricing changes. This is a lot less costly, and it’s easier for other chains to implement.

  3. Charge for net storage changes in a transaction denominated in ETH, not denominated in gas: The big one. A lot of tooling will need to change. Ensures that blocks with low demand can’t just fill storage at near free prices.

My preference, if we were making a change, would be for an opcode level price increase for new storage slots / contracts. This gives us our increase in computation/communication gas, with the least tooling difficulties and complexity. Then once the dust settles later on, we can add long term complexity only where it will actually make a difference.

1 Like

During implementation of this EIP, we found a few misspecifications for state_gas under some edge cases. In order to address these ahead of bal-devent-4, I am posting here a review on these edges cases/issues. This is not an exhaustive review of all implementation details, but rather a focused review of gas accounting of state gas and its edge cases.

We use the latest EIP-8037 specification, its EELS implementation (branch `eips/amsterdam/eip-8037`), and the execution-spec-tests release `bal@v5.6.1`. The goal is to identify edge cases or specification gaps that violate the EIP’s guiding principle that **state gas should be consumed if and only if new state is created**. We explicitly flag where this principle conflicts with current EVM design.

The recommendations try to target keeping the principle intact. However, when there are clear deviations from current EVM behavior, we also list options. The goal is to open the discussion and decide on the best path forward.

For the full description of each of these issues and a sugestion of how to tackle it, please refer to the full report here.

I would like to thank @rakita and @spencer-tb for their review.

As a complement, I would also like to link the analysis from @kclowes that compares the current EIP draft with the existing EELS spec.

1 Like

I’m particularly interested in point 4 of your report. In my opinion, an account created by CREATE/CREATE2 and then destroyed by SELFDESTRUCT is a very interesting case for creating ephemeral contract. An example is the CREATE3 factory, which has a proxy created via CREATE2 used to allow deployments of the same address regardless of logic. If we allow refunds upon destruction of these proxies, the deployer would save 120 x cpsb (each proxy occupies 8 bytes) gas costs per proxy removed. Ethereum currently lacks opcode that allows the creation of temporary addresses that are then deleted within the same transaction, so this is the most efficient way to do it. Of course, we should lower the SELFDESTRUCT price to encourage this if it doesn’t harm the network.

The refund process might look like this:
- If SELFDESTRUCT is called in the CREATE/CREATE2 context, refund the full cost of creating the state, as defined in this EIP (112 x cpsb) to reservoir.

- Otherwise, add this refund to the refund counter. However, this widens the gap between the minimum gas required for a successful transaction and the actual gas used, which is particularly disadvantageous on Monad where gas is calculated based on a gas limit. My idea is to consider the order of each newly created address in the current transaction and allow direct refunds into the reservoir if SELFDESTRUCT is placed adjacent to CREATE/CREATE2, otherwise, add it to the refund counter. For example:

1. Create account A with runtime bytecode, then call this account to trigger SELFDESTRUCT. In this case, refund the entire cost of creating account A to the reservoir.
2. Create account A and then account B with runtime bytecode, then call account A to trigger SELFDESTRUCT, at which point the refund will be added to the refund counter, while triggering SELFDESTRUCT on B will receive the refund in the reservoir.

I haven’t looked at the implementation details for the above proposal, so I’m not sure if it’s feasible.

We should avoid refunding to the refund counter unless it’s used to combat refund-based attacks (e.g., transaction A writes to a slot and then deletes it in transaction B) because this widens the gap between the minimum gas amount for the transaction and the gas used.

It is possible to split/define state reservoir and regular gas by users. To do so one would delegate their EOA to a heavily audited helper contract (with emphasis on heavily audited as one should not blindly delegate their EOA to some unknown code as this could give access to malicious actors which could e.g. drain your balance or perform any operation from your EOA).
This helper contract would decode the input calldata (the tx.data) and then perform a EVM CALL to the provided address, with the provided value (or just CALLVALUE), with the provided data, but most importantly, also the gas specified in the tx.data.

Note that if one sends a transaction with nonzero state reservoir (so above EIP-7825 limit as tx.gasLimit) the limiting of the gas sent by the EVM CALL only applies to the regular gas, which can thus be set by tx.data. Therefore this forwards the regular gas as defined by the user. Since the state reservoir is always forwarded in full this can thus be tuned by tx.gasLimit.

(EIP version when writing this comment: EIPs/EIPS/eip-8037.md at 80c580b2ad323eb2797058801467b160ae2d5968 · ethereum/EIPs · GitHub)

Hello. We’ve been looking at how EIP-8037 interacts with a common try/catch pattern in production contracts, and want to flag a concern.

contract Outer {
    Inner public inner;
    uint256 public flag;

    constructor(Inner i) { inner = i; }

    function enter() external {
        try inner.run() {} catch {
            flag = 1;
        }
    }
}

contract Inner {
    uint256 constant MIN_GAS = 20_000;

    function run() external view {
        if (gasleft() < MIN_GAS) revert();
    }
}

contract Attacker {
    function strike(Outer o, uint256 innerGas) external {
        o.enter{gas: innerGas}();
    }
}

The pattern: a contract calls a child via try/catch and, on revert, performs state changes.
The catch path cannot distinguish a legitimate revert from an out-of-gas revert.
Today, forcing the catch via OOG also depletes the regular gas that the catch’s SSTOREs need, so the whole tx OOGs and the state change does not persist.

Under EIP-8037 the regular-gas portion of a new-slot SSTORE drops from ~22,100 to ~5,000, with the remainder (64 * CPSB = 97,920 at the current 1,530 CPSB) drawn from the state-gas reservoir filled by overprovisioning gas_limit. Two consequences:

  1. The window for gas-sniping the inner call gets wider. An attacker can land innerGas just below an inner gas-check threshold. The child reverts, and the Outer still has a regular-gas budget for the catch path’s SSTOREs.
  2. Catch paths that previously did not fit within a tx (multi-SSTORE shutdown / liquidation / freeze state changes) now do, because most of their cost is paid from the reservoir rather than the inner-call gas budget.

We have a minimal reproducer that runs the same try/catch + gas-sniped child under PRAGUE and AMSTERDAM+EIP8037 settings.
Let us know if you have done a contract search for this potential issue.

2 Likes

This problem has existed since eip1884, it is now an anti-pattern. The protocol strongly discourages the deployment of static gas usage contracts because they are highly susceptible by repricing. The best approach is to migrate them before the upgrade ships.

While I agree that gasleft() < 
 is seen as an anti-pattern by many, this doesn’t really matter here in my opinion.

We happen to know that there are popular contracts using it that cannot be easily migrated.

So the real question is: Will this EIP make real-world code interacting with such contracts unsafe? Even though that real-world code is currently safe. Or is this just a synthetic example?

We mostly wanted to

  1. raise awareness (motivated by https://x.com/lightclients/status/2062592768439202225)
  2. ask whether a contract search for such contracts has already been performed
  3. potentially offer our help with such a contract search (within our availability limits)
2 Likes

Of little matter how many contract may be impacted, or awareness.

The question is does Ethereum favours ensuring backward compatibility or move forward.

Some contracts simply cannot be updated.

Hi all, we are several protocols currently building confidential smart-contract on top of the ERC-7984 standard and OpenZeppelin’s reference implementation. We’ve been analyzing how EIP-8037 lands on our design and wanted to share the results. We believe confidential tokens turn out to be a near-worst-case for this update as of today and is worth making you aware of this.

TL;DR: we support the goal of reducing state growth in Ethereum, and we’re actively reviewing our design for improvements that align. However, the current direction to include ERC-8037 in Glamsterdam creates an unreasonable timeframe to solve this complex issue that we believe the standard authors were not aware of. This will impact an entire category of privacy solutions while keeping non-private transactions cheap.

What are confidential tokens?

Confidential tokens, as defined in draft ERC-7984, are fungible Ethereum tokens that keep balances and transfer amounts private while still using an account-based model similar to familiar token standards. Instead of exposing numeric amounts directly, all amounts are represented as bytes32 confidential pointers whose underlying values may be resolved or manipulated by implementation-specific privacy systems, such as FHE, MPC, TEE, or future mechanisms. Confidential tokens enable private value transfer for use cases like payroll, confidential DeFi, and institutional settlement while preserving interoperability across wallets, exchanges, and applications.

Confidential tokens are a vendor agnostic standard supported by the Confidential Token Association (https://www.confidentialtoken.org/).

Why confidential tokens are state-creation heavy?

FHEVM’s access control works through an on-chain ACL contract storing persistent grants as:

mapping(bytes32 handle => mapping(address => bool)) persistedAllowedPairs;

where a handle is a 32-byte commitment to an encrypted value. Every FHE computation output is a fresh handle. The consequence: every persistent ACL grant is a zero→nonzero SSTORE, there is no slot reuse, ever, by construction.

A single ERC-7984 confidentialTransfer (OpenZeppelin’s reference implementation) issues 7 new persistent grants.

Quantified impact

Assuming the current values of EIP 8037:

  • STATE_BYTES_PER_STORAGE_SET = 64b

  • CPSB = 1530

We anticipate the following measurements:

Operation New slots State-creation gas today Under EIP-8037
ERC-20 transfer, existing holders 0 0 0
ERC-7984 confidential transfer, existing holders ≄7 ≄140,000 ≄685,440

At the current rates, the state-gas component of a confidential transfer roughly increases by x5 in absolute terms while existing ERC-20 transfer is mostly unaffected - making privacy much more expensive for all Ethereum users.

Additional impact

The current proposal also creates meaningful cost for any asynchronous flow that needs to store state across blocks temporarily. For example, we are considering an asynchronous request-response pattern for managing intents in one of our design. One suggestion would be to reassess storage slot refund values on deletion, but our understanding is that this would be unlikely, as past updates seem to favor decreasing them over increasing. We would then like to discuss other alternatives.

What we’re doing on our side

The pressure this creates points at our designs, and we have already started investigating mitigations. We have also made other protocols from the confidential ecosystem aware of this EIP as they are impacted in the same way.

Tension between values

While EIP-8037 aligns with Ethereum’s scaling roadmap, it forces important components (such as privacy ACL) to be pushed offchain (which can hurt permissionless management and transparent public verification) and hurts one of the most advanced privacy directions that is already on mainnet and working on Ethereum with more than $150M processed.

What’s next

We believe this impact described was not considered in the conversation so far and is a meaningful hurdle in choosing to implement this EIP and, if so, when, to give the confidential ecosystem proper planning time:

  1. Is EIP-8037 confirmed for Glamsterdam? We would love to see it delayed to Hegota at the least for proper time to adapt protocols

  2. Has the 2-phase proposal been considered as impact? What are possible solutions that would allow cheap 2-step execution (as it should not impact long term storage)?

  3. When is cost_per_state_byte expected to be final enough and how it can be adapted to support important onchain information

Happy to further discuss this and run new numbers against specific parameter proposals if useful.

5 Likes

Thank you for the analysis. To answer your questions:

  1. This EIP is currently Scheduled for Inclusion. It is already part of the glamsterdam devnets and it is a blocker for us to increase the gas limit further, so it is very unlikely to be declined at this point.
  2. Can you elaborate what the 2-phase proposal is? I am not sure what you are refering to.
  3. The current cost_per_state_byte is derived based on our expectations of the block gas limit if glamsterdam. I don’t expect it to change significantly at this point.

I think your comment on the temporary storage is very interesting. I am looking into whether we could design a new type of state that is temporary and thus could be made cheaper. I am looking for use-cases for such a state type and how it could work in practice. I would love to chat more about this.

1 Like

Glamsterdam also increased the block limit (from 60M to 200M) in addition to increasing the state creation cost, which will essentially reduce the base fee on the network to almost zero if demand remains unchanged. This means the state cost increases several times, but the gas price per transaction decreases by at least tens of times. When transaction costs are almost zero, users hardly notice the impact, even if their gas usage has increased many times over.

Impact on the maximum number of states that can be created per block: Considering the half-block usage (exceeding this threshold will increase the base fee due to EIP-1559). Currently, the number of slots that can be created per block is 30,000,000 / 22,100 = 1357 slots. After Glamsterdam, it will be 100,000,000 / (1530 * 64) = 1021 slots. This reduction is relatively small and has little impact on current state creation activity.

Appreciate the thoughtful comments.

Let’s take the conversation about the temporary storage slots (used in 2-phase products) into DM to discuss deeper as a new initiative - I find it very interesting.

Regarding this EIP, understandably the EIP is already in SFI state which is obviously not easy to reopen conversation and a lot of effort has been put into it.

From our point of view it seems to be fast-tracked to this state and we believe that it happened without deep enough understanding of impact on the application layer - so although it’s a bit late, we believe it is a good enough argument to reconsider the approach and timing.

Privacy is as important as scaling today, and this creates a situation where these two equally important things are at odds with one another.

Importantly, this is not some old bad practice or anti-pattern but rather some of the most forward thinking protocols innovating in the privacy space, with ongoing new developments coming up to solve one of the biggest problems in the Ethereum ecosystem.

I would argue this is worth serious consideration to see how some mitigation can be achieved.

There are multiple ways to make this better, a delay of one fork to do deeper work with the application layer is one way to go. Another way is making the increase more gradual, with small impact on the first fork (to not waste implemetnation/testing time) and a bigger impact on the second fork. This might lose some of the shock value of a single increase, but as a result create much less damage in the privacy ecosystem.

We are happy to bring this conversation into the next ACD if people find it valuable to discuss in more detail and consider options of mitigating the impact together.

1 Like

Additional regular-gas charges (e.g., ACCOUNT_WRITE, STORAGE_WRITE, hash cost) defined in EIP-8038 apply on top.

This is confusing. ACCOUNT_WRITE is not a “regular-gas” charge, is it?

1 Like

I was made aware of the concerns some developers have with this EIP, and I thought I would share the view that OpenZeppelin developers hold on the topic, as maintainers of (one of) the largest libraries of open-source smart contracts.

First of all, I understand this change is needed to ensure the sustainability and security of the L1. This is obviously not something we want to compromise on. Any vulnerability of the execution layer itself (due to an improperly priced operation) is a threat to all applications. It is also not the first time we have seen opcode repricing. There have been many concerns in the past, particularly when developers realised that the gas stipend of Solidity’s .send mechanism was no longer sufficient to perform some operations. It has been years since the gas cost of a given operation could be considered a “protocol constant,” and contracts (and compilers) are designed to take this into account.

So overall, we could say: “there is nothing to discuss here, contracts are going to continue working; it may be more expensive, but the important part is that they are not broken — case closed.”

However, I cannot deny that some smart contracts are going to be significantly affected, while others not so much. And I think it is important to identify what will be affected, and whether there is any lesson to be learned for the development of future smart contracts.

My understanding is that the EIP increases the cost of expanding storage, regardless of what is being stored (code or data), and makes that cost consistent across operations that touch storage. To be fair, there are very good reason for Ethereum sotrage to be expensive, and IMO, if your data doesn’t need the features and guarantees that it provides, then you should probably not store it onchain! (Events plus indexers can help.)

The applications most affected are the contracts that continuously extend storage to track “non-fungible past activities.” An ERC-20 token that tracks balances will update those balances, reusing existing storage; unless a new account is created/funded, this EIP has no impact. On the other hand, an ERC-20 token with a voting mechanism (such as COMP) keeps track of historical (delegated) balances for vote tracking. This means every transfer can potentially create two new checkpoints: one updating the sender’s delegate’s voting weight, and one updating the receiver’s delegate’s voting weight. This kind of token will be affected significantly.

For such tokens, this EIP incentivises token holders not to delegate their voting power to anyone (including themselves) in order to avoid the (costly) creation of checkpoints. It could therefore be argued that this EIP will weaken some governance protocols by incentivising holders to remain in a position where they cannot vote.

Among the other contract designs that are affected, I can think of USDC’s transferWithAuthorization (EIP-3009). This system uses user-signed operations that are “consumed.” Where the standard approach is to use nonces to avoid signature replay — which can be made smarter by adding “keys” (see the ERC-4337 EntryPoint) — USDC uses a “salt” system. They call it a nonce, but it is actually implemented using a mapping(address => mapping(bytes32 => bool)) private _authorizationStates; that is switched to true when an authorization is used (or cancelled). This system requires a full 0 → 1 SSTORE for each authorization processed. At OpenZeppelin, we are considering providing an implementation of transferWithAuthorization that supports keyed nonces (for versatility and gas costs), but in doing so we would break compatibility with the ERC-3009 standard.

The last category of contract we have in mind is ACL contracts (used, among others, by Zama for tracking handlers’ permissions). These contracts are basically big mappings [address, bytes32] => bool, where the boolean stores read permission for a given handle by a given account. These permissions are created continuously — even for handles that are not actually stored onchain (like amounts in events) — and are never cleaned up. When I said that “if your data doesn’t need the level of guarantee provided by Ethereum’s state, then you should probably not store it onchain,” maybe some of that ACL data deserves to be offchain. But maybe some of it still needs to be available for contracts to operate on. Currently, “updating the ACL” is already a significant part of the cost of doing confidential computation onchain. With this EIP, it is only going to get worse.

The truth is, Solidity (and Vyper) boolean mappings — where the value is a boolean — are notoriously bad in terms of data packing. They use a full slot (256 bits, i.e. 32 bytes) to store a single bit of meaningful information. If we had a design where slots were “fully used,” we could reduce the number of slots required by a factor of up to 256, and the increased gas cost from EIP-8037 would become largely irrelevant. However, because the key part of these mappings is effectively random, we don’t have a good packing solution.

In conclusion, I believe EIP-8037 simply updates L1 costs to ensure the security of the blockchain. It also calls into question some smart contract design choices. More generally, it shows how essential it is for smart contract developers to keep track of the evolution of the execution layer they rely on. In particular, it raises a few questions:

  • What do we do about the cost of “tracking/checkpointing” for onchain voting? Should we identify alternative designs that are less storage-intensive?

  • How do we deal with “old” standards like EIP-3009 that have been in production for a while and could be improved? Do we have a process to encourage new deployments to adopt an updated design, when they may otherwise be incentivised to stick with the old version (for maximum compatibility) even though that means reproducing bad practice?

  • At the compiler/library level, do we have the resources needed to research alternatives to our current (naive) data structures? Can we come up with storage primitives that contracts can reuse and that are optimised for the specificities of EVM storage costs? And if we do, will we be able to guarantee that these design choices remain valid through future evolutions of the EVM?

Last, but very not least, we should not assume that increase in gas costs is necessarily going to translate to increase costs for the user. Users don’t care about many unit gas they pay. They care about how much ETH/USD they pay. Not only is the gas market dynamic, but it is also bounded by the size of blocks. If transaction get 3x bigger, and the block size remains constant, price could increase by much more than 3x, because of the scarcity of the ressouces. On the other hand increase in block space could completelly negate the effect of EIP-8037 as far as “USD cost of transaction” is concerned. I guess we’ll have to wait and see.

6 Likes

Thank you for the analysis, @Amxx ! It is reassuring to see this and to know you are on top of it. I think the points you raise are very important. We can really only solve the larger state growth problem with the help of developer tools. We need to make state usage more efficient and to provide good alternatives to devs.

On a different note, in the next weeks, we expect to share more information on a backward compatibility analysis we are running on mainnet historical transactions. I will share here when we have more results.

I propose to charge new account cost in CREATE-like operations as they go. Better alternative to “charge unconditionally and refund if not used”. Update EIP-8037: charge account creation conditionally at access by chfast · Pull Request #11858 · ethereum/EIPs · GitHub

In its current specification EIP-8037: “Requires:
,EIP-8038“

My understanding is that EIP-8038 will not be part of Amsterdam. Does that requirement make sense then?

EIP-8038 is included in Amsterdam and it is already in devnets.