diff --git a/Cargo.lock b/Cargo.lock index 2b6cab446..4c8d4f25b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8600,6 +8600,7 @@ dependencies = [ "reth-provider", "reth-revm", "reth-transaction-pool", + "reth-trie", "revm", "sha2 0.10.8", "thiserror 2.0.11", diff --git a/crates/optimism/payload/Cargo.toml b/crates/optimism/payload/Cargo.toml index 4921e3f80..de637b2c7 100644 --- a/crates/optimism/payload/Cargo.toml +++ b/crates/optimism/payload/Cargo.toml @@ -27,6 +27,7 @@ reth-payload-util.workspace = true reth-payload-primitives = { workspace = true, features = ["op"] } reth-basic-payload-builder.workspace = true reth-chain-state.workspace = true +reth-trie.workspace = true # op-reth reth-optimism-consensus.workspace = true diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index de45db85f..a17879b6f 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -46,6 +46,7 @@ use reth_revm::{ cancelled::CancelOnDrop, database::StateProviderDatabase, witness::ExecutionWitnessRecord, }; use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction, TransactionPool}; +use reth_trie::HashedStorage; use revm::{ db::{states::bundle_state::BundleRetention, State}, primitives::{ExecutionResult, ResultAndState}, @@ -377,14 +378,22 @@ impl OpBuilder<'_, Txs> { state.merge_transitions(BundleRetention::Reverts); let withdrawals_root = if ctx.is_isthmus_active() { + let hashed_storage_updates = + state.bundle_state.state().get(&ADDRESS_L2_TO_L1_MESSAGE_PASSER).map(|account| { + // block contained withdrawals transactions, use predeploy storage updates from + // execution + HashedStorage::from_plain_storage( + account.status, + account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), + ) + }); + // withdrawals root field in block header is used for storage root of L2 predeploy // `l2tol1-message-passer` - Some( - state - .database - .as_ref() - .storage_root(ADDRESS_L2_TO_L1_MESSAGE_PASSER, Default::default())?, - ) + Some(state.database.as_ref().storage_root( + ADDRESS_L2_TO_L1_MESSAGE_PASSER, + hashed_storage_updates.unwrap_or_default(), + )?) } else if ctx.is_canyon_active() { Some(EMPTY_WITHDRAWALS) } else {