From cb634ca7d1a3c00963f95bb1b3a98d159131d9ca Mon Sep 17 00:00:00 2001 From: Brian Bland Date: Wed, 29 May 2024 13:58:44 -0700 Subject: [PATCH] Support variable base fee params --- crates/primitives/src/chain/spec.rs | 134 +++++++++++++++++++++++----- 1 file changed, 112 insertions(+), 22 deletions(-) diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index cf571cdbe40d7..7300abd94c96b 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -1066,7 +1066,7 @@ impl From for ChainSpec { paris_block_and_final_difficulty, deposit_contract: None, #[cfg(feature = "optimism")] - base_fee_params: optimism_genesis_info.base_fee_params.into(), + base_fee_params: optimism_genesis_info.base_fee_params, ..Default::default() } } @@ -1619,29 +1619,51 @@ struct OptimismGenesisInfo { regolith_time: Option, ecotone_time: Option, canyon_time: Option, - base_fee_params: BaseFeeParams, + base_fee_params: BaseFeeParamsKind, } #[cfg(feature = "optimism")] impl OptimismGenesisInfo { fn extract_from(genesis: &Genesis) -> Self { - let eip1559_elasticity = genesis.config.extra_fields.get("optimism").and_then(|value| { - value - .as_object() - .and_then(|obj| obj.get("eip1559Elasticity").and_then(|value| value.as_u64())) - }); - let eip1559_denominator = genesis.config.extra_fields.get("optimism").and_then(|value| { - value - .as_object() - .and_then(|obj| obj.get("eip1559Denominator").and_then(|value| value.as_u64())) - }); + let optimism_config = + genesis.config.extra_fields.get("optimism").and_then(|value| value.as_object()); + + let eip1559_elasticity = optimism_config + .and_then(|config| config.get("eip1559Elasticity")) + .and_then(|value| value.as_u64()); + + let eip1559_denominator = optimism_config + .and_then(|config| config.get("eip1559Denominator")) + .and_then(|value| value.as_u64()); + + let eip1559_denominator_canyon = optimism_config + .and_then(|config| config.get("eip1559DenominatorCanyon")) + .and_then(|value| value.as_u64()); + let base_fee_params = if let (Some(elasticity), Some(denominator)) = (eip1559_elasticity, eip1559_denominator) { - BaseFeeParams::new(denominator as u128, elasticity as u128) + if let Some(canyon_denominator) = eip1559_denominator_canyon { + BaseFeeParamsKind::Variable( + vec![ + ( + Hardfork::London, + BaseFeeParams::new(denominator as u128, elasticity as u128), + ), + ( + Hardfork::Canyon, + BaseFeeParams::new(canyon_denominator as u128, elasticity as u128), + ), + ] + .into(), + ) + } else { + BaseFeeParams::new(denominator as u128, elasticity as u128).into() + } } else { - BaseFeeParams::ethereum() + BaseFeeParams::ethereum().into() }; + Self { bedrock_block: genesis .config @@ -3270,8 +3292,63 @@ Post-merge hard forks (timestamp based): "config": { "bedrockBlock": 10, "regolithTime": 20, - "ecotoneTime": 30, - "canyonTime": 40, + "canyonTime": 30, + "ecotoneTime": 40, + "optimism": { + "eip1559Elasticity": 50, + "eip1559Denominator": 60 + } + } + } + "#; + let genesis: Genesis = serde_json::from_str(geth_genesis).unwrap(); + + let actual_bedrock_block = genesis.config.extra_fields.get("bedrockBlock"); + assert_eq!(actual_bedrock_block, Some(serde_json::Value::from(10)).as_ref()); + let actual_regolith_timestamp = genesis.config.extra_fields.get("regolithTime"); + assert_eq!(actual_regolith_timestamp, Some(serde_json::Value::from(20)).as_ref()); + let actual_canyon_timestamp = genesis.config.extra_fields.get("canyonTime"); + assert_eq!(actual_canyon_timestamp, Some(serde_json::Value::from(30)).as_ref()); + let actual_ecotone_timestamp = genesis.config.extra_fields.get("ecotoneTime"); + assert_eq!(actual_ecotone_timestamp, Some(serde_json::Value::from(40)).as_ref()); + + let optimism_object = genesis.config.extra_fields.get("optimism").unwrap(); + assert_eq!( + optimism_object, + &serde_json::json!({ + "eip1559Elasticity": 50, + "eip1559Denominator": 60, + }) + ); + + let chain_spec: ChainSpec = genesis.into(); + + assert_eq!( + chain_spec.base_fee_params, + BaseFeeParamsKind::Constant(BaseFeeParams::new(60, 50)) + ); + + assert!(!chain_spec.is_fork_active_at_block(Hardfork::Bedrock, 0)); + assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, 0)); + assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, 0)); + assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, 0)); + + assert!(chain_spec.is_fork_active_at_block(Hardfork::Bedrock, 10)); + assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, 20)); + assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, 30)); + assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, 40)); + } + + #[cfg(feature = "optimism")] + #[test] + fn parse_optimism_hardforks_variable_base_fee_params() { + let geth_genesis = r#" + { + "config": { + "bedrockBlock": 10, + "regolithTime": 20, + "canyonTime": 30, + "ecotoneTime": 40, "optimism": { "eip1559Elasticity": 50, "eip1559Denominator": 60, @@ -3286,10 +3363,10 @@ Post-merge hard forks (timestamp based): assert_eq!(actual_bedrock_block, Some(serde_json::Value::from(10)).as_ref()); let actual_regolith_timestamp = genesis.config.extra_fields.get("regolithTime"); assert_eq!(actual_regolith_timestamp, Some(serde_json::Value::from(20)).as_ref()); - let actual_ecotone_timestamp = genesis.config.extra_fields.get("ecotoneTime"); - assert_eq!(actual_ecotone_timestamp, Some(serde_json::Value::from(30)).as_ref()); let actual_canyon_timestamp = genesis.config.extra_fields.get("canyonTime"); - assert_eq!(actual_canyon_timestamp, Some(serde_json::Value::from(40)).as_ref()); + assert_eq!(actual_canyon_timestamp, Some(serde_json::Value::from(30)).as_ref()); + let actual_ecotone_timestamp = genesis.config.extra_fields.get("ecotoneTime"); + assert_eq!(actual_ecotone_timestamp, Some(serde_json::Value::from(40)).as_ref()); let optimism_object = genesis.config.extra_fields.get("optimism").unwrap(); assert_eq!( @@ -3300,15 +3377,28 @@ Post-merge hard forks (timestamp based): "eip1559DenominatorCanyon": 70 }) ); + let chain_spec: ChainSpec = genesis.into(); + + assert_eq!( + chain_spec.base_fee_params, + BaseFeeParamsKind::Variable( + vec![ + (Hardfork::London, BaseFeeParams::new(60, 50)), + (Hardfork::Canyon, BaseFeeParams::new(70, 50)), + ] + .into() + ) + ); + assert!(!chain_spec.is_fork_active_at_block(Hardfork::Bedrock, 0)); assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, 0)); - assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, 0)); assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, 0)); + assert!(!chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, 0)); assert!(chain_spec.is_fork_active_at_block(Hardfork::Bedrock, 10)); assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, 20)); - assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, 30)); - assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, 40)); + assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, 30)); + assert!(chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, 40)); } }