-
Notifications
You must be signed in to change notification settings - Fork 49
Add minimum base fee design doc #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
82a977b
design doc: add minimum base fee
niran 03910ac
Update the table to use powers of two
niran c30b977
Make sure extraData version bump clearer
niran 2905796
Reformat metadata
niran a56d3c1
Add a note on gas target vs congestion threshold
niran 9277a5f
Specify that 0 disables the minimum base fee
niran 2e1c720
Add a note about censorship
niran d0f5bf8
Add backwards compatibility notes
niran 048b4f7
Add a time saved column to the log2 table
niran File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| # Minimum Base Fee | ||
|
|
||
| | | | | ||
| | ------------------ | -------------------------------------------------- | | ||
| | Author | @niran | | ||
| | Created at | 2025-07-01 | | ||
|
|
||
| --- | ||
|
|
||
| # Purpose | ||
|
|
||
| This document proposes establishing a configurable minimum base fee for OP Stack chains to shorten the length of priority fee auctions. | ||
|
|
||
| # Summary | ||
|
|
||
| We introduce a new configuration value that can be modified via `SystemConfig`: | ||
|
|
||
| | Name | Type | Default | Meaning | | ||
| |------------------|---------|---------|---------| | ||
| | `minBaseFeeLog2` | `uint8` | `0` | The log2 of the minimum base fee that can be charged for a transaction. 0 disables the minimum base fee entirely. | | ||
|
|
||
| These values are updated via a new function in `SystemConfig`: | ||
|
|
||
| ```solidity | ||
| function setMinBaseFeeLog2(uint8 minBaseFeeLog2) external onlyOwner; | ||
| ``` | ||
|
|
||
| This function will emit a `ConfigUpdate` log-event, with a new `UpdateType`: `UpdateType.MINIMUM_BASE_FEE`. | ||
|
|
||
| Like [Holocene's dynamic EIP 1559 parameters](https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/holocene/exec-engine.md#eip-1559-parameters-in-block-header), the minimum base fee is included in the block header's `extraData` field. | ||
|
|
||
| ## Minimum Base Fee in Block Header | ||
|
|
||
| The `extraData` header field of each block must have the following format: | ||
|
|
||
| | Name | Type | Byte Offset | | ||
| | ---------------- | ------------------ | ----------- | | ||
| | `version` | `u8` | `[0, 1)` | | ||
| | `denominator` | `u32 (big-endian)` | `[1, 5)` | | ||
| | `elasticity` | `u32 (big-endian)` | `[5, 9)` | | ||
| | `minBaseFeeLog2` | `u8` | `[9, 10)` | | ||
|
|
||
| Additionally, | ||
|
|
||
| - `version` must be 1 (incremented from 0) | ||
| - `denominator` must be non-zero | ||
| - there is no additional data beyond these 10 bytes | ||
|
|
||
| Note that `extraData` has a maximum capacity of 32 bytes (to fit in the L1 beacon-chain `extraData` data-type) and its | ||
| format may be modified/extended by future upgrades. | ||
|
|
||
| ## Minimum Base Fee in `PayloadAttributesV3` | ||
|
|
||
| The [`PayloadAttributesV3`](https://github.com/ethereum-optimism/specs/blob/a773587fca6756f8468164613daa79fcee7bbbe4/specs/protocol/exec-engine.md#extended-payloadattributesv3) | ||
| type is modified to add an extra byte for `minBaseFeeLog2` to the `eip1559Params` field: | ||
|
|
||
| ```rs | ||
| PayloadAttributesV3: { | ||
| timestamp: QUANTITY | ||
| prevRandao: DATA (32 bytes) | ||
| suggestedFeeRecipient: DATA (20 bytes) | ||
| withdrawals: array of WithdrawalV1 | ||
| parentBeaconBlockRoot: DATA (32 bytes) | ||
| transactions: array of DATA | ||
| noTxPool: bool | ||
| gasLimit: QUANTITY or null | ||
| eip1559Params: DATA (9 bytes) or null | ||
| } | ||
| ``` | ||
|
|
||
| # Problem Statement + Context | ||
|
|
||
| Ethereum's EIP 1559 has successfully made first-price auctions for transaction fees rare. Users used to always have to set a fee that was high enough to outbid all other transactions to be included in a block. Now they can set a maximum fee that is high enough to cover the base fee with a margin for base fee increases caused by congestion and expect to be included in a block without ever having to outbid other transactions. In some conditions, Ethereum-based chains still experience first-price auctions via priority fees, and this happens more often on OP Stack chains. During these periods, many users experience a denial of service. They submit transactions that they expect to be included in a block but they are not included for long periods of time (and may be dropped from the mempool entirely). | ||
|
|
||
| Priority fee auctions occur when blocks are near the gas limit or when the base fee is significantly below the market-clearing fee. Other than full blocks, the most common cause of priority fee auctions today is [batcher sequencer throttling](https://docs.optimism.io/operators/chain-operators/configuration/batcher#batcher-sequencer-throttling), which intentionally processes fewer transactions to avoid a backlog of batches that need to be posted to L1. Similarly, if the sequencer runs out of time to execute transactions for a block, the transactions that get included will be the ones with the highest priority fees. | ||
|
|
||
| It can also be argued that **scaled** rollups will run well below their gas target in typical conditions, which makes the "gas target" more of a "congestion threshold." Ethereum's base fees are _congestion_ fees, and scaled rollups should rarely be congested: their maximum capacity should be much higher than typical usage. A minimum base fee would be charged in the vast majority of cases, and higher fees would only be charged when the rollup needs to discourage transactions near its capacity. In this scenario, we would need to think of congestion often starting from base fees that are the lowest the chain will allow. Today, that's 1 wei, which takes far too long to adjust to the market prices that are needed to prevent first-price auctions using priority fees. | ||
|
|
||
| When the base fee is at or near its minimum value, it can only increase as fast as the `BASE_FEE_MAX_CHANGE_DENOMINATOR` of EIP 1559 allows. Ethereum has this value set to `8`. The maximum the base fee can increase in one block is `(ELASTICITY_MULTIPLIER - 1) / BASE_FEE_MAX_CHANGE_DENOMINATOR`, which is `(2 - 1) / 8 = 1/8` or 12.5%. That produces a doubling time of 5.9 blocks at 12 seconds each, or 71 seconds. On OP Mainnet, the denominator is `250`, which produces a maximum increase per block of 0.4% and a doubling time of 17.7 blocks at 2 seconds each, or 35be seconds. On Base, the denominator is `50`, which produces a maximum increase per block of 2% and a doubling time of 35 blocks at 2 seconds each, or 70 seconds. Base's elasticity was recently changed from `2` to `3`, which gives a maximum increase per block of 4% and a doubling time of 17.7 blocks at 2 seconds each, or 35 seconds. | ||
|
|
||
| The current prevailing base fee on Base today is slightly below 0.001 gwei. It takes 411 blocks (13.7 minutes) for the base fee to increase from 1 wei to 0.001 gwei if every block is completely full at the gas limit. (In practice, we see 70% full blocks in these scenarios, so the fees take even longer to increase.) If we could configure a minimum base fee of 0.0001 gwei, we could speed up the fee adjustment (and the corresponding end of the priority fee auction) to 59 blocks, or a little under two minutes. We could even eliminate the priority fee auctions that occur while the chain is adjusting from the minimum to the typical market fee price by setting the minimum to that price to begin with. [Arbitrum One sets a minimum of 0.01 gwei](https://docs.arbitrum.io/how-arbitrum-works/gas-fees#child-chain-gas-pricing). At recent ETH prices around $2500, any of these three minimum base fees (which correspond to `2**20` through `2**24`) would be much less than one cent for a USDC transfer (about 40,500 gas). As ETH prices change, rollup operators will want to adjust the minimum base fee accordingly. | ||
joshklop marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| | log2(minBaseFee) | Minimum Base Fee (gwei) | USDC Transfer Cost (ETH) | Cost (USD, ~$2,500/ETH) | Time Saved on OP Mainnet (minutes) | | ||
| | ---------------- | ----------------------- | ------------------------ | ----------------------- | ----------------------------------- | | ||
| | 19 | 0.000524288 | 2.12e-8 | $0.0000531 | 11.2 | | ||
| | 20 | 0.001048576 | 4.25e-8 | $0.000106 | 11.8 | | ||
| | 21 | 0.002097152 | 8.49e-8 | $0.000212 | 12.4 | | ||
| | 22 | 0.004194304 | 1.70e-7 | $0.000425 | 13.0 | | ||
| | 23 | 0.008388608 | 3.40e-7 | $0.000849 | 13.6 | | ||
| | 24 | 0.016777216 | 6.79e-7 | $0.00170 | 14.2 | | ||
| | 25 | 0.033554432 | 1.36e-6 | $0.00340 | 14.8 | | ||
| | 26 | 0.067108864 | 2.72e-6 | $0.00679 | 15.3 | | ||
| | 27 | 0.134217728 | 5.44e-6 | $0.0136 | 15.9 | | ||
|
|
||
| # Backwards Compatibility | ||
|
|
||
| We expect this change to have little impact on applications. Applications estimate the base fee component of their costs by looking at the previous block's base fee and potentially adding a margin of [12.5%](https://ethereum.org/en/developers/docs/gas/#base-fee) or [100%](https://www.blocknative.com/blog/eip-1559-fees) for base fee increases caused by congestion. | ||
|
|
||
| # Alternatives Considered | ||
niran marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| * **Hard-code a minimum base fee** (like [EIP 7762](https://eips.ethereum.org/EIPS/eip-7762)). This is the simplest solution, but it doesn't give the chain operator any flexibility to adjust the minimum base fee. Establishing a Superchain-wide consensus on a minimum base fee seems difficult, especially if the value will have to wait for the next fork to be changed. | ||
| * **Link the minimum base fee to an outside price signal** (like [EIP 7918](https://eips.ethereum.org/EIPS/eip-7918)). This approach avoids choosing a magic number for the minimum base fee and has more elegant economics: the fee doesn't drop when we have a good signal that reducing the base fee wouldn't increase gas usage. The downside is that it's harder to reason about the right values to use in the formula, which makes it hard to build a consensus around. A configurable minimum base fee gives us an option that L1 doesn't have: it allows rollup operators to change the minimum base fee as needed to ensure the fee market is working properly. | ||
niran marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * **Do nothing**. We expect to make batcher sequencer throttling unnecessary by repricing calldata correctly, but setting a minimum base fee still gives us two big wins: we can protect the fee market from long periods of first-price auctions in a generalized way, and we can make sure OP Stack is prepared for scaled rollups that persistently operate below their gas target. | ||
|
|
||
| # Risks & Uncertainties | ||
|
|
||
| * **The rollup operator can attempt to censor the chain with an extremely high minimum base fee**. The minimum base fee can be as high as 2^255, which is more than the total supply of ETH (~2^87). As a workaround, deposit transactions can force inclusion without being affected by the minimum base fee because they [pay for gas on L1 using a separate fee market](https://docs.optimism.io/stack/transactions/deposit-flow#denial-of-service-dos-prevention). | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.