EIP-8046 - Uniform price auction over inclusion lists

Created 2025-10-16
Status Draft
Category Core
Type Standards Track
Authors
Requires

Abstract

This EIP proposes a uniform price auction over inclusion lists (UPIL), which ranks transactions by their ranking fee: how much they are willing to pay per gas for inclusion above the base fee. When the block is full, no transaction is allowed to displace an inclusion-list (IL) transaction that offers a higher ranking fee and is valid when accounting for ranking. All included transactions pay a uniform marginal ranking fee on top of the base fee, equal to the highest ranking fee offered by a valid IL transaction excluded from the block, and this fee is burned. UPIL achieves strong censorship resistance by not allowing builders to circumvent propagated ILs when the block is full. This is particularly valuable for time-sensitive transactions and promotes fairness while preventing cheap block-stuffing under a multidimensional fee market, to which UPIL extends seamlessly. UPIL is specified on top of FOCIL (EIP-7805).

Motivation

Censorship resistance (CR) is a key property of decentralized blockchains. To ensure that transactions cannot be censored by the entity building the block (denoted "builder" in this EIP, which may sometimes be the proposer), a mechanism called fork-choice enforced inclusion lists (FOCIL) has been proposed in EIP-7805. A set of includers propagate inclusion lists (ILs), and the attesters uphold that the transactions in the ILs are included in the block via the fork-choice. There is no mechanism for ranking transactions in the ILs, and therefore not viable to uphold CR when the block is full. If IL transactions must be prioritized under full blocks, the builder could simply integrate with includers to propagate ILs containing the transactions it wishes to include in the block.

To uphold CR also under full blocks, it is necessary to have a framework for which transactions to include and exclude. This EIP specifies a uniform price auction over inclusion lists (UPIL), which ranks transactions by their offered ranking_fee_per_gas, derived from their specified max_fee_per_gas. If a block is full, no transaction is allowed to displace an IL transaction with a higher ranking_fee_per_gas, as long as the displaced IL transaction passes regular inclusion criteria. All included transactions pay the "marginal" ranking fee, corresponding to the highest ranking fee offered by a valid IL transaction excluded from the block, and this fee is burned. If no IL transaction was excluded, the marginal ranking fee is 0. In essence, the existing base fee prices inter-block contention, while UPIL is an auction mechanism that relies on ILs to impose a secondary base fee that prices intra-block contention.

Ethereum is currently pursuing scaling by tracking gas consumption across separate resources, allowing each resource to be consumed at its maximum capacity. With a multidimensional approach, it can become cheaper to "stuff the block" such that it is full in any dimension by creating "dummy transactions" that only consume one specific resource. This degrades the CR of FOCIL, since builders can ignore ILs in full blocks. In the multidimensional EIP-7706 and EIP-7999, the degradation of CR can become rather pronounced. Base fees are set individually per resource and may become very low, depending on whether reserve prices in the style of EIP-7918 are adopted or not. Furthermore, if the builder varies which resource that is full across blocks, there is no longer an exponentially increasing cost to keep a transaction censored block after block.

The strong CR of UPIL is particularly suitable under a multidimensional fee market, but can be beneficial under any fee market. Some transactions are time-sensitive: what matters is inclusion within a set time frame. Sometimes, that time frame consists of just a few or a single block. UPIL guarantees inclusion in the next block for a transaction offering a sufficient ranking fee, assuming includers and attesters do their duties. This puts includers and the builder on a more equal footing. Furthermore, the lack of ranking in FOCIL gives builders an incentive to amass private transactions to facilitate low-cost temporary censorship, which could negatively affect the public mempool. However, both FOCIL and UPIL also have properties that strengthen the public mempool.

Specification

Ranking fee

The ranking is performed on the ranking_fee_per_gas, corresponding to the maximum ranking fee that the transactor was willing to pay under the current base fee. Transactions use their entire headroom for their offered ranking fee.

def get_max_fee_per_gas(tx: Transaction) -> int:
    if is_legacy(tx.type):
        return tx.gas_price
    elif is_frame(tx.type):
        return tx.fees.max_fee_per_gas
    else:
        return tx.max_fee_per_gas

def get_ranking_fee_per_gas(tx: Transaction, block: Block) -> int:
    return get_max_fee_per_gas(tx) - block.base_fee_per_gas

The ranking fee does not impose ordering constraints within the block, and only governs inclusion. The alternative specifications section discusses other options for computing the ranking_fee_per_gas, including a dedicated ranking fee field that could be introduced for frame transactions.

Transaction processing

The builder specifies in the block body the marginal_ranking_fee_per_gas that all transactions must pay. The full inclusion_fee_per_gas corresponding to base_fee_per_gas + marginal_ranking_fee_per_gas is covered before the priority fee. A valid transaction must have max_fee_per_gas >= inclusion_fee_per_gas.

Since the marginal_ranking_fee_per_gas depends on the outcome of execution, execution must not depend on it. Relative to EIP-1559, each transaction is therefore charged, and refunded for unused gas, at its max_fee_per_gas instead of its effective_gas_price during execution, and no priority fee is paid to block.author. The GASPRICE opcode still returns the EIP-1559 effective_gas_price. Once all transactions have been executed, they are settled as follows:

# executed_transactions holds each executed transaction with its signer and gas_used
inclusion_fee_per_gas = block.base_fee_per_gas + block.marginal_ranking_fee_per_gas
for transaction, signer, gas_used in executed_transactions:
    assert transaction.max_fee_per_gas >= inclusion_fee_per_gas
    # The priority fee is capped by the inclusion fee instead of the base fee
    priority_fee_per_gas = min(transaction.max_priority_fee_per_gas, transaction.max_fee_per_gas - inclusion_fee_per_gas)
    effective_gas_price = priority_fee_per_gas + inclusion_fee_per_gas
    signer.balance += gas_used * (transaction.max_fee_per_gas - effective_gas_price)
    self.account(block.author).balance += gas_used * priority_fee_per_gas

The inclusion fee is never distributed and thus burned. Legacy transactions are assigned max_fee_per_gas = gas_price and max_priority_fee_per_gas = gas_price in a prior normalization step. Frame transactions of EIP-8141 are settled in the same way, with the payer in place of the signer and with charged_fee computed from max_fee_per_gas at the end of the transaction. The inclusion check uses the state before settlement.

Altered FOCIL post-execution inclusion check

The post-execution inclusion check of EIP-7805 is altered as outlined in the figure. A transaction X of the block is ranked at least as high as an IL transaction T if get_ranking_fee_per_gas(X, B) >= get_ranking_fee_per_gas(T, B), and is otherwise lower-ranked than T. For each transaction T in ILs, the check performs the following steps.

Figure 1

(1) If T is present in B, is not willing to pay the inclusion fee (get_ranking_fee_per_gas(T, B) < block.marginal_ranking_fee_per_gas), or fails static validity, jump to the next IL transaction. A frame transaction passes static validity only if it is a Profile 2 candidate with an occurrence admitted by the per-IL VERIFY budget of EIP-8369.

(2) In each gas dimension of EIP-8037, compute gas_ranked_left(T) as B.gas_limit minus the gas that transactions ranked at least as high as T count toward that dimension. If, in either dimension, gas_ranked_left(T) is smaller than the gas that T reserves there, jump to the next IL transaction. A regular transaction reserves min(TX_MAX_GAS_LIMIT, tx.gas) in execution gas and tx.gas in state gas, while a frame transaction reserves its execution_reservation and state_reservation from EIP-8141.

(3a) For a regular transaction, validate T against the nonce and balance of T.origin at the start of the block, updated with the net changes that transactions ranked at least as high as T made to them, and with the net change that each lower-ranked transaction made to the balance, if this change is negative. If a lower-ranked transaction changed the nonce of T.origin, T is invalid.

(3b) For a frame transaction, check whether T is Profile 2 eligible against the state at the transaction index claimed by the builder, or at the end of the payload if no valid index is claimed.

If T is valid, terminate and return an INCLUSION_LIST_UNSATISFIED error; otherwise jump to the next IL transaction.

Check on the marginal ranking fee

An IL transaction that does not fit in (2) is still validated in (3a) or (3b), as indicated by the dashed line in the figure, but (3a) then disregards lower-ranked transactions, so that neither their balance decreases nor their nonce changes count. If the IL transaction is valid, its ranking fee is recorded instead of failing the block, unless it reserves more than TX_MAX_GAS_LIMIT (2**24) in state gas. The marginal_ranking_fee_per_gas must equal the highest recorded ranking fee, or 0 if none is recorded.

Rationale

Updated inclusion check

Accounting for ranking

The inclusion check accounts for ranking with four goals in mind. First, no lower-ranked transaction should be able to take the place of an IL transaction in a full block, which is the purpose of the auction. Second, an IL transaction should be protected when transactions ranked at least as high make it valid, for example when one of them funds its sender or holds the preceding nonce of that sender. Third, the builder must always be able to construct a block that passes the check, which requires avoiding circular dependencies, where the requirement to include an IL transaction depends on the inclusion of a lower-ranked transaction. Fourth, the builder should be free to execute the highest-ranked transactions in any order, for example to extract MEV.

These goals are met by treating the transactions of the block differently depending on whether they are ranked at least as high as an IL transaction or lower. Transactions ranked at least as high are counted in full. Step (2) counts the gas of these transactions alone, so that no lower-ranked transaction can take up the room of the IL transaction, as the first goal requires. Step (3a) counts all changes that they make to the nonce and balance of the sender of the IL transaction. The IL transaction is thus protected when such a transaction makes it valid, as the second goal requires, and its exclusion is excused when such a transaction makes it invalid.

Lower-ranked transactions are treated asymmetrically in step (3a): they can count against an IL transaction, but never in its favor. Their increases to the balance are ignored, so a lower-ranked transaction can never make an IL transaction valid, and the builder is never required to include one for this purpose. This rules out the circular dependencies of the third goal. Consider transactions ranked A>B>C, where B funds A, and only one of A and B fits. If the funding from B counted, A could not be included without B, B could not be included in place of the higher-ranked A, and including C instead would leave out the higher-ranked B. Since the funding does not count, A is invalid, and the builder includes B. The same applies if B holds the preceding nonce of the sender of A. If B instead changes the state such that a higher-ranked transaction X funds A, the builder avoids the dependency by executing X before B.

Decreases to the balance by lower-ranked transactions are, however, counted, and any change that a lower-ranked transaction makes to the nonce renders the IL transaction invalid. Only the sender can authorize such changes, through its own transactions, authorizations it has signed, or code it has delegated to. The exclusion is then acceptable as a consequence of the sender's own choices, just as under FOCIL. For example, the builder may include the original transaction of a sender instead of a replacement IL transaction with the same nonce and a higher ranking fee. Counting these changes ensures that an IL transaction that is valid in step (3a) is also valid at any point in the block after all transactions ranked at least as high have been executed, whatever the order of execution. The builder can therefore execute the transactions of a batch in any order, as described in the Security Considerations section, which meets the fourth goal. Along the dashed line, lower-ranked transactions are not counted at all, so that the builder cannot lower the marginal ranking fee by including a lower-ranked transaction that invalidates a regular IL transaction setting the fee.

Compared with FOCIL, a transaction that only becomes valid through a lower-ranked transaction is not protected, even if the block has room for it. For several transactions from the same sender, a transaction is thus only protected if the transactions with its preceding nonces in the block are ranked at least as high, so senders should not offer a higher ranking fee for a later nonce. A lower-ranked transaction executed before a higher-ranked one can still change what the higher-ranked transaction does, just as the order of execution matters under FOCIL.

Gas dimensions

UPIL uses one marginal ranking fee for both gas dimensions, just as EIP-8037 uses one base fee: an IL transaction that is outranked in either dimension sets the price of all gas. A fee per dimension would mainly benefit frame transactions that reserve no gas in the congested dimension, since a regular transaction reserves gas in both. Frame transactions reserve exact amounts in each dimension, whereas a regular transaction reserves its entire gas limit in state gas, because EIP-8037 only splits its gas between the dimensions at runtime.

Under EIP-8037, a regular transaction can reserve up to 2**32 - 1 in state gas, and a frame transaction even more, well above the block gas limit. Such a transaction could be outranked even when the transactions ranked above it use little state gas, and raise the marginal ranking fee without ever paying it. It therefore remains protected whenever it fits, as under FOCIL, but does not set the fee. Every other transaction can only be outranked if the transactions ranked at least as high use all but TX_MAX_GAS_LIMIT of a dimension, as in a single dimension under EIP-7825.

Claimed index for frame transactions

Frame transactions are validated at the index claimed by the builder, as in EIP-8369, since their validity can depend on any state that their validation frames read. The claimed index only selects this state, while the check of the remaining gas in step (2) decides whether T fits. If the gas remaining at the claimed index were used instead, the builder could claim the end of a full block and excuse every excluded frame IL transaction. The circular dependency cannot arise, since the builder can always claim an index before the transactions that make T valid.

Compute requirements

The check is inexpensive. For the remaining gas in step (2), the client sorts the transactions of the block by ranking_fee_per_gas and computes the cumulative gas in each dimension, so that each IL transaction only requires a lookup. For the validation in step (3a), the client records during execution the nonce and balance changes that each transaction makes to the origins of excluded IL transactions, together with its ranking_fee_per_gas, and sums them in the same way. For lower-ranked transactions, which the dashed line disregards, it only sums the negative net balance changes and notes whether any of them changed the nonce. A block-level access list (BAL) already records these changes. For the check on the marginal ranking fee, the client keeps the highest recorded ranking fee.

Settlement after execution

If execution could observe the marginal_ranking_fee_per_gas, for example through GASPRICE or account balances, a transaction could condition its gas use on the fee such that no consistent fee exists. An attacker could then force the builder to fill the block with its own transactions, at little cost to the attacker. As in any uniform-price auction, payments are therefore settled after the auction has cleared.

Auction design

The uniform price auction design allows transactors to signal intent (to overcome censorship if the block is full), without actually having to pay more than necessary. A transactor may not know beforehand if they will be censored, and may not wish to pay a very high fee for no reason. There are similarities to the current base fee model. Everyone specifies their willingness to pay, but pays the same minimum fee for inclusion, and this fee is burned. The combination of intents and fairness is attractive. A key difference is that the base fee is a clearing fee tracking contention for blockspace at the inter-block level, whereas the marginal ranking fee is a clearing fee tracking contention for blockspace at the intra-block level (locally for each block).

In essence, Ethereum's current fee mechanism combines a uniform-price base fee that clears congestion across blocks with a first-price priority fee allocating space within each block. What UPIL does is to expand the uniform-price component to the intra-block level by introducing a marginal ranking fee that all included transactions pay equally. Inclusion will thus be governed primarily by protocol-defined uniform clearing (assuming transactions are surfaced in ILs).

The offered ranking fee corresponds to the headroom that transactors leave between their max_fee_per_gas and the base fee. Transactors already leave headroom for the base fee to rise, and since the next block will have a 12.5% higher base fee after a full block, most transactions will offer a ranking fee of at least 12.5% of the current base fee. The increase in burned fees extracted from transactors in full blocks will be offset by a decrease in priority fees, since the builder no longer controls which transactions that are included (furthermore, includers may also receive other fees, as discussed in the section on includer rewards). The ranking fee will also help with clearing in a fair manner under congestion during sudden spikes in transaction demand. All transactions included in the same block will pay the same ranking fee, with transactions willing to pay the most during a sudden spike included in the first available block. This is arguably an improvement to the UX for Ethereum's users.

The reason for burning the marginal ranking fee instead of paying it out to includers is that includers otherwise could have an incentive to engineer artificial congestion in order to raise the fee. This is not trivial, requiring many separate entities to agree to withhold transaction inclusion for consecutive blocks. Various configurations for how to reward includers for their work are outlined in a subsequent section, including the option to distribute the marginal ranking fee to them.

The builder may sometimes, via its private orderflow or late-arriving transactions, have some ability to raise the marginal_ranking_fee_per_gas by including transactions that outrank IL transactions. But a builder that raises the marginal ranking fee will also inadvertently reduce the priority-fee headroom for all transactions, since the inclusion fee is subtracted from the max fee before calculating the capped priority fee for all transactions in the block.

Multidimensional UPIL

With one base fee per resource, as in EIP-7999, each resource can instead receive its own marginal ranking fee, while each transaction keeps a single ranking fee. With an aggregate max_fee, the ranking fee is the headroom above the base fees per unit of gas reserved in the conditional resources:

def get_ranking_fee_per_gas(tx: Transaction, block: Block) -> int:
    gas_limits = get_gas_limits(tx)
    base_cost = sum(block.base_fee_per_gas[i] * gas_limits[i] for i in RESOURCES)
    reserved_gas = sum(gas_limits[i] for i in CONDITIONAL_RESOURCES)
    return (get_max_fee(tx) - base_cost) // reserved_gas

A transaction is then willing to pay the inclusion fee if its ranking fee is at least the marginal ranking fee of every conditional resource in which it reserves gas, and it pays base_fee_per_gas[i] + marginal_ranking_fee_per_gas[i] per unit of gas used in resource i, which never exceeds its max_fee. An IL transaction is outranked in each resource in which it does not fit in (2), and the marginal ranking fee of a resource is the highest ranking fee recorded for IL transactions outranked in it. A builder that fills one resource thus raises the price only there, while lower-ranked transactions that reserve no gas in it can still be included. When constructing the block as in the Security Considerations section, the builder therefore does not stop at a valid IL transaction that does not fit, but sets the fee of each resource in which it did not fit, and continues with transactions that are still willing to pay. Since the dashed line only counts transactions ranked at least as high, the lower-ranked transactions that the builder then includes cannot undo a fee once set.

Using the notation of EIP-7999, only conditional resources are checked and priced. Transactions that consume any deconditional resource are exempt from the check, and a lack of capacity in an unconditional resource never excuses an exclusion. Fees per resource thus become relevant once several conditional resources have their own base fees.

Censorship resistance under FOCIL and UPIL

This subsection offers a comparison of the censorship resistance achieved under FOCIL and UPIL. The premise is a builder seeking to censor a transaction under different fee market designs. We begin by rudimentarily quantifying the cost $C_i$ of censoring a transaction in block $i$ ($i=0$ for the first censored block) as:

$C_i = g_df_b (1+r)^i + g_df_r + m(i, f_r).$

In this equation, $g_d$ is the gas that the builder must pay by creating so-called "dummy transactions" to fill the block, $f_b$ is the base fee for that gas, $r$ is the rate by which the base fee increases in full blocks (i.e., 12.5%), $f_r$ is the ranking_fee_per_gas of the censored transaction, and $m(i, f_r)$ is the MEV (including priority fees) forgone when forced to exclude pending transactions with a lower ranking than the censored transaction for block $i$ (the opportunity cost).

Multidimensional fee market

Under a multidimensional fee market envisioned in EIP-7706 and EIP-7999, the base fee is set individually per resource to maximize utilization of blockspace. As noted in EIP-7999, the base fee may therefore sometimes become very low for a resource, meaning that the cost of generating dummy transactions to fill the block also becomes very low. In a potential multidimensional FOCIL, it is then only necessary that one resource used by a transaction is filled to censor that transaction. Furthermore, while the base fee will increase for the resource that was filled with dummy transactions, the base fees of all other resources will not. These base fees will instead vary based on gas consumed by regular transactions included in the block. The builder can potentially vary which resource it fills the block for, to keep any base fee from exploding during prolonged censorship. Define $\mathbf{f_b}$ as the vector of base fees. The outcome for FOCIL and UPIL respectively is:

FOCIL: The cost of censorship for the first block is $C_0 = g_d\min(\mathbf{f_b})$, and thus $C_0 \to 0$ if $\min(\mathbf{f_b}) \to 0$. The cost can potentially be kept close to 0 even under continued censorship, depending on the distribution of the equilibrium base fees under no censorship and the fee elasticities of demand.

UPIL: The cost of censorship for the first block is $C_0 = g_d\min(\mathbf{f_b}) + g_df_r + m(i, f_r)$, and thus $C_0 = g_df_r + m(i, f_r)$ if $\min(\mathbf{f_b}) \to 0$. This cost can be hundreds or thousands of times higher than whatever ranking fee the censored transaction specifies, and it rises with continued censorship due to the opportunity cost of keeping all pending transactions with a lower ranking fee that consume the filled resource out of the block.

Current fee market

We now discuss the situation under the current fee market with a single base fee (ignoring the blob resource). In this case, the base fee term of the previous equation does not vanish. If the builder does not use the "slow transaction" strategies outlined in the next subsection, the outcome for FOCIL and UPIL respectively is:

FOCIL: The builder must cover the base fees: $g_df_b(1+r)^i$ of block $i$. The required amount of purchased gas $g_d$ will in the average case be $g_d=g_l/2$. However, there will be many instances where pending transactions in the public mempool or via private orderflow consume more than $g_l/2$. Censorship for one or two blocks can therefore be inexpensive even if pending transactions do not completely fill the block. The $(1+r)^i$ term grows by 12.5% per block, doubling in six blocks, and pending transactions are quickly depleted. Therefore, censorship becomes costly rather quickly: FOCIL ensures that transactions are included within a limited number of blocks if includers do their duties, but not in the first few blocks.

UPIL: The builder must cover the base fee, the ranking fee, and forego pending transactions, thus suffering a cost of $g_df_b(1+r)^i + g_df_r + m(i, f_r)$. The required gas $g_d$ is higher than in FOCIL, and—just as for the multidimensional fee market—potentially the full gas limit, because the builder cannot rely on pending transactions with a lower ranking fee for block stuffing. Due to the $g_df_r$ term, the cost for censoring a transaction for a single block can easily become a thousand times higher than whatever the transactor was willing to pay for inclusion, just as under the multidimensional fee market.

Current fee market with "slow transactions"

Note the importance of pending transactions for sidestepping the ILs in FOCIL: the cost for covering base fees when filling the block provides the CR. A strategy the builder could use to reduce the cost of censorship over a few blocks is to amass "slow transactions" through private orderflow—transactions that do not have to execute immediately. These are transactions for which the transactor is willing to substitute speed for some other benefit, predominantly rebated fees, but potentially also convenience or MEV protection. The builder (or realistically a MEV-protecting RPC endpoint) guarantees (trustfully) inclusion within some set time frame, and that the total cost for the transactor will be below the cost that would have been incurred given the base fee at the time that the tx is sent to the builder. The concept can be integrated as:

$C_i = g_df_b ((1+r)^i-s) + g_df_r + m(i, f_r).$

Here, $s$ represents the cost reduction factor relative to the initial base fee. This models a scenario where the builder has stored and promised to include blockspace-filling transactions at a fixed discount. If the rebate to transactors for slow transactions is 10%, then $s=0.9$, with the cost of censoring the first block in FOCIL reduced by 90%. Such a strategy can thus be useful for censoring a couple of blocks in a row. After around 5 blocks or less, $(1+r)^i - s > 1$, meaning that the cost is the same as the cost of censoring the first block without slow transactions. Since the supply of slow transactions would likely be limited, the strategy cannot be applied too often.

Slow transactions must be propagated privately to remain useful, and reach their full economic potential by contributing to censorship. When the value in sidestepping ILs exceeds the costs of facilitating slow transactions, the proportion of transactions propagated p2p may thus fall. On the other hand, the transactions that indeed are propagated p2p are upon IL listing guaranteed inclusion in non-full blocks, and therefore do not need to pay priority fees. The effect of FOCIL on the public mempool may therefore be negative or positive depending on the demand for censorship from builders. Alternatively, the protocol could facilitate "trustless slow transactions" by letting builders sponsor transactions offering a max fee below the prevailing base fee, for example by charging the base fee jointly for all transactions at the end of the block.

Under UPIL, slow transactions do not contribute meaningfully to censorship due to the $g_df_r + m(i, f_r)$ terms, and there is furthermore no rationale for paying a priority fee upon listing, further strengthening the public mempool.

Multidimensional gas metering

Under multidimensional gas metering, as proposed in EIP-8011 and applied to execution gas and state gas in EIP-8037, the situation is closer to the current fee market than the multidimensional fee market. There is still just one base fee, so the cost of censoring a transaction for a sustained period rises exponentially. Censorship may become slightly cheaper than currently, due to the equilibrium reduction in the base fee with a maintained slack in the block relative to the most consumed resource. On the other hand, utilization of slow transactions may become slightly less efficient.

In the current fee market, half the gas limit $g_l/2$ is consumed in the average block. Transactors spend $f_bg_l/2$ on average and the cost of censoring a block via dummy transactions is also $f_bg_l/2$. Under multidimensional gas metering, $g_l/2$ is consumed on average individually for the most used resource. Transactors however consume the higher $xg_l/2$ amount of gas on average over all resources, while the gas required for censorship remains at $g_l/2$ (filling up the most consumed resource). Here $x$ corresponds to the scaling factor achieved when gas of different resources can be consumed in parallel, a scaling factor that might end up in the range 2-4. Keeping demand and $g_l$ fixed, the base fee $f_b$ will fall, reducing the cost $f_bg_l/2$ of censoring a block in the average case. Had we instead simply increased the gas limit, CR would have been affected differently, because then the cost of censorship would also have increased according to the increase in $g_l$, such that the censoring builder would have needed to purchase more dummy transactions in the average case.

Transaction inclusion and MEV

In FOCIL, including an existing transaction is always possible without raising the inclusion fee, regardless of whether this means that an IL transaction must be excluded or not. In UPIL, if the block is full, including an existing transaction over an IL transaction willing to pay more is treated as censorship. Ostensibly, MEV and censorship are not separate topics: in many scenarios, censorship is also MEV. To displace the IL transaction offering the lowest ranking fee among IL transactions in the block, the new transaction must pay at least the ranking fee offered by that IL transaction.

Since the builder cannot freely decide which of the pending transactions to include in UPIL, it might not be able to extract all MEV from pending transactions that it could have in FOCIL. It lacks the ability to exclude IL transactions at will from full blocks. Once a transaction is in an IL, its inclusion is guaranteed if it is willing to pay at least the same as the smallest offer by other transactions that go into the block. This levels the playing field between includers and the builder, giving the includer the opportunity to offer real inclusion guarantees to transactors. In FOCIL, the protocol offers real inclusion guarantees, eventually. In UPIL, the includer offers real inclusion guarantees, immediately.

Some includers might charge transactors for their services in FOCIL, but the value of the provided services is further strengthened in UPIL. MEV might thus shift from the builder to includers in the form of fees for listing the transaction. A transaction listed by an IL has no need to pay a priority fee for inclusion. Indeed, we may even see "IL-builders" that collate full ILs as a service both in FOCIL and UPIL. Some MEV will also shift to the protocol in the form of burned ranking fees. It is natural to then consider what options the builder has, to retain some power over transaction inclusion. It may of course try to bribe includers to not list transactions. A problem for a builder trying to stay competitive is that this requires bribing all includers, and that any includer remaining faithful to its duties can earn a greater reward from transactors when others take the bribe, particularly in UPIL.

There are nuances to the design that need careful consideration before adoption. Something to be attentive to is the effect of burning the marginal ranking fee, given that avoiding the burn is not a zero-sum outcome for builders and includers. This is further discussed in the next section.

Alternative specifications for rewarding includers

Transactors might wish to reward includers in both FOCIL and UPIL for surfacing their transaction in an IL. They may recognize that the space in each IL is limited, meaning includers sometimes need to prioritize between available transactions. They might also fear that builders could bribe includers to not fulfill their duties, so that the builder can exclude unwanted transactions. As discussed previously, UPIL strengthens the position of includers, giving them in some sense equal power to the builder in deciding which transactions enter the block. For this reason, the case for rewarding includers is also stronger: an IL transaction does not require a priority fee to be included, even in full blocks—it must be included if it offers a higher ranking fee than competing transactions.

Out-of-protocol inclusion fees

If there is no in-protocol reward mechanism, individual staking service providers might start offering (trustfully) to list transactions in their next assigned IL slot, against a small fee. We might also see public orderflow of includable transactions offering a certain reward for inclusion, with includers and transactors coming to agreement via a third-party software. This can improve the UX, but also has the potential to become a centralization vector.

In-protocol inclusion fee sources

It is possible that the protocol can be of direct assistance. Three fee sources will first be reviewed, and relevant distribution mechanisms then explored.

Includer fee: One example is to allow transactions to specify an includer fee via a new field max_includer_fee_per_gas. To split the max_includer_fee_per_gas and the max_priority_fee_per_gas when they are capped by the max_fee_per_gas, the "aggregate-cap-divide" method outlined in the "pay-as-you-bid" subsection is the recommended approach. Alternatively, it is possible to distribute only the includer fee or the priority fee, depending on if the transaction was listed in an IL or not, and never both. The builder must then specify whether each transaction originated from an IL or not (at the transaction or IL level), and attesters vote against the block if the builder fails to make such an assignment when they observed the transaction in a timely IL.

Priority fee: It is possible to instead let the includers receive the priority fee if they list a transaction. The builder will have no choice but to include a transaction once it is listed by an includer, and the priority fee then serves little purpose. From the transactor's perspective, giving a priority fee to the builder for an IL transaction is a wasteful expenditure. Once again, with this option the builder must specify whether each transaction originated from an IL or not.

Marginal ranking fee: The marginal ranking fee can be distributed to includers instead of being burned. As discussed previously, one potential downside of this is the increase in rewards for engineering contention—in collaboration with builders—by first withholding transactions, and then releasing all transactions in the same block.

The question is whether includers will be able to engineer such contention, given the coordination problem at hand: withholding transactions over several slots, with several slots' includers working together, where anyone breaking the cartel could reap higher rewards from transactors paying includers for their services. Transactors might also end up leaving less headroom above the base fee if such an approach becomes systematic. Finally, we do not see builders coordinating to bring down the base fee in order to reap higher priority fees today (at the same time, the control over the priority fee is indirect, and they do not directly attain the base fee).

A potential benefit of distributing the marginal ranking fee to includers is that if the builder wishes to bribe includers to avoid contention (in order to bring up priority fees), then includers taking such a bribe would miss out on rewards for that contention (in addition to any rewards they may already miss out on from includer priority fees).

Mechanisms for distributing inclusion fees in-protocol

Four options for how to distribute the fee from any of the three in-protocol inclusion fee sources listed in the previous section will now be reviewed:

(1) Keyed distribution: Let transactors set one or several keys, with each key linking to one includer (i.e., validator ID) or to many includers (e.g., enabling all validators of an SSP to associate one key to all its validators). The protocol can then ensure that the rewards are distributed only to validators represented by a key, if it listed the transaction. This means that transactions shared with an includer privately still can use an in-protocol fee distribution without risking dilution. Options (2)-(4) below can be applied when the transactor does not provide a key or when the keyed includer(s) failed to list the transaction.

(2) Individual distribution: Split the fee between all includers listing a transaction. All includers then have an incentive to list a transaction, with the incentive being stronger if other includers have ignored it. It may however lead to unnecessary duplicate listings, since there is an incentive to list transactions even after they have been observed in another IL. It may also lead includers to integrate with builders to propagate the optimal IL by leveraging the builder's last look.

(3) Seniority distribution: Use a "seniority waterfall" rule. The transaction hash is combined with includer validator IDs to assign an order of seniority by which each includer has the right to the full includer fee. If a transaction's senior includer lists it, there is no purpose for a less senior includer to also list it. The idea is to promote a broader coverage while maintaining fairness. The mechanism will however not remove all duplicates, as a more senior includer will still list a transaction already listed by a less senior includer. It is straightforward to combine (1) with (3), by giving keyed includers the highest seniority, with remaining includers assigned a seniority based on the transaction hash. This could also prevent transaction hash grinding in the case when some senior includers are more reliable than others. Under the priority fee redistribution rule, the builder is in essence appended to the waterfall, having the lowest seniority.

To further reduce duplicates, a potential extension could allow includers to stagger their inclusion list so that they first broadcast transactions they are the most senior includer for, and then append the list with transactions they are less senior for or that arrive late. This can also increase the includer's expected value (EV) since an early broadcast increases margins and the late broadcast allows for better coverage. Another way to increase EV under this rule is to combine it with (4) below. Each partial list must have timeliness observed in isolation, and the rules for IL equivocation must be amended to allow append operations.

(4) Collective distribution: Distribute the includer fee collectively to all includers. There is then no need to keep track of who propagated which transaction in which IL. It also serves to promote independence of includers. Builders cannot help includers to extract a relatively higher proportion of the ranking fee by constructing an optimal IL for them from their last look. Includers are further encouraged to facilitate as broad coverage as possible, given that there are no incentives to propagate a (high-paying) transaction if one of the other includers already propagates it. This means that some includers can pivot to propagating their ILs early, while others observe and select late or missed transactions.

A downside is that includers are not incentivized individually to do a good job, and gain individually only 1/IL_COMMITTEE_SIZE of any ranking fee of a transaction they uniquely include. The point however is that the collective distribution alters the meaning of "doing a good job", aligning protocol design goals with includer incentives.

Builders may try to bribe includers to not include transactions. If an includer will receive 1/IL_COMMITTEE_SIZE of any collective rewards for not including a transaction that eventually is not surfaced by any IL, then they may elect to leave it out to preserve space for other transactions. However, the builder would then also forego a sum corresponding to the entire collective rewards by paying out such bribes to the includers. In the setup where the priority fee is distributed to includers if they surface a transaction, the builder would thus need to forego the entire priority fee it stands to receive.

However, due to the gradual construction of the aggregate IL, the builder can offer higher bribes than 1/IL_COMMITTEE_SIZE to the last remaining includers, to keep some transactions not yet included out of the IL aggregate. The last remaining includer that spots a late transaction might be able to choose between including it to receive 1/IL_COMMITTEE_SIZE of the priority fee, or to receive 1/2 of a conditional priority fee as a bribe to not include it.

Alternative specifications for the auction and transaction format

Dedicated ranking fee field

This EIP ranks transactions using max_fee_per_gas, without a dedicated field for the ranking fee, to keep the UX simple. Transactors may not care about how much they have to pay to specifically cover the marginal_ranking_fee_per_gas as they have already specified how much they are willing to pay for inclusion in total with the max_fee_per_gas. This also has the benefit that we do not need to change the transaction format.

A potential downside is that transactors cannot differentiate between how high contention fees they are willing to pay to cover the base fee and to cover the marginal ranking fee in full blocks. The builder has some control over the marginal ranking fee: if there are transactions outside of the ILs that are willing to pay a higher fee for inclusion than the IL transactions, then it may or may not elect to include those transactions. This influences the marginal ranking fee which is determined by the highest offered ranking fee of an excluded IL transaction. It is more difficult for the builder to control the base fee. Transactors wishing to limit their ranking fees, while at the same time giving ample room for the base fee to rise before inclusion, may therefore find that this does not offer sufficient expressiveness.

A dedicated field max_ranking_fee_per_gas could cap the offered ranking fee, with get_ranking_fee_per_gas returning min(tx.max_ranking_fee_per_gas, get_max_fee_per_gas(tx) - block.base_fee_per_gas) and transaction processing requiring max_ranking_fee_per_gas >= marginal_ranking_fee_per_gas. Instead of introducing a new transaction type for this purpose, the field could be introduced for frame transactions (EIP-8141). If the fee fields of frame transactions follow the aggregate max_fee of EIP-7999, the field would take the form of an aggregate max_ranking_fee, capping the part of the max_fee that is available for ranking.

Pay-as-you-bid auction

Two alternative pay-as-you-bid auction designs will now be highlighted. The first, which relies on the dedicated ranking fee field of the previous subsection, is that transactors always pay their offered ranking fee upon inclusion. In this case, there is no risk that the includers or the builder engineer contention for blockspace to drive up the price, and the full ranking fee is distributed to includers instead of being burned, using the collective method previously described. The post-execution check stays the same as in the main specification, with the only difference that the check on outranked IL transactions concerning the marginal_ranking_fee_per_gas (dashed line in the figure) is removed.

Transaction processing is altered to, e.g., facilitate payment to includers. The split between the specified max_ranking_fee_per_gas and max_priority_fee_per_gas can be done in two ways. Either the ranking fee takes precedence over the priority fee as previously, or the two are given equal precedence. In the first case, the same strategy as in the main specification can be used. In the second case, the two fees can first be summed into a single max_payout_fee_per_gas, and the capped payout_fee_per_gas then distributed proportionally to the size of the original max ranking/priority fees.

Additionally, the builder is given the ability to set a priority_fee_shift_per_gas parameter for each transaction to allow transactions without a sufficient ranking_fee_per_gas to become eligible for inclusion in the block. We can envision a scenario where the builder otherwise integrates deeper with transactors to help them set the optimal ranking fee anyway. Such an integration could have detrimental effects on the builder competitive landscape, and it is therefore desirable to allow the builder—who has the last look when building blocks—to raise the ranking fee as it sees fit in a trustless manner. This means that many transactors will elect to just provide a priority fee, and that there is limited downside for transactors using older transaction types.

If a transactor believes that the builder may leave their transactions out of the block, then it is still well served by providing a ranking fee and propagating the transaction publicly so that it can be surfaced by an IL. The builder needs to boost all transactions up to the ranking fee of the transaction it wishes to exclude from the block, and a modest ranking fee can therefore be sufficient to ensure inclusion. The spec shows the ranking fee taking precedence and omits some overflow checks:

for i, unnormalized_transaction in enumerate(transactions):
    ...
    # After this existing check...
    assert transaction.max_fee_per_gas >= transaction.max_priority_fee_per_gas

    # ..Optionally shift a proportion of the priority fee over to the ranking fee
    assert block.priority_fee_shift_per_gas[i] <= transaction.max_priority_fee_per_gas
    max_priority_fee_per_gas = transaction.max_priority_fee_per_gas - block.priority_fee_shift_per_gas[i]

    # ..then fill in order of: base fee, ranking fee, priority fee
    max_shifted_ranking_fee_per_gas = transaction.max_ranking_fee_per_gas + block.priority_fee_shift_per_gas[i]
    ranking_fee_per_gas = min(max_shifted_ranking_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas)
    inclusion_fee_per_gas = block.base_fee_per_gas + ranking_fee_per_gas
    priority_fee_per_gas = min(max_priority_fee_per_gas, transaction.max_fee_per_gas - inclusion_fee_per_gas)
    effective_gas_price = inclusion_fee_per_gas + priority_fee_per_gas

    ...
    # ..after refunding the transactor as normal, the includer fee is computed
    includer_fee = gas_used * ranking_fee_per_gas // IL_COMMITTEE_SIZE
    # ..balances of the `IL_COMMITTEE_SIZE` includers increased
    for j in range(IL_COMMITTEE_SIZE):
        self.account(block.includer(j)).balance += includer_fee
    # ..and the priority fee is distributed to the builder just as in EIP-1559
    self.account(block.author).balance += gas_used * priority_fee_per_gas

The consensus layer (CL) constructs a list of execution-layer (EL) payout addresses for the slot, ordered by IL committee index, and provides it to the EL via a new engine API call: engine_setIncluderPayoutsV1. For committee members with 0x00 credentials, the CL inserts the zero address 0x000..., thus burning these rewards.

Pay-as-you-bid auction using only priority fee

A second alternative is to let the priority fee act as a ranking fee in a pay-as-you-bid auction. The priority fee is distributed collectively to includers if it was surfaced by at least one inclusion list. Otherwise it is distributed to the builder. Only priority fees distributed to the includers count towards the transaction's ranking.

The builder specifies whether an included transaction was surfaced by an IL via a bitfield IL_transaction in the payload body, of equal length to the number of transactions. For all transactions where IL_transaction[i]=FALSE, the attesters check that they are not in any observed timely ILs, and otherwise return INCLUSION_LIST_UNSATISFIED. For these transactions, the builder can also apply the priority_fee_shift_per_gas described in the previous subsection, which however here is the same for all transactions since none have an initial ranking fee. Under EIP-1559, transaction processing is changed as follows:

...
for i, unnormalized_transaction in enumerate(transactions):
  ...
    # Processing begins after this existing line
    signer.balance += gas_refund * effective_gas_price

    # Redistribute priority fee
    if block.IL_transaction[i]==TRUE:
        ranking_fee_per_gas = priority_fee_per_gas
        priority_fee_per_gas = 0
    else:
        assert block.priority_fee_shift_per_gas <= priority_fee_per_gas
        ranking_fee_per_gas = block.priority_fee_shift_per_gas
        priority_fee_per_gas -= block.priority_fee_shift_per_gas

    # The fee given to each includer (small division remainder burned)
    includer_fee = gas_used * ranking_fee_per_gas // IL_COMMITTEE_SIZE
    # Increase the balances of the `IL_COMMITTEE_SIZE` includers 
    for j in range(IL_COMMITTEE_SIZE):
        self.account(block.includer(j)).balance += includer_fee

    # Proposer receives the priority fee
    self.account(block.author).balance += gas_used * priority_fee_per_gas

Payout to includers uses the same CL construction as in the previous subsection and the check on the marginal_ranking_fee_per_gas (dashed line in the figure) is once again removed.

If the ranking was based on the priority fee paid to the builder, the builder could offer kickbacks, allowing transactors to achieve a high ranking for free. To prevent this, the ranking portion of the fee must be distributed to a wider set of validators or be burned. Any arbitrary fee split between the builder and includers when IL_transaction[i]=FALSE would likely prove suboptimal and encourage off-chain agreements and builder–includer integration to circumvent the intended mechanism.

Allow builder to shift priority fee under UPIL

With a dedicated ranking fee field, the priority_fee_shift_per_gas could be used also in the main UPIL specification. The primary rationale is that transactions with a max_ranking_fee_per_gas below the marginal_ranking_fee_per_gas then also can be included, by having the builder reallocate the priority fee. Another option is to simply charge all base fees and ranking fees jointly for all transactions at the end of the block, as previously discussed.

UPIL batch auctions

A more extensive modification of the protocol is to make use of the improved CR and pricing of intra-block contention to eliminate the slack in the block, targeting 100% of the gas limit to facilitate scaling. The base fee can in such an implementation either be removed entirely, or the price information obtained via the marginal ranking fee can be relied upon for appropriate increases to the base fee.

Backwards Compatibility

Transactions using the EIP-1559, EIP-4844 or EIP-8141 transaction formats can with this change spend up to their entire max_fee_per_gas to cover the marginal_ranking_fee_per_gas in blocks with high contention. Previously, the max_fee_per_gas could only be consumed by the base_fee_per_gas (which grows slowly each block) or the priority_fee_per_gas (which can be explicitly capped). A user setting max_fee_per_gas to twice the current base_fee_per_gas, while using a negligible priority_fee_per_gas, may be surprised to see the entire max_fee_per_gas consumed directly in the next block. However, this also implies that contention was high, and that they may have needed to spend the entire max_fee_per_gas for inclusion a few blocks later anyway. Importantly, the total fee paid will never exceed the max_fee_per_gas the user originally authorized.

Since transactions are charged at their max_fee_per_gas until the end of the block, a signer has less balance available than under EIP-1559, both during its transaction and for its later transactions in the block, and the coinbase receives priority fees only at the end of the block. The GASPRICE opcode may understate the price paid in blocks with a positive marginal_ranking_fee_per_gas, so contracts that reimburse gas according to it may pay too little.

Security Considerations

This EIP does not allow the builder to control which transactions that go into the block, with implications on CR and MEV. To retain full control over the block's content, the builder would have to bribe includers to not surface unwanted transactions. A concern then is that the builder bribes includers to not surface transactions, such that it can build the most profitable block, by excluding unwanted transactions. However, even if all includers were to be willing to forgo their duty to uphold CR if there is a profit to be made, the profit from surfacing transactions in the IL against a fee would reasonably be higher than whatever bribe a competitive builder is able to pay; especially if some includers have already taken the bribe, making remaining IL space more valuable. The option otherwise remains to distribute the marginal ranking fee to includers.

For frame transactions, the builder chooses the index at which an excluded transaction is evaluated. As described in EIP-8369, a frame transaction is therefore only guaranteed to be protected, and to set the marginal ranking fee, if it remains valid at every index that the builder could claim.

A builder can always construct a block that passes the check by filling it with the highest-ranked transactions in batches, executing each batch in any order. Its candidate transactions include all IL transactions. The builder forms a batch by taking all remaining candidates with the highest ranking fee, then all with the next ranking fee, and so on, for as long as their combined gas reservations fit in the remaining gas in both dimensions. It executes the batch in any order and then retries the IL transactions of the batch that failed until none of them can be appended, since a transaction executed later in the batch may have made them valid. It then forms the next batch from the remaining gas. If the candidates with the next ranking fee do not fit together, the builder instead appends them in any order if they fit and are valid, attempting them repeatedly until none of them can be appended. If a valid IL transaction with this ranking fee then still does not fit, and does not reserve more than TX_MAX_GAS_LIMIT in state gas, the builder sets the marginal_ranking_fee_per_gas to this ranking fee and stops. Otherwise, it continues with the next batch. If the builder never stops, the fee is 0. For a frame IL transaction that was not appended, the builder claims the index of its last attempt.

By the end of the batch of an IL transaction, all transactions ranked at least as high have been executed, and lower-ranked ones can only count against it. If the IL transaction still fails after the retries, it is therefore invalid in (3a), or in (3b) at the index of its last attempt, while it fits in (2), since its reservation is part of the batch. When the candidates with a ranking fee do not fit together, the partial block at the last attempt of each of them holds exactly the transactions that (2) and the dashed line count. Every IL transaction that was not appended is thus outranked, invalid, or not willing to pay the inclusion fee, and the fee is set as required. IL transactions from earlier batches are not retried, since appending them could make IL transactions ranked below them valid after the block has run out of room. The builder may also order the transactions differently, for example to extract MEV, as long as the block passes the check.

Copyright

Copyright and related rights waived via CC0.