A transaction pricing mechanism with a fixed-per-block network fee and a median inclusion fee with additive updates.
Abstract
There is a base fee per gas in protocol, which can move up or down by a maximum of 1/8 in each block. The base fee per gas is adjusted by the protocol to target an average gas usage per block instead of an absolute gas usage per block. The base fee is increased when blocks are over the gas limit target and decreases when blocks are under the gas limit target. Transaction senders specify their fees by providing only one value:
The fee cap which represents the maximum total (base fee + gas premium) that the transaction sender would be willing to pay to get their transaction included, resembles the current maximum gas price specified by senders but in this protocol change proposal the final gas price paid, most of the time, will be lower than the proposed by the transaction sender.
Then there is a gas premium that is directly computed as 50% of (fee cap - base fee). This gas premium gets added onto the base fee to calculate the gas price that will be used in the weighted median computation. The gas premium, determined directly by a specified fee cap, can either be set to a fairly low value to compensate miners for uncle rate risk only with the base fee, or to a high value to compete during sudden bursts of activity. Using all transactions that the miner wants to include in the block, a weighted median gas premium is computed, not considering in the computation 5% of gas price outliers on the upper-side for extra robustness against miner manipulation.
Motivation
We target the following goals:
Gas prices spikes are mathematically smoothed out. EIP1559 does not seems to really tackle gas premium volatility and UX.
Maintain gas price preference, i.e. transaction senders willing to pay extra in fees will be rewarded with early preferential inclusion in the blocks, because the miners want to maximize their profits and include transactions with higher fee caps first to maximize the median.
Final gas price paid by the sender is, most of the time, smaller than the maximum gas price specified by sender.
Gas pricing is more robust to sender manipulation or miner manipulation.
Ethereum currently prices transaction fees using a simple auction mechanism, where users send transactions with bids (“gasprices”) and miners choose transactions with the highest bids, and transactions that get included pay the bid that they specify. This leads to several large sources of inefficiency:
Current extreme volatility of gas prices is hurting user experience: if you observe online gas price metrics, the current trends in recommended gas prices can change substantially by the minute, making the user experience in the network very awkward. Also, gas volatility makes the mining business more unpredictable and costly, because miners need to spend money hedging the risks.
Mismatch between volatility of transaction fee levels and social cost of transactions: bids to include transactions on mature public blockchains, that have enough usage so that blocks are full, tend to be extremely volatile. On Ethereum, minimum bids range between 1 nanoeth (10^9 nanoeth = 1 ETH), but sometimes go over 100 nanoeth and have reached over 200 nanoeth. This clearly creates many inefficiencies, because it’s absurd to suggest that the cost incurred by the network from accepting one more transaction into a block actually is 200x more when gas prices are 200 nanoeth than when they are 1 nanoeth; in both cases, it’s a difference between 8 million gas and 8.02 million gas.
Needless delays for users: because of the hard per-block gas limit coupled with natural volatility in transaction volume, transactions often wait for several blocks before getting included, but this is socially unproductive; no one significantly gains from the fact that there is no “slack” mechanism that allows one block to be bigger and the next block to be smaller to meet block-by-block differences in demand.
Inefficiencies of first price auctions: The current approach, where transaction senders publish a transaction with a bid a maximum fee, miners choose the highest-paying transactions, and everyone pays what they bid. This is well-known in mechanism design literature to be highly inefficient, and so complex fee estimation algorithms are required. But even these algorithms often end up not working very well, leading to frequent fee overpayment. We need a more stable fee metric that is computed inside the protocol.
The proposal in this EIP is to start with a base fee amount which is adjusted up and down by the protocol based on how congested the network is. When the network exceeds the target per-block gas usage, the base fee increases slightly and when capacity is below the target, it decreases slightly. Because these base fee changes are constrained, the maximum difference in base fee from block to block is predictable. This then allows wallets to auto-set the gas fees for users in a highly reliable fashion. It is expected that most users will not have to manually adjust gas fees, even in periods of high network activity. For most users the base fee will be estimated by their wallet and a small gas premium related to the urgency and the priority they want to instill into the transaction.
Specification
Definitions
This is a classic fork without a long migration time.
FORK_BLOCK_NUMBER: TBD. Block number at or after which EIP-3416 transactions are valid.
GAS_TARGET_MAX_CHANGE: 1 // 1024.
BLOCK_GAS_USED: total gas consumed by transaction included in the block.
PARENT_GAS_USED: same as BLOCK_GAS_USED for parent block.
CURRENT_BLOCK: The current block that is being worked with (either being validated, or being produced).
BASE_FEE: 16th item in the block header. Represents the amount of attoeth burned for every unit of gas a transaction uses.
PARENT_BASE_FEE: same as BASE_FEE for parent block.
BASE_FEE_MAX_CHANGE: 1 // 8
INITIAL_BASE_FEE : Median gas price in FORK_BLOCK_NUMBER - 1.
Process
At block.number == FORK_BLOCK_NUMBER we set BASE_FEE = INITIAL_BASE_FEE
BASE_FEE is set, from FORK_BLOCK_NUMBER + 1, as follows
Let GAS_DELTA = (PARENT_GAS_USED - PARENT_GAS_TARGET) // PARENT_GAS_TARGET (possibly negative).
Set BASE_FEE = PARENT_BASE_FEE + GSA_DELTA * BASE_FEE_MAX_CHANGE
Transactions since FORK_BLOCK_NUMBER are encoded the same as the current ones rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s]) where v,r,s is a signature of rlp([nonce, gasPrice, gasLimit, to, value, data]) and gasPrice is the FEE_CAP specified by the sender according to this proposal.
To produce transactions since FORK_BLOCK_NUMBER, the new FEE_CAP field (maintaining legacy name of gasPrice in the transaction) is set as follows (and the GAS_PREMIUM is computed as specified):
FEE_CAP: tx.gasPrice, serves as the absolute maximum that the transaction sender is willing to pay.
GAS_PREMIUM = (FEE_CAP - BASE_FEE) / 2 serves as a sender-preferred median premium to the miner, beyond the base fee.
If FEE_CAP < BASE_FEE then the transaction is considered invalid and cannot be included in the current block, but might be included in future blocks.
During transaction execution, for EIP3416 transactions we calculate the cost to the tx.origin and the gain to the block.coinbase as follows:
Set GASPRICE = BASE_FEE + median((tx_i.gasPrice - BASE_FEE) / 2) among all transactions tx_i included in the same block, weighted by gas consumed and not including the top 5% of outlier gas price in calculation. By weighted median without 5% of the upper-side outliers, we mean that each gas unit spent is ordered according to the corresponding transaction by BASE_FEE + tx.gasPrice / 2 and then the value chosen will be the one separating the lower 95% in two parts.
Let GASUSED be the gas used during the transaction execution/state transition.
The tx.origin initially pays GASPRICE * tx.gasLimit, and gets refunded GASPRICE * (tx.gasLimit - GASUSED).
The miners can still use a greedy strategy to include new transactions in the proposed blocks by adding the transactions ordered by larger FEE_CAP first. This is similar to how current blocks are filled, and is a consequence of FEE_CAP and GAS_PREMIUM being a positive linear function of each other.
Rationale
The rationale behind the premium being 50% of (fee cap - base fee) is that at any given point the average network sender has an average fee cap, and we assume that between base fee and fee cap the sender has no specific preference, as long as the transaction is included in some block. Then, the sender is happy with a median premium among this uniform range. Another justification can be that the user also knows that this new version of the pricing protocol for the complete block uses a median, then is fair for him to apply a median within his preferential range, assuming an uniform sampling there. Simulations (here) with Ethereum gas data shows indeed that median one of the most robust metric.s
The 5% top outliers removal, not considered in the median, or similar number, is to give extra robustness against miner manipulation, because as current network utilization has been around 97% for the last 6 months the miners can include their own transactions on the empty 3% to try to manipulate and increase the median price (even this manipulation effect will be very small on the final price).
The rationale for the BASE_FEE update formula is that we are using an additive version (PARENT_BASE_FEE + GAS_DELTA * BASE_FEE_MAX_CHANGE) to avoid an attack of senders sending this fee to zero. This attack was simulated and observed for multiplicative formula proposed in previous version (PARENT_BASE_FEE + PARENT_BASE_FEE * GAS_DELTA * BASE_FEE_MAX_CHANGE). See an article about the attack and the simulation here.
Another rationale for the additive BASE_FEE update formula is that it guarantees (see this article) that the optimal execution strategy (scheduling broadcasts in order to pay less fee) for a batch of nonurgent transactions is to spread the transactions across different blocks which in turn helps to avoid network congestion and lowers volatility. For the multiplicative formula, it is exactly the reverse, that is, spikes (dumping all your transactions at once) are incentivized as described here.
The rationale for the BASE_FEE_MAX_CHANGE being 1 // 8 is that the BASE_FEE is designed to be very adaptative to block utilization changes.
Backwards Compatibility
The backward compatibility is very straightforward because there are no new fields added to the transactions. Pricing of the gas per block on the miner/validator side is still fast to compute but a little more complex. Changes only affect miners/validators. Wallets are no affected by this proposal.
Test Cases
TBD.
Security Considerations
Senders cannot manipulate the minimum fee because the minimum BASE_FEE is controlled by the miners with small increments or decrements on each new block proposed.
Above the BASE_FEE the senders have a very limited ability to manipulate and lower the final gas price they pay because they have to move the weighted median close to BASE_FEE and, as we know, this is a very robust statistic.
Miners have a very limited ability to manipulate and raise the final gas price paid by senders above BASE_FEE because to influence the final gas price they have to stuff fake transactions beyond the top 5% of the blocks. In average and currently, only the top 3% of the block is empty, so to fill-up 5% of the block they need to start dropping profitable transactions to reach 5%. Only beyond 5% of the top block gas they can start moving the median a little and the median is still a very robust statistic, not liable to being easily manipulated.