Local Fee Markets are Necessary to Scale Ethereum
Local Fee Markets are Necessary to Scale Ethereum
Local Fee Markets are Necessary to Scale Ethereum
Local Fee Markets are Necessary to Scale Ethereum
Local Fee Markets are Necessary to Scale Ethereum
By @fikunmi_ap
Special thanks to @smyyguy @0xNagu @0xtaetaehoho @purplepill3m for discussions and review.
Local fee markets ensure that transactions pay only for the state they access. Transactions that access contentious state pay more, and transactions accessing non-contentious state pay less. While seemingly simple, local fee markets are extremely nuanced and crucial for blockspace efficiency, long-term network stability, and user experience.
This article covers all there is to know (in great detail) about local fee markets; what they are, how they work, and most importantly, why they are indispensable for general-purpose chains. By the end of this article, you will walk away with a new understanding and appreciation for local fee markets and gain a new perspective on how they interplay with the app chain thesis.
Table of Contents
- What is a Fee Market?
- Global Fee Markets
- Local Fee Markets
- Why Parallelization is not enough—pessimistic parallelization and per account limits
- Alternate approaches to local fee market design.
- Local Fee Markets in Practice
- Understanding transaction fees
- Analyzing transaction fee data
- Local Fee Markets and the Fat Protocol Thesis
- Conclusion
Before we get started, it’s important to define a few terms that will come up often:
- state: the condition of something at an instant in time.
In the blockchain context, state refers to the condition of the ledger; more precisely, the accounts, programs (also called contracts), and their associated data (code and balances). - atomic: a process is atomic if it’s all or nothing–if one component fails, the entire process fails. A cross-rollup transaction is (currently) not atomic because the states of rollups are independent, and a failure on one chain does not impact the other.
- synchronous: two events are said to be synchronous if they occur simultaneously. This property is distinct from atomicity.
- composability: two pieces of state are composable when they can (trustlessly) access (read) each other.
- Atomic Synchronous Composability (ASC): two pieces of state are said to be atomically synchronously composable if they can access each other (composability) without delay with the guarantee of execution atomicity.
The best example of using ASC is a flashloan. In a flashloan, you borrow from a lending pool with no collateral because you’re programmatically guaranteed to pay back your borrowed sum (+ interest) by the end of the transaction. If the transaction fails to satisfy this invariant, the whole interaction fails. - contention: two transactions A and B are said to be contentious if they need to access the same resources. The definition of a resource varies depending on the context.
In sequential execution runtimes, both state and compute are shared resources. Since there is only one processing unit executing transactions, all transactions must share compute resources, so all transactions are conflicting.
In parallel execution runtimes, there are multiple processing units, so transactions only need to share state. Two transactions are said to be contentious if and only if they want to access the same state.
What is a fee market
A fee market is a mechanism for block producers and blockspace consumers (users) to trade blockspace and specific parts of blockspace.
Functional fee markets address three major issues:
- They allow the efficient trading of blockspace: Blockspace is implicitly valuable even without MEV. Functional fee markets enable the efficient pricing of blockspace between buyers and sellers; efficient being a keyword. Ethereum’s EIP-1559 is seen as the gold standard for fee market efficiency as it massively simplifies UX.
- Fee markets prevent spam: Blockchains are permissionless, which means preventing spam is challenging. The system must ensure that spam or spam-like transactions are dropped as early as possible to prevent an actor from using them to overwhelm the network (see Solana in 2022). Fee markets solve this problem by often requiring a base payment that compensates a validator for using its computational and bandwidth resources.
- Different parts of the block should be priced differently: Due to the economic nature of blockchains, different parts of the block are worth different amounts to different market participants. We’ve seen that a market will inevitably form to trade specific portions of blockspace (usually the top), internal or external to the protocol. A functional fee market is internal to the protocol and allows market participants to express the desire for (at least) the top of the block.
In summary, functional fee markets are crucial to the effectiveness and sustainability of any blockchain. Designing a fee market is as complex as it is crucial. There are multiple components, but this article is interested in the most important: how fee markets price access to state.There are two systems: Global and Local fee markets
Global Fee Markets
In a global fee market, access to state is priced indiscriminately–all transactions, irrespective of the state they access, must compete with all other transactions. The system is essentially a reverse (gwei/gas) auction for priority and under sufficient load, it devolves to a reverse auction for inclusion.
Global fee markets are suboptimal. Many transactions are disjoint (they don’t touch the same state), so their pricing should be independent of each other. A user trying to execute a simple send should not have to pay high fees because there's a much-hyped NFT mint happening at the same time.
The significance of this problem is most evident in the historical data of Ethereum’s MEDIAN fees.
Figure 1: Ethereum median transaction fees in the last year | Source
Figure 1shows that the median fee is highly unstable. Digging further we find that (very) small portions of state are responsible for most of the activity (using gas and number of transactions as the metrics). For reference, in the last 90 days, three contracts have accounted for 60% of all transactions on mainnet (see figure 2).
Figure 2: Most called contracts by transaction count on Ethereum mainnet | Source
As seen in figure 2, there is a ridiculously long tail for activity per account on Ethereum. Keep in mind, this data only accounts for the top 1000, the complete data is even more revealing.
In a nutshell, Ethereum’s median fees spike because (very) small portions of state get highly contentious.
And contrary to the prevailing sentiment, this issue is not limited to low-throughput chains (like Ethereum mainnet.) We will prove this emphatically later but the data shows that with enough demand, even a high-throughput (but global fee market) chain like Arbitrum or Base will eventually saturate and experience similar fee volatility as Ethereum.
In summary, global fee markets are unsuitable for any chain that plans to host more than one application.
Local Fee Markets
In a local fee market, the transactions only compete with transactions that want to access the same portions of state. For example, Bob sending 5 ETH to Alice and Caitlyn sending 10 USDC to Danny are priced independently of each other. Both of these transactions should pay the lowest fee possible as they touch uncontended state, but a transaction trying to trade the hottest memecoin should and will pay significantly more because more people want to trade that memecoin.
Contrary to intuition, local fee markets do not keep fees for uncontested state low by increasing fees for transactions vying for contentious states; rather, they make better use of hardware to maximize block space!
Understanding true local fee markets
There are two components needed to create true local fee markets: parallel execution and state access lists. We will also discuss what a true local fee market is in the following sections.
Parallel execution
Parallel execution is necessary for true local fee markets because it allows block builders to execute non-contentious transactions simultaneously, meaning transactions that don’t touch the same state can be executed independently of each other i.e., (native) state isolation.
To create state isolation on a sequentially executed chain, the execution environment would have to constrain the compute that a piece of state can take up in a block. For example, with a max block size of 30M gas, to get ten isolated “lanes”, you would constrain the maximum blockspace of any account to 3M gas per account (30M/10). Hence, even if there were 100M gas worth of Uniswap transactions to be included, once 3M gas worth of transactions is in the block, the builder must stop including transactions that touch the Uniswap account preventing activity on that account from becoming global.
The problem with this approach is that it artificially imposes a limit on the blockspace a piece of state can take up within a block, and the more the lanes, the lesser the blockspace a single account can consume. This is not the case with parallel execution chains. Let us examine why.
Consider the illustration in Figure 2; this is an overview of sequential execution. Transactions are blocked by all other transactions irrespective of the state they want to access; i.e., all transactions fight for the same block space.
Figure 2: Sequential execution
However, in parallel execution, a transaction only contends with other transactions that want to access the same state (see Figure 3).
Figure 3: Parallel execution
The difference between parallel and sequential execution is that in parallel, each piece of state is isolated; it has its own “block”. Strictly speaking, this is also true of sequential execution. There’s nothing that prevents Uniswap from taking up the entire block on Ethereum but because state is not isolated, it must do so at the cost of taking away blockspace from other pieces of state. But when transactions are processed in parallel the maximum blockspace that a single piece of state can consume (in a shared block) is the exact same as the blockspace that it would consume if it had its own block!
And this is the distinction for true fee market locality; in a true local fee market, the blockspace that a piece of state can consume must be the same as it would if it had its own block (or even chain.)
As to why the SVM has them (even though it has parallel execution); the state access limits in the SVM exist to ensure that a heterogeneous validator set can execute the block within the allotted time. The limits ensure that a superminority of validators with better hardware cannot overload smaller validators and compromise the integrity of the network. But they are not necessary for state isolation! Parallel execution creates that.
State access lists
However, while parallelization creates state isolation, it is not enough to create local fee markets by itself. And the reason is simple: the block builder must be aware of the state isolation prior to building the block! If the block builder does not know what state a transaction touches prior to building the block then he can not identify non-conflicting transactions. And without this knowledge, the builder simply defaults to selecting the highest fee-paying transactions regardless of the contention (barring MEV considerations).
The most practical way to identify non-conflicting transactions prior to block building is via state access lists as seen in the SVM, and this is why I’ve described state access lists as the second essential component for local fee markets. However, any design that gives the validator pre-execution knowledge of dependencies will work as well.
Unfortunately, implementing access lists on chains that were not built from the ground up to support it is difficult. This paper shows that on Ethereum, only “1.46% of transactions included a TAL (EIP-2930), even though 42.6% of transactions would have benefited from it”.
Runtime hints (currently in development by Aptos) are the leading (and arguably only) potential alternative to access lists, but this approach is also faced with a number of problems:
- There is no guarantee of accuracy with runtime hints; they are at the end of the day hints. Using them to determine state access does not provide any certainty and adds great complexity to the execution process.
- Chains without access lists benefit from dynamic parallelism. Dynamic execution means the state that a transaction will read from and/or write to is not decided until runtime. Dynamic parallelism combines dynamic execution with parallelism. And it is a major benefit for chains that do not require state access lists as dynamic execution expands the range of applications that can be built (e.g., dynamic DEX aggregators). However, runtime hints or any other methods to determine state access prior to runtime are directly at odds with the goal of runtime hints.
- The state representation model (usually accounts) in chains without state access lists are usually different from those on chains with. And the non-access list account models are incompatible with the granular state representation needed for local fee markets.
On SVM chains, each account is an individual piece of state with a unique identifier. Chains without state access lists don’t have such granular account models because there are no benefits, and are greater resource requirements for highly granular state representation.
For example, on Ethereum, a token is essentially a hashmap between addresses and balances all stored on the same account. On SVM, each token balance has its own account. Enforcing account limits on chains with Ethereum-like account models will throttle many applications because the network's programming model doesn’t support those types of apps. Case in point: Uniswap is moving to a singleton contract!
In summary, there are no known substitutes for either parallel execution or state access lists when creating true local fee markets. There are a few other approaches, but the results are inferior pseudo-local fee markets.
Sharding as local fee markets
Strictly speaking, parallelization and state access lists are not necessary for local fee markets; there are two other known approaches—state access limits and execution sharding. We have extensively discussed why state access limits create inferior locality in the previous section so we will focus on sharing and why it also comes up short.
There is a notion that sharding, whether in the form of rollups or execution sharded chains, is functionally equivalent to local fee markets. The core idea is that fee market locality exists because different pieces of state are isolated from each other.
This approach is similar to the ideal local fee market design in that there’s parallel execution (different machines instead of different processing units). However, this approach faces two problems: intra-shard global fee markets and fragmentation.
Sharding only creates true local fee markets if each piece of state has its own shard or if blockspace is abundant on every shard. And while many efforts are underway to create ASC between sharded chains, it does not yet exist.
The rollup flavor of sharding is also faced with another problem—DA global fee markets. Today, a spike on Base will increase its blob consumption and raise costs for Optimism and Chiuhaha chain, resulting in higher gas prices even with no activity on other chains! For full fee market locality, each rollup would also need its own DA solution.
The importance of local fee markets in practice
We’ve discussed the theoretical benefits of local fee markets so far. Let's look at how they perform in practice.
Understanding transaction fees
When considering transaction fee data for users, there are two measures of average used: mean (often misnomered as just average) fees and median fees.
Figure 4: Calculating Median
While mean fees are calculated as:
$\overline{x} = \frac{\sum_{i = 1}^{n} x_i}{n}$
Median fees are fees paid by an average user of the chain while the average fees over-represent contention. By definition, median fees are what the 50th percentile user pays, but average fees are skewed because blocks are top-heavy. For example, the block for Solana slot 296299516 has the cumulative fee graph shown in figure 5:
Figure 5: Cumulative transaction fees paid in slot 296299516
The graph shows that the first 500 transactions of 524 (95.4%) user transactions pay a measly 29.2% of the cumulative fees. The remaining 24 (4.6%) transactions pay the other 70.8%. Repetition for emphasis: 5% of transactions paid 70% of the transaction fees. And blocks are generally this way–extremely top-heavy; therefore, median fees, not mean accurately represent the fees paid by a “normal” user of a chain.
Transaction fee data
Figure 6: Mean and Median fees for Solana in the last 180 days | Source
Figure 7: Mean and Median fees for Ethereum in the last 180 days | Source
Figures 6 and 7 show Solana and Ethereum's average and median fees, respectively. Ignoring that Ethereum is more expensive to use than Solana (it’s not relevant), you can see a CLEAR difference in the correlation between average and median fees.
On Ethereum, where we have global fee markets, average and median fees are highly correlated - in fact they have an almost linear relationship. On the other hand, Solana’s average and median fees are completely uncorrelated.
Average fees rise for two reasons: contention for a piece of state and global contention (aka congestion). Let’s break down both:
- Contention for a piece of state (local): When there is an opportunity on-chain that many parties want to capture (first) e.g., an arbitrage opportunity or a hyped NFT mint, there is usually contention for that portion of state. Fee markets are designed to give priority to the highest bidder, so interested parties bid higher in hopes of getting the opportunity first. This raises the average fees (since some transactions pay more), but it doesn’t (shouldn’t) affect the average user i.e., median fees stay flat. This isn’t always the case, bringing us to the second type of contention.
- Contention for blockspace (global): When blockspace is limited, users are forced to bid higher just to get their transactions included because demand > supply. This also has the effect of raising average fees but this time median fees also rise.
The magic of a local fee market is that it prevents the first type of contention (local contention) from ever becoming the second (global). This is where the SVM clearly offers better UX. Not because the fees are cheaper, but because the “normal” user always pays the same fees, regardless of activity on-chain (reflected in average fees).
Now, you could argue that a global fee market chain with enough capacity would behave the same as Solana to users, and you’d be correct. If blockspace supply is surplus, then all transactions will get picked up regardless of the fees paid. Users who want transaction priority can still pay higher to get included first but this will not preclude inclusion of users that don’t care about transaction priority.
But blockspace is not surplus. And the data shows that on high performance chains, blockspace suffers from a “tragedy of commons”—cheap blockspace disproportionately encourages spam transactions. This phenomenon is observable here where the data shows that bot wallets take up 75% of Solana blockspace and pay the lowest median and average fees! This behavior is also observable on Base as well. Given this fact, it's evident that more throughput is not the answer and the following data confirms this. See figures 8 through 11.
Figure 8: Aptos average and median fees in the last 180 days | Source
Figure 9: Base average and median fees over the last 180 days | Source
Figure 10: Optimism average and median fees over the last 180 days | Source
Figure 11: Scroll Average and median fees in the last 180 days | Source
From the data, we see that high-performance L1s (Aptos) and L2s (especially optimistic rollups) perform much better than Ethereum in that average and median fees are less correlated, yet none come close to the stability of Solana’s median fees.
Figure 12: Eth and Solana median fees for the last 180 days | Source
Figure 13: Arbitrum and Solana median fees in the last 180 days | Source
Figure 14: Starknet and Solana median fees in the last 180 days | Source
Again, ignoring the fact that Solana is cheaper, the data shows that the SVM’s local fee markets offer superior UX when compared to global fee market alt-L1s and L2s. More impressive is the fact that the fees remain stable even while Solana processes more transactions than all of these chains combined! (See figure 10)
Figure 13: Solana TPS vs. Ethereum + L2s + Aptos + BNB TPS in the last 60 days | Source
This data shows that throughput is not infinite (shocker, I know), and that it’s even not enough to prevent observable contention even at today’s demand! This in turn means local fee markets are an absolute necessity for any chain that plans to host more than one app.
Next, we’ll concretize a metric to evaluate fee market locality
Formalizing an evaluation for fee markets
So far, we’ve shown theoretically and statistically how local fee markets influence fee market structure. Next, we will mathematically describe a concrete metric to evaluate how local a fee market is.
- Let average fee be $\alpha$
- Let a change in average fee be $\Delta \alpha$
- Let the median fee be $\beta$
- Let a change in median fee be $\Delta \beta$
Statistical analysis has shown that for all fee markets, the change in average fees and median fees are directly related. We can write this relation as:
$\Delta \beta \propto \Delta \alpha $
[1]
From equation 1, we can say:
$\Delta \beta = k \Delta \alpha$ {where k 0}
[1.1]
From equation 1.1, we can solve for k and write it as:
$k = \Delta \beta \div \Delta \alpha$
[1.2]
The term k which quantifies the change in median fees relative to the change in average fees is locality $\lambda$ of a fee market. We can rewrite equation 1.2 as
$\lambda = \frac{\Delta \beta}{\Delta \alpha}$
[1.2.1]
A fee market is said to be completely local when over any time period $\tau T$, a change in the average fee causes no change in the median fee i.e., $\lambda = 0$. And conversely, the fee market is global when a change in average fee causes an equivalent change in the median fee i.e., $\lambda = 1$.
By this definition, there are no true local or global fee markets, all chains exist somewhere in-between. For Ethereum and EVM-L2s, they exist on the spectrum where $\lambda$ is closer to 1. SVM chains like Eclipse are on the other end of the spectrum, closer to where $\lambda = 0$.
Note: The term $\lambda$ over any time period $\tau T$ is unlikely to be a constant as it is dependent on variables but for the sake of simplicity, we’ll leave it as is.
Rounding Up: Local Fee Markets and the “Fat Protocol Thesis”
There has been much discussion recently about app chains and the death of the fat protocol thesis. While this article will not wander into the realm of speculating on how things will shake out, it’s relevant to discuss how local fee markets interplay with the 10,000 chain vision.
Much of the desire for appchains exists because L1s and general-purpose L2s have failed to deliver a single-state machine where many applications can co-exist. In addition, running an appchain allows providers to be extremely opinionated about the chain’s properties (MEV, consensus, etc.). While local fee markets don’t solve all the problems that appchains promise to solve, they solve one of the biggest: they prevent (local) state contention from spilling over to (global) median fees WHILE retaining ASC.
Local fee markets allow apps (more accurately, portions of state) to (in a limited capacity) own their own blockspace even while residing on a shared ledger!
Conclusion
Local fee markets are table stakes for any blockchain that plans to host more than one application. They are useful not only to ensure that transactions pay (only) for the state they access but also to ensure the most efficient use of blockspace. Without local fee markets, transaction fees are high and extremely volatile, resulting in terrible UX and execution inefficiencies.
To create local fee markets, a combination of parallel execution and state access lists is needed. Parallel execution creates state isolation, and access lists reveal the isolation prior to building the block, allowing the block builders to take advantage of it.
Finally, local fee market chains like Solana, and Eclipse provide an alternative route to the appchain world. While this route has received some valid criticism, it’s important to account for the fact that local fee markets improve blockspace efficiency and help retain ASC. They are a viable and advantageous alternative to a world of 1000s of appchains.
Furthermore, the state and trend of computer hardware are leaning towards scaling by adding more cores instead of improving single-core performance. This trend is yet another positive for the local fee market thesis.
References
- DYNAMIC TRANSACTION FEE MECHANISM DESIGN
- https://dune.com/elovianoo/median-and-average-transaction-fees-eth-alts-l2s
- https://dune.com/elovianoo/tps-for-l2s-and-high-performance-l1s
- https://bitinfocharts.com/comparison/ethereum-median_transaction_fee.html#1y
- https://arxiv.org/abs/2312.06574v1
- https://aptos.dev/en/network/blockchain/execution#dynamic-parallelism
- https://dune.com/fikunmi/most-contract-calls-on-ethereum
- https://x.com/smyyguy/status/1835030196258246692/photo/1
- https://x.com/smyyguy/status/1835390690131583045
- https://x.com/toghrulmaharram/status/1843723223365550174