From 8accc6175e8b649949681c8893f77271b301a1f8 Mon Sep 17 00:00:00 2001 From: panos Date: Tue, 31 Mar 2026 22:45:31 +0800 Subject: [PATCH] fix(chainspec): use MORPH_BASE_FEE as genesis default instead of INITIAL_BASE_FEE When `baseFeePerGas` is null/absent in genesis JSON, upstream reth defaults to Ethereum's INITIAL_BASE_FEE (1_000_000_000 = 1 Gwei). morph-geth defaults to CalcBaseFee() which returns 1_000_000 (0.001 Gwei). This mismatch causes different genesis block header hashes between morph-reth and morph-geth. Override the default in both genesis header construction paths (make_genesis_header for predefined networks, and from_genesis_with_config for CLI-provided genesis) to use MORPH_BASE_FEE when baseFeePerGas is not explicitly set. --- crates/chainspec/src/spec.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/chainspec/src/spec.rs b/crates/chainspec/src/spec.rs index f761cc3..53e8c5a 100644 --- a/crates/chainspec/src/spec.rs +++ b/crates/chainspec/src/spec.rs @@ -6,6 +6,7 @@ use crate::{ hardfork::{MorphHardfork, MorphHardforks}, }; use alloy_chains::Chain; +use alloy_consensus::Sealable; use alloy_eips::eip7840::BlobParams; use alloy_evm::eth::spec::EthExecutorSpec; use alloy_genesis::Genesis; @@ -37,7 +38,12 @@ pub(crate) fn make_genesis_header(genesis: &Genesis, state_root: B256) -> MorphH let base_spec = ChainSpec::from_genesis(genesis.clone()); let mut inner = base_spec.genesis_header.header().clone(); inner.state_root = state_root; - + // morph-geth defaults to MORPH_BASE_FEE (1_000_000) when baseFeePerGas is + // absent, not Ethereum's INITIAL_BASE_FEE (1_000_000_000). Apply the same + // default so the genesis block header hash matches. + if genesis.base_fee_per_gas.is_none() { + inner.base_fee_per_gas = Some(MORPH_BASE_FEE); + } MorphHeader::from(inner) } @@ -256,8 +262,16 @@ impl MorphChainSpec { None => { // Compute MPT state root from alloc (for CLI-provided genesis) let base_spec = ChainSpec::from_genesis(genesis.clone()); - let header = MorphHeader::from(base_spec.genesis_header.header().clone()); - let hash = base_spec.genesis_hash(); + let mut header = base_spec.genesis_header.header().clone(); + // morph-geth defaults to MORPH_BASE_FEE (1_000_000) when + // baseFeePerGas is absent, not Ethereum's INITIAL_BASE_FEE + // (1_000_000_000). Override to match. + if genesis.base_fee_per_gas.is_none() { + header.base_fee_per_gas = Some(MORPH_BASE_FEE); + } + let header = MorphHeader::from(header); + // Recompute genesis hash with the corrected base fee + let hash = header.hash_slow(); SealedHeader::new(header, hash) } };