diff --git a/crates/primitives/src/revm/env.rs b/crates/primitives/src/revm/env.rs index a46eaf5b32a2..14e7cc1083e0 100644 --- a/crates/primitives/src/revm/env.rs +++ b/crates/primitives/src/revm/env.rs @@ -49,7 +49,18 @@ pub fn fill_block_env_with_coinbase( /// Return the coinbase address for the given header and chain spec. pub fn block_coinbase(chain_spec: &ChainSpec, header: &Header, after_merge: bool) -> Address { - if chain_spec.chain == Chain::goerli() && !after_merge { + // Clique consensus fills the EXTRA_SEAL (last 65 bytes) of the extra data with the + // signer's signature. + // + // On the genesis block, the extra data is filled with zeros, so we should not attempt to + // recover the signer on the genesis block. + // + // From EIP-225: + // + // * `EXTRA_SEAL`: Fixed number of extra-data suffix bytes reserved for signer seal. + // * 65 bytes fixed as signatures are based on the standard `secp256k1` curve. + // * Filled with zeros on genesis block. + if chain_spec.chain == Chain::goerli() && !after_merge && header.number > 0 { recover_header_signer(header).unwrap_or_else(|err| { panic!( "Failed to recover goerli Clique Consensus signer from header ({}, {}) using extradata {}: {:?}", @@ -324,3 +335,18 @@ pub fn fill_op_tx_env>( } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::GOERLI; + + #[test] + fn test_recover_genesis_goerli_signer() { + // just ensures that `block_coinbase` does not panic on the genesis block + let chain_spec = GOERLI.clone(); + let header = chain_spec.genesis_header(); + let block_coinbase = block_coinbase(&chain_spec, &header, false); + assert_eq!(block_coinbase, header.beneficiary); + } +}