EIP-8038: State-access gas cost update

Discussion topic for EIP-8038; Web;

Abstract

This EIP updates the gas cost of state-access operations to reflect Ethereum’s larger state and the consequent slowdown of these operations. It raises the base costs for GAS_STORAGE_UPDATE, GAS_COLD_SLOAD, and GAS_COLD_ACCOUNT_ACCESS and updates the access cost for EXTCODESIZE and EXTCODECOPY. The design coordinates with EIP-8032: before EIP-8032, parameters assume worst-case contract size; after EIP-8032, they assume worst-case up to ACTIVATION_THRESHOLD, with additional depth-based scaling beyond.

3 Likes

what are the potential metric targets for benchmarking across clients, what should we see pre a d post ideally?

One of the goals would be to have these statefull tests performing at the same million gas per second target (or close enough), accounting for the added cost of state creation. Of course, SSTORE will not have the same million gas per second performance as SLOAD since it also includes a state creation cost component.

Also, state access operations should be harmonized with other compute operations. So these tests should also have similar million gas per second performances.

How does this EIP interact with 8037? Given that 7825 severely limits the amount of state that can be accessed atomically, increasing the cost of that state limits the amount even further. Using the 8037 “reservoir” mechanism in combination with the 8038 state access cost increases bills end users appropriately for the state that they touch and constrains the amount of state that a block can touch, without degrading the maximum transaction complexity and impacting dApp end users. Obviously the regular gas billed by each opcode would still need to represent the cost of proving that state access, but what I’m understanding from the text of the EIP is that the desire to increase the cost of state access comes from the cost of accessing state in a larger on-disk database, not the cost of proving that state against the root.

In fact, adopting the same state gas reservoir model as 8037 could improve transaction complexity.

1 Like

@Nerolation we discussed briefly on Twitter/X about the data behind how often the EIP-7825 limit is tripped at the current gas schedule. I now have this data. Where would be the best place to drop it?

I can also recalculate based on a potential EIP-8038 schedule if you have an example for me to try.

I also asked Titan Builder to reach out to y’all about the impact of EIP-8038 on the various builder-assisted techniques that they are rolling out. The short of it being that an EIP-8038 increase of ~3.8x (like Monad) would severely limit aggregators’ ability to use those features permissionlessly and trustlessly.

1 Like

Best to drop the data into a GitHub repo or something similar. I’d be happy to go through it.

Also, do you have more details on what these transactions are actually doing that can’t reasonably be done off-chain, and that ends up consuming so much gas? Docs, contracts, or any related material would already be helpful, especially since we can’t directly observe those transactions on-chain.

In the end, it’s a trade-off between scaling for the majority of users while not being overly restrictive for minority use cases. The goal is to keep as many use cases feasible as possible without compromising security or scalability, since those improvements benefit everyone.

Adding some data, 0.00060% (407 of 68,364,508 txs; 13 txs/day) of all mainnet transactions in the last 30 days used more than 15M gas (~89% of the 2**24 cap).

Of course, we cannot see transaction going above that limit right now, but this still shows how marginal the fraction of such big transactions is in practice.

My two cents for 8038: repricing state access this way effectively penalizes IO-heavy workloads while making relatively more room for compute/memory-heavy workloads. But mainnet activity may already be quite IO-sensitive: ERC20 transfers, contract deployment, account touches, storage reads/writes, etc. So a complementary benchmark that replays recent/worst-case mainnet blocks and decomposes pressure across IO, CPU, memory, calldata, and state growth might be very helpful. e.g., mainnet traffic replay test.

@CarlBeek started this work with 8037 and I’m continuing with 8038 on the solid basis he left for the analysis.

We will soon get results on that!

2 Likes

Hi all,

I’ve been looking into the impact of proposed gas changes on DeFi transactions, as a weekend project. The repo is available here.

Initial experiments cover SLOAD and SSTORE repricing and evaluate 4 recent mainnet DeFi transactions:

  • a lending protocol liquidation (Aave v3, ~780K gas)
  • three AMM arbitrages: simple (~195K), intermediate (~1.9M), and complex (~10M)

Results show that the dominant effect is SLOAD repricing (EIP-8038) and that the gas cost
increase is around 50% with 3x multiplier, and >200% with 10x multiplier.

60M block gas limit calibration (3× SLOAD/SSTORE multiplier):

Transaction baseline gas AMSTERDAM 3× Δ%
Liquidation 781,399 1,265,399 +61.9%
Simple arb 194,977 289,177 +48.3%
Intermediate arb 1,884,138 2,996,938 +59.1%
Complex arb 10,018,653 15,947,493 +59.2%

All four complete their full execution paths within TX_GAS_LIMIT_CAP at 3×.

200M block gas limit calibration (≈10× SLOAD/SSTORE multiplier):

Transaction baseline gas AMSTERDAM 10× Δ%
Liquidation 781,399 2,959,399 +278.7%
Simple arb 194,977 618,877 +217.4%
Intermediate arb 1,884,138 6,891,738 +265.8%
Complex arb 10,018,653 did not fit

At 10×, the three smaller transactions still complete fully. The complex arb saturates TX_GAS_LIMIT_CAP (16,777,216) and cannot complete its full code path — the EIP-7825 cap becomes the binding constraint. (AMSTERDAM here refers to EIP-8037 + EIP-8038 combined for SLOAD and SSTORE specifically.)

Next steps could be finalizing the gas repricing harness, looking into a larger and representative sample of DeFi txs, and reasoning about the potential $ impact.

Happy to hear any feedback!

Interesting analysis!

I would be curious to see the impact assuming the numbers from this PR: Update EIP-8038: Add preliminary numbers by misilva73 · Pull Request #11802 · ethereum/EIPs · GitHub

The current version of 8038 still charges in a very INEFFICIENT and harmful way to users, and although I have warned this out, the core devs seem to deliberately ignore it. The 8037 performed very well, but the 8038 seems to have been designed simply to fill the gaps left by previous proposals, it’s rough and full of areas that need optimization.

First, the cost for read-only operations (like SLOAD, EXT*), which read data from cache, so their warm access cost must be less than 100, perhaps only slightly more expensive than MLOAD. However, the cost of 100 is still valid for operations that include path processing REVERT (like xCALL, CREATEx). This means we need to have two types of warm access costs for each different group of operations.

Second, the refund for state access costs is sent directly to the refund counter, which is extremely inefficient because this gas gets stuck there and cannot be used effectively for subsequent operations. The principle is that only external fee sources should be controlled, such as the cost of refunding a slot clearing, in this case, a refund counter is necessary. Conversely, state access costs are internal resources, so including them in a refund counter is illogical. Ideally, we should add a separate counter for them, similar to the one used in the 8037.

Third, there is a lack of warm access cost for subsequent ether transfers on the same account. Currently, the cost per transfer is set as ACCOUNT_WRITE + CALL_STIPEND and is not differentiated between warm and cold cases while slot updates benefit from this incentive, this continues to create a barrier to the use of ether, which 2780 is trying to avoid. This disadvantage is evident in multisend operations, where continuously updating the ERC20 balance on the same account is cheaper than continuously updating the ETH balance on the same account.

Fourth, the refunds in this eip are unclear. Will refund if reverted? Will refund if an account updates its balance in the pattern x -> y -> x? In conjunction with the second point, the semantics of refund need to be reconsidered, perhaps splitting it into refund and refill similar to 8037. Currently, I only see refunds applied to storage updates.

Fifth, this is just a minor point. If an account has already had its balance updated before it becomes the target of CREATE, then we must discount the ACCOUNT_WRITE on the CREATE_ACCESS cost.

It’s almost impossible to remove it from Glamsterdam as it’s nearly complete, but I’d like to negotiate the calculations to be more advantageous for users before it’s integrated into the network. You can’t just increase fees without offering reasonable incentives to users.

Here are the main results. Liquidation got cheaper, the other tx slightly more expensive, and complex are now unable to completely fit in the gas limit.

60 M blocks

Transaction baseline pr11802 gas Δ gas Δ% execution diverged?
Liquidation 781 399 1 122 499 +341 100 +43.7% no
Simple arb 194 977 285 877 +90 900 +46.6% no
Intermediate arb 1 884 138 3 073 038 +1 188 900 +63.1% no
Complex arb 10 018 653 16 384 630 +6 365 977 +63.5% yes

200 M blocks

Transaction baseline pr11802_200m gas Δ gas Δ% execution diverged?
Liquidation 781 399 2 701 899 +1 920 500 +245.8% no
Simple arb 194 977 671 877 +476 900 +244.6% no
Intermediate arb 1 884 138 8 007 238 +6 123 100 +325.0% no
Complex arb 10 018 653 16 563 364 +6 544 711 +65.3% yes

Full results: https://github.com/atiselsts/evm-repricing-cost-analysis/blob/main/results/eip8038-pr11802.md

2 Likes

With these result, it is almost certain that state access costs will have to be put into a separate dimension.

2 Likes

Super interesting! Thanks for the analysis.

I have a couple of questions:

  1. For the 200M block, you are linearly scaling the preliminary costs currently in EIP-8038, right? If yes, then the results for the 200M are not accurate. The preliminary costs currently in the EIP are the cost required to get to 200M block. This means that they will not increase further. So, the results we really care about are the ones in the 60M block table.
  2. Can you give more details on inner_oog? Were you assuming the same transaction gas limit as the baseline case? Or were your increasing the initial gas limit?

This is not true. If you look at the analysis, these costs include both EIP-8038 and EIP-8037 and the complex arb does not diverse because of the transaction cap. Only the increases introduced by EIP-8037 make it go over the cap, but these costs are already metered seperately

Yes. However, the data also shows that 1261 SSTORE operations were executed, consuming 12.61M of gas. This is already very close to the current 7825 limit, so we need to expand the limit for state access costs. The simplest way is to increase the 7825 limit or create a gas fee dimension for it, similar to the 8037, as I mentioned earlier.

  1. Yes, that’s exactly it! If that’s the case then most of my concerns related to the results are gone.
  2. I used EIP-7825 TX_GAS_LIMIT_CAP (2^24) as the limit. Tried rerunning it with 100M gas limit and the result is pretty similar. (It should be pretty easy to play around with the repo if anyone is interested.)

I would edit the previous post to reduce the confusion, but looks like as a new user I don’t have edit privileges yet. Here’s the updated table (only one now):

Label baseline gas eip8038_pr11802 gas Δ gas Δ% execution diverged?
liquidation 781 399 1 122 399 +341 000 +43.6% no
simple 194 977 285 877 +90 900 +46.6% no
intermediate 1 884 138 3 073 038 +1 188 900 +63.1% no
complex (TX_GAS_LIMIT_CAP) 10 018 653 16 384 620 +6 365 967 +63.5% yes
complex (100 M cap) 10 018 653 16 772 401 +6 753 748 +67.4% yes†

All runs use TX_GAS_LIMIT_CAP = 16 777 216 (EIP-7825) unless noted.

complex completes at the outer level but some inner subcalls run OOG due to the dominant
STORAGE_WRITE cost: 1 261 SSTOREs × 10 000 ≈ 12.6 M gas from writes alone. At TX_GAS_LIMIT_CAP
(16.8 M), the constrained forwarded gas causes major inner path divergence (+63.5%). At a
100 M cap, nearly the full code path runs (+67.4%), revealing the true cost increase.

† Minor residual path divergence at 100 M cap (compute gas 142 871 vs 147 695 at baseline,
a 4 824-gas difference); some deeply nested subcall still receives insufficient forwarded gas.

I don’t see refunding for clearing slots as really necessary, given how cheap the cost has become after Glamsterdam; users will hardly notice the cost when considering the amount of ETH they have to pay. Another compelling argument is that slot clearing is typically passive (e.g., transferring the entire ERC20 balance to a new address) rather than active (e.g., GasToken, which was disabled by eip3529). Eliminating the old refund mechanism (external-tx refund) simplifies the specification and focuses resources on strengthening the internal-tx refund mechanism, this also means that eip7778 needs to be modified.
Additionally, I also noticed something wrong with the way the slot clearing was accounted for. When a slot is cleared (x -> x -> 0), it receives a STORAGE_CLEAR_REFUND, but then x -> 0 (y) -> x receives another SRORAGE_WRITE refund. Assuming eip2200 is applied implicitly, the total of these two operations will yield a net profit of STORAGE_WRITE - 2 * WARM_ACCESS. Am I making a mistake in my reasoning?

1 Like

I think you got a bug. The EIP was not undoing STORAGE_CLEAR_REFUND. I opened an PR:

1 Like