feat: make base fee computation parameters configurable via chain spec (#3992)

This commit is contained in:
Roberto Bayardo
2023-08-07 08:52:27 -07:00
committed by GitHub
parent aaf2d2cf19
commit 9569debbb5
24 changed files with 211 additions and 78 deletions

View File

@@ -1,11 +1,13 @@
//! Helpers for working with EIP-1559 base fee
use crate::constants;
/// Calculate base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec
pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u64) -> u64 {
let gas_target = gas_limit / constants::EIP1559_ELASTICITY_MULTIPLIER;
pub fn calculate_next_block_base_fee(
gas_used: u64,
gas_limit: u64,
base_fee: u64,
base_fee_params: crate::BaseFeeParams,
) -> u64 {
let gas_target = gas_limit / base_fee_params.elasticity_multiplier;
if gas_used == gas_target {
return base_fee
}
@@ -15,14 +17,14 @@ pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u6
1,
base_fee as u128 * gas_used_delta as u128 /
gas_target as u128 /
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128,
base_fee_params.max_change_denominator as u128,
);
base_fee + (base_fee_delta as u64)
} else {
let gas_used_delta = gas_target - gas_used;
let base_fee_per_gas_delta = base_fee as u128 * gas_used_delta as u128 /
gas_target as u128 /
constants::EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR as u128;
base_fee_params.max_change_denominator as u128;
base_fee.saturating_sub(base_fee_per_gas_delta as u64)
}
@@ -54,7 +56,12 @@ mod tests {
for i in 0..base_fee.len() {
assert_eq!(
next_base_fee[i],
calculate_next_block_base_fee(gas_used[i], gas_limit[i], base_fee[i])
calculate_next_block_base_fee(
gas_used[i],
gas_limit[i],
base_fee[i],
crate::BaseFeeParams::ethereum(),
)
);
}
}

View File

@@ -10,7 +10,7 @@ use std::{fmt, str::FromStr};
// The chain spec module.
mod spec;
pub use spec::{
AllGenesisFormats, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition,
AllGenesisFormats, BaseFeeParams, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition,
ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA,
};

View File

@@ -1,5 +1,8 @@
use crate::{
constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_WITHDRAWALS},
constants::{
EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, EIP1559_DEFAULT_ELASTICITY_MULTIPLIER,
EIP1559_INITIAL_BASE_FEE, EMPTY_WITHDRAWALS,
},
forkid::ForkFilterKey,
header::Head,
proofs::genesis_state_root,
@@ -60,6 +63,7 @@ pub static MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
11052984,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
@@ -100,6 +104,7 @@ pub static GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
4367322,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
@@ -144,6 +149,7 @@ pub static SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
1273020,
H256(hex!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")),
)),
..Default::default()
}
.into()
});
@@ -182,10 +188,30 @@ pub static DEV: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
(Hardfork::Shanghai, ForkCondition::Timestamp(0)),
]),
deposit_contract: None, // TODO: do we even have?
..Default::default()
}
.into()
});
/// BaseFeeParams contains the config parameters that control block base fee computation
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub struct BaseFeeParams {
/// The base_fee_max_change_denominator from EIP-1559
pub max_change_denominator: u64,
/// The elasticity multiplier from EIP-1559
pub elasticity_multiplier: u64,
}
impl BaseFeeParams {
/// Get the base fee parameters for ethereum mainnet
pub const fn ethereum() -> BaseFeeParams {
BaseFeeParams {
max_change_denominator: EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR,
elasticity_multiplier: EIP1559_DEFAULT_ELASTICITY_MULTIPLIER,
}
}
}
/// An Ethereum chain specification.
///
/// A chain specification describes:
@@ -224,6 +250,24 @@ pub struct ChainSpec {
/// The deposit contract deployed for PoS.
#[serde(skip, default)]
pub deposit_contract: Option<DepositContract>,
/// The parameters that configure how a block's base fee is computed
pub base_fee_params: BaseFeeParams,
}
impl Default for ChainSpec {
fn default() -> ChainSpec {
ChainSpec {
chain: Default::default(),
genesis_hash: Default::default(),
genesis: Default::default(),
paris_block_and_final_difficulty: Default::default(),
fork_timestamps: Default::default(),
hardforks: Default::default(),
deposit_contract: Default::default(),
base_fee_params: BaseFeeParams::ethereum(),
}
}
}
impl ChainSpec {
@@ -457,6 +501,7 @@ impl From<Genesis> for ChainSpec {
hardforks,
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
}
}
}
@@ -680,6 +725,7 @@ impl ChainSpecBuilder {
hardforks: self.hardforks,
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
}
}
}

View File

@@ -37,11 +37,15 @@ pub const BEACON_NONCE: u64 = 0u64;
/// See <https://github.com/paradigmxyz/reth/issues/3233>.
pub const ETHEREUM_BLOCK_GAS_LIMIT: u64 = 30_000_000;
/// The minimal value the basefee can decrease to.
/// The minimum tx fee below which the txpool will reject the transaction.
///
/// The `BASE_FEE_MAX_CHANGE_DENOMINATOR` <https://eips.ethereum.org/EIPS/eip-1559> is `8`, or 12.5%.
/// Once the base fee has dropped to `7` WEI it cannot decrease further because 12.5% of 7 is less
/// than 1.
/// Configured to `7` WEI which is the lowest possible value of base fee under mainnet EIP-1559
/// parameters. `BASE_FEE_MAX_CHANGE_DENOMINATOR` <https://eips.ethereum.org/EIPS/eip-1559>
/// is `8`, or 12.5%. Once the base fee has dropped to `7` WEI it cannot decrease further because
/// 12.5% of 7 is less than 1.
///
/// Note that min base fee under different 1559 parameterizations may differ, but there's no
/// signifant harm in leaving this setting as is.
pub const MIN_PROTOCOL_BASE_FEE: u64 = 7;
/// Same as [MIN_PROTOCOL_BASE_FEE] but as a U256.
@@ -51,10 +55,10 @@ pub const MIN_PROTOCOL_BASE_FEE_U256: U256 = U256::from_limbs([7u64, 0, 0, 0]);
pub const EIP1559_INITIAL_BASE_FEE: u64 = 1_000_000_000;
/// Base fee max change denominator as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
pub const EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8;
pub const EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8;
/// Elasticity multiplier as defined in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
pub const EIP1559_ELASTICITY_MULTIPLIER: u64 = 2;
pub const EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u64 = 2;
/// Multiplier for converting gwei to wei.
pub const GWEI_TO_WEI: u64 = 1_000_000_000;

View File

@@ -162,9 +162,9 @@ mod tests {
genesis: Genesis::default(),
genesis_hash: None,
hardforks: BTreeMap::from([(Hardfork::Frontier, ForkCondition::Never)]),
fork_timestamps: Default::default(),
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
};
assert_eq!(Hardfork::Frontier.fork_id(&spec), None);
@@ -177,9 +177,9 @@ mod tests {
genesis: Genesis::default(),
genesis_hash: None,
hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Never)]),
fork_timestamps: Default::default(),
paris_block_and_final_difficulty: None,
deposit_contract: None,
..Default::default()
};
assert_eq!(Hardfork::Shanghai.fork_filter(&spec), None);

View File

@@ -3,7 +3,8 @@ use crate::{
blobfee::calculate_excess_blob_gas,
keccak256,
proofs::{EMPTY_LIST_HASH, EMPTY_ROOT},
BlockBodyRoots, BlockHash, BlockNumHash, BlockNumber, Bloom, Bytes, H160, H256, H64, U256,
BaseFeeParams, BlockBodyRoots, BlockHash, BlockNumHash, BlockNumber, Bloom, Bytes, H160, H256,
H64, U256,
};
use bytes::{Buf, BufMut, BytesMut};
@@ -176,8 +177,13 @@ impl Header {
/// Calculate base fee for next block according to the EIP-1559 spec.
///
/// Returns a `None` if no base fee is set, no EIP-1559 support
pub fn next_block_base_fee(&self) -> Option<u64> {
Some(calculate_next_block_base_fee(self.gas_used, self.gas_limit, self.base_fee_per_gas?))
pub fn next_block_base_fee(&self, base_fee_params: BaseFeeParams) -> Option<u64> {
Some(calculate_next_block_base_fee(
self.gas_used,
self.gas_limit,
self.base_fee_per_gas?,
base_fee_params,
))
}
/// Calculate excess blob gas for the next block according to the EIP-4844 spec.

View File

@@ -60,8 +60,8 @@ pub use block::{
};
pub use bloom::Bloom;
pub use chain::{
AllGenesisFormats, Chain, ChainInfo, ChainSpec, ChainSpecBuilder, DisplayHardforks,
ForkCondition, ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA,
AllGenesisFormats, BaseFeeParams, Chain, ChainInfo, ChainSpec, ChainSpecBuilder,
DisplayHardforks, ForkCondition, ForkTimestamps, DEV, GOERLI, MAINNET, SEPOLIA,
};
pub use compression::*;
pub use constants::{