EVM Workloads in the Wild: Measuring Gas, State Growth, and State Sensitivity Across L1 and L2

EthCC[9] · 2 Apr 2026 · 21:11

Lioba Heimbach presents a measurement study of Ethereum and Base in 2025. The presentation compares EVM workloads, persistent state growth and the sensitivity of transactions to the state against which they execute.

Speakers

Topics

From EthCC[9], hosted by Ethereum France.

Transcript

So, should I start? You can start. Uh yes, what The the mic is here. Sorry. Uh welcome everyone. Uh I'll be talking about EVM workloads in the wild. My name is Lioba Heimbach, and this talk is largely based on joint work with Kushal Babel and Jason Milliones, and we're all at Category Labs. So, this talk is generally motivated by two problems that we generally have with the EVM or the EVM pricing today. The first is that gas, as we have it in the EVM, it collapses many different resources of CPU, storage reads, storage writes, bandwidth, and more all into one single number.

This is generally fine if our workload mix stays the same, but if it doesn't, which maybe we would expect with different chains that all use the same EVM, or even on the same chain as it evolves over time, it isn't fully fine anymore because it will mean that um if the resource mix shifts, but we the relative pricing all stays the same, that some resources will be underpriced. Now, the second problem is that the state of the EVM evolves. So, when you go and you submit a transaction, in all likelihood, you simulate your transaction on the current state that you will have available you have available. But, in all likelihood, there will be blocks or maybe just transactions before you in the block

where you uh will be executed that execute before you and move the state. And with that, it is also not unlikely that your transaction will have a different outcome than it had during the simulation. So, both of these problems, they stem from, at least in my opinion, um the same assumption which the EVM makes. That is that execution conditions are largely stable. And we measured sort of to what extent they are. For that, we have two data sets. So, we collect uh data set of yearly data from the Ethereum Layer 1 and the Base Layer 2 to have an example of a high-throughput EVM chain. And for both of them, we sampled 3,000 blocks a day. That gives us around

220 million transactions on Ethereum, and it gives us 275 million on Base. And then for each of these transactions, we go ahead and we simulate again them again. Through that, we get the desk the gas decomposition. So, we get like what opcodes were actually used by these transactions, and we can break down the gas usage in terms of how much of the gas usage went to compute, how much went to storage reads, writes, and so on. Then, for all of these transactions, we also measure their individual um storage growth. So, did they create new accounts? Did they write to new slots?

Maybe they even deleted slots. And did they add new bytecode, and if so, how much? We also then classify all of these transactions like is a transaction MEV? Is it DeFi? And so on to be able to make statements later on by category, cuz the profiles of these transactions vary widely depending on whether it's MEV or simple transfer, for example. Then, we also have a second data set, which is more the state sensitivity data set, and we have that for the September month of 2025 as well. So, we're for the same set of daily um blocks.

And essentially, what we do here is that if we have a transaction that executed at position I in block B, we will also simulate this transaction at as if it were uh executed at um the beginning of block B. So, instead of position I, at block the beginning of block B minus five, B minus 10, and B minus 20, and so on. And essentially, what this allows us to do is to see how this transaction's execution differs as we execute it on like older and older state essentially. So, we the same transaction, just executed on different state, how does the behavior change? And here, in addition to our full year data set, which we have

for the workloads, um we also record in addition like exactly which storage slots are being read and exactly which are being written to. So, let's start with the first problem, which is that um the workload mix is not stable. So, to see why under these conditions maybe it is not up it could be a problem that we collapse all these different resources into one single number, um I want to go through like a sample transaction. So, we have a Uniswap we three swap here that swaps USDT to ETH, and it was on Ethereum in January 1st, this transaction. And I just went ahead and like looked a bit at what opcodes was this transaction actually using, like what physical resources was it

using. So, this transaction did 10 S store operations, so that's writing to storage. It did 18 S load operations, that's reading. It had 805 bytes of call data, that uses bandwidth. And it emitted five uh logs during its execution. So, we have all these different resources that have different costs to the network. But, what the EVM does in its gas metering, it just takes this and it um collapses it it to collapses it into one number. So, here we have in the end 156,000 gas.

Um that is all sort of that the EVM will see when scheduling. And what I'm showing in the bar below, like how much of that is writes, how much of that is reads, how much of that is compute, that is hidden to the EVM when it's scheduling. And yes. So, this having this uh translation from all these physical resources into one um unit of gas, it works if your workload mix stays roughly constant over time or otherwise, you would need to adjust. And we wanted to see to what extent uh the workload is the same both across chains and within the same chain.

So, first, let's compare how sort of the uh workload is different on Ethereum Ethereum Layer 1 versus the Base Layer 2. So, on Ethereum, as you can see um on the slide here, I'm showing sort of the gas breakdown by category, like how much gas was spent on storage writes, reads, and so on. And in general, you can see that the Ethereum Layer 1, it's pretty write-heavy. Around 34% of all gas usage went to storage writes. If we go to the Base Layer 2, on the other hand, only around 25% went to storage writes. Instead, on the Base Layer 2, we see that it's more read-and-compute-heavy, relatively, where we have around 30 and 25% going to reads and compute, and less so more so than it on the Ethereum Layer

1. So, these two chains, they both are EVM chains, they have the same opcode prices, but they have very different workloads. Like, the same translation can't work for them both. But, it isn't only that we have different profiles um different chains, we also have different profiles on the same chain. So, what I'm showing on the slide now is just a breakdown of gas on two days on the Ethereum Layer 1. I'm comparing a day in January to a day in December. And you can see that the writes went from around 34% to 20%, and the compute went from 17.5% to 37.5%.

So, this is the same chain, again the same prices, and again a vastly different uh research usage that we have here. And it is a problem if we have these fixed prices, but our moving workload. So, to illustrate that, let's look at the figure that I'm showing here, and essentially, you can see on the graph like the share the gas share of reads and the gas share of compute. And like, each dot is one of the two days on Ethereum we just saw. And the star is sort of where we assume the ratio to be when we're setting prices. Like, it can only be at one point in the space. Let's just assume it is at the point that is shown.

And then the distance between uh this fixed price that we're assuming, and um the what we see on an actual day is how wrong it is on that particular day. One side effect of this, for instance, is that blocks will appear full, while like individual resources will still have headroom. So, we're mispricing something here if we're not meeting the desired um ratio. Another thing, or like one reason why this might be happening on Ethereum, that we're seeing these different uh resource mixes on different days, is that Ethereum actually went through some scaling in 2025. So, we went from a 30 million gas limit to a 60 million gas limit. But, largely, the opcodes were

not repriced, and the implicit assumption behind this is that in each resource that each resource dimension then grows uniformly, essentially. And what we then did is like we just wanted to see, okay, if we compare January, which was before the increases, and December, which was after the increases, we doubled the capacity, but in doing that, we actually tripled compute uh while reads only grew by 1.65% 1. a factor of 1.65 in terms of gas usage. So, that means that if we have like a uniform capacity increase, it does not necessarily produce a uniform resource growth.

At the same time, though, maybe we also don't always want this uniform resource growth, because while CPU and IO, they're like per block cost, we execute something, then we're done with it, we can forget about it. State is permanent. So, every slot we add, every node needs to keep it forever. And then, if the state were to rise uniformly, doubling capacity would also double the rate of permanent accumulation. So, we looked at the storage as the state growth on both Ethereum and Base, and essentially, on Ethereum, the state grew by um extrapolated from the 3,000 blocks we have around 45 GB in 2025 and around 440 GB on Base.

Now, when we again look whether the state uh growth goes uniformly with the gas target increase, we see that it actually outpaces it. So, it goes by uh while on Ethereum the gas target went a factor of two between January and December, state growth went by a factor of three and for Base we see a similar pattern. But arguably state is actually the one resource where maybe you want to grow it to grow less that proportionally when you're increasing your gas target, but like with this 1D um gas, it is very difficult to for you to target that.

We can also see where the state growth is actually coming from, which is quite different on the two chains. So, on Ethereum it's largely coming from account state and interestingly 30 um percent of all state growth on Ethereum is coming from simple transfers that transfer ETH to like a new account. And this there's no surcharge for this, they just pay the 21,000 base gas essentially. There are already IPs being proposed to address this discrepancy. Then if we go to Base on the other hand, we see that much of the storage growth comes from storage slot and contract byte code. And here the main culprit is the Zen token um or like one of the main culprits where we have one contract that is only

accounting for 0.03 percent of all transactions, but responsible for 12% of the entire storage growth. So, again you can see that they have very different profiles Base and Ethereum, but again we're using the exact same opcode prices for both of them. So, that brings me to the second problem, which is that transaction behavior varies. So, let's look at maybe how a transaction like a DeFi transaction looks um um on Ethereum. And again, we have a sample transaction from September of last year. And we had a user here that wanted to swap 83 million Clankers for ETH and they wanted a minimum output of 0.3705

ETH for it and they specified this with their slippage tolerance. Now, as I mentioned before, when we're doing our state sensitivity analysis, we simulate the transaction on historic states. Like in comparison to the block where it was actually executed, how would it have executed 20 blocks ago, 10 blocks ago, five blocks ago, and at the start of the same block? And you can see that for this transaction it would have succeeded for all of these lookbacks. At the start of the block it would have received 0. 3812 ETH and this is more than it wanted with the slippage tolerance and it would have um executed successfully. However, it wasn't at position one, it was at position 27 and there was another transaction at

position 25 in the same block that did a swap in the same pool in the same direction. It's moved the price by around 5 and 1/2% as a result of that since there wasn't too much um liquidity in the pool. Um the transaction now would have received only 0.36 um ETH, which is lower than the slippage tolerance that was specified and the transaction ended up reverting still executing on chain and using some gas. Now, this all is probably not surprising to you. We all know that this is happening uh to DeFi swaps, but I think the point is here like we wanted to understand how sensitive are transactions to the state, like how often does this happen to transaction

and by extension of that, like what is the impact on users? So, the simplest thing you can do to figure out like are transactions sensitive to the state, you just look at the gas usage. If I execute them on different states, do they use the same amount of gas or different amounts of gas? If the number is different, something at least slightly different was happening. So, we compare the gas estimates um for all the lookbacks um and we compare and on Ethereum we see that around 14% of transactions exhibit some sort of gas variance, while on Base it's around it's nearly 50% of all transactions where we see some gas variance.

Now, we also look at this by category and I think there's also no surprise to all of you probably that especially MEV and DeFi we see a lot of gas variance, nearly 50% of all transactions on Base and Ethereum exhibit um gas variance. While simple transfers, for example, exhibit almost no gas variance. Now, gas, all it does if we see some variance here, it tells you that something changed, but it doesn't tell us much about what is actually changing. So, we also wanted to look at that in more detail and for that we looked at three metrics. So, for each transaction at all of the simulations that we're doing, we're recording what storage slots is it accessing, so what is it reading, to which slots is it writing to

and then we also compare like what value it is writing. And essentially um what we then show here what I'm showing on the slide here is the overlap. So, between two simulations, what is the overlap of reads, what is the overlap of writes, what is the overlap if we wrote of the value that we're writing. And you can see that on Ethereum actually um the most important line is the one that is highlighted in orange. This just shows you like the difference between the simulation at the start of the block which that is like the state that the user in all likelihood like that's the max state they have access to in all likelihood. They don't have um access to the state after some transactions in the same block already when they're simulating during their

submission uh when they're submitting their transactions. So, we see that the read overlap on Base um between the actual and the start of the block is pretty high, same for the right overlap. But when we look at the actual values that are written, around one in five transaction writes a different value. So, that means something changes in the execution, for example, they get a different price. Um when we move to Base, it's a bit of a different profile. The read overlap is pretty low. Right is again high and for the values around one in three of them write a different value to a slot. So, generally like transactions are in quite sensitive to the state, especially um MEV and DeFi again, which we look in

more detail here. So, this is again a comparison of the actual execution versus the start of the block and you can see that um on Ethereum like MEV across all categories has a bit of an overlap um of between 70 and 80%, while on Base it's very high for reads at almost 100% and very low for the values at around half, so only half of um the writes that we're doing are actually writing the same value. While for DeFi, the profile looks very similar on both of them. Um in general, they're reading the same slots the transactions if we execute them on a bit of an older state, but one in three write a different value.

So, all this variance, I mean, for MEV we're really anticipating it, but we're also to a lesser extent anticipating it to DeFi, but at that point it becomes a bit of more of a UX problem because the user is getting a different outcome than what they are expecting. So, we know now that the workload mix it shifts and we know that transactions uh are sensitive to the state that they execute on. But what does this mean? Well, for the workload live mix, it just means that one dimension doesn't can't really do it all because we see that the workload mix is different across chains, it's different on the same chain and one dimension can't adapt on its own. So, this would require manual repricing if

we were to adapt. And when the ratio is wrong essentially, some resource will be underpriced. Um in the example, which is very simple by chance on the slide, you see two sample blocks. They both appear full, but uh one of the they have very different resource profiles. Like in one of them the computer is completely idle and with one dimension you can't differentiate between the two. There's already some unbundling being done to move away from this one dimension and other EIPs are being proposed um to tackle this further. In general, you want to be able to tackle it without maybe introducing too much complexity.

Then the other thing we saw is that transactions they are sensitive to the state, especially the MEV ones and the DeFi ones. Around 50% of them exhibit variance to the state. This is a UX problem like users want to know what their transaction will do when submitting it, but it also makes block building uh harder. For example, when like the transaction execution just varies a lot depending on where you put it in a block. Now, what does this mean for future designs? Well, in the EVM space in general, we have future designs that are being proposed that in general they increase the state divergence. Like higher throughput, state is going to diverge more cuz we're processing more per unit of time. Encrypted mem pools, for example, they increase a bit of

uncertainty and asynchronous execution also, which Monad has, increases uncertainty since by the time we're scheduling block N plus one we might not even have the state of post execution of block N available. Now, at the same time there's various things in the EVM that sort of assume stable execution paths. Like access lists assume you know what you're going to be accessing, parallel execution assumes um that if you're doing it optimistically, you um uh want the access patterns to not be dynamic so that you don't have cache misses when you're re-executing them.

And same for gas estimation, which you have with uh when this is also you um You if you're charging on the declared limit which some of the asynchronous execution chains like Monad are doing, you want users to be able to predict this. Now, there's many things already being done to address this, but um This is something that I we want to bring your attention to that more work should be done in this direction in order to deal with this uncertainty. So, the takeaways are the workload mix shifts, execution varies with state, and future designs amplify both. So, we really need to be paying attention to how to deal with this uncertainty.

So, yeah. Then, I'll leave you with that that the EVM pricing model assumes that execution conditions are stable. We show that they're not, and as the EVM chains scale and evolve, this just needs to be accounted for. Thank you.