From 375cf9368fac6907cfedf057604ee888ac9300ae Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:00:49 -0300 Subject: [PATCH 1/4] feat(test-utils): PlatformWithTestnet and better BlockContextMock --- src/test_utils/exts/mock.rs | 119 +++++++++++++------------------ src/test_utils/macros/src/lib.rs | 30 ++++---- src/test_utils/platform.rs | 5 +- 3 files changed, 68 insertions(+), 86 deletions(-) diff --git a/src/test_utils/exts/mock.rs b/src/test_utils/exts/mock.rs index 725e927..9f5c0aa 100644 --- a/src/test_utils/exts/mock.rs +++ b/src/test_utils/exts/mock.rs @@ -5,18 +5,41 @@ use { super::*, alloy::primitives::{Address, B256}, reth::{ - chainspec::{DEV, EthChainSpec}, + chainspec::EthChainSpec, ethereum::{ node::engine::EthPayloadAttributes as PayloadAttributes, primitives::AlloyBlockHeader, }, - node::builder::NodeTypes, payload::builder::EthPayloadBuilderAttributes, primitives::SealedHeader, }, - std::sync::LazyLock, + std::sync::{Arc, LazyLock}, }; +/// A helper trait to provide a default testnet for a platform +pub trait PlatformWithTestnet: Platform { + fn dev_chainspec() -> Arc>; +} + +/// Blanket implementation for ethereum +impl PlatformWithTestnet for Ethereum { + fn dev_chainspec() -> Arc> { + LazyLock::force(&crate::reth::chainspec::DEV) + .clone() + .with_funded_accounts() + } +} + +/// Blanket implementation for optimism +#[cfg(feature = "optimism")] +impl PlatformWithTestnet for Optimism { + fn dev_chainspec() -> Arc> { + LazyLock::force(&crate::reth::optimism::chainspec::OP_DEV) + .clone() + .with_funded_accounts() + } +} + /// Payload builder attributes typically come from the Consensus Layer with a /// forkchoiceUpdate request, and are typically obtained from instances of types /// that implement [`PayloadJobGenerator`] and are configured as payload @@ -29,17 +52,23 @@ pub trait PayloadBuilderAttributesMocked { fn mocked(parent: &SealedHeader>) -> Self; } +fn default_eth_payload_builder_attributed( + parent: &SealedHeader>, +) -> EthPayloadBuilderAttributes { + EthPayloadBuilderAttributes::new(parent.hash(), PayloadAttributes { + timestamp: parent.header().timestamp() + 1, + prev_randao: B256::random(), + suggested_fee_recipient: Address::random(), + withdrawals: Some(vec![]), + parent_beacon_block_root: Some(B256::ZERO), + }) +} + impl PayloadBuilderAttributesMocked

for EthPayloadBuilderAttributes { fn mocked(parent: &SealedHeader>) -> Self { - EthPayloadBuilderAttributes::new(parent.hash(), PayloadAttributes { - timestamp: parent.header().timestamp() + 1, - prev_randao: B256::random(), - suggested_fee_recipient: Address::random(), - withdrawals: Some(vec![]), - parent_beacon_block_root: Some(B256::ZERO), - }) + default_eth_payload_builder_attributed::

(parent) } } @@ -69,16 +98,7 @@ impl PayloadBuilderAttributesMocked

); OpPayloadBuilderAttributes { - payload_attributes: EthPayloadBuilderAttributes::new( - parent.hash(), - PayloadAttributes { - timestamp: parent.header().timestamp() + 1, - prev_randao: B256::random(), - suggested_fee_recipient: Address::random(), - withdrawals: Some(vec![]), - parent_beacon_block_root: Some(B256::ZERO), - }, - ), + payload_attributes: default_eth_payload_builder_attributed::

(parent), transactions: vec![sequencer_tx], gas_limit: Some(BASE_MAINNET_MAX_GAS_LIMIT), ..Default::default() @@ -86,9 +106,8 @@ impl PayloadBuilderAttributesMocked

} } -/// Allows the creation of a block context for the first block post genesis with -/// all [`FundedAccounts`] pre-funded with 100 ETH. -pub trait BlockContextMocked { +/// Allows the creation of a block context for the first block post genesis +pub trait BlockContextMocked { /// Returns an instance of a [`BlockContext`] that is rooted at the genesis /// block the given platform's DEV chainspec. /// @@ -100,53 +119,13 @@ pub trait BlockContextMocked { fn mocked() -> BlockContext

; } -impl BlockContextMocked> for BlockContext

-where - P: Platform< - NodeTypes: NodeTypes< - ChainSpec = types::ChainSpec, - Primitives = types::Primitives, - Payload = types::PayloadTypes, - >, - >, -{ - fn mocked() -> BlockContext

{ - let chainspec = LazyLock::force(&DEV).clone().with_funded_accounts(); - let provider_factory = GenesisProviderFactory::

::new(chainspec.clone()); - let base_state = provider_factory.state_provider(); - - let parent = SealedHeader::new( - chainspec.genesis_header().clone(), - chainspec.genesis_hash(), - ); - - let payload_attribs = >::mocked(&parent); - - BlockContext::

::new( - parent, - payload_attribs, - base_state, - chainspec.clone(), - None, - ) - .expect("Failed to create mocked block context") - } -} - -#[cfg(feature = "optimism")] -impl BlockContextMocked> for BlockContext

+impl

BlockContextMocked

for BlockContext

where - P: Platform< - NodeTypes: NodeTypes< - ChainSpec = types::ChainSpec, - Primitives = types::Primitives, - Payload = types::PayloadTypes, - >, - >, + P: PlatformWithTestnet, + types::PayloadBuilderAttributes

: PayloadBuilderAttributesMocked

, { fn mocked() -> BlockContext

{ - use reth::optimism::{chainspec::OP_DEV, node::OpPayloadBuilderAttributes}; - let chainspec = LazyLock::force(&OP_DEV).clone().with_funded_accounts(); + let chainspec = P::dev_chainspec(); let provider_factory = GenesisProviderFactory::

::new(chainspec.clone()); let base_state = provider_factory.state_provider(); @@ -156,9 +135,9 @@ where ); let payload_attributes = - > as PayloadBuilderAttributesMocked

>::mocked( - &parent, - ); + as PayloadBuilderAttributesMocked< + P, + >>::mocked(&parent); BlockContext::

::new( parent, diff --git a/src/test_utils/macros/src/lib.rs b/src/test_utils/macros/src/lib.rs index 02ad97b..67bfbb9 100644 --- a/src/test_utils/macros/src/lib.rs +++ b/src/test_utils/macros/src/lib.rs @@ -30,20 +30,24 @@ impl Parse for PlatformList { pub fn rblib_test(args: TokenStream, input: TokenStream) -> TokenStream { let platform_list = parse_macro_input!(args as PlatformList); let original_fn = parse_macro_input!(input as ItemFn); + let sig = &original_fn.sig; - let original_fn_name = &original_fn.sig.ident; - let original_fn_block = &original_fn.block; - let original_fn_attrs = &original_fn.attrs; + let name = &sig.ident; + let attrs = &original_fn.attrs; + let generics = &sig.generics; + let where_clause = &generics.where_clause; + let output = &sig.output; + let block = &original_fn.block; // Determine if the original function returns `eyre::Result<()>` - let returns_eyre_result_unit = match &original_fn.sig.output { + let returns_eyre_result_unit = match output { syn::ReturnType::Default => false, syn::ReturnType::Type(_, ty) => is_eyre_result_unit(ty), }; // Preserve return type only when it is `eyre::Result<()>` let generic_fn_output = if returns_eyre_result_unit { - let ty = match &original_fn.sig.output { + let ty = match output { syn::ReturnType::Type(_, ty) => ty, _ => unreachable!(), }; @@ -55,23 +59,21 @@ pub fn rblib_test(args: TokenStream, input: TokenStream) -> TokenStream { // Generate test functions for each platform let test_functions = platform_list.platforms.iter().map(|platform| { let platform_lowercase = platform.to_string().to_lowercase(); - let test_fn_name = Ident::new( - &format!("{original_fn_name}_{platform_lowercase}"), - original_fn_name.span(), - ); + let test_fn_name = + Ident::new(&format!("{name}_{platform_lowercase}"), name.span()); if returns_eyre_result_unit { quote! { #[tokio::test] async fn #test_fn_name() { - #original_fn_name::<#platform>().await.unwrap(); + #name::<#platform>().await.unwrap(); } } } else { quote! { #[tokio::test] async fn #test_fn_name() { - #original_fn_name::<#platform>().await + #name::<#platform>().await } } } @@ -79,8 +81,10 @@ pub fn rblib_test(args: TokenStream, input: TokenStream) -> TokenStream { // Generate the original function (made private and generic) let expanded = quote! { - #(#original_fn_attrs)* - async fn #original_fn_name() #generic_fn_output #original_fn_block + #(#attrs)* + async fn #name #generics () #generic_fn_output + #where_clause + #block #(#test_functions)* }; diff --git a/src/test_utils/platform.rs b/src/test_utils/platform.rs index 4c32297..9066af7 100644 --- a/src/test_utils/platform.rs +++ b/src/test_utils/platform.rs @@ -36,7 +36,7 @@ use { /// variants of all internal unit tests for all platforms. You can use /// [`rblib_test`] with externally defined platforms as long as they implement /// this trait. -pub trait TestNodeFactory { +pub trait TestNodeFactory { type ConsensusDriver: ConsensusDriver

; type CliExtArgs: Default + Send + Sync; @@ -73,8 +73,7 @@ pub trait TestNodeFactory { } /// A helper trait that is automatically implemented for all platform -/// implementations that have a `TestNodeFactory` implementation and a -/// `NetworkSelector` implementation. +/// implementations that have a `TestNodeFactory` implementation and rpc types /// /// This allows the `rblib_test` macro to automatically synthesize tests for /// many platforms without needing to create separate versions of the test for From 5250127c9749b79953ebfa63d52ee6ec82907823 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:01:01 -0300 Subject: [PATCH 2/4] doc: custom platform example --- .../{custom-bundle-type.rs => custom-platform.rs} | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) rename examples/{custom-bundle-type.rs => custom-platform.rs} (95%) diff --git a/examples/custom-bundle-type.rs b/examples/custom-platform.rs similarity index 95% rename from examples/custom-bundle-type.rs rename to examples/custom-platform.rs index fd8d2ad..5b1adec 100644 --- a/examples/custom-bundle-type.rs +++ b/examples/custom-platform.rs @@ -1,4 +1,5 @@ -//! Example of extending an existing platform with a custom bundle type. +//! Example of a custom platform extending an existing platform (`Optimism`) +//! with a custom bundle type. //! //! In this example, we define a new platform type that inherits all properties //! and behaviors of the `Optimism` platform but uses a custom bundle type that @@ -22,7 +23,7 @@ use { revm::db::BundleState, }, serde::{Deserialize, Serialize}, - std::sync::Arc, + std::sync::{Arc, LazyLock}, }; #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] @@ -63,6 +64,14 @@ impl Platform for CustomPlatform { } } +impl PlatformWithTestnet for CustomPlatform { + fn dev_chainspec() -> Arc> { + LazyLock::force(&crate::reth::optimism::chainspec::OP_DEV) + .clone() + .with_funded_accounts() + } +} + fn main() -> eyre::Result<()> { // Construct a mock build context for the custom platform. let block = BlockContext::::mocked(); From 8f3bd68f3b2f42de32971dc9f5367a5ddc6671b1 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:01:17 -0300 Subject: [PATCH 3/4] fix(test): missing platform generic --- src/steps/ordering/profit.rs | 2 +- src/steps/ordering/tip.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/steps/ordering/profit.rs b/src/steps/ordering/profit.rs index 1ecef75..0a70939 100644 --- a/src/steps/ordering/profit.rs +++ b/src/steps/ordering/profit.rs @@ -99,7 +99,7 @@ mod tests { } #[rblib_test(Ethereum, Optimism)] - async fn correct_order_remains_unchanged_nonce_deps() { + async fn correct_order_remains_unchanged_nonce_deps() { let payload = vec![ (1, 0, 170), (2, 0, 160), diff --git a/src/steps/ordering/tip.rs b/src/steps/ordering/tip.rs index 9d89110..f700987 100644 --- a/src/steps/ordering/tip.rs +++ b/src/steps/ordering/tip.rs @@ -85,7 +85,7 @@ mod tests { } #[rblib_test(Ethereum, Optimism)] - async fn correct_order_remains_unchanged_nonce_deps() { + async fn correct_order_remains_unchanged_nonce_deps() { let payload = vec![ (1, 0, 170), (2, 0, 160), From 5369f97b1a592d91798d2f22e77ddba35dc63a08 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:03:00 -0300 Subject: [PATCH 4/4] test: optimism execution --- src/payload/exec.rs | 274 +++++++++++++++++++++++++++----------------- 1 file changed, 167 insertions(+), 107 deletions(-) diff --git a/src/payload/exec.rs b/src/payload/exec.rs index 6d9ba54..34ca1c5 100644 --- a/src/payload/exec.rs +++ b/src/payload/exec.rs @@ -477,13 +477,22 @@ impl ExecutionResult

{ mod tests { use { super::*, - crate::test_utils::{BlockContextMocked, test_bundle, test_tx, test_txs}, + crate::test_utils::{ + BlockContextMocked, + TestablePlatform, + test_bundle, + test_tx, + test_txs, + }, + rblib_tests_macros::rblib_test, }; - #[test] - fn test_executable_transaction_returns_single_transaction() { - let tx = test_tx::(0, 0); - let executable = Executable::::Transaction(tx.clone()); + #[rblib_test(Ethereum, Optimism)] + fn test_executable_transaction_returns_single_transaction< + P: TestablePlatform, + >() { + let tx = test_tx::

(0, 0); + let executable = Executable::

::Transaction(tx.clone()); assert_eq!(executable.transactions().len(), 1); assert_eq!(executable.transactions()[0], tx); @@ -491,10 +500,13 @@ mod tests { assert!(!executable.is_bundle()); } - #[test] - fn test_executable_bundle_returns_all_transactions() { - let (bundle, txs) = test_bundle::(0, 0); - let executable = Executable::::Bundle(bundle); + #[rblib_test(Ethereum, Optimism)] + fn test_executable_bundle_returns_all_transactions

() + where + P: TestablePlatform>, + { + let (bundle, txs) = test_bundle::

(0, 0); + let executable = Executable::

::Bundle(bundle); assert_eq!(executable.transactions().len(), txs.len()); assert_eq!(executable.transactions(), txs.as_slice()); @@ -502,11 +514,15 @@ mod tests { assert!(executable.is_bundle()); } - #[test] - fn test_execute_transaction_success() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execute_transaction_success

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); + let tx = test_tx::

(0, 0); let result = Executable::execute_transaction(tx.clone(), &block, &checkpoint); @@ -518,11 +534,15 @@ mod tests { assert!(exec_result.results()[0].is_success()); } - #[test] - fn test_execute_transaction_produces_state_changes() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execute_transaction_produces_state_changes

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); + let tx = test_tx::

(0, 0); let result = Executable::execute_transaction(tx, &block, &checkpoint); @@ -531,23 +551,31 @@ mod tests { assert!(exec_result.gas_used() > 0); } - #[test] - fn test_execute_via_execute_method() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execute_via_execute_method

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); - let executable = Executable::::Transaction(tx); + let tx = test_tx::

(0, 0); + let executable = Executable::

::Transaction(tx); let result = executable.execute(&block, &checkpoint); assert_eq!(result.unwrap().results().len(), 1); } - #[test] - fn test_execute_bundle_all_successful() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execute_bundle_all_successful

() + where + P: TestablePlatform>, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let (bundle, txs) = test_bundle::(0, 0); + let (bundle, txs) = test_bundle::

(0, 0); let result = Executable::execute_bundle(bundle, &block, &checkpoint); @@ -558,11 +586,15 @@ mod tests { assert_eq!(exec_result.transactions(), txs.as_slice()); } - #[test] - fn test_execute_bundle_aggregates_gas() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execute_bundle_aggregates_gas

() + where + P: TestablePlatform>, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let (bundle, _) = test_bundle::(0, 0); + let (bundle, _) = test_bundle::

(0, 0); let result = Executable::execute_bundle(bundle, &block, &checkpoint); @@ -573,17 +605,18 @@ mod tests { assert!(total_gas > 0); } - #[test] - fn test_execute_bundle_sequential_execution() { + #[rblib_test(Ethereum, Optimism)] + fn test_execute_bundle_sequential_execution

() + where + P: TestablePlatform>, + BlockContext

: BlockContextMocked

, + { // Each transaction in a bundle executes on the state from the previous - let block = BlockContext::::mocked(); + let block = BlockContext::

::mocked(); let checkpoint = block.start(); // Use the same account for all transactions to test sequential nonces - let txs = test_txs::(0, 0, 3); - let bundle = FlashbotsBundle::::default() - .with_transaction(txs[0].clone()) - .with_transaction(txs[1].clone()) - .with_transaction(txs[2].clone()); + let txs = test_txs::

(0, 0, 3); + let (bundle, _) = test_bundle::

(0, 0); let result = Executable::execute_bundle(bundle, &block, &checkpoint); @@ -592,90 +625,103 @@ mod tests { assert!(exec_result.results().iter().all(|r| r.is_success())); } - #[test] - fn test_into_executable_from_recovered_transaction() { - let tx = test_tx::(0, 0); - let result: Result, _> = - IntoExecutable::>::try_into_executable(tx.clone()); + #[rblib_test(Ethereum, Optimism)] + fn test_into_executable_from_recovered_transaction() { + let tx = test_tx::

(0, 0); + let result: Result, _> = + IntoExecutable::>::try_into_executable(tx.clone()); let executable = result.unwrap(); assert!(executable.is_transaction()); assert_eq!(executable.transactions()[0], tx); } - #[test] - fn test_into_executable_from_bundle() { - let (bundle, _) = test_bundle::(0, 0); - let result: Result, _> = - IntoExecutable::>::try_into_executable(bundle); + #[rblib_test(Ethereum, Optimism)] + fn test_into_executable_from_bundle

() + where + P: TestablePlatform>, + { + let (bundle, _) = test_bundle::

(0, 0); + let result: Result, _> = + IntoExecutable::>::try_into_executable(bundle); assert!(result.unwrap().is_bundle()); } - #[test] - fn test_into_executable_from_executable() { - let tx = test_tx::(0, 0); - let executable = Executable::::Transaction(tx); - let result: Result, _> = - IntoExecutable::>::try_into_executable( - executable.clone(), - ); + #[rblib_test(Ethereum, Optimism)] + fn test_into_executable_from_executable() { + let tx = test_tx::

(0, 0); + let executable = Executable::

::Transaction(tx); + let result: Result, _> = + IntoExecutable::>::try_into_executable(executable.clone()); assert_eq!(result.unwrap(), executable); } - #[test] - fn test_into_executable_from_checkpoint() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_into_executable_from_checkpoint

() + where + P: TestablePlatform>, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); + let tx = test_tx::

(0, 0); let checkpoint_with_tx = checkpoint.apply(tx.clone()).unwrap(); - let result: Result, _> = - IntoExecutable::>::try_into_executable( - checkpoint_with_tx, - ); + let result: Result, _> = + IntoExecutable::>::try_into_executable(checkpoint_with_tx); let executable = result.unwrap(); assert!(executable.is_transaction()); assert_eq!(executable.transactions()[0], tx); } - #[test] - fn test_into_executable_from_checkpoint_ref() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_into_executable_from_checkpoint_ref

() + where + P: TestablePlatform>, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); + let tx = test_tx::

(0, 0); let checkpoint_with_tx = checkpoint.apply(tx.clone()).unwrap(); - let result: Result, _> = - IntoExecutable::>::try_into_executable( - &checkpoint_with_tx, - ); + let result: Result, _> = + IntoExecutable::>::try_into_executable(&checkpoint_with_tx); let executable = result.unwrap(); assert!(executable.is_transaction()); assert_eq!(executable.transactions()[0], tx); } - #[test] - fn test_into_executable_from_barrier_checkpoint_fails() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_into_executable_from_barrier_checkpoint_fails

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); let barrier = checkpoint.barrier(); - let result: Result, _> = - IntoExecutable::>::try_into_executable(&barrier); + let result: Result, _> = + IntoExecutable::>::try_into_executable(&barrier); assert!(result.is_err()); } - #[test] - fn test_execution_result_source() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execution_result_source

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); - let executable = Executable::::Transaction(tx.clone()); + let tx = test_tx::

(0, 0); + let executable = Executable::

::Transaction(tx.clone()); let result = executable.execute(&block, &checkpoint).unwrap(); @@ -685,49 +731,59 @@ mod tests { } } - #[test] - fn test_execution_result_transactions() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execution_result_transactions

() + where + P: TestablePlatform>, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let (bundle, txs) = test_bundle::(0, 0); - let executable = Executable::::Bundle(bundle); + let (bundle, txs) = test_bundle::

(0, 0); + let executable = Executable::

::Bundle(bundle); let result = executable.execute(&block, &checkpoint).unwrap(); assert_eq!(result.transactions(), txs.as_slice()); } - #[test] - fn test_executable_hash_transaction() { - let tx = test_tx::(0, 0); + #[rblib_test(Ethereum, Optimism)] + fn test_executable_hash_transaction() { + let tx = test_tx::

(0, 0); let expected_hash = *tx.tx_hash(); - let executable = Executable::::Transaction(tx); + let executable = Executable::

::Transaction(tx); assert_eq!(executable.hash(), expected_hash); } - #[test] - fn test_executable_hash_bundle() { - let (bundle, _) = test_bundle::(0, 0); + #[rblib_test(Ethereum, Optimism)] + fn test_executable_hash_bundle

() + where + P: TestablePlatform>, + { + let (bundle, _) = test_bundle::

(0, 0); let expected_hash = bundle.hash(); - let executable = Executable::::Bundle(bundle); + let executable = Executable::

::Bundle(bundle); assert_eq!(executable.hash(), expected_hash); } - #[test] - fn test_execution_error_invalid_signature_display() { - let err = - ExecutionError::::InvalidSignature(RecoveryError::new()); + #[rblib_test(Ethereum, Optimism)] + fn test_execution_error_invalid_signature_display() { + let err = ExecutionError::

::InvalidSignature(RecoveryError::new()); let display = format!("{err}"); assert!(display.contains("Invalid signature")); } - #[test] - fn test_execution_result_state_is_bundle_state() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execution_result_state_is_bundle_state

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); + let tx = test_tx::

(0, 0); let result = Executable::execute_transaction(tx, &block, &checkpoint).unwrap(); @@ -736,11 +792,15 @@ mod tests { assert!(!result.state().is_empty()); } - #[test] - fn test_execution_result_clone() { - let block = BlockContext::::mocked(); + #[rblib_test(Ethereum, Optimism)] + fn test_execution_result_clone

() + where + P: TestablePlatform, + BlockContext

: BlockContextMocked

, + { + let block = BlockContext::

::mocked(); let checkpoint = block.start(); - let tx = test_tx::(0, 0); + let tx = test_tx::

(0, 0); let result = Executable::execute_transaction(tx, &block, &checkpoint).unwrap();