From 4096b88fbfcc74a52c3ff5aec21dcf1548e27f04 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 21 Aug 2025 13:36:06 -0400 Subject: [PATCH 1/4] test: add tests for bundle guarantees --- crates/bundle/src/lib.rs | 4 +- crates/bundle/src/send/bundle.rs | 9 +- crates/bundle/src/send/mod.rs | 2 +- crates/test-utils/src/contracts/counter.rs | 5 +- crates/test-utils/src/contracts/mod.rs | 6 + crates/test-utils/src/contracts/reverts.rs | 21 ++++ crates/test-utils/src/evm.rs | 71 +++++++++--- crates/test-utils/src/specs/mod.rs | 61 +++++++++- crates/test-utils/src/specs/ru_spec.rs | 11 +- crates/test-utils/tests/basic_sim.rs | 4 + crates/test-utils/tests/bundle.rs | 126 ++++++++++++++++++++- crates/test-utils/tests/evm.rs | 29 +++-- 12 files changed, 307 insertions(+), 42 deletions(-) create mode 100644 crates/test-utils/src/contracts/reverts.rs diff --git a/crates/bundle/src/lib.rs b/crates/bundle/src/lib.rs index 86b1a092..76ffcae6 100644 --- a/crates/bundle/src/lib.rs +++ b/crates/bundle/src/lib.rs @@ -51,6 +51,6 @@ pub use call::{SignetBundleDriver, SignetCallBundle, SignetCallBundleResponse}; mod send; pub use send::{ - SignetEthBundle, SignetEthBundleDriver, SignetEthBundleError, SignetEthBundleInsp, - SignetEthBundleResponse, + BundleInspector, SignetEthBundle, SignetEthBundleDriver, SignetEthBundleError, + SignetEthBundleInsp, SignetEthBundleResponse, }; diff --git a/crates/bundle/src/send/bundle.rs b/crates/bundle/src/send/bundle.rs index 5582382a..ee5baf08 100644 --- a/crates/bundle/src/send/bundle.rs +++ b/crates/bundle/src/send/bundle.rs @@ -12,7 +12,14 @@ use alloy::{ use serde::{Deserialize, Serialize}; use signet_types::{SignedFill, SignedPermitError}; use signet_zenith::HostOrders::HostOrdersInstance; -use trevm::{revm::Database, BundleError}; +use trevm::{ + inspectors::{Layered, TimeLimit}, + revm::{inspector::NoOpInspector, Database}, + BundleError, +}; + +/// The inspector type required by the Signet bundle driver. +pub type BundleInspector = Layered; /// Bundle of transactions for `signet_sendBundle`. /// diff --git a/crates/bundle/src/send/mod.rs b/crates/bundle/src/send/mod.rs index 92f23d62..4e3abbc2 100644 --- a/crates/bundle/src/send/mod.rs +++ b/crates/bundle/src/send/mod.rs @@ -1,5 +1,5 @@ mod bundle; -pub use bundle::{SignetEthBundle, SignetEthBundleResponse}; +pub use bundle::{BundleInspector, SignetEthBundle, SignetEthBundleResponse}; mod driver; pub use driver::{SignetEthBundleDriver, SignetEthBundleError, SignetEthBundleInsp}; diff --git a/crates/test-utils/src/contracts/counter.rs b/crates/test-utils/src/contracts/counter.rs index 0a3a93a5..7bc136ca 100644 --- a/crates/test-utils/src/contracts/counter.rs +++ b/crates/test-utils/src/contracts/counter.rs @@ -1,5 +1,5 @@ use alloy::{ - primitives::{b256, bytes, Address, Bytes, B256}, + primitives::{b256, bytes, Address, Bytes, B256, U256}, providers::Provider, }; @@ -14,6 +14,9 @@ alloy::sol! { } } +/// The storage slot where the counter value is stored in the Counter contract. +pub const COUNTER_SLOT: U256 = U256::ZERO; + /// A test address for the Counter.sol contract, which will be pre-deployed in /// test EVMs. pub const COUNTER_TEST_ADDRESS: Address = Address::repeat_byte(0x49); diff --git a/crates/test-utils/src/contracts/mod.rs b/crates/test-utils/src/contracts/mod.rs index 3ce43243..0441a8c7 100644 --- a/crates/test-utils/src/contracts/mod.rs +++ b/crates/test-utils/src/contracts/mod.rs @@ -1,5 +1,11 @@ +/// A Counter contract that can be incremented. pub mod counter; +/// Orders, Passage, and Token system contracts. pub mod system; +/// A token contract, deployed for Wbtc and Weth. pub mod token; + +/// A contract that always reverts. +pub mod reverts; diff --git a/crates/test-utils/src/contracts/reverts.rs b/crates/test-utils/src/contracts/reverts.rs new file mode 100644 index 00000000..7a6872f6 --- /dev/null +++ b/crates/test-utils/src/contracts/reverts.rs @@ -0,0 +1,21 @@ +use crate::contracts::counter::Counter; +use alloy::{ + primitives::{bytes, Address, Bytes}, + providers::Provider, +}; + +/// A test address for the Revert contract, which will be pre-deployed in +/// test EVMs. +pub const REVERT_TEST_ADDRESS: Address = Address::repeat_byte(0x50); + +/// Revert deploycode for testing purposes. +pub const REVERT_DEPLOY_CODE: Bytes = bytes!("0x608060405234601957600e601d565b60c76028823960c790f35b6023565b60405190565b5f80fdfe608060405234156073576013565b60405190565b5f80fd5b60209181520190565b5f7f5265766572742063616c6c656400000000000000000000000000000000000000910152565b6052600d6020926017565b6059816020565b0190565b60709060208101905f8183039101526047565b90565b6079600d565b62461bcd60e51b815280608d60048201605d565b0390fdfea2646970667358221220ca26ecb1412cc6e87fe99712d1085a242349863e03e3e43ef6ee7dde7a3478cc64736f6c634300081a0033"); + +/// Revert bytecode for testing purposes. +pub const REVERT_BYTECODE: Bytes = bytes!( + "0x608060405234156073576013565b60405190565b5f80fd5b60209181520190565b5f7f5265766572742063616c6c656400000000000000000000000000000000000000910152565b6052600d6020926017565b6059816020565b0190565b60709060208101905f8183039101526047565b90565b6079600d565b62461bcd60e51b815280608d60048201605d565b0390fdfea2646970667358221220ca26ecb1412cc6e87fe99712d1085a242349863e03e3e43ef6ee7dde7a3478cc64736f6c634300081a0033"); + +/// Get an instance of the pre-deployed Counter contract. +pub fn revert(p: P) -> Counter::CounterInstance

{ + Counter::CounterInstance::new(REVERT_TEST_ADDRESS, p) +} diff --git a/crates/test-utils/src/evm.rs b/crates/test-utils/src/evm.rs index 1d3a6c44..adc7eab9 100644 --- a/crates/test-utils/src/evm.rs +++ b/crates/test-utils/src/evm.rs @@ -1,22 +1,57 @@ -use signet_constants::test_utils::*; -use trevm::revm::{ - context::CfgEnv, database::in_memory_db::InMemoryDB, primitives::hardfork::SpecId, - state::Bytecode, +use crate::{ + contracts::{ + counter::{COUNTER_BYTECODE, COUNTER_TEST_ADDRESS}, + reverts::{REVERT_BYTECODE, REVERT_TEST_ADDRESS}, + system::{RU_ORDERS_BYTECODE, RU_PASSAGE_BYTECODE}, + token::{ + MINTER, MINTER_SLOT, NAME_SLOT, SYMBOL_SLOT, TOKEN_BYTECODE, WBTC_NAME, WBTC_SYMBOL, + WETH_NAME, WETH_SYMBOL, + }, + }, + users::TEST_USERS, }; - -use crate::contracts::{ - counter::{COUNTER_BYTECODE, COUNTER_TEST_ADDRESS}, - system::{RU_ORDERS_BYTECODE, RU_PASSAGE_BYTECODE}, - token::{ - MINTER, MINTER_SLOT, NAME_SLOT, SYMBOL_SLOT, TOKEN_BYTECODE, WBTC_NAME, WBTC_SYMBOL, - WETH_NAME, WETH_SYMBOL, +use alloy::{consensus::constants::ETH_TO_WEI, primitives::U256}; +use signet_constants::test_utils::*; +use trevm::{ + helpers::Ctx, + revm::{ + context::CfgEnv, database::in_memory_db::InMemoryDB, inspector::NoOpInspector, + primitives::hardfork::SpecId, state::Bytecode, Inspector, }, }; -/// Create a new Signet EVM with an in-memory database for testing. Deploy -/// system contracts and pre-deployed tokens. +/// Create a new Signet EVM with an in-memory database for testing. +/// +/// Performs initial setup to +/// - Deploy [`RU_ORDERS`] and and [`RU_PASSAGE`] system contracts +/// - Deploy a [`COUNTER`] contract for testing at [`COUNTER_TEST_ADDRESS`]. +/// - Deploy Token contracts for WBTC and WETH with their respective bytecodes +/// and storage. +/// - Deploy a `Revert` contract for testing at [`REVERT_TEST_ADDRESS`]. +/// - Fund the [`TEST_USERS`] with 1000 ETH each. +/// +/// [`COUNTER`]: crate::contracts::counter::Counter pub fn test_signet_evm() -> signet_evm::EvmNeedsBlock { - let mut evm = signet_evm::signet_evm(InMemoryDB::default(), TEST_SYS).fill_cfg(&TestCfg); + test_signet_evm_with_inspector(NoOpInspector) +} + +/// Create a new Signet EVM with an in-memory database for testing. +/// +/// Performs initial setup to +/// - Deploy [`RU_ORDERS`] and and [`RU_PASSAGE`] system contracts +/// - Deploy a [`COUNTER`] contract for testing at [`COUNTER_TEST_ADDRESS`]. +/// - Deploy Token contracts for WBTC and WETH with their respective bytecodes +/// and storage. +/// - Deploy a `Revert` contract for testing at [`REVERT_TEST_ADDRESS`]. +/// - Fund the [`TEST_USERS`] with 1000 ETH each. +/// +/// [`COUNTER`]: crate::contracts::counter::Counter +pub fn test_signet_evm_with_inspector(inspector: I) -> signet_evm::EvmNeedsBlock +where + I: Inspector>, +{ + let mut evm = signet_evm::signet_evm_with_inspector(InMemoryDB::default(), inspector, TEST_SYS) + .fill_cfg(&TestCfg); // Set the bytecode for system contracts evm.set_bytecode_unchecked(TEST_SYS.ru_orders(), Bytecode::new_legacy(RU_ORDERS_BYTECODE)); @@ -37,6 +72,14 @@ pub fn test_signet_evm() -> signet_evm::EvmNeedsBlock { // Set the bytecode for the Counter contract evm.set_bytecode_unchecked(COUNTER_TEST_ADDRESS, Bytecode::new_legacy(COUNTER_BYTECODE)); + // Set the bytecode for the Revert contract + evm.set_bytecode_unchecked(REVERT_TEST_ADDRESS, Bytecode::new_legacy(REVERT_BYTECODE)); + + // increment the balance for each test signer + TEST_USERS.iter().copied().for_each(|user| { + evm.set_balance_unchecked(user, U256::from(1000 * ETH_TO_WEI)); + }); + evm } diff --git a/crates/test-utils/src/specs/mod.rs b/crates/test-utils/src/specs/mod.rs index 7db757b0..c1809c05 100644 --- a/crates/test-utils/src/specs/mod.rs +++ b/crates/test-utils/src/specs/mod.rs @@ -8,16 +8,22 @@ mod ru_spec; pub use ru_spec::RuBlockSpec; use alloy::{ - consensus::{constants::GWEI_TO_WEI, SignableTransaction, TxEip1559}, + consensus::{ + constants::GWEI_TO_WEI, SignableTransaction, TxEip1559, TxEnvelope, TypedTransaction, + }, + eips::Encodable2718, primitives::{Address, TxKind, B256, U256}, + rpc::types::mev::EthSendBundle, signers::{local::PrivateKeySigner, SignerSync}, + sol_types::SolCall, }; -use signet_types::primitives::{Transaction, TransactionSigned}; +use signet_bundle::SignetEthBundle; +use signet_types::SignedFill; /// Sign a transaction with a wallet. -pub fn sign_tx_with_key_pair(wallet: &PrivateKeySigner, tx: Transaction) -> TransactionSigned { +pub fn sign_tx_with_key_pair(wallet: &PrivateKeySigner, tx: TypedTransaction) -> TxEnvelope { let signature = wallet.sign_hash_sync(&tx.signature_hash()).unwrap(); - TransactionSigned::new_unhashed(tx, signature) + TxEnvelope::new_unhashed(tx, signature) } /// Make a wallet with a deterministic keypair. @@ -26,7 +32,7 @@ pub fn make_wallet(i: u8) -> PrivateKeySigner { } /// Make a simple send transaction. -pub fn simple_send(to: Address, amount: U256, nonce: u64, ru_chain_id: u64) -> Transaction { +pub fn simple_send(to: Address, amount: U256, nonce: u64, ru_chain_id: u64) -> TypedTransaction { TxEip1559 { nonce, gas_limit: 21_000, @@ -39,3 +45,48 @@ pub fn simple_send(to: Address, amount: U256, nonce: u64, ru_chain_id: u64) -> T } .into() } + +/// Make a simple contract call transaction. +pub fn simple_call(to: Address, input: &T, nonce: u64, ru_chain_id: u64) -> TypedTransaction +where + T: SolCall, +{ + TxEip1559 { + nonce, + gas_limit: 2_100_000, + to: TxKind::Call(to), + value: U256::ZERO, + chain_id: ru_chain_id, + max_fee_per_gas: GWEI_TO_WEI as u128 * 100, + max_priority_fee_per_gas: GWEI_TO_WEI as u128, + input: input.abi_encode().into(), + ..Default::default() + } + .into() +} + +/// Create a simple bundle from a list of transactions. +pub fn simple_bundle<'a>( + txs: impl IntoIterator, + host_fills: Option, + block_number: u64, +) -> SignetEthBundle { + let txs = txs.into_iter().map(|tx| tx.encoded_2718().into()).collect(); + + SignetEthBundle { + bundle: EthSendBundle { + txs, + block_number, + min_timestamp: None, + max_timestamp: None, + reverting_tx_hashes: vec![], + replacement_uuid: None, + dropping_tx_hashes: vec![], + refund_percent: None, + refund_recipient: None, + refund_tx_hashes: vec![], + extra_fields: Default::default(), + }, + host_fills, + } +} diff --git a/crates/test-utils/src/specs/ru_spec.rs b/crates/test-utils/src/specs/ru_spec.rs index 77ebca61..5531acf9 100644 --- a/crates/test-utils/src/specs/ru_spec.rs +++ b/crates/test-utils/src/specs/ru_spec.rs @@ -8,10 +8,7 @@ use alloy::{ }; use signet_constants::test_utils::*; use signet_extract::{Extractable, Extracts}; -use signet_types::{ - constants::{KnownChains, ParseChainError, SignetSystemConstants}, - primitives::TransactionSigned, -}; +use signet_types::constants::{KnownChains, ParseChainError, SignetSystemConstants}; use signet_zenith::Zenith::{self}; use std::str::FromStr; @@ -66,7 +63,7 @@ impl RuBlockSpec { } /// Add a transaction to the block. - pub fn add_tx(&mut self, tx: &TransactionSigned) { + pub fn add_tx(&mut self, tx: &TxEnvelope) { self.tx.push(tx.encoded_2718()); } @@ -81,7 +78,7 @@ impl RuBlockSpec { } /// Add a transaction to the block, returning self. - pub fn tx(mut self, tx: &TransactionSigned) -> Self { + pub fn tx(mut self, tx: &TxEnvelope) -> Self { self.add_tx(tx); self } @@ -99,7 +96,7 @@ impl RuBlockSpec { to: Address, amount: U256, nonce: u64, - ) -> TransactionSigned { + ) -> TxEnvelope { let tx = sign_tx_with_key_pair( wallet, simple_send(to, amount, nonce, self.constants.ru_chain_id()), diff --git a/crates/test-utils/tests/basic_sim.rs b/crates/test-utils/tests/basic_sim.rs index 50aab433..8653972e 100644 --- a/crates/test-utils/tests/basic_sim.rs +++ b/crates/test-utils/tests/basic_sim.rs @@ -85,6 +85,10 @@ pub async fn test_simulator() { dbg!(time.elapsed()); } +// utilities below this point are reproduced from other places, however, +// because this test modifies the _db_ rather than the _evm_, +// we need to handle them slightly differently here. + /// Modify an account with a closure and commit the modified account. /// /// This code is reproduced and modified from trevm diff --git a/crates/test-utils/tests/bundle.rs b/crates/test-utils/tests/bundle.rs index 7c507ea7..31057979 100644 --- a/crates/test-utils/tests/bundle.rs +++ b/crates/test-utils/tests/bundle.rs @@ -3,5 +3,129 @@ //! - Txns must not revert, unless marked as revertible. //! - Txns must not be dropped by market rules, unless marked as droppable. +use alloy::primitives::{Address, U256}; +use signet_bundle::{BundleInspector, SignetEthBundleDriver, SignetEthBundleError}; +use signet_evm::EvmNeedsTx; +use signet_test_utils::{ + chain::{RU_CHAIN_ID, TEST_SYS}, + contracts::{ + counter::{Counter, COUNTER_SLOT, COUNTER_TEST_ADDRESS}, + reverts::REVERT_TEST_ADDRESS, + }, + evm::test_signet_evm_with_inspector, + specs::{sign_tx_with_key_pair, simple_bundle, simple_call, simple_send}, + users::TEST_SIGNERS, +}; +use std::time::{Duration, Instant}; +use trevm::{ + inspectors::{Layered, TimeLimit}, + revm::{database::InMemoryDB, inspector::NoOpInspector}, + BundleDriver, BundleError, NoopBlock, +}; + +fn bundle_evm() -> EvmNeedsTx { + let inspector: BundleInspector<_> = + Layered::new(TimeLimit::new(Duration::from_secs(5)), NoOpInspector); + test_signet_evm_with_inspector(inspector).fill_block(&NoopBlock) +} + +#[tokio::test] +async fn test_bundle_ok() { + let trevm = bundle_evm(); + let recipient = Address::repeat_byte(0x31); + + // This bundle contains two transactions: + // 1. A simple send from user 0 to 0x3131.... + // 2. A call to the Counter contract to increment the counter. + let user_wallet = &TEST_SIGNERS[0]; + + let tx_1 = simple_send(recipient, U256::ONE, 0, RU_CHAIN_ID); + let tx_2 = simple_call(COUNTER_TEST_ADDRESS, &Counter::incrementCall, 1, RU_CHAIN_ID); + + let tx_1 = sign_tx_with_key_pair(user_wallet, tx_1); + let tx_2 = sign_tx_with_key_pair(user_wallet, tx_2); + + let bundle = simple_bundle(&[tx_1, tx_2], None, 0); + + let mut driver = SignetEthBundleDriver::new( + &bundle, + TEST_SYS.host_chain_id(), + Instant::now() + Duration::from_secs(5), + ); + + // We expect this to work. + let trevm = driver.run_bundle(trevm).unwrap(); + + // Assert that the bundle was executed successfully. + + // Check the balance of the recipient increased. + assert_eq!(trevm.read_balance_ref(recipient), U256::ONE); + assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::from(1)); +} + +#[tokio::test] +async fn test_bundle_revert() { + let trevm = bundle_evm(); + let recipient = Address::repeat_byte(0x31); + + // This bundle contains two transactions: + // 1. A simple send from user 0 to 0x3131.... + // 2. A call to the Counter contract to increment the counter. + let user_wallet = &TEST_SIGNERS[0]; + + let tx_1 = simple_send(recipient, U256::ONE, 0, RU_CHAIN_ID); + let tx_2 = simple_call(REVERT_TEST_ADDRESS, &Counter::incrementCall, 1, RU_CHAIN_ID); + + let tx_1 = sign_tx_with_key_pair(user_wallet, tx_1); + let tx_2 = sign_tx_with_key_pair(user_wallet, tx_2); + + let bundle = simple_bundle(&[tx_1, tx_2], None, 0); + + let mut driver = SignetEthBundleDriver::new( + &bundle, + TEST_SYS.host_chain_id(), + Instant::now() + Duration::from_secs(5), + ); + + let (err, trevm) = driver.run_bundle(trevm).unwrap_err().take_err(); + assert!(matches!(err, SignetEthBundleError::BundleError(BundleError::BundleReverted))); + + // Bundle should not have executed any transactions. + assert_eq!(trevm.read_balance_ref(recipient), U256::ZERO); + assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::ZERO); +} + #[tokio::test] -async fn test_bundle_guarantees() {} +async fn test_bundle_droppable() { + let trevm = bundle_evm(); + let recipient = Address::repeat_byte(0x31); + + // This bundle contains two transactions: + // 1. A simple send from user 0 to 0x3131.... + // 2. A call to the Counter contract to increment the counter. + let user_wallet = &TEST_SIGNERS[0]; + + let tx_1 = simple_send(recipient, U256::ONE, 0, RU_CHAIN_ID); + let tx_2 = simple_call(REVERT_TEST_ADDRESS, &Counter::incrementCall, 1, RU_CHAIN_ID); + + let tx_1 = sign_tx_with_key_pair(user_wallet, tx_1); + let tx_2 = sign_tx_with_key_pair(user_wallet, tx_2); + + // Mark the second transaction as droppable. + let hash = *tx_2.hash(); + let mut bundle = simple_bundle(&[tx_1, tx_2], None, 0); + bundle.bundle.reverting_tx_hashes.push(hash); + + let mut driver = SignetEthBundleDriver::new( + &bundle, + TEST_SYS.host_chain_id(), + Instant::now() + Duration::from_secs(5), + ); + + // We expect this to work and drop the second transaction. + let trevm = driver.run_bundle(trevm).unwrap(); + + // Check the balance of the recipient increased, and the counter was not incremented. + assert_eq!(trevm.read_balance_ref(recipient), U256::ONE); + assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::ZERO); +} diff --git a/crates/test-utils/tests/evm.rs b/crates/test-utils/tests/evm.rs index 2d1bf97c..1d8fe9f2 100644 --- a/crates/test-utils/tests/evm.rs +++ b/crates/test-utils/tests/evm.rs @@ -1,7 +1,7 @@ use alloy::{ consensus::{ constants::{ETH_TO_WEI, GWEI_TO_WEI}, - Header, ReceiptEnvelope, TxEip1559, + Header, ReceiptEnvelope, TxEip1559, TxEnvelope, }, primitives::{Address, U256}, signers::{local::PrivateKeySigner, Signature}, @@ -68,7 +68,7 @@ impl TestEnv { block } - fn signed_simple_send(&mut self, from: usize, to: Address, amount: U256) -> TransactionSigned { + fn signed_simple_send(&mut self, from: usize, to: Address, amount: U256) -> TxEnvelope { let wallet = &self.wallets[from]; let tx = simple_send(to, amount, self.nonces[from], RU_CHAIN_ID); let tx = sign_tx_with_key_pair(wallet, tx); @@ -88,7 +88,7 @@ fn test_simple_send() { // Setup the driver let block = context.next_block(); let mut extracts = Extracts::::empty(&block); - let mut driver = context.driver(&mut extracts, vec![tx.clone()]); + let mut driver = context.driver(&mut extracts, vec![tx.clone().into()]); // Run the EVM let mut trevm = context.trevm().drive_block(&mut driver).unwrap(); @@ -96,7 +96,7 @@ fn test_simple_send() { // Assert that the EVM balance increased assert_eq!(sealed_block.senders.len(), 1); - assert_eq!(sealed_block.block.body.transactions().next(), Some(&tx)); + assert_eq!(sealed_block.block.body.transactions().next(), Some(&tx.clone().into())); assert_eq!(receipts.len(), 1); assert_eq!(trevm.read_balance(to), U256::from(100)); @@ -116,7 +116,7 @@ fn test_two_sends() { // Setup the driver let block = context.next_block(); let mut extracts = Extracts::::empty(&block); - let mut driver = context.driver(&mut extracts, vec![tx1.clone(), tx2.clone()]); + let mut driver = context.driver(&mut extracts, vec![tx1.clone().into(), tx2.clone().into()]); // Run the EVM let mut trevm = context.trevm().drive_block(&mut driver).unwrap(); @@ -124,7 +124,10 @@ fn test_two_sends() { // Assert that the EVM balance increased assert_eq!(sealed_block.senders.len(), 2); - assert_eq!(sealed_block.block.body.transactions().collect::>(), vec![&tx1, &tx2]); + assert_eq!( + sealed_block.block.body.transactions().collect::>(), + vec![&tx1.clone().into(), &tx2.clone().into()] + ); assert_eq!(receipts.len(), 2); assert_eq!(trevm.read_balance(to), U256::from(100)); @@ -142,14 +145,17 @@ fn test_execute_two_blocks() { // Setup the driver let block = context.next_block(); let mut extracts = Extracts::::empty(&block); - let mut driver = context.driver(&mut extracts, vec![tx.clone()]); + let mut driver = context.driver(&mut extracts, vec![tx.clone().into()]); // Run the EVM let mut trevm = context.trevm().drive_block(&mut driver).unwrap(); let (sealed_block, receipts) = driver.finish(); assert_eq!(sealed_block.senders.len(), 1); - assert_eq!(sealed_block.block.body.transactions().collect::>(), vec![&tx]); + assert_eq!( + sealed_block.block.body.transactions().collect::>(), + vec![&tx.clone().into()] + ); assert_eq!(receipts.len(), 1); assert_eq!(trevm.read_balance(to), U256::from(100)); assert_eq!(trevm.read_nonce(sender), 1); @@ -161,14 +167,17 @@ fn test_execute_two_blocks() { // Setup the driver let block = context.next_block(); let mut extracts = Extracts::::empty(&block); - let mut driver = context.driver(&mut extracts, vec![tx.clone()]); + let mut driver = context.driver(&mut extracts, vec![tx.clone().into()]); // Run the EVM let mut trevm = trevm.drive_block(&mut driver).unwrap(); let (sealed_block, receipts) = driver.finish(); assert_eq!(sealed_block.senders.len(), 1); - assert_eq!(sealed_block.block.body.transactions().collect::>(), vec![&tx]); + assert_eq!( + sealed_block.block.body.transactions().collect::>(), + vec![&tx.clone().into()] + ); assert_eq!(receipts.len(), 1); assert_eq!(trevm.read_balance(to), U256::from(200)); } From fee08a20b255eb7d793556f666bc2f3a77e62926 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 21 Aug 2025 15:44:40 -0400 Subject: [PATCH 2/4] fix: bundle driver rejection works more correctly --- crates/bundle/src/send/driver.rs | 34 ++-- crates/test-utils/src/specs/mod.rs | 10 +- crates/test-utils/tests/bundle.rs | 277 +++++++++++++++++++++++------ 3 files changed, 256 insertions(+), 65 deletions(-) diff --git a/crates/bundle/src/send/driver.rs b/crates/bundle/src/send/driver.rs index 7911f09c..45803591 100644 --- a/crates/bundle/src/send/driver.rs +++ b/crates/bundle/src/send/driver.rs @@ -1,8 +1,10 @@ use crate::send::SignetEthBundle; use alloy::primitives::U256; -use signet_evm::{DriveBundleResult, EvmNeedsTx, EvmTransacted, SignetInspector, SignetLayered}; +use signet_evm::{ + DriveBundleResult, EvmErrored, EvmNeedsTx, EvmTransacted, SignetInspector, SignetLayered, +}; use signet_types::{AggregateFills, MarketError, SignedPermitError}; -use tracing::debug; +use tracing::{debug, error}; use trevm::{ helpers::Ctx, inspectors::{Layered, TimeLimit}, @@ -143,9 +145,7 @@ impl<'a> SignetEthBundleDriver<'a> { // We check the AggregateFills here, and if it fails, we discard the // transaction outcome and push a failure receipt. - self.agg_fills.checked_remove_ru_tx_events(&agg_orders, &agg_fills).inspect_err(|err| { - debug!(%err, "Discarding transaction outcome due to market error"); - }) + self.agg_fills.checked_remove_ru_tx_events(&agg_orders, &agg_fills) } } @@ -200,6 +200,8 @@ where let txs = trevm_try!(self.bundle.decode_and_validate_txs(), trevm); for tx in txs.into_iter() { + let _span = tracing::debug_span!("bundle_tx_loop", tx_hash = %tx.hash()).entered(); + // Update the inner deadline. let limit = trevm.inner_mut_unchecked().ctx_inspector().1.outer_mut().outer_mut(); *limit = TimeLimit::new(self.deadline - std::time::Instant::now()); @@ -209,7 +211,10 @@ where // Temporary rebinding of trevm within each loop iteration. // The type of t is `EvmTransacted`, while the type of trevm is // `EvmNeedsTx`. - let mut t = trevm.run_tx(&tx).map_err(|err| err.err_into())?; + let mut t = trevm + .run_tx(&tx) + .map_err(EvmErrored::err_into) + .inspect_err(|err| error!(err = %err.error(), "error while running transaction"))?; // Check the result of the transaction. let result = t.result(); @@ -221,10 +226,14 @@ where // not, and the tx is not marked as revertible by the bundle, we // error our simulation. if result.is_success() { - if self.check_fills(&mut t).is_err() - && !self.bundle.reverting_tx_hashes().contains(tx_hash) - { - return Err(t.errored(BundleError::BundleReverted.into())); + if self.check_fills(&mut t).is_err() { + debug!("transaction dropped due to insufficient fills"); + if self.bundle.reverting_tx_hashes().contains(tx_hash) { + trevm = t.reject(); + continue; + } else { + return Err(t.errored(BundleError::BundleReverted.into())); + } } self.total_gas_used = self.total_gas_used.saturating_add(gas_used); @@ -233,13 +242,14 @@ where // not marked as revertible by the bundle, we error our // simulation. if !self.bundle.reverting_tx_hashes().contains(tx_hash) { + debug!("transaction reverted, not marked as revertible"); return Err(t.errored(BundleError::BundleReverted.into())); } self.total_gas_used = self.total_gas_used.saturating_add(gas_used); } - // If we did not shortcut return, we accept the state changes - // from this transaction. + // If we did not shortcut return/continue, we accept the state + // changes from this transaction. trevm = t.accept_state() } diff --git a/crates/test-utils/src/specs/mod.rs b/crates/test-utils/src/specs/mod.rs index c1809c05..918243aa 100644 --- a/crates/test-utils/src/specs/mod.rs +++ b/crates/test-utils/src/specs/mod.rs @@ -47,7 +47,13 @@ pub fn simple_send(to: Address, amount: U256, nonce: u64, ru_chain_id: u64) -> T } /// Make a simple contract call transaction. -pub fn simple_call(to: Address, input: &T, nonce: u64, ru_chain_id: u64) -> TypedTransaction +pub fn simple_call( + to: Address, + input: &T, + value: U256, + nonce: u64, + ru_chain_id: u64, +) -> TypedTransaction where T: SolCall, { @@ -55,7 +61,7 @@ where nonce, gas_limit: 2_100_000, to: TxKind::Call(to), - value: U256::ZERO, + value, chain_id: ru_chain_id, max_fee_per_gas: GWEI_TO_WEI as u128 * 100, max_priority_fee_per_gas: GWEI_TO_WEI as u128, diff --git a/crates/test-utils/tests/bundle.rs b/crates/test-utils/tests/bundle.rs index 31057979..437f464e 100644 --- a/crates/test-utils/tests/bundle.rs +++ b/crates/test-utils/tests/bundle.rs @@ -3,49 +3,158 @@ //! - Txns must not revert, unless marked as revertible. //! - Txns must not be dropped by market rules, unless marked as droppable. -use alloy::primitives::{Address, U256}; -use signet_bundle::{BundleInspector, SignetEthBundleDriver, SignetEthBundleError}; +use alloy::{ + consensus::TypedTransaction, + primitives::{keccak256, Address, U256}, + signers::local::PrivateKeySigner, + uint, +}; +use signet_bundle::{ + BundleInspector, SignetEthBundle, SignetEthBundleDriver, SignetEthBundleError, +}; +use signet_constants::pecorino::{HOST_WBTC, HOST_WETH}; use signet_evm::EvmNeedsTx; use signet_test_utils::{ - chain::{RU_CHAIN_ID, TEST_SYS}, + chain::{HOST_CHAIN_ID, RU_CHAIN_ID, RU_ORDERS, TEST_SYS}, contracts::{ counter::{Counter, COUNTER_SLOT, COUNTER_TEST_ADDRESS}, reverts::REVERT_TEST_ADDRESS, }, evm::test_signet_evm_with_inspector, specs::{sign_tx_with_key_pair, simple_bundle, simple_call, simple_send}, - users::TEST_SIGNERS, + users::{TEST_SIGNERS, TEST_USERS}, +}; +use signet_types::SignedFill; +use signet_zenith::HostOrders::{ + initiateCall, Input, Output, Permit2Batch, PermitBatchTransferFrom, TokenPermissions, +}; +use std::{ + sync::LazyLock, + time::{Duration, Instant}, }; -use std::time::{Duration, Instant}; use trevm::{ inspectors::{Layered, TimeLimit}, revm::{database::InMemoryDB, inspector::NoOpInspector}, BundleDriver, BundleError, NoopBlock, }; +const SENDER: LazyLock

= LazyLock::new(|| TEST_USERS[0]); +const SENDER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[0]); + +const FILLER: Address = Address::repeat_byte(0x30); +const TX_0_RECIPIENT: Address = Address::repeat_byte(0x31); +const TX_2_RECIPIENT: Address = Address::repeat_byte(0x32); + +const INPUT_AMOUNT: U256 = uint!(100_000_000_000_000_000_000_U256); +const OUTPUT_WBTC: U256 = uint!(100_U256); +const OUTPUT_WETH: U256 = uint!(200_U256); + fn bundle_evm() -> EvmNeedsTx { let inspector: BundleInspector<_> = Layered::new(TimeLimit::new(Duration::from_secs(5)), NoOpInspector); test_signet_evm_with_inspector(inspector).fill_block(&NoopBlock) } -#[tokio::test] -async fn test_bundle_ok() { - let trevm = bundle_evm(); - let recipient = Address::repeat_byte(0x31); +fn permit_2_batch(owner: Address, nonce: U256) -> Permit2Batch { + Permit2Batch { + permit: PermitBatchTransferFrom { + permitted: vec![ + TokenPermissions { token: HOST_WBTC, amount: OUTPUT_WBTC }, + TokenPermissions { token: HOST_WETH, amount: OUTPUT_WETH }, + ], + nonce, + deadline: U256::MAX, + }, + owner, + signature: Default::default(), + } +} + +fn host_fills(owner: Address, nonce: U256) -> SignedFill { + let permit = permit_2_batch(owner, nonce); + let outputs = vec![ + Output { + token: HOST_WBTC, + amount: OUTPUT_WBTC, + recipient: TX_0_RECIPIENT, + chainId: RU_CHAIN_ID as u32, + }, + Output { + token: HOST_WETH, + amount: OUTPUT_WETH, + recipient: TX_2_RECIPIENT, + chainId: RU_CHAIN_ID as u32, + }, + ]; + SignedFill { permit, outputs } +} + +fn simple_order(nonce: u64) -> TypedTransaction { + simple_call( + RU_ORDERS, + &initiateCall { + deadline: U256::MAX, + inputs: vec![Input { token: Address::ZERO, amount: INPUT_AMOUNT }], + outputs: vec![ + Output { + token: HOST_WBTC, + amount: OUTPUT_WBTC, + recipient: TX_0_RECIPIENT, + chainId: HOST_CHAIN_ID as u32, + }, + Output { + token: HOST_WETH, + amount: OUTPUT_WETH, + recipient: TX_2_RECIPIENT, + chainId: HOST_CHAIN_ID as u32, + }, + ], + }, + INPUT_AMOUNT, + nonce, + RU_CHAIN_ID, + ) +} + +// This bundle contains two transactions: +// 1. A simple send from user 0 to 0x3131.... +// 2. A call to the Counter contract to increment the counter. +// 3. A simple send from user 0 to 0x3232.... +fn test_bundle( + counter_reverts: bool, + order: bool, + host_fills: Option, +) -> SignetEthBundle { + let call_addr = if counter_reverts { REVERT_TEST_ADDRESS } else { COUNTER_TEST_ADDRESS }; + + let tx_1 = simple_send(TX_0_RECIPIENT, U256::ONE, 0, RU_CHAIN_ID); + let tx_2 = if order { + simple_order(1) + } else { + simple_call(call_addr, &Counter::incrementCall, U256::ZERO, 1, RU_CHAIN_ID) + }; + let tx_3 = simple_send(TX_2_RECIPIENT, U256::ONE, 2, RU_CHAIN_ID); + + let tx_1 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_1); + let tx_2 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_2); + let tx_3 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_3); + + simple_bundle(&[tx_1, tx_2, tx_3], host_fills, 0) +} - // This bundle contains two transactions: - // 1. A simple send from user 0 to 0x3131.... - // 2. A call to the Counter contract to increment the counter. - let user_wallet = &TEST_SIGNERS[0]; +fn order_bundle(host_fills: Option) -> SignetEthBundle { + test_bundle(false, true, host_fills) +} - let tx_1 = simple_send(recipient, U256::ONE, 0, RU_CHAIN_ID); - let tx_2 = simple_call(COUNTER_TEST_ADDRESS, &Counter::incrementCall, 1, RU_CHAIN_ID); +fn counter_bundle(should_revert: bool) -> SignetEthBundle { + test_bundle(should_revert, false, None) +} - let tx_1 = sign_tx_with_key_pair(user_wallet, tx_1); - let tx_2 = sign_tx_with_key_pair(user_wallet, tx_2); +#[test] +fn test_bundle_ok() { + let trevm = bundle_evm(); - let bundle = simple_bundle(&[tx_1, tx_2], None, 0); + let bundle = counter_bundle(false); let mut driver = SignetEthBundleDriver::new( &bundle, @@ -59,27 +168,94 @@ async fn test_bundle_ok() { // Assert that the bundle was executed successfully. // Check the balance of the recipient increased. - assert_eq!(trevm.read_balance_ref(recipient), U256::ONE); + assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::from(1)); + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ONE); +} + +#[test] +fn test_bundle_revert() { + let trevm = bundle_evm(); + + let bundle = counter_bundle(true); + + let mut driver = SignetEthBundleDriver::new( + &bundle, + TEST_SYS.host_chain_id(), + Instant::now() + Duration::from_secs(5), + ); + + let (err, trevm) = driver.run_bundle(trevm).unwrap_err().take_err(); + assert!(matches!(err, SignetEthBundleError::BundleError(BundleError::BundleReverted))); + + // Erroring leaves the evm in a dirty state. The first txn was executed, + // the second reverted, and the third was not executed. + assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); + assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::ZERO); + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ZERO); } -#[tokio::test] -async fn test_bundle_revert() { +#[test] +fn test_bundle_droppable() { let trevm = bundle_evm(); - let recipient = Address::repeat_byte(0x31); - // This bundle contains two transactions: - // 1. A simple send from user 0 to 0x3131.... - // 2. A call to the Counter contract to increment the counter. - let user_wallet = &TEST_SIGNERS[0]; + let mut bundle = counter_bundle(true); - let tx_1 = simple_send(recipient, U256::ONE, 0, RU_CHAIN_ID); - let tx_2 = simple_call(REVERT_TEST_ADDRESS, &Counter::incrementCall, 1, RU_CHAIN_ID); + // Mark the second transaction as droppable. + let hash = keccak256(&bundle.txs()[1]); + bundle.bundle.reverting_tx_hashes.push(hash); + + let mut driver = SignetEthBundleDriver::new( + &bundle, + TEST_SYS.host_chain_id(), + Instant::now() + Duration::from_secs(5), + ); + + // We expect this to work and drop the second transaction. + let trevm = driver.run_bundle(trevm).unwrap(); + + // Check the balance of the recipients increased, and the counter was not incremented. + assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); + assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::ZERO); + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ONE); +} + +#[test] +fn test_order_bundle() { + let trevm = bundle_evm(); + + let inital_balance = trevm.read_balance_ref(*SENDER); + + let host_fills = host_fills(FILLER, U256::from(0)); - let tx_1 = sign_tx_with_key_pair(user_wallet, tx_1); - let tx_2 = sign_tx_with_key_pair(user_wallet, tx_2); + let bundle = order_bundle(Some(host_fills)); - let bundle = simple_bundle(&[tx_1, tx_2], None, 0); + let mut driver = SignetEthBundleDriver::new( + &bundle, + TEST_SYS.host_chain_id(), + Instant::now() + Duration::from_secs(5), + ); + + // We expect this to work and drop the second transaction. + let trevm = driver.run_bundle(trevm).unwrap(); + + // Check the balance of the recipients increased, and the balance of the + // sender decreased by at least the input amount. + let post_balance = trevm.read_balance_ref(*SENDER); + + assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); + assert!(post_balance < inital_balance - INPUT_AMOUNT); + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ONE); +} + +#[test] +fn test_order_bundle_revert() { + let trevm = bundle_evm(); + + let inital_balance = trevm.read_balance_ref(*SENDER); + + // This should cause the order to be invalid, as no fill is provided. + let bundle = order_bundle(None); let mut driver = SignetEthBundleDriver::new( &bundle, @@ -90,31 +266,28 @@ async fn test_bundle_revert() { let (err, trevm) = driver.run_bundle(trevm).unwrap_err().take_err(); assert!(matches!(err, SignetEthBundleError::BundleError(BundleError::BundleReverted))); - // Bundle should not have executed any transactions. - assert_eq!(trevm.read_balance_ref(recipient), U256::ZERO); - assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::ZERO); + // Erroring leaves the evm in a dirty state. The first txn was executed, + // the second was dropped, and the third was not executed. + assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); + assert_eq!(trevm.read_balance_ref(*SENDER), inital_balance - uint!(21000000000001_U256)); // less the value+gas of tx_0 + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ZERO); } -#[tokio::test] -async fn test_bundle_droppable() { +#[test] +fn test_order_bundle_droppable() { let trevm = bundle_evm(); - let recipient = Address::repeat_byte(0x31); - // This bundle contains two transactions: - // 1. A simple send from user 0 to 0x3131.... - // 2. A call to the Counter contract to increment the counter. - let user_wallet = &TEST_SIGNERS[0]; + let inital_balance = trevm.read_balance_ref(*SENDER); - let tx_1 = simple_send(recipient, U256::ONE, 0, RU_CHAIN_ID); - let tx_2 = simple_call(REVERT_TEST_ADDRESS, &Counter::incrementCall, 1, RU_CHAIN_ID); - - let tx_1 = sign_tx_with_key_pair(user_wallet, tx_1); - let tx_2 = sign_tx_with_key_pair(user_wallet, tx_2); + let mut bundle = order_bundle(None); // Mark the second transaction as droppable. - let hash = *tx_2.hash(); - let mut bundle = simple_bundle(&[tx_1, tx_2], None, 0); + let hash = keccak256(&bundle.txs()[1]); bundle.bundle.reverting_tx_hashes.push(hash); + // The 3rd transaction is a send to 0x3232..., which will become INVALID if + // the 2nd transaction is dropped, as the nonce will be too high. + // So we remove it. + bundle.bundle.txs.pop(); let mut driver = SignetEthBundleDriver::new( &bundle, @@ -125,7 +298,9 @@ async fn test_bundle_droppable() { // We expect this to work and drop the second transaction. let trevm = driver.run_bundle(trevm).unwrap(); - // Check the balance of the recipient increased, and the counter was not incremented. - assert_eq!(trevm.read_balance_ref(recipient), U256::ONE); - assert_eq!(trevm.read_storage_ref(COUNTER_TEST_ADDRESS, COUNTER_SLOT), U256::ZERO); + // Check that the balance of the prevert recipient increased, and the balance of the sender decreased by the right gas amount + let post_balance = trevm.read_balance_ref(*SENDER); + assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); + assert_eq!(post_balance, inital_balance - uint!(21000000000001_U256)); // less the value+gas of tx_0 + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ZERO); } From 24f3e97fad355360b2c0a339f6f6666e9744c5b4 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 21 Aug 2025 15:49:15 -0400 Subject: [PATCH 3/4] refactor: distinguish between sender and orderer --- crates/test-utils/tests/bundle.rs | 33 ++++++++++++++----------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/crates/test-utils/tests/bundle.rs b/crates/test-utils/tests/bundle.rs index 437f464e..52c1a6ef 100644 --- a/crates/test-utils/tests/bundle.rs +++ b/crates/test-utils/tests/bundle.rs @@ -38,9 +38,11 @@ use trevm::{ BundleDriver, BundleError, NoopBlock, }; -const SENDER: LazyLock
= LazyLock::new(|| TEST_USERS[0]); const SENDER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[0]); +const ORDERER: LazyLock
= LazyLock::new(|| TEST_USERS[1]); +const ORDERER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[1]); + const FILLER: Address = Address::repeat_byte(0x30); const TX_0_RECIPIENT: Address = Address::repeat_byte(0x31); const TX_2_RECIPIENT: Address = Address::repeat_byte(0x32); @@ -129,14 +131,14 @@ fn test_bundle( let tx_1 = simple_send(TX_0_RECIPIENT, U256::ONE, 0, RU_CHAIN_ID); let tx_2 = if order { - simple_order(1) + simple_order(0) } else { - simple_call(call_addr, &Counter::incrementCall, U256::ZERO, 1, RU_CHAIN_ID) + simple_call(call_addr, &Counter::incrementCall, U256::ZERO, 0, RU_CHAIN_ID) }; - let tx_3 = simple_send(TX_2_RECIPIENT, U256::ONE, 2, RU_CHAIN_ID); + let tx_3 = simple_send(TX_2_RECIPIENT, U256::ONE, 1, RU_CHAIN_ID); let tx_1 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_1); - let tx_2 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_2); + let tx_2 = sign_tx_with_key_pair(&*ORDERER_WALLET, tx_2); let tx_3 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_3); simple_bundle(&[tx_1, tx_2, tx_3], host_fills, 0) @@ -224,7 +226,7 @@ fn test_bundle_droppable() { fn test_order_bundle() { let trevm = bundle_evm(); - let inital_balance = trevm.read_balance_ref(*SENDER); + let inital_balance = trevm.read_balance_ref(*ORDERER); let host_fills = host_fills(FILLER, U256::from(0)); @@ -241,7 +243,7 @@ fn test_order_bundle() { // Check the balance of the recipients increased, and the balance of the // sender decreased by at least the input amount. - let post_balance = trevm.read_balance_ref(*SENDER); + let post_balance = trevm.read_balance_ref(*ORDERER); assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); assert!(post_balance < inital_balance - INPUT_AMOUNT); @@ -252,7 +254,7 @@ fn test_order_bundle() { fn test_order_bundle_revert() { let trevm = bundle_evm(); - let inital_balance = trevm.read_balance_ref(*SENDER); + let inital_balance = trevm.read_balance_ref(*ORDERER); // This should cause the order to be invalid, as no fill is provided. let bundle = order_bundle(None); @@ -269,7 +271,7 @@ fn test_order_bundle_revert() { // Erroring leaves the evm in a dirty state. The first txn was executed, // the second was dropped, and the third was not executed. assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); - assert_eq!(trevm.read_balance_ref(*SENDER), inital_balance - uint!(21000000000001_U256)); // less the value+gas of tx_0 + assert_eq!(trevm.read_balance_ref(*ORDERER), inital_balance); assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ZERO); } @@ -277,17 +279,13 @@ fn test_order_bundle_revert() { fn test_order_bundle_droppable() { let trevm = bundle_evm(); - let inital_balance = trevm.read_balance_ref(*SENDER); + let inital_balance = trevm.read_balance_ref(*ORDERER); let mut bundle = order_bundle(None); // Mark the second transaction as droppable. let hash = keccak256(&bundle.txs()[1]); bundle.bundle.reverting_tx_hashes.push(hash); - // The 3rd transaction is a send to 0x3232..., which will become INVALID if - // the 2nd transaction is dropped, as the nonce will be too high. - // So we remove it. - bundle.bundle.txs.pop(); let mut driver = SignetEthBundleDriver::new( &bundle, @@ -298,9 +296,8 @@ fn test_order_bundle_droppable() { // We expect this to work and drop the second transaction. let trevm = driver.run_bundle(trevm).unwrap(); - // Check that the balance of the prevert recipient increased, and the balance of the sender decreased by the right gas amount - let post_balance = trevm.read_balance_ref(*SENDER); + // The order tx was dropped, but both sends were executed. assert_eq!(trevm.read_balance_ref(TX_0_RECIPIENT), U256::ONE); - assert_eq!(post_balance, inital_balance - uint!(21000000000001_U256)); // less the value+gas of tx_0 - assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ZERO); + assert_eq!(trevm.read_balance_ref(*ORDERER), inital_balance); + assert_eq!(trevm.read_balance_ref(TX_2_RECIPIENT), U256::ONE); } From fb1afa2c3cfa576e53b5e3909057b75ab5678f33 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 21 Aug 2025 15:52:00 -0400 Subject: [PATCH 4/4] lint: clippy --- crates/test-utils/tests/bundle.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/test-utils/tests/bundle.rs b/crates/test-utils/tests/bundle.rs index 52c1a6ef..64706f55 100644 --- a/crates/test-utils/tests/bundle.rs +++ b/crates/test-utils/tests/bundle.rs @@ -38,10 +38,10 @@ use trevm::{ BundleDriver, BundleError, NoopBlock, }; -const SENDER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[0]); +static SENDER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[0]); -const ORDERER: LazyLock
= LazyLock::new(|| TEST_USERS[1]); -const ORDERER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[1]); +static ORDERER: LazyLock
= LazyLock::new(|| TEST_USERS[1]); +static ORDERER_WALLET: LazyLock<&PrivateKeySigner> = LazyLock::new(|| &TEST_SIGNERS[1]); const FILLER: Address = Address::repeat_byte(0x30); const TX_0_RECIPIENT: Address = Address::repeat_byte(0x31); @@ -137,9 +137,9 @@ fn test_bundle( }; let tx_3 = simple_send(TX_2_RECIPIENT, U256::ONE, 1, RU_CHAIN_ID); - let tx_1 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_1); - let tx_2 = sign_tx_with_key_pair(&*ORDERER_WALLET, tx_2); - let tx_3 = sign_tx_with_key_pair(&*SENDER_WALLET, tx_3); + let tx_1 = sign_tx_with_key_pair(&SENDER_WALLET, tx_1); + let tx_2 = sign_tx_with_key_pair(&ORDERER_WALLET, tx_2); + let tx_3 = sign_tx_with_key_pair(&SENDER_WALLET, tx_3); simple_bundle(&[tx_1, tx_2, tx_3], host_fills, 0) }