From a063be71beb66b61ae19c696ce805fa1085d12a4 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 14 Nov 2025 13:02:20 +0100 Subject: [PATCH] fix: add minbasefee for jovian attributes (#19726) --- crates/optimism/payload/src/payload.rs | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/optimism/payload/src/payload.rs b/crates/optimism/payload/src/payload.rs index 6f530acd85..41b825a2b7 100644 --- a/crates/optimism/payload/src/payload.rs +++ b/crates/optimism/payload/src/payload.rs @@ -342,6 +342,9 @@ where /// Generates the payload id for the configured payload from the [`OpPayloadAttributes`]. /// /// Returns an 8-byte identifier by hashing the payload components with sha256 hash. +/// +/// Note: This must be updated whenever the [`OpPayloadAttributes`] changes for a hardfork. +/// See also pub fn payload_id_optimism( parent: &B256, attributes: &OpPayloadAttributes, @@ -387,6 +390,10 @@ pub fn payload_id_optimism( hasher.update(eip_1559_params.as_slice()); } + if let Some(min_base_fee) = attributes.min_base_fee { + hasher.update(min_base_fee.to_be_bytes()); + } + let mut out = hasher.finalize(); out[0] = payload_version; PayloadId::new(out.as_slice()[..8].try_into().expect("sufficient length")) @@ -473,6 +480,37 @@ mod tests { ); } + #[test] + fn test_payload_id_parity_op_geth_jovian() { + // + let expected = + PayloadId::new(FixedBytes::<8>::from_str("0x046c65ffc4d659ec").unwrap().into()); + let attrs = OpPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1728933301, + prev_randao: b256!("0x9158595abbdab2c90635087619aa7042bbebe47642dfab3c9bfb934f6b082765"), + suggested_fee_recipient: address!("0x4200000000000000000000000000000000000011"), + withdrawals: Some([].into()), + parent_beacon_block_root: b256!("0x8fe0193b9bf83cb7e5a08538e494fecc23046aab9a497af3704f4afdae3250ff").into(), + }, + transactions: Some([bytes!("7ef8f8a0dc19cfa777d90980e4875d0a548a881baaa3f83f14d1bc0d3038bc329350e54194deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e20000f424000000000000000000000000300000000670d6d890000000000000125000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000014bf9181db6e381d4384bbf69c48b0ee0eed23c6ca26143c6d2544f9d39997a590000000000000000000000007f83d659683caf2767fd3c720981d51f5bc365bc")].into()), + no_tx_pool: None, + gas_limit: Some(30000000), + eip_1559_params: None, + min_base_fee: Some(100), + }; + + // Reth's `PayloadId` should match op-geth's `PayloadId`. This fails + assert_eq!( + expected, + payload_id_optimism( + &b256!("0x3533bf30edaf9505d0810bf475cbe4e5f4b9889904b9845e83efdeab4e92eb1e"), + &attrs, + EngineApiMessageVersion::V4 as u8 + ) + ); + } + #[test] fn test_get_extra_data_post_holocene() { let attributes: OpPayloadBuilderAttributes =