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 quantized steps are a brilliant hack. Nice work!

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.