From 3b12940864e473515a9a465e61ad92bce9c79299 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Sat, 7 Dec 2024 01:02:06 +0200 Subject: [PATCH 01/83] chore: interfaces --- crates/cheatcodes/spec/src/cheatcode.rs | 8 ++++++++ crates/cheatcodes/spec/src/vm.rs | 4 ++++ crates/cheatcodes/src/credible.rs | 8 ++++++++ crates/cheatcodes/src/lib.rs | 2 ++ 4 files changed, 22 insertions(+) create mode 100644 crates/cheatcodes/src/credible.rs diff --git a/crates/cheatcodes/spec/src/cheatcode.rs b/crates/cheatcodes/spec/src/cheatcode.rs index 89cfb31f1df32..4d8ea5a1919b7 100644 --- a/crates/cheatcodes/spec/src/cheatcode.rs +++ b/crates/cheatcodes/spec/src/cheatcode.rs @@ -68,6 +68,12 @@ pub enum Status<'a> { #[serde(rename_all = "camelCase")] #[non_exhaustive] pub enum Group { + /// Cheatcodes that are related to the Phylax Credible Layer + /// + /// Examples: `assertionEx`. + /// + /// Safety: safe + Credible, /// Cheatcodes that read from, or write to the current EVM execution state. /// /// Examples: any of the `record` cheatcodes, `chainId`, `coinbase`. @@ -137,6 +143,7 @@ impl Group { /// `None`. pub const fn safety(self) -> Option { match self { + Self::Credible => Some(Safety::Safe), Self::Evm | Self::Testing => None, Self::Scripting | Self::Filesystem @@ -152,6 +159,7 @@ impl Group { /// Returns this value as a string. pub const fn as_str(self) -> &'static str { match self { + Self::Credible => "credible", Self::Evm => "evm", Self::Testing => "testing", Self::Scripting => "scripting", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 87d938db5691e..8dfe5d685e8a2 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -19,6 +19,10 @@ sol! { #[derive(Debug, Cheatcode)] // Keep this list small to avoid unnecessary bloat. #[sol(abi)] interface Vm { + /// Gets the address for a given private key. + #[cheatcode(group = Credible, safety = Safe)] + function assertionEx(bytes memory tx, bytes memory assertionBytecode) external returns (bool success); + // ======== Types ======== /// Error thrown by cheatcodes. diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs new file mode 100644 index 0000000000000..fd53c569bc880 --- /dev/null +++ b/crates/cheatcodes/src/credible.rs @@ -0,0 +1,8 @@ + +use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; + +impl Cheatcode for assertionExCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + unimplemented!() + } +} \ No newline at end of file diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index 1124f65dda9c4..275aa4f4fe7b2 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -63,6 +63,8 @@ mod toml; mod utils; +mod credible; + /// Cheatcode implementation. pub(crate) trait Cheatcode: CheatcodeDef + DynCheatcode { /// Applies this cheatcode to the given state. From deaea5524a140af017330582d8b766349cb8eaa7 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Mon, 9 Dec 2024 12:11:27 -0500 Subject: [PATCH 02/83] chore: assertion executor dep --- Cargo.toml | 3 +++ crates/cheatcodes/Cargo.toml | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index dbeac987c0358..e1da5a3fb3451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -465,3 +465,6 @@ solar = { package = "solar-compiler", git = "https://github.com/paradigmxyz/sola solar-interface = { package = "solar-interface", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } solar-ast = { package = "solar-ast", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } solar-sema = { package = "solar-sema", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } + +[patch."ssh://git@github.com/phylaxsystems/assertion-executor.git"] +assertion-executor = { path = "../assertion-executor" } diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 799945a663161..3cff95f9e8095 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -14,7 +14,16 @@ exclude.workspace = true [lints] workspace = true +[build-dependencies] +vergen = { workspace = true, default-features = false, features = [ + "build", + "git", + "gitcl", +] } + + [dependencies] +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true @@ -67,3 +76,4 @@ tracing.workspace = true walkdir.workspace = true proptest.workspace = true serde.workspace = true + From 11d19b1186debfff6b70bfa29f935bcabe8e0d8b Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Mon, 9 Dec 2024 12:11:38 -0500 Subject: [PATCH 03/83] fix: add Send boundary --- crates/evm/core/src/backend/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 26e56e7bf883f..cb061f856b608 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -77,7 +77,7 @@ pub type JournaledState = JournalInner; /// An extension trait that allows us to easily extend the `revm::Inspector` capabilities #[auto_impl::auto_impl(&mut)] -pub trait DatabaseExt: Database + DatabaseCommit + Debug { +pub trait DatabaseExt: Database + DatabaseCommit + Debug + Send { /// Creates a new state snapshot at the current point of execution. /// /// A state snapshot is associated with a new unique id that's created for the snapshot. From a747a99463cdd1a8f463693f68ac3972abf3721c Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Mon, 9 Dec 2024 12:11:48 -0500 Subject: [PATCH 04/83] fix: cheatcode interface --- crates/cheatcodes/spec/src/vm.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 8dfe5d685e8a2..4c12376294de5 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -21,7 +21,8 @@ sol! { interface Vm { /// Gets the address for a given private key. #[cheatcode(group = Credible, safety = Safe)] - function assertionEx(bytes memory tx, bytes memory assertionBytecode) external returns (bool success); + function assertionEx(bytes memory tx, address assertionAdopter, bytes[] memory assertionBytecode) external returns (bool success); + // ======== Types ======== From cb4c413a48a2af7338e301fd3f54ae7a6784d8bc Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Wed, 18 Dec 2024 00:34:59 -0500 Subject: [PATCH 05/83] wip: threadsafedb --- crates/cheatcodes/src/credible.rs | 42 +++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index fd53c569bc880..f2fff7a525c33 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,8 +1,46 @@ - use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; +use alloy_sol_types::SolValue; +use assertion_executor::{store::AssertionStore, AssertionExecutorBuilder}; +use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; +use revm::primitives::{Address, B256, U256, Bytecode, AccountInfo}; +use revm::DatabaseRef; +use std::sync::{Arc, Mutex}; + +struct ThreadSafeDb<'a> { + db: Mutex<&'a mut dyn DatabaseExt> +} + +impl<'a> DatabaseRef for ThreadSafeDb<'a> { + type Error = DatabaseError; + + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + self.db.lock().unwrap().basic(address) + } + + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + self.db.lock().unwrap().code_by_hash(code_hash) + } + + fn storage_ref(&self, address: Address, index: U256) -> Result { + self.db.lock().unwrap().storage(address, index) + } + + fn block_hash_ref(&self, number: u64) -> Result { + self.db.lock().unwrap().block_hash(number) + } +} + impl Cheatcode for assertionExCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - unimplemented!() + let Self{tx, assertionAdopter, assertionBytecode} = self.clone(); + let store = AssertionStore::new(100, 100); + let block_number = ccx.ecx.env.block.number; + let db = ThreadSafeDb { db: Mutex::new(ccx.ecx.db) }; + let assertions = vec![(assertionAdopter, assertionBytecode.iter().map(|bytes| Bytecode::LegacyRaw(bytes.to_owned())).collect())]; + store.writer().write(block_number, assertions ); + let assertion_executor = AssertionExecutorBuilder::new(db, store.reader()).build(); + let result = assertion_executor.validate_transaction(); + Ok(true.abi_encode()) } } \ No newline at end of file From b26cb35e1230d0f8920b75a29605ebd4b73e74c7 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Thu, 26 Dec 2024 15:36:15 +0200 Subject: [PATCH 06/83] wip: use broadcast cheatcode to simulate transactions --- Cargo.toml | 5 +- crates/cheatcodes/Cargo.toml | 3 +- crates/cheatcodes/src/credible.rs | 96 +++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e1da5a3fb3451..d940142e8d04c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -464,7 +464,4 @@ rexpect = { git = "https://github.com/rust-cli/rexpect", rev = "2ed0b1898d7edaf6 solar = { package = "solar-compiler", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } solar-interface = { package = "solar-interface", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } solar-ast = { package = "solar-ast", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } -solar-sema = { package = "solar-sema", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } - -[patch."ssh://git@github.com/phylaxsystems/assertion-executor.git"] -assertion-executor = { path = "../assertion-executor" } +solar-sema = { package = "solar-sema", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } \ No newline at end of file diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 3cff95f9e8095..2b4cef78225a5 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -23,7 +23,8 @@ vergen = { workspace = true, default-features = false, features = [ [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git" } +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "feat/revm-18" } +tokio.workspace = true foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index f2fff7a525c33..59aad9449f010 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,15 +1,36 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; +use alloy_consensus::{Transaction, TxEnvelope}; +use alloy_primitives::TxKind; use alloy_sol_types::SolValue; use assertion_executor::{store::AssertionStore, AssertionExecutorBuilder}; +use foundry_common::TransactionMaybeSigned; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; -use revm::primitives::{Address, B256, U256, Bytecode, AccountInfo}; +use revm::primitives::{AccountInfo, Address, Bytecode, OptimismFields, TxEnv, B256, U256}; use revm::DatabaseRef; -use std::sync::{Arc, Mutex}; +use std::sync::{ Arc, Mutex}; +use tokio; +/// Wrapper around DatabaseExt to make it thread-safe +#[derive(Clone)] struct ThreadSafeDb<'a> { - db: Mutex<&'a mut dyn DatabaseExt> + db: Arc>, } +impl std::fmt::Debug for ThreadSafeDb<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ThreadSafeDb") + } +} + +/// Separate implementation block for constructor and helper methods +impl<'a> ThreadSafeDb<'a> { + /// Creates a new thread-safe database wrapper + pub fn new(db: &'a mut dyn DatabaseExt) -> Self { + Self { db: Arc::new(Mutex::new(db)) } + } +} + +/// Keep DatabaseRef implementation separate impl<'a> DatabaseRef for ThreadSafeDb<'a> { type Error = DatabaseError; @@ -30,17 +51,68 @@ impl<'a> DatabaseRef for ThreadSafeDb<'a> { } } - impl Cheatcode for assertionExCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - let Self{tx, assertionAdopter, assertionBytecode} = self.clone(); - let store = AssertionStore::new(100, 100); + let Self { tx, assertionAdopter, assertionBytecode } = self.clone(); + + // Setup assertion store and database + let store = AssertionStore::new(100); + let db = ThreadSafeDb::new(ccx.ecx.db); + + // Prepare assertions data let block_number = ccx.ecx.env.block.number; - let db = ThreadSafeDb { db: Mutex::new(ccx.ecx.db) }; - let assertions = vec![(assertionAdopter, assertionBytecode.iter().map(|bytes| Bytecode::LegacyRaw(bytes.to_owned())).collect())]; - store.writer().write(block_number, assertions ); + let block = ccx.ecx.env.block.clone(); + let assertions = vec![( + assertionAdopter, + assertionBytecode + .iter() + .map(|bytes| Bytecode::LegacyRaw(bytes.to_owned().into())) + .collect(), + )]; + + // Store assertions + store.writer().write(block_number, assertions); + + // Execute assertions let assertion_executor = AssertionExecutorBuilder::new(db, store.reader()).build(); - let result = assertion_executor.validate_transaction(); - Ok(true.abi_encode()) + + // TODO: Add a function in assertion executor which returns: + // 1. Which assertions were touched by which assertions + // 2. Which assertion invalidated which transaction + + let transactions = ccx.state.broadcastable_transactions; + let results = transactions.into_iter().map(|btx| { + let tx = btx.transaction; + let cloned_db = db.clone(); + tokio::runtime::Runtime::new() + .unwrap() + .block_on(async move { + assertion_executor + .validate_transaction(block, envelope_to_environment(&tx), cloned_db) + .await + }) + .expect("Assertion execution failed") + .is_some() + }).collect(); + Ok(results.abi_encode()) + } +} + +pub fn envelope_to_environment(tx: &TransactionMaybeSigned) -> TxEnv { + match tx { + TransactionMaybeSigned::Signed{ tx, from} => + TxEnv { + caller: *from, + gas_limit: tx.gas_limit(), + gas_price: U256::from(0), + gas_priority_fee: None, + transact_to: if tx.is_create() { TxKind::Create } else { TxKind::Call(tx.to().unwrap()) }, + value: tx.value(), + data: tx.input().clone(), + chain_id: tx.chain_id(), + nonce: Some(tx.nonce()), + .. Default::default() + }, + _ => todo!(), } -} \ No newline at end of file +} From 0f84769deb900a12e85fb3f5f3cda62080881b56 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Thu, 26 Dec 2024 17:39:37 +0200 Subject: [PATCH 07/83] feat: execute assertions --- crates/cheatcodes/src/credible.rs | 80 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 59aad9449f010..6c4f2911697c1 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,11 +1,10 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; -use alloy_consensus::{Transaction, TxEnvelope}; use alloy_primitives::TxKind; -use alloy_sol_types::SolValue; +use alloy_sol_types::{sol, SolValue}; +use assertion_executor::db::fork_db::ForkDb; use assertion_executor::{store::AssertionStore, AssertionExecutorBuilder}; -use foundry_common::TransactionMaybeSigned; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; -use revm::primitives::{AccountInfo, Address, Bytecode, OptimismFields, TxEnv, B256, U256}; +use revm::primitives::{AccountInfo, Address, Bytecode, TxEnv, B256, U256}; use revm::DatabaseRef; use std::sync::{ Arc, Mutex}; use tokio; @@ -30,6 +29,15 @@ impl<'a> ThreadSafeDb<'a> { } } +sol ! { + struct SimpleTransaction { + address from; + address to; + uint256 value; + bytes data; + } +} + /// Keep DatabaseRef implementation separate impl<'a> DatabaseRef for ThreadSafeDb<'a> { type Error = DatabaseError; @@ -69,50 +77,40 @@ impl Cheatcode for assertionExCall { .map(|bytes| Bytecode::LegacyRaw(bytes.to_owned().into())) .collect(), )]; + + let decoded_tx= SimpleTransaction::abi_decode(&tx, true)?; + let tx = TxEnv { + caller: decoded_tx.from, + gas_limit: 1000000, + gas_price: U256::from(0), + gas_priority_fee: None, + transact_to: TxKind::Call(decoded_tx.to), + value: decoded_tx.value, + data: decoded_tx.data, + chain_id: Some(ccx.ecx.env.cfg.chain_id), + nonce: None, + .. Default::default() + }; - // Store assertions - store.writer().write(block_number, assertions); - // Execute assertions - let assertion_executor = AssertionExecutorBuilder::new(db, store.reader()).build(); // TODO: Add a function in assertion executor which returns: // 1. Which assertions were touched by which assertions // 2. Which assertion invalidated which transaction - let transactions = ccx.state.broadcastable_transactions; - let results = transactions.into_iter().map(|btx| { - let tx = btx.transaction; - let cloned_db = db.clone(); - tokio::runtime::Runtime::new() - .unwrap() - .block_on(async move { - assertion_executor - .validate_transaction(block, envelope_to_environment(&tx), cloned_db) - .await - }) - .expect("Assertion execution failed") - .is_some() - }).collect(); - Ok(results.abi_encode()) + let result = tokio::runtime::Runtime::new() + .unwrap() + .block_on(async move { + // Store assertions + let _ = store.writer().write(block_number, assertions).await.expect("Failed to store assertions"); + let mut assertion_executor = AssertionExecutorBuilder::new(db.clone(), store.reader()).build(); + assertion_executor + .validate_transaction(block, tx, &mut ForkDb::new(db)) + .await + }) + .expect("Assertion execution failed") + .is_some(); + Ok(result.abi_encode()) } } -pub fn envelope_to_environment(tx: &TransactionMaybeSigned) -> TxEnv { - match tx { - TransactionMaybeSigned::Signed{ tx, from} => - TxEnv { - caller: *from, - gas_limit: tx.gas_limit(), - gas_price: U256::from(0), - gas_priority_fee: None, - transact_to: if tx.is_create() { TxKind::Create } else { TxKind::Call(tx.to().unwrap()) }, - value: tx.value(), - data: tx.input().clone(), - chain_id: tx.chain_id(), - nonce: Some(tx.nonce()), - .. Default::default() - }, - _ => todo!(), - } -} From 70a57b555f5460109754adbe6ed11c0a95f48379 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Fri, 27 Dec 2024 16:02:07 +0200 Subject: [PATCH 08/83] chore: move credible tests to folder and profile --- crates/cheatcodes/assets/cheatcodes.json | 20 ++++ .../cheatcodes/assets/cheatcodes.schema.json | 7 ++ crates/cheatcodes/spec/src/vm.rs | 2 +- crates/cheatcodes/src/credible.rs | 14 ++- testdata/credible/Credible.t.sol | 94 +++++++++++++++++++ testdata/foundry.toml | 4 + testdata/utils/Vm.sol | 1 + 7 files changed, 133 insertions(+), 9 deletions(-) create mode 100644 testdata/credible/Credible.t.sol diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 8b6eeb049c9fd..e69614a08794c 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -3160,6 +3160,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "assertionEx", + "description": "Gets the address for a given private key.", + "declaration": "function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success);", + "visibility": "external", + "mutability": "", + "signature": "assertionEx(bytes,address,bytes[])", + "selector": "0x07e99d9d", + "selectorBytes": [ + 7, + 233, + 157, + 157 + ] + }, + "group": "credible", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "assume", diff --git a/crates/cheatcodes/assets/cheatcodes.schema.json b/crates/cheatcodes/assets/cheatcodes.schema.json index c98cfb69357bd..456c8a90744c5 100644 --- a/crates/cheatcodes/assets/cheatcodes.schema.json +++ b/crates/cheatcodes/assets/cheatcodes.schema.json @@ -226,6 +226,13 @@ "Group": { "description": "Cheatcode groups.\nInitially derived and modified from inline comments in [`forge-std`'s `Vm.sol`][vmsol].\n\n[vmsol]: https://github.com/foundry-rs/forge-std/blob/dcb0d52bc4399d37a6545848e3b8f9d03c77b98d/src/Vm.sol", "oneOf": [ + { + "description": "Cheatcodes that are related to the Phylax Credible Layer\n\nExamples: `assertionEx`.\n\nSafety: safe", + "type": "string", + "enum": [ + "credible" + ] + }, { "description": "Cheatcodes that read from, or write to the current EVM execution state.\n\nExamples: any of the `record` cheatcodes, `chainId`, `coinbase`.\n\nSafety: ambiguous, depends on whether the cheatcode is read-only or not.", "type": "string", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 4c12376294de5..1bed604deeb22 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -21,7 +21,7 @@ sol! { interface Vm { /// Gets the address for a given private key. #[cheatcode(group = Credible, safety = Safe)] - function assertionEx(bytes memory tx, address assertionAdopter, bytes[] memory assertionBytecode) external returns (bool success); + function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success); // ======== Types ======== diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 6c4f2911697c1..40438e47d478f 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -61,20 +61,19 @@ impl<'a> DatabaseRef for ThreadSafeDb<'a> { impl Cheatcode for assertionExCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - let Self { tx, assertionAdopter, assertionBytecode } = self.clone(); + let Self { tx, assertionAdopter, assertions} = self.clone(); // Setup assertion store and database - let store = AssertionStore::new(100); let db = ThreadSafeDb::new(ccx.ecx.db); // Prepare assertions data let block_number = ccx.ecx.env.block.number; let block = ccx.ecx.env.block.clone(); - let assertions = vec![( + let associated_assertions= vec![( assertionAdopter, - assertionBytecode + assertions .iter() - .map(|bytes| Bytecode::LegacyRaw(bytes.to_owned().into())) + .map(|bytes| Bytecode::LegacyRaw(bytes.to_vec().into())) .collect(), )]; @@ -92,8 +91,6 @@ impl Cheatcode for assertionExCall { .. Default::default() }; - - // TODO: Add a function in assertion executor which returns: // 1. Which assertions were touched by which assertions // 2. Which assertion invalidated which transaction @@ -101,8 +98,9 @@ impl Cheatcode for assertionExCall { let result = tokio::runtime::Runtime::new() .unwrap() .block_on(async move { + let store = AssertionStore::new(100); // Store assertions - let _ = store.writer().write(block_number, assertions).await.expect("Failed to store assertions"); + let _ = store.writer().write(block_number, associated_assertions).await.expect("Failed to store assertions"); let mut assertion_executor = AssertionExecutorBuilder::new(db.clone(), store.reader()).build(); assertion_executor .validate_transaction(block, tx, &mut ForkDb::new(db)) diff --git a/testdata/credible/Credible.t.sol b/testdata/credible/Credible.t.sol new file mode 100644 index 0000000000000..f59ac98735b1c --- /dev/null +++ b/testdata/credible/Credible.t.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +//FIXME(Odysseas): Add Credible-std as a git submodule + +interface PhEvm { + //Forks to the state prior to the assertion triggering transaction. + function forkPreState() external; + + //Forks to the state after the assertion triggering transaction. + function forkPostState() external; +} + +/// @notice The Credible contract +contract Credible { + //Precompile address - + PhEvm ph = PhEvm(address(uint160(uint256(keccak256("Kim Jong Un Sucks"))))); +} + +/// @notice Assertion interface for the PhEvm precompile +abstract contract Assertion is Credible { + /// @notice The type of state change that triggers the assertion + enum TriggerType { + /// @notice The assertion is triggered by a storage change + STORAGE, + /// @notice The assertion is triggered by a transfer of ether + ETHER, + /// @notice The assertion is triggered by both a storage change and a transfer of ether + BOTH + } + + /// @notice A struct that contains the type of state change and the function selector of the assertion function + struct Trigger { + /// @notice The type of state change that triggers the assertion + TriggerType triggerType; + /// @notice The assertion function selector + bytes4 fnSelector; + } + + /// @notice Returns all the triggers for the assertion + /// @return An array of Trigger structs + function fnSelectors() external pure virtual returns (Trigger[] memory); +} + +contract MockAssertion is Assertion { + function fnSelectors() external pure override returns (Trigger[] memory) { + Trigger[] memory triggers = new Trigger[](1); + triggers[0] = Trigger({ + triggerType: TriggerType.STORAGE, + fnSelector: this.assertionTrue.selector + }); + return triggers; + } + + function assertionTrue() external returns (bool) { + return true; + } +} + +contract MockContract { +} + +contract CredibleTest is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + address assertionAdopter; + bytes[] assertions; + + struct SimpleTransaction { + address from; + address to; + uint256 value; + bytes data; + } + + function setUp() public { + assertionAdopter = address(new MockContract()); + } + + function testAssertionPass() public { + SimpleTransaction memory transaction = SimpleTransaction({ + from: address(0xbeef), + to: address(0), + value: 0, + data: bytes("") + }); + bytes memory assertionBytecode = abi.encodePacked(type(MockAssertion).creationCode); + assertions.push(assertionBytecode); + vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions); + } +} diff --git a/testdata/foundry.toml b/testdata/foundry.toml index 0fd8135bbcd22..621a5b85c4ccb 100644 --- a/testdata/foundry.toml +++ b/testdata/foundry.toml @@ -58,3 +58,7 @@ bsc = "${RPC_BSC}" avaxTestnet = "https://api.avax-test.network/ext/bc/C/rpc" moonbeam = "https://moonbeam-rpc.publicnode.com" rpcEnvAlias = "${RPC_ENV_ALIAS}" + +[profile.credible] +src = "./credible" +test = "./credible" diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index cf5930928cf8e..d7531fb5486ff 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -151,6 +151,7 @@ interface Vm { function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; function assertTrue(bool condition) external pure; function assertTrue(bool condition, string calldata error) external pure; + function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] calldata assertions) external returns (bool success); function assume(bool condition) external pure; function assumeNoRevert() external pure; function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure; From d2b6afb3f7622019ea8451f1d26744c244646ffa Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Sat, 28 Dec 2024 02:35:17 -0700 Subject: [PATCH 09/83] feat: update ae --- crates/cheatcodes/src/credible.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 40438e47d478f..b30726cc14596 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -2,7 +2,7 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; use alloy_sol_types::{sol, SolValue}; use assertion_executor::db::fork_db::ForkDb; -use assertion_executor::{store::AssertionStore, AssertionExecutorBuilder}; +use assertion_executor::{store::InMemoryStore, AssertionExecutorBuilder}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::primitives::{AccountInfo, Address, Bytecode, TxEnv, B256, U256}; use revm::DatabaseRef; @@ -61,21 +61,25 @@ impl<'a> DatabaseRef for ThreadSafeDb<'a> { impl Cheatcode for assertionExCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - let Self { tx, assertionAdopter, assertions} = self.clone(); + let Self { tx, assertionAdopter: assertion_adopter, assertions} = self; + let spec_id = ccx.ecx.spec_id(); + // Setup assertion store and database let db = ThreadSafeDb::new(ccx.ecx.db); // Prepare assertions data - let block_number = ccx.ecx.env.block.number; let block = ccx.ecx.env.block.clone(); - let associated_assertions= vec![( - assertionAdopter, - assertions + let assertions_bytecode = assertions .iter() .map(|bytes| Bytecode::LegacyRaw(bytes.to_vec().into())) - .collect(), - )]; + .collect(); + + let mut store = InMemoryStore::new(spec_id); + store.insert(*assertion_adopter, assertions_bytecode).expect("Failed to store assertions"); + + let mut assertion_executor = AssertionExecutorBuilder::new(db.clone(), store.reader()).build(); + let decoded_tx= SimpleTransaction::abi_decode(&tx, true)?; let tx = TxEnv { @@ -98,10 +102,7 @@ impl Cheatcode for assertionExCall { let result = tokio::runtime::Runtime::new() .unwrap() .block_on(async move { - let store = AssertionStore::new(100); // Store assertions - let _ = store.writer().write(block_number, associated_assertions).await.expect("Failed to store assertions"); - let mut assertion_executor = AssertionExecutorBuilder::new(db.clone(), store.reader()).build(); assertion_executor .validate_transaction(block, tx, &mut ForkDb::new(db)) .await From 13f4aeaa53421979e7e85f89b24375483e4021c0 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Fri, 3 Jan 2025 14:09:57 -0700 Subject: [PATCH 10/83] feat: use credible-std --- .gitmodules | 4 ++ crates/cheatcodes/Cargo.toml | 3 +- crates/cheatcodes/src/credible.rs | 96 +++++++++++++++++-------------- crates/forge/Cargo.toml | 2 +- testdata/credible/Credible.t.sol | 87 +++++++++++----------------- testdata/lib/credible-std | 1 + testdata/remappings.txt | 2 + 7 files changed, 95 insertions(+), 100 deletions(-) create mode 100644 .gitmodules create mode 160000 testdata/lib/credible-std create mode 100644 testdata/remappings.txt diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000..40e736c3a48e0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "testdata/lib/credible-std"] + path = testdata/lib/credible-std + url = git@github.com:phylaxsystems/credible-std.git + branch = feat/update-assertion-interface diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 2b4cef78225a5..227ab49c78075 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -23,7 +23,7 @@ vergen = { workspace = true, default-features = false, features = [ [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "feat/revm-18" } +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "feat/revm-18", features = ["phoundry"] } tokio.workspace = true foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true @@ -77,4 +77,5 @@ tracing.workspace = true walkdir.workspace = true proptest.workspace = true serde.workspace = true +tokio-util = "0.7.13" diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index b30726cc14596..ee5dfd0efd967 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,12 +1,13 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; use alloy_sol_types::{sol, SolValue}; -use assertion_executor::db::fork_db::ForkDb; -use assertion_executor::{store::InMemoryStore, AssertionExecutorBuilder}; +use assertion_executor::{db::fork_db::ForkDb, store::MockStore, AssertionExecutorBuilder}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; -use revm::primitives::{AccountInfo, Address, Bytecode, TxEnv, B256, U256}; -use revm::DatabaseRef; -use std::sync::{ Arc, Mutex}; +use revm::{ + primitives::{AccountInfo, Address, Bytecode, TxEnv, B256, U256}, + DatabaseCommit, DatabaseRef, +}; +use std::sync::{Arc, Mutex}; use tokio; /// Wrapper around DatabaseExt to make it thread-safe @@ -29,7 +30,7 @@ impl<'a> ThreadSafeDb<'a> { } } -sol ! { +sol! { struct SimpleTransaction { address from; address to; @@ -61,55 +62,62 @@ impl<'a> DatabaseRef for ThreadSafeDb<'a> { impl Cheatcode for assertionExCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - let Self { tx, assertionAdopter: assertion_adopter, assertions} = self; - + let Self { tx, assertionAdopter: assertion_adopter, assertions } = self; + let spec_id = ccx.ecx.spec_id(); + let block = ccx.ecx.env.block.clone(); + let state = ccx.ecx.journaled_state.state.clone(); + let chain_id = ccx.ecx.env.cfg.chain_id; - // Setup assertion store and database + // Setup assertion database let db = ThreadSafeDb::new(ccx.ecx.db); - - // Prepare assertions data - let block = ccx.ecx.env.block.clone(); - let assertions_bytecode = assertions - .iter() - .map(|bytes| Bytecode::LegacyRaw(bytes.to_vec().into())) - .collect(); - let mut store = InMemoryStore::new(spec_id); - store.insert(*assertion_adopter, assertions_bytecode).expect("Failed to store assertions"); + // Prepare assertion store + let assertions_bytecode = + assertions.iter().map(|bytes| Bytecode::LegacyRaw(bytes.to_vec().into())).collect(); - let mut assertion_executor = AssertionExecutorBuilder::new(db.clone(), store.reader()).build(); + let mut store = MockStore::new(spec_id, chain_id.clone()); + store.insert(*assertion_adopter, assertions_bytecode).expect("Failed to store assertions"); + let decoded_tx = SimpleTransaction::abi_decode(&tx, true)?; - let decoded_tx= SimpleTransaction::abi_decode(&tx, true)?; - let tx = TxEnv { + let tx_env = TxEnv { caller: decoded_tx.from, - gas_limit: 1000000, - gas_price: U256::from(0), - gas_priority_fee: None, + gas_limit: ccx.ecx.env.block.gas_limit.try_into().unwrap_or(u64::MAX), transact_to: TxKind::Call(decoded_tx.to), value: decoded_tx.value, data: decoded_tx.data, - chain_id: Some(ccx.ecx.env.cfg.chain_id), - nonce: None, - .. Default::default() + chain_id: Some(chain_id), + ..Default::default() }; - - // TODO: Add a function in assertion executor which returns: - // 1. Which assertions were touched by which assertions - // 2. Which assertion invalidated which transaction - - let result = tokio::runtime::Runtime::new() - .unwrap() - .block_on(async move { - // Store assertions - assertion_executor - .validate_transaction(block, tx, &mut ForkDb::new(db)) - .await - }) - .expect("Assertion execution failed") - .is_some(); - Ok(result.abi_encode()) + + let rt = tokio::runtime::Runtime::new().unwrap(); + + // Execute the future, blocking the current thread until completion + match rt.block_on(async move { + let cancellation_token = tokio_util::sync::CancellationToken::new(); + + let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); + + let mut assertion_executor = + AssertionExecutorBuilder::new(db, reader).with_chain_id(chain_id).build(); + + // Commit current journal state so that it is available for assertions and + // triggering tx + let mut fork_db = ForkDb::new(assertion_executor.db.clone()); + fork_db.commit(state); + + // Store assertions + let result = assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; + + cancellation_token.cancel(); + + let _ = handle.await; + + result + }) { + Ok(val) => Ok(val.is_some().abi_encode()), + Err(e) => Result::Err(format!("Error in assertionExCall: {:#?}", e).into()), + } } } - diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index 53b5243d54b38..eed519a2c0731 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -14,7 +14,7 @@ repository.workspace = true workspace = true [[bin]] -name = "forge" +name = "phorge" path = "bin/main.rs" [[test]] diff --git a/testdata/credible/Credible.t.sol b/testdata/credible/Credible.t.sol index f59ac98735b1c..16282468aad8a 100644 --- a/testdata/credible/Credible.t.sol +++ b/testdata/credible/Credible.t.sol @@ -3,64 +3,31 @@ pragma solidity ^0.8.18; import "ds-test/test.sol"; import "cheats/Vm.sol"; +import {Assertion} from "credible-std/Assertion.sol"; -//FIXME(Odysseas): Add Credible-std as a git submodule - -interface PhEvm { - //Forks to the state prior to the assertion triggering transaction. - function forkPreState() external; - - //Forks to the state after the assertion triggering transaction. - function forkPostState() external; -} - -/// @notice The Credible contract -contract Credible { - //Precompile address - - PhEvm ph = PhEvm(address(uint160(uint256(keccak256("Kim Jong Un Sucks"))))); -} - -/// @notice Assertion interface for the PhEvm precompile -abstract contract Assertion is Credible { - /// @notice The type of state change that triggers the assertion - enum TriggerType { - /// @notice The assertion is triggered by a storage change - STORAGE, - /// @notice The assertion is triggered by a transfer of ether - ETHER, - /// @notice The assertion is triggered by both a storage change and a transfer of ether - BOTH - } +contract MockAssertion is Assertion { + MockContract mockContract; - /// @notice A struct that contains the type of state change and the function selector of the assertion function - struct Trigger { - /// @notice The type of state change that triggers the assertion - TriggerType triggerType; - /// @notice The assertion function selector - bytes4 fnSelector; + constructor(address mockContract_) { + mockContract = MockContract(mockContract_); } - /// @notice Returns all the triggers for the assertion - /// @return An array of Trigger structs - function fnSelectors() external pure virtual returns (Trigger[] memory); -} - -contract MockAssertion is Assertion { - function fnSelectors() external pure override returns (Trigger[] memory) { - Trigger[] memory triggers = new Trigger[](1); - triggers[0] = Trigger({ - triggerType: TriggerType.STORAGE, - fnSelector: this.assertionTrue.selector - }); - return triggers; + function fnSelectors() external pure override returns (bytes4[] memory selectors) { + selectors = new bytes4[](1); + selectors[0] = this.assertIsOne.selector; } - function assertionTrue() external returns (bool) { - return true; + function assertIsOne() external view returns (bool) { + return mockContract.value() == 1; } } contract MockContract { + uint256 public value = 1; + + function increment() public { + value++; + } } contract CredibleTest is DSTest { @@ -69,6 +36,8 @@ contract CredibleTest is DSTest { address assertionAdopter; bytes[] assertions; + address constant caller = address(0xdead); + struct SimpleTransaction { address from; address to; @@ -78,17 +47,27 @@ contract CredibleTest is DSTest { function setUp() public { assertionAdopter = address(new MockContract()); + vm.deal(caller, 1 ether); } function testAssertionPass() public { SimpleTransaction memory transaction = SimpleTransaction({ - from: address(0xbeef), - to: address(0), + from: address(caller), + to: address(assertionAdopter), value: 0, - data: bytes("") + data: abi.encodeWithSelector(MockContract.increment.selector) }); - bytes memory assertionBytecode = abi.encodePacked(type(MockAssertion).creationCode); - assertions.push(assertionBytecode); - vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions); + + emit log_address(assertionAdopter); + + assertions.push(abi.encodePacked(type(MockAssertion).creationCode, abi.encode(assertionAdopter))); + + assertTrue(vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions)); + assertTrue(MockContract(assertionAdopter).value() == 1); + + MockContract(assertionAdopter).increment(); + assertTrue(MockContract(assertionAdopter).value() == 2); + + assertTrue(vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions)); } } diff --git a/testdata/lib/credible-std b/testdata/lib/credible-std new file mode 160000 index 0000000000000..04cd6ed6ce81b --- /dev/null +++ b/testdata/lib/credible-std @@ -0,0 +1 @@ +Subproject commit 04cd6ed6ce81b9eb09471e6a5b2512b833af4f9d diff --git a/testdata/remappings.txt b/testdata/remappings.txt new file mode 100644 index 0000000000000..ddd50dc64477e --- /dev/null +++ b/testdata/remappings.txt @@ -0,0 +1,2 @@ +ds-test/=lib/ds-test/src/ +credible-std/=lib/credible-std/src/ From 0b3e2034b3f6b378c096a88702eb7060da5af376 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Fri, 3 Jan 2025 14:27:57 -0700 Subject: [PATCH 11/83] chore: rename forge pkg --- crates/forge/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index eed519a2c0731..510da3774f5ed 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "forge" +name = "phorge" description = "Fast and flexible Ethereum testing framework" version.workspace = true From fa6e3dba783b278f764dbdb568c2d625e2db649c Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Fri, 3 Jan 2025 14:35:09 -0700 Subject: [PATCH 12/83] fix: pkg name --- crates/forge/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index 510da3774f5ed..eed519a2c0731 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "phorge" +name = "forge" description = "Fast and flexible Ethereum testing framework" version.workspace = true From 4a097fba9e55735d0b93ea73ae878814bc1c2e02 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Mon, 6 Jan 2025 23:19:58 +0200 Subject: [PATCH 13/83] chore: cleanup --- crates/cheatcodes/Cargo.toml | 3 ++- crates/cheatcodes/spec/src/vm.rs | 11 +++++++++++ crates/cheatcodes/src/credible.rs | 11 +---------- crates/forge/Cargo.toml | 2 +- testdata/{credible => default/cheats}/Credible.t.sol | 0 5 files changed, 15 insertions(+), 12 deletions(-) rename testdata/{credible => default/cheats}/Credible.t.sol (100%) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 227ab49c78075..495acd87fd78a 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -23,7 +23,8 @@ vergen = { workspace = true, default-features = false, features = [ [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "feat/revm-18", features = ["phoundry"] } +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "main", features = ["phoundry"] } + tokio.workspace = true foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 1bed604deeb22..0fc510a9d461f 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -19,6 +19,17 @@ sol! { #[derive(Debug, Cheatcode)] // Keep this list small to avoid unnecessary bloat. #[sol(abi)] interface Vm { + /// Simple transaction struct for assertion execution testing + struct AssertionExTransaction { + /// The address of the sender + address from; + /// The address of the receiver + address to; + /// The value of the transaction + uint256 value; + /// The abi encoded calldata of the transaction + bytes data; + } /// Gets the address for a given private key. #[cheatcode(group = Credible, safety = Safe)] function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success); diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index ee5dfd0efd967..1b7542c64c3eb 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -30,15 +30,6 @@ impl<'a> ThreadSafeDb<'a> { } } -sol! { - struct SimpleTransaction { - address from; - address to; - uint256 value; - bytes data; - } -} - /// Keep DatabaseRef implementation separate impl<'a> DatabaseRef for ThreadSafeDb<'a> { type Error = DatabaseError; @@ -79,7 +70,7 @@ impl Cheatcode for assertionExCall { let mut store = MockStore::new(spec_id, chain_id.clone()); store.insert(*assertion_adopter, assertions_bytecode).expect("Failed to store assertions"); - let decoded_tx = SimpleTransaction::abi_decode(&tx, true)?; + let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; let tx_env = TxEnv { caller: decoded_tx.from, diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index eed519a2c0731..53b5243d54b38 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -14,7 +14,7 @@ repository.workspace = true workspace = true [[bin]] -name = "phorge" +name = "forge" path = "bin/main.rs" [[test]] diff --git a/testdata/credible/Credible.t.sol b/testdata/default/cheats/Credible.t.sol similarity index 100% rename from testdata/credible/Credible.t.sol rename to testdata/default/cheats/Credible.t.sol From a2e8512eca73f635a48afda2723311426a82080a Mon Sep 17 00:00:00 2001 From: fredo Date: Tue, 21 Jan 2025 21:20:54 +0100 Subject: [PATCH 14/83] feat: update latest credible-std and assertion executor --- testdata/lib/credible-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/lib/credible-std b/testdata/lib/credible-std index 04cd6ed6ce81b..ae66a331c27a8 160000 --- a/testdata/lib/credible-std +++ b/testdata/lib/credible-std @@ -1 +1 @@ -Subproject commit 04cd6ed6ce81b9eb09471e6a5b2512b833af4f9d +Subproject commit ae66a331c27a817bc09754370176c36150717931 From fdc9c846128d01db4432019bb1e3cd037bd6070b Mon Sep 17 00:00:00 2001 From: fredo Date: Fri, 24 Jan 2025 13:20:06 +0100 Subject: [PATCH 15/83] Update credible.rs --- crates/cheatcodes/src/credible.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 1b7542c64c3eb..93ab36c4795b4 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,6 +1,6 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; -use alloy_sol_types::{sol, SolValue}; +use alloy_sol_types::SolValue; use assertion_executor::{db::fork_db::ForkDb, store::MockStore, AssertionExecutorBuilder}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::{ From a316c28b1744703d9292d63aab7ab05d3f38618b Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Thu, 30 Jan 2025 00:10:59 +0200 Subject: [PATCH 16/83] feat: gas metering in assertion execution --- crates/cheatcodes/spec/src/vm.rs | 2 +- crates/cheatcodes/src/credible.rs | 21 ++++++++++++++------- testdata/default/cheats/Credible.t.sol | 8 ++++++-- testdata/lib/credible-std | 2 +- testdata/utils/Vm.sol | 2 +- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 0fc510a9d461f..8798cfb056767 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -32,7 +32,7 @@ interface Vm { } /// Gets the address for a given private key. #[cheatcode(group = Credible, safety = Safe)] - function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success); + function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success, uint256 total_assertion_gas, uint256 total_assertions_ran); // ======== Types ======== diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 93ab36c4795b4..aab7b75343bc5 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,7 +1,7 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; use alloy_sol_types::SolValue; -use assertion_executor::{db::fork_db::ForkDb, store::MockStore, AssertionExecutorBuilder}; +use assertion_executor::{db::fork_db::ForkDb, store::MockStore, ExecutorConfig}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::{ primitives::{AccountInfo, Address, Bytecode, TxEnv, B256, U256}, @@ -67,7 +67,9 @@ impl Cheatcode for assertionExCall { let assertions_bytecode = assertions.iter().map(|bytes| Bytecode::LegacyRaw(bytes.to_vec().into())).collect(); - let mut store = MockStore::new(spec_id, chain_id.clone()); + let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; + + let mut store = MockStore::new(config.clone()); store.insert(*assertion_adopter, assertions_bytecode).expect("Failed to store assertions"); let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; @@ -90,8 +92,7 @@ impl Cheatcode for assertionExCall { let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); - let mut assertion_executor = - AssertionExecutorBuilder::new(db, reader).with_chain_id(chain_id).build(); + let mut assertion_executor = config.build(db, reader); // Commit current journal state so that it is available for assertions and // triggering tx @@ -99,15 +100,21 @@ impl Cheatcode for assertionExCall { fork_db.commit(state); // Store assertions - let result = assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; + let validate_result = + assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; cancellation_token.cancel(); let _ = handle.await; - result + validate_result }) { - Ok(val) => Ok(val.is_some().abi_encode()), + Ok(val) => Ok(( + val.result_and_state.is_some(), + val.total_assertion_gas, + val.total_assertions_ran, + ) + .abi_encode()), Err(e) => Result::Err(format!("Error in assertionExCall: {:#?}", e).into()), } } diff --git a/testdata/default/cheats/Credible.t.sol b/testdata/default/cheats/Credible.t.sol index 16282468aad8a..ef223f2364bd5 100644 --- a/testdata/default/cheats/Credible.t.sol +++ b/testdata/default/cheats/Credible.t.sol @@ -62,12 +62,16 @@ contract CredibleTest is DSTest { assertions.push(abi.encodePacked(type(MockAssertion).creationCode, abi.encode(assertionAdopter))); - assertTrue(vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions)); + (bool success, uint256 total_assertion_gas, uint256 total_assertions_ran) = vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions); + assertTrue(success); assertTrue(MockContract(assertionAdopter).value() == 1); MockContract(assertionAdopter).increment(); assertTrue(MockContract(assertionAdopter).value() == 2); - assertTrue(vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions)); + (success, total_assertion_gas, total_assertions_ran) = vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions); + assertTrue(success); + assertTrue(total_assertion_gas == 234094); + assertTrue(total_assertions_ran == 1); } } diff --git a/testdata/lib/credible-std b/testdata/lib/credible-std index ae66a331c27a8..04cd6ed6ce81b 160000 --- a/testdata/lib/credible-std +++ b/testdata/lib/credible-std @@ -1 +1 @@ -Subproject commit ae66a331c27a817bc09754370176c36150717931 +Subproject commit 04cd6ed6ce81b9eb09471e6a5b2512b833af4f9d diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index d7531fb5486ff..2232e3e443214 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -151,7 +151,7 @@ interface Vm { function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; function assertTrue(bool condition) external pure; function assertTrue(bool condition, string calldata error) external pure; - function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] calldata assertions) external returns (bool success); + function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] calldata assertions) external returns (bool success, uint256 total_assertion_gas, uint256 total_assertions_ran); function assume(bool condition) external pure; function assumeNoRevert() external pure; function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure; From 58214fc7146c9f4c4d1073e9ea2d606fdb404265 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Thu, 6 Feb 2025 14:42:10 +0100 Subject: [PATCH 17/83] Ref/tx revert msg (#26) * feat: surface tx revert msg * chore: cargo fmt * fix: remove explicit lifetimes * feat: surface assertion revert reasons * fix: update tests * fix: update signature * nit: add fixme * feat: print error as logs and use fail_slot instead of bail * fix: accept single assertion contract * chore: cleanup * fix: Revert on Assertion execution fail * fix: dependency * chore: cargo fmt --- crates/cheatcodes/assets/cheatcodes.json | 14 +-- crates/cheatcodes/spec/src/vm.rs | 2 +- crates/cheatcodes/src/credible.rs | 142 +++++++++++++++++------ testdata/default/cheats/Credible.t.sol | 11 +- testdata/utils/Vm.sol | 2 +- 5 files changed, 116 insertions(+), 55 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index e69614a08794c..c616984023ba2 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -3164,16 +3164,16 @@ "func": { "id": "assertionEx", "description": "Gets the address for a given private key.", - "declaration": "function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success);", + "declaration": "function assertionEx(bytes calldata tx, address assertionAdopter, bytes calldata assertionContract, string calldata assertionContractLabel) external;", "visibility": "external", "mutability": "", - "signature": "assertionEx(bytes,address,bytes[])", - "selector": "0x07e99d9d", + "signature": "assertionEx(bytes,address,bytes,string)", + "selector": "0x6a401fc5", "selectorBytes": [ - 7, - 233, - 157, - 157 + 106, + 64, + 31, + 197 ] }, "group": "credible", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 8798cfb056767..c6db80849ee99 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -32,7 +32,7 @@ interface Vm { } /// Gets the address for a given private key. #[cheatcode(group = Credible, safety = Safe)] - function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] assertions) external returns (bool success, uint256 total_assertion_gas, uint256 total_assertions_ran); + function assertionEx(bytes calldata tx, address assertionAdopter, bytes calldata assertionContract, string calldata assertionContractLabel) external; // ======== Types ======== diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index aab7b75343bc5..34cefd4d9222b 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,13 +1,16 @@ -use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; +use crate::{Cheatcode, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; -use alloy_sol_types::SolValue; +use alloy_sol_types::{Revert, SolError, SolValue}; use assertion_executor::{db::fork_db::ForkDb, store::MockStore, ExecutorConfig}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::{ - primitives::{AccountInfo, Address, Bytecode, TxEnv, B256, U256}, + primitives::{AccountInfo, Address, Bytecode, ExecutionResult, TxEnv, B256, U256}, DatabaseCommit, DatabaseRef, }; -use std::sync::{Arc, Mutex}; +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; use tokio; /// Wrapper around DatabaseExt to make it thread-safe @@ -52,8 +55,13 @@ impl<'a> DatabaseRef for ThreadSafeDb<'a> { } impl Cheatcode for assertionExCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - let Self { tx, assertionAdopter: assertion_adopter, assertions } = self; + fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { + let Self { + tx, + assertionAdopter: assertion_adopter, + assertionContract, + assertionContractLabel, + } = self; let spec_id = ccx.ecx.spec_id(); let block = ccx.ecx.env.block.clone(); @@ -64,13 +72,14 @@ impl Cheatcode for assertionExCall { let db = ThreadSafeDb::new(ccx.ecx.db); // Prepare assertion store - let assertions_bytecode = - assertions.iter().map(|bytes| Bytecode::LegacyRaw(bytes.to_vec().into())).collect(); + let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; let mut store = MockStore::new(config.clone()); - store.insert(*assertion_adopter, assertions_bytecode).expect("Failed to store assertions"); + store + .insert(*assertion_adopter, vec![assertion_contract_bytecode]) + .expect("Failed to store assertions"); let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; @@ -87,35 +96,92 @@ impl Cheatcode for assertionExCall { let rt = tokio::runtime::Runtime::new().unwrap(); // Execute the future, blocking the current thread until completion - match rt.block_on(async move { - let cancellation_token = tokio_util::sync::CancellationToken::new(); - - let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); - - let mut assertion_executor = config.build(db, reader); - - // Commit current journal state so that it is available for assertions and - // triggering tx - let mut fork_db = ForkDb::new(assertion_executor.db.clone()); - fork_db.commit(state); - - // Store assertions - let validate_result = - assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; - - cancellation_token.cancel(); - - let _ = handle.await; - - validate_result - }) { - Ok(val) => Ok(( - val.result_and_state.is_some(), - val.total_assertion_gas, - val.total_assertions_ran, - ) - .abi_encode()), - Err(e) => Result::Err(format!("Error in assertionExCall: {:#?}", e).into()), + let tx_validation = rt + .block_on(async move { + let cancellation_token = tokio_util::sync::CancellationToken::new(); + + let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); + + let mut assertion_executor = config.build(db, reader); + + // Commit current journal state so that it is available for assertions and + // triggering tx + let mut fork_db = ForkDb::new(assertion_executor.db.clone()); + fork_db.commit(state); + + // Store assertions + let validate_result = + assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; + + cancellation_token.cancel(); + + let _ = handle.await; + + validate_result + }) + .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; + let assertion_contract = tx_validation.assertions_executions.first().unwrap(); + let total_assertion_gas = tx_validation.total_assertions_gas(); + let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); + let mut assertion_gas_message = format!( + "Assertion Functions gas cost\n Total gas cost: {}\n Total assertions ran: {}\n", + total_assertion_gas, total_assertions_ran + ); + + // Format individual assertion function results + for (fn_selector_index, assertion_fn) in + assertion_contract.assertion_fns_results.iter().enumerate() + { + assertion_gas_message.push_str(&format!( + " └─ [selector {}:index {}] gas cost: {}\n", + assertion_fn.id.fn_selector, + fn_selector_index, + assertion_fn.as_result().gas_used() + )); + } + executor.console_log(ccx, assertion_gas_message); + + if !tx_validation.is_valid() { + if !tx_validation.result_and_state.result.is_success() { + let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); + bail!("Transaction Execution Reverted: {}", decoded_error.reason()); + } + + let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); + + // Collect failed assertions + let reverted_assertions: HashMap<_, _> = assertion_contract + .assertion_fns_results + .iter() + .enumerate() + .filter(|(_, assertion_fn)| !assertion_fn.is_success()) + .map(|(fn_selector_index, assertion_fn)| { + let key = format!( + "[selector {}:index {}]", + assertion_fn.id.fn_selector, fn_selector_index + ); + let revert = decode_revert_error(assertion_fn.as_result()); + (key, revert) + }) + .collect(); + + // Format error messages + for (key, revert) in reverted_assertions { + error_msg.push_str(&format!( + " └─ {} - Revert Reason: {} \n", + key, + revert.reason() + )); + } + + executor.console_log(ccx, error_msg); + bail!("Assertions Reverted"); } + Ok(Default::default()) } } + +fn decode_revert_error(revert: &ExecutionResult) -> Revert { + Revert::abi_decode(&revert.clone().into_output().unwrap_or_default(), false) + .unwrap_or(Revert::new(("Unknown Revert Reason".to_string(),))) +} diff --git a/testdata/default/cheats/Credible.t.sol b/testdata/default/cheats/Credible.t.sol index ef223f2364bd5..d7b89b6ec15be 100644 --- a/testdata/default/cheats/Credible.t.sol +++ b/testdata/default/cheats/Credible.t.sol @@ -34,7 +34,6 @@ contract CredibleTest is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); address assertionAdopter; - bytes[] assertions; address constant caller = address(0xdead); @@ -60,18 +59,14 @@ contract CredibleTest is DSTest { emit log_address(assertionAdopter); - assertions.push(abi.encodePacked(type(MockAssertion).creationCode, abi.encode(assertionAdopter))); + bytes memory assertion = abi.encodePacked(type(MockAssertion).creationCode, abi.encode(assertionAdopter)); - (bool success, uint256 total_assertion_gas, uint256 total_assertions_ran) = vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions); - assertTrue(success); + vm.assertionEx(abi.encode(transaction), assertionAdopter, assertion, "MockAssertion"); assertTrue(MockContract(assertionAdopter).value() == 1); MockContract(assertionAdopter).increment(); assertTrue(MockContract(assertionAdopter).value() == 2); - (success, total_assertion_gas, total_assertions_ran) = vm.assertionEx(abi.encode(transaction), assertionAdopter, assertions); - assertTrue(success); - assertTrue(total_assertion_gas == 234094); - assertTrue(total_assertions_ran == 1); + vm.assertionEx(abi.encode(transaction), assertionAdopter, assertion, "MockAssertion"); } } diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index 2232e3e443214..6e855f9f95377 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -151,7 +151,7 @@ interface Vm { function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; function assertTrue(bool condition) external pure; function assertTrue(bool condition, string calldata error) external pure; - function assertionEx(bytes calldata tx, address assertionAdopter, bytes[] calldata assertions) external returns (bool success, uint256 total_assertion_gas, uint256 total_assertions_ran); + function assertionEx(bytes calldata tx, address assertionAdopter, bytes calldata assertionContract, string calldata assertionContractLabel) external; function assume(bool condition) external pure; function assumeNoRevert() external pure; function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure; From 3f99258d309f39e3b30251108307b04faf20f7c6 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Tue, 11 Feb 2025 09:54:07 +0100 Subject: [PATCH 18/83] fix: check tx revert first (#27) --- crates/cheatcodes/src/credible.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 34cefd4d9222b..f15feb4934ced 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -120,6 +120,12 @@ impl Cheatcode for assertionExCall { validate_result }) .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; + // if transaction execution reverted, bail + if !tx_validation.result_and_state.result.is_success() { + let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); + bail!("Transaction Execution Reverted: {}", decoded_error.reason()); + } + // else get information about the assertion execution let assertion_contract = tx_validation.assertions_executions.first().unwrap(); let total_assertion_gas = tx_validation.total_assertions_gas(); let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); @@ -142,13 +148,7 @@ impl Cheatcode for assertionExCall { executor.console_log(ccx, assertion_gas_message); if !tx_validation.is_valid() { - if !tx_validation.result_and_state.result.is_success() { - let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); - bail!("Transaction Execution Reverted: {}", decoded_error.reason()); - } - let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); - // Collect failed assertions let reverted_assertions: HashMap<_, _> = assertion_contract .assertion_fns_results From 1170bab5ab2afc89de15ffff8c6a7dd03fd95bd9 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Wed, 12 Feb 2025 16:57:13 +0100 Subject: [PATCH 19/83] feat: print tx gas cost (#29) --- crates/cheatcodes/src/credible.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index f15feb4934ced..fb138963621aa 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -123,15 +123,17 @@ impl Cheatcode for assertionExCall { // if transaction execution reverted, bail if !tx_validation.result_and_state.result.is_success() { let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); - bail!("Transaction Execution Reverted: {}", decoded_error.reason()); + executor.console_log(ccx, format!("Transaction reverted: {}", decoded_error.reason())); + bail!("Transaction Reverted"); } // else get information about the assertion execution let assertion_contract = tx_validation.assertions_executions.first().unwrap(); let total_assertion_gas = tx_validation.total_assertions_gas(); let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); + let tx_gas_used = tx_validation.result_and_state.result.gas_used(); let mut assertion_gas_message = format!( - "Assertion Functions gas cost\n Total gas cost: {}\n Total assertions ran: {}\n", - total_assertion_gas, total_assertions_ran + "Transaction gas cost: {}\n Total Assertion gas cost: {}\n Total assertions ran: {}\n Assertion Functions gas cost\n ", + tx_gas_used, total_assertion_gas, total_assertions_ran ); // Format individual assertion function results From ce623bd9766ff2119ced023568cea76a5b3bc6b5 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Sat, 5 Apr 2025 21:35:54 +0300 Subject: [PATCH 20/83] Merge branch 'pcl' --- crates/cheatcodes/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 495acd87fd78a..396977e9fc5fa 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -21,9 +21,10 @@ vergen = { workspace = true, default-features = false, features = [ "gitcl", ] } - [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "main", features = ["phoundry"] } +# assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "main", features = ["phoundry"] } + +assertion-executor = { path = "../../../assertion-executor", features = ["phoundry"] } tokio.workspace = true foundry-cheatcodes-spec.workspace = true From d9e56fb9587b3797bf09d05e2f80c9c86295e52f Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Sat, 5 Apr 2025 21:58:49 +0300 Subject: [PATCH 21/83] wip: merge forge --- crates/cheatcodes/Cargo.toml | 2 +- crates/cheatcodes/src/credible.rs | 236 +++++++++++++++--------------- 2 files changed, 119 insertions(+), 119 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 396977e9fc5fa..e198d4a86aac5 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -24,7 +24,7 @@ vergen = { workspace = true, default-features = false, features = [ [dependencies] # assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "main", features = ["phoundry"] } -assertion-executor = { path = "../../../assertion-executor", features = ["phoundry"] } +assertion-executor = { path = "../../../assertion-executor" } tokio.workspace = true foundry-cheatcodes-spec.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index fb138963621aa..2cca42a8cb026 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,7 +1,7 @@ use crate::{Cheatcode, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; use alloy_sol_types::{Revert, SolError, SolValue}; -use assertion_executor::{db::fork_db::ForkDb, store::MockStore, ExecutorConfig}; +use assertion_executor::{db::fork_db::ForkDb, ExecutorConfig}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::{ primitives::{AccountInfo, Address, Bytecode, ExecutionResult, TxEnv, B256, U256}, @@ -63,122 +63,122 @@ impl Cheatcode for assertionExCall { assertionContractLabel, } = self; - let spec_id = ccx.ecx.spec_id(); - let block = ccx.ecx.env.block.clone(); - let state = ccx.ecx.journaled_state.state.clone(); - let chain_id = ccx.ecx.env.cfg.chain_id; - - // Setup assertion database - let db = ThreadSafeDb::new(ccx.ecx.db); - - // Prepare assertion store - let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); - - let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; - - let mut store = MockStore::new(config.clone()); - store - .insert(*assertion_adopter, vec![assertion_contract_bytecode]) - .expect("Failed to store assertions"); - - let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; - - let tx_env = TxEnv { - caller: decoded_tx.from, - gas_limit: ccx.ecx.env.block.gas_limit.try_into().unwrap_or(u64::MAX), - transact_to: TxKind::Call(decoded_tx.to), - value: decoded_tx.value, - data: decoded_tx.data, - chain_id: Some(chain_id), - ..Default::default() - }; - - let rt = tokio::runtime::Runtime::new().unwrap(); - - // Execute the future, blocking the current thread until completion - let tx_validation = rt - .block_on(async move { - let cancellation_token = tokio_util::sync::CancellationToken::new(); - - let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); - - let mut assertion_executor = config.build(db, reader); - - // Commit current journal state so that it is available for assertions and - // triggering tx - let mut fork_db = ForkDb::new(assertion_executor.db.clone()); - fork_db.commit(state); - - // Store assertions - let validate_result = - assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; - - cancellation_token.cancel(); - - let _ = handle.await; - - validate_result - }) - .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; - // if transaction execution reverted, bail - if !tx_validation.result_and_state.result.is_success() { - let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); - executor.console_log(ccx, format!("Transaction reverted: {}", decoded_error.reason())); - bail!("Transaction Reverted"); - } - // else get information about the assertion execution - let assertion_contract = tx_validation.assertions_executions.first().unwrap(); - let total_assertion_gas = tx_validation.total_assertions_gas(); - let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); - let tx_gas_used = tx_validation.result_and_state.result.gas_used(); - let mut assertion_gas_message = format!( - "Transaction gas cost: {}\n Total Assertion gas cost: {}\n Total assertions ran: {}\n Assertion Functions gas cost\n ", - tx_gas_used, total_assertion_gas, total_assertions_ran - ); - - // Format individual assertion function results - for (fn_selector_index, assertion_fn) in - assertion_contract.assertion_fns_results.iter().enumerate() - { - assertion_gas_message.push_str(&format!( - " └─ [selector {}:index {}] gas cost: {}\n", - assertion_fn.id.fn_selector, - fn_selector_index, - assertion_fn.as_result().gas_used() - )); - } - executor.console_log(ccx, assertion_gas_message); - - if !tx_validation.is_valid() { - let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); - // Collect failed assertions - let reverted_assertions: HashMap<_, _> = assertion_contract - .assertion_fns_results - .iter() - .enumerate() - .filter(|(_, assertion_fn)| !assertion_fn.is_success()) - .map(|(fn_selector_index, assertion_fn)| { - let key = format!( - "[selector {}:index {}]", - assertion_fn.id.fn_selector, fn_selector_index - ); - let revert = decode_revert_error(assertion_fn.as_result()); - (key, revert) - }) - .collect(); - - // Format error messages - for (key, revert) in reverted_assertions { - error_msg.push_str(&format!( - " └─ {} - Revert Reason: {} \n", - key, - revert.reason() - )); - } - - executor.console_log(ccx, error_msg); - bail!("Assertions Reverted"); - } + // let spec_id = ccx.ecx.spec_id(); + // let block = ccx.ecx.env.block.clone(); + // let state = ccx.ecx.journaled_state.state.clone(); + // let chain_id = ccx.ecx.env.cfg.chain_id; + + // // Setup assertion database + // let db = ThreadSafeDb::new(ccx.ecx.db); + + // // Prepare assertion store + // let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); + + // let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; + + // let mut store = MockStore::new(config.clone()); + // store + // .insert(*assertion_adopter, vec![assertion_contract_bytecode]) + // .expect("Failed to store assertions"); + + // let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; + + // let tx_env = TxEnv { + // caller: decoded_tx.from, + // gas_limit: ccx.ecx.env.block.gas_limit.try_into().unwrap_or(u64::MAX), + // transact_to: TxKind::Call(decoded_tx.to), + // value: decoded_tx.value, + // data: decoded_tx.data, + // chain_id: Some(chain_id), + // ..Default::default() + // }; + + // let rt = tokio::runtime::Runtime::new().unwrap(); + + // // Execute the future, blocking the current thread until completion + // let tx_validation = rt + // .block_on(async move { + // let cancellation_token = tokio_util::sync::CancellationToken::new(); + + // let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); + + // let mut assertion_executor = config.build(db, reader); + + // // Commit current journal state so that it is available for assertions and + // // triggering tx + // let mut fork_db = ForkDb::new(assertion_executor.db.clone()); + // fork_db.commit(state); + + // // Store assertions + // let validate_result = + // assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; + + // cancellation_token.cancel(); + + // let _ = handle.await; + + // validate_result + // }) + // .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; + // // if transaction execution reverted, bail + // if !tx_validation.result_and_state.result.is_success() { + // let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); + // executor.console_log(ccx, format!("Transaction reverted: {}", decoded_error.reason())); + // bail!("Transaction Reverted"); + // } + // // else get information about the assertion execution + // let assertion_contract = tx_validation.assertions_executions.first().unwrap(); + // let total_assertion_gas = tx_validation.total_assertions_gas(); + // let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); + // let tx_gas_used = tx_validation.result_and_state.result.gas_used(); + // let mut assertion_gas_message = format!( + // "Transaction gas cost: {}\n Total Assertion gas cost: {}\n Total assertions ran: {}\n Assertion Functions gas cost\n ", + // tx_gas_used, total_assertion_gas, total_assertions_ran + // ); + + // // Format individual assertion function results + // for (fn_selector_index, assertion_fn) in + // assertion_contract.assertion_fns_results.iter().enumerate() + // { + // assertion_gas_message.push_str(&format!( + // " └─ [selector {}:index {}] gas cost: {}\n", + // assertion_fn.id.fn_selector, + // fn_selector_index, + // assertion_fn.as_result().gas_used() + // )); + // } + // executor.console_log(ccx, assertion_gas_message); + + // if !tx_validation.is_valid() { + // let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); + // // Collect failed assertions + // let reverted_assertions: HashMap<_, _> = assertion_contract + // .assertion_fns_results + // .iter() + // .enumerate() + // .filter(|(_, assertion_fn)| !assertion_fn.is_success()) + // .map(|(fn_selector_index, assertion_fn)| { + // let key = format!( + // "[selector {}:index {}]", + // assertion_fn.id.fn_selector, fn_selector_index + // ); + // let revert = decode_revert_error(assertion_fn.as_result()); + // (key, revert) + // }) + // .collect(); + + // // Format error messages + // for (key, revert) in reverted_assertions { + // error_msg.push_str(&format!( + // " └─ {} - Revert Reason: {} \n", + // key, + // revert.reason() + // )); + // } + + // executor.console_log(ccx, error_msg); + // bail!("Assertions Reverted"); + // } Ok(Default::default()) } } @@ -186,4 +186,4 @@ impl Cheatcode for assertionExCall { fn decode_revert_error(revert: &ExecutionResult) -> Revert { Revert::abi_decode(&revert.clone().into_output().unwrap_or_default(), false) .unwrap_or(Revert::new(("Unknown Revert Reason".to_string(),))) -} +} \ No newline at end of file From 2575335974662f4f16b240e81855cf546df68f37 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Sat, 5 Apr 2025 21:00:29 +0200 Subject: [PATCH 22/83] Merge branch 'master' into feat/bump-forge Signed-off-by: odysseas.eth --- crates/cheatcodes/src/credible.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 2cca42a8cb026..5a376bc85a9c2 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -62,7 +62,6 @@ impl Cheatcode for assertionExCall { assertionContract, assertionContractLabel, } = self; - // let spec_id = ccx.ecx.spec_id(); // let block = ccx.ecx.env.block.clone(); // let state = ccx.ecx.journaled_state.state.clone(); From c16f09639ca34188e6f2bef433819249e31b7b41 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Sat, 5 Apr 2025 22:11:35 +0300 Subject: [PATCH 23/83] fix: replace mockstore --- crates/cheatcodes/src/credible.rs | 225 +++++++++++++++--------------- 1 file changed, 113 insertions(+), 112 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 5a376bc85a9c2..72e78b6e005f6 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,7 +1,7 @@ use crate::{Cheatcode, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; use alloy_sol_types::{Revert, SolError, SolValue}; -use assertion_executor::{db::fork_db::ForkDb, ExecutorConfig}; +use assertion_executor::{db::fork_db::ForkDb, store::{AssertionState, AssertionStore}, ExecutorConfig}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::{ primitives::{AccountInfo, Address, Bytecode, ExecutionResult, TxEnv, B256, U256}, @@ -62,122 +62,123 @@ impl Cheatcode for assertionExCall { assertionContract, assertionContractLabel, } = self; +<<<<<<< Updated upstream // let spec_id = ccx.ecx.spec_id(); // let block = ccx.ecx.env.block.clone(); // let state = ccx.ecx.journaled_state.state.clone(); // let chain_id = ccx.ecx.env.cfg.chain_id; +||||||| Stash base - // // Setup assertion database - // let db = ThreadSafeDb::new(ccx.ecx.db); - - // // Prepare assertion store - // let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); - - // let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; - - // let mut store = MockStore::new(config.clone()); - // store - // .insert(*assertion_adopter, vec![assertion_contract_bytecode]) - // .expect("Failed to store assertions"); - - // let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; - - // let tx_env = TxEnv { - // caller: decoded_tx.from, - // gas_limit: ccx.ecx.env.block.gas_limit.try_into().unwrap_or(u64::MAX), - // transact_to: TxKind::Call(decoded_tx.to), - // value: decoded_tx.value, - // data: decoded_tx.data, - // chain_id: Some(chain_id), - // ..Default::default() - // }; - - // let rt = tokio::runtime::Runtime::new().unwrap(); - - // // Execute the future, blocking the current thread until completion - // let tx_validation = rt - // .block_on(async move { - // let cancellation_token = tokio_util::sync::CancellationToken::new(); - - // let (reader, handle) = store.cancellable_reader(cancellation_token.clone()); - - // let mut assertion_executor = config.build(db, reader); - - // // Commit current journal state so that it is available for assertions and - // // triggering tx - // let mut fork_db = ForkDb::new(assertion_executor.db.clone()); - // fork_db.commit(state); - - // // Store assertions - // let validate_result = - // assertion_executor.validate_transaction(block, tx_env, &mut fork_db).await; - - // cancellation_token.cancel(); - - // let _ = handle.await; - - // validate_result - // }) - // .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; - // // if transaction execution reverted, bail - // if !tx_validation.result_and_state.result.is_success() { - // let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); - // executor.console_log(ccx, format!("Transaction reverted: {}", decoded_error.reason())); - // bail!("Transaction Reverted"); - // } - // // else get information about the assertion execution - // let assertion_contract = tx_validation.assertions_executions.first().unwrap(); - // let total_assertion_gas = tx_validation.total_assertions_gas(); - // let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); - // let tx_gas_used = tx_validation.result_and_state.result.gas_used(); - // let mut assertion_gas_message = format!( - // "Transaction gas cost: {}\n Total Assertion gas cost: {}\n Total assertions ran: {}\n Assertion Functions gas cost\n ", - // tx_gas_used, total_assertion_gas, total_assertions_ran - // ); - - // // Format individual assertion function results - // for (fn_selector_index, assertion_fn) in - // assertion_contract.assertion_fns_results.iter().enumerate() - // { - // assertion_gas_message.push_str(&format!( - // " └─ [selector {}:index {}] gas cost: {}\n", - // assertion_fn.id.fn_selector, - // fn_selector_index, - // assertion_fn.as_result().gas_used() - // )); - // } - // executor.console_log(ccx, assertion_gas_message); - - // if !tx_validation.is_valid() { - // let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); - // // Collect failed assertions - // let reverted_assertions: HashMap<_, _> = assertion_contract - // .assertion_fns_results - // .iter() - // .enumerate() - // .filter(|(_, assertion_fn)| !assertion_fn.is_success()) - // .map(|(fn_selector_index, assertion_fn)| { - // let key = format!( - // "[selector {}:index {}]", - // assertion_fn.id.fn_selector, fn_selector_index - // ); - // let revert = decode_revert_error(assertion_fn.as_result()); - // (key, revert) - // }) - // .collect(); - - // // Format error messages - // for (key, revert) in reverted_assertions { - // error_msg.push_str(&format!( - // " └─ {} - Revert Reason: {} \n", - // key, - // revert.reason() - // )); - // } - - // executor.console_log(ccx, error_msg); - // bail!("Assertions Reverted"); - // } + // let spec_id = ccx.ecx.spec_id(); + // let block = ccx.ecx.env.block.clone(); + // let state = ccx.ecx.journaled_state.state.clone(); + // let chain_id = ccx.ecx.env.cfg.chain_id; +======= + + let spec_id = ccx.ecx.spec_id(); + let block = ccx.ecx.env.block.clone(); + let state = ccx.ecx.journaled_state.state.clone(); + let chain_id = ccx.ecx.env.cfg.chain_id; +>>>>>>> Stashed changes + + // Setup assertion database + let db = ThreadSafeDb::new(ccx.ecx.db); + + // Prepare assertion store + let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); + + let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; + + let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); + + let assertion_state= AssertionState::new_active(assertion_contract_bytecode.bytes(), &config).expect("Failed to create assertion state"); + + store + .insert(*assertion_adopter, assertion_state) + .expect("Failed to store assertions"); + + let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; + + let tx_env = TxEnv { + caller: decoded_tx.from, + gas_limit: ccx.ecx.env.block.gas_limit.try_into().unwrap_or(u64::MAX), + transact_to: TxKind::Call(decoded_tx.to), + value: decoded_tx.value, + data: decoded_tx.data, + chain_id: Some(chain_id), + ..Default::default() + }; + + let mut assertion_executor = config.build(db,store); + + // Commit current journal state so that it is available for assertions and + // triggering tx + let mut fork_db = ForkDb::new(assertion_executor.db.clone()); + fork_db.commit(state); + + // Store assertions + let tx_validation= + assertion_executor.validate_transaction(block, tx_env, &mut fork_db).map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; + + // if transaction execution reverted, bail + if !tx_validation.result_and_state.result.is_success() { + let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); + executor.console_log(ccx, &format!("Transaction reverted: {}", decoded_error.reason())); + bail!("Transaction Reverted"); + } + // else get information about the assertion execution + let assertion_contract = tx_validation.assertions_executions.first().unwrap(); + let total_assertion_gas = tx_validation.total_assertions_gas(); + let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); + let tx_gas_used = tx_validation.result_and_state.result.gas_used(); + let mut assertion_gas_message = format!( + "Transaction gas cost: {}\n Total Assertion gas cost: {}\n Total assertions ran: {}\n Assertion Functions gas cost\n ", + tx_gas_used, total_assertion_gas, total_assertions_ran + ); + + // Format individual assertion function results + for (fn_selector_index, assertion_fn) in + assertion_contract.assertion_fns_results.iter().enumerate() + { + assertion_gas_message.push_str(&format!( + " └─ [selector {}:index {}] gas cost: {}\n", + assertion_fn.id.fn_selector, + fn_selector_index, + assertion_fn.as_result().gas_used() + )); + } + executor.console_log(ccx, &assertion_gas_message); + + if !tx_validation.is_valid() { + let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); + // Collect failed assertions + let reverted_assertions: HashMap<_, _> = assertion_contract + .assertion_fns_results + .iter() + .enumerate() + .filter(|(_, assertion_fn)| !assertion_fn.is_success()) + .map(|(fn_selector_index, assertion_fn)| { + let key = format!( + "[selector {}:index {}]", + assertion_fn.id.fn_selector, fn_selector_index + ); + let revert = decode_revert_error(assertion_fn.as_result()); + (key, revert) + }) + .collect(); + + // Format error messages + for (key, revert) in reverted_assertions { + error_msg.push_str(&format!( + " └─ {} - Revert Reason: {} \n", + key, + revert.reason() + )); + } + + executor.console_log(ccx, &error_msg); + bail!("Assertions Reverted"); + } Ok(Default::default()) } } From b5164fa15657923d0d3e5fe9e6136d8c93643560 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Sat, 5 Apr 2025 22:12:54 +0300 Subject: [PATCH 24/83] chore: cargo fmt --- crates/cheatcodes/src/credible.rs | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 72e78b6e005f6..d34e80d3b57f3 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,7 +1,11 @@ use crate::{Cheatcode, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::TxKind; use alloy_sol_types::{Revert, SolError, SolValue}; -use assertion_executor::{db::fork_db::ForkDb, store::{AssertionState, AssertionStore}, ExecutorConfig}; +use assertion_executor::{ + db::fork_db::ForkDb, + store::{AssertionState, AssertionStore}, + ExecutorConfig, +}; use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::{ primitives::{AccountInfo, Address, Bytecode, ExecutionResult, TxEnv, B256, U256}, @@ -62,24 +66,11 @@ impl Cheatcode for assertionExCall { assertionContract, assertionContractLabel, } = self; -<<<<<<< Updated upstream - // let spec_id = ccx.ecx.spec_id(); - // let block = ccx.ecx.env.block.clone(); - // let state = ccx.ecx.journaled_state.state.clone(); - // let chain_id = ccx.ecx.env.cfg.chain_id; -||||||| Stash base - - // let spec_id = ccx.ecx.spec_id(); - // let block = ccx.ecx.env.block.clone(); - // let state = ccx.ecx.journaled_state.state.clone(); - // let chain_id = ccx.ecx.env.cfg.chain_id; -======= let spec_id = ccx.ecx.spec_id(); let block = ccx.ecx.env.block.clone(); let state = ccx.ecx.journaled_state.state.clone(); let chain_id = ccx.ecx.env.cfg.chain_id; ->>>>>>> Stashed changes // Setup assertion database let db = ThreadSafeDb::new(ccx.ecx.db); @@ -91,11 +82,11 @@ impl Cheatcode for assertionExCall { let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); - let assertion_state= AssertionState::new_active(assertion_contract_bytecode.bytes(), &config).expect("Failed to create assertion state"); + let assertion_state = + AssertionState::new_active(assertion_contract_bytecode.bytes(), &config) + .expect("Failed to create assertion state"); - store - .insert(*assertion_adopter, assertion_state) - .expect("Failed to store assertions"); + store.insert(*assertion_adopter, assertion_state).expect("Failed to store assertions"); let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; @@ -109,7 +100,7 @@ impl Cheatcode for assertionExCall { ..Default::default() }; - let mut assertion_executor = config.build(db,store); + let mut assertion_executor = config.build(db, store); // Commit current journal state so that it is available for assertions and // triggering tx @@ -117,8 +108,9 @@ impl Cheatcode for assertionExCall { fork_db.commit(state); // Store assertions - let tx_validation= - assertion_executor.validate_transaction(block, tx_env, &mut fork_db).map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; + let tx_validation = assertion_executor + .validate_transaction(block, tx_env, &mut fork_db) + .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; // if transaction execution reverted, bail if !tx_validation.result_and_state.result.is_success() { From 5062c38c7e40de86205d191a28651c375cf846b9 Mon Sep 17 00:00:00 2001 From: "Odysseas.eth" Date: Sat, 5 Apr 2025 22:20:22 +0300 Subject: [PATCH 25/83] chore: cargo clippy --- crates/cheatcodes/Cargo.toml | 1 - crates/cheatcodes/src/credible.rs | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index e198d4a86aac5..e27f27ff0322f 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -79,5 +79,4 @@ tracing.workspace = true walkdir.workspace = true proptest.workspace = true serde.workspace = true -tokio-util = "0.7.13" diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index d34e80d3b57f3..14c591059e74c 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -15,7 +15,6 @@ use std::{ collections::HashMap, sync::{Arc, Mutex}, }; -use tokio; /// Wrapper around DatabaseExt to make it thread-safe #[derive(Clone)] @@ -88,7 +87,7 @@ impl Cheatcode for assertionExCall { store.insert(*assertion_adopter, assertion_state).expect("Failed to store assertions"); - let decoded_tx = AssertionExTransaction::abi_decode(&tx, true)?; + let decoded_tx = AssertionExTransaction::abi_decode(tx, true)?; let tx_env = TxEnv { caller: decoded_tx.from, @@ -110,7 +109,7 @@ impl Cheatcode for assertionExCall { // Store assertions let tx_validation = assertion_executor .validate_transaction(block, tx_env, &mut fork_db) - .map_err(|e| format!("Assertion Executor Error: {:#?}", e))?; + .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; // if transaction execution reverted, bail if !tx_validation.result_and_state.result.is_success() { @@ -124,8 +123,7 @@ impl Cheatcode for assertionExCall { let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); let tx_gas_used = tx_validation.result_and_state.result.gas_used(); let mut assertion_gas_message = format!( - "Transaction gas cost: {}\n Total Assertion gas cost: {}\n Total assertions ran: {}\n Assertion Functions gas cost\n ", - tx_gas_used, total_assertion_gas, total_assertions_ran + "Transaction gas cost: {tx_gas_used}\n Total Assertion gas cost: {total_assertion_gas}\n Total assertions ran: {total_assertions_ran}\n Assertion Functions gas cost\n " ); // Format individual assertion function results From 1b190e0bd4ef6e644285158239b966b0555fd925 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Tue, 8 Apr 2025 15:34:47 +0200 Subject: [PATCH 26/83] fix(cheatcodes): New Assertion Execution (#37) * fix: use assertin executor from branch * fix: assex version * chore: add rust toolchain --- crates/cheatcodes/Cargo.toml | 5 +---- rust-toolchain.toml | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index e27f27ff0322f..04b7fd50747a5 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,11 +22,8 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -# assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", branch = "main", features = ["phoundry"] } +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", rev = "1cbbf30" } -assertion-executor = { path = "../../../assertion-executor" } - -tokio.workspace = true foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000000000..14eb32bef3a5b --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +components = ["rustfmt", "clippy"] \ No newline at end of file From 66236f06af1e23248ee209809ad3d27f9476789b Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Fri, 11 Apr 2025 14:26:25 +0200 Subject: [PATCH 27/83] Odysseas/chore/defaults (#38) * nit: update default src/test * nit: make field pub * fix: libs assertion defa * fix: assertions not in lib --- crates/config/src/lib.rs | 20 ++++++++++---------- crates/forge/src/cmd/flatten.rs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index da1461f4647be..c7537687827f8 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -2478,16 +2478,16 @@ impl Default for Config { isolate: cfg!(feature = "isolate-by-default"), root: root_default(), extends: None, - src: "src".into(), - test: "test".into(), - script: "script".into(), - out: "out".into(), + src: "assertions/src".into(), + test: "assertions/test".into(), + script: "assertions/script".into(), + out: "assertions/out".into(), libs: vec!["lib".into()], cache: true, dynamic_test_linking: false, - cache_path: "cache".into(), - broadcast: "broadcast".into(), - snapshots: "snapshots".into(), + cache_path: "assertions/cache".into(), + broadcast: "assertions/broadcast".into(), + snapshots: "assertions/snapshots".into(), gas_snapshot_check: false, gas_snapshot_emit: true, allow_paths: vec![], @@ -2516,11 +2516,11 @@ impl Default for Config { path_pattern: None, path_pattern_inverse: None, coverage_pattern_inverse: None, - test_failures_file: "cache/test-failures".into(), + test_failures_file: "assertions/cache/test-failures".into(), threads: None, show_progress: false, - fuzz: FuzzConfig::new("cache/fuzz".into()), - invariant: InvariantConfig::new("cache/invariant".into()), + fuzz: FuzzConfig::new("assertions/cache/fuzz".into()), + invariant: InvariantConfig::new("assertions/cache/invariant".into()), always_use_create_2_factory: false, ffi: false, allow_internal_expect_revert: false, diff --git a/crates/forge/src/cmd/flatten.rs b/crates/forge/src/cmd/flatten.rs index 3dc508d577cf9..3917b0418179f 100644 --- a/crates/forge/src/cmd/flatten.rs +++ b/crates/forge/src/cmd/flatten.rs @@ -26,7 +26,7 @@ pub struct FlattenArgs { pub output: Option, #[command(flatten)] - project_paths: ProjectPathOpts, + pub project_paths: ProjectPathOpts, } impl FlattenArgs { From d864784ed6c5b5dbc1d880911124aa18d72d3e1b Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Fri, 11 Apr 2025 19:49:13 +0200 Subject: [PATCH 28/83] fix: use unified interface (#39) * fix: use unified interface * fix: add comments * chore: pin to rev --- crates/cheatcodes/Cargo.toml | 2 +- crates/cheatcodes/src/credible.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 04b7fd50747a5..e9bec123f2823 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", rev = "1cbbf30" } +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", rev = "6f74915" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 14c591059e74c..5f59d4507e094 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -106,9 +106,15 @@ impl Cheatcode for assertionExCall { let mut fork_db = ForkDb::new(assertion_executor.db.clone()); fork_db.commit(state); + // Odysseas: This is a hack to use the new unified codepath for validate_transaction_ext_db + // Effectively, we are applying the transaction in a clone of the currently running database + // which is then used by the fork_db. + // TODO: Remove this once we have a proper way to handle this. + let mut ext_db = revm::db::WrapDatabaseRef(fork_db.clone()); + // Store assertions let tx_validation = assertion_executor - .validate_transaction(block, tx_env, &mut fork_db) + .validate_transaction_ext_db(block, tx_env, &mut fork_db, &mut ext_db) .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; // if transaction execution reverted, bail From 3d39d8e61f8a22ea533828338d1549188c199ae7 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Wed, 16 Apr 2025 10:26:23 +0200 Subject: [PATCH 29/83] chore: remove warning (#40) Signed-off-by: odysseas.eth --- crates/cli/src/opts/global.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crates/cli/src/opts/global.rs b/crates/cli/src/opts/global.rs index 8bfc13c00001f..7d24db8daf563 100644 --- a/crates/cli/src/opts/global.rs +++ b/crates/cli/src/opts/global.rs @@ -68,14 +68,6 @@ impl GlobalArgs { self.force_init_thread_pool()?; } - // Display a warning message if the current version is not stable. - if IS_NIGHTLY_VERSION - && !self.json - && std::env::var_os("FOUNDRY_DISABLE_NIGHTLY_WARNING").is_none() - { - let _ = sh_warn!("{}", NIGHTLY_VERSION_WARNING_MESSAGE); - } - Ok(()) } From cb1ceb578f0560f267fef967fe32776a898801d4 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Thu, 24 Apr 2025 22:03:10 +0200 Subject: [PATCH 30/83] fix: improve wording (#41) --- crates/cheatcodes/src/credible.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 5f59d4507e094..ac210469af24e 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -146,7 +146,7 @@ impl Cheatcode for assertionExCall { executor.console_log(ccx, &assertion_gas_message); if !tx_validation.is_valid() { - let mut error_msg = format!("\n {assertionContractLabel} Assertions Failed:\n"); + let mut error_msg = format!("\n {assertionContractLabel} Enforced Assertions:\n"); // Collect failed assertions let reverted_assertions: HashMap<_, _> = assertion_contract .assertion_fns_results From 6e0f13e160ae275e3a45c316efdb65c1916b3532 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Wed, 21 May 2025 08:39:32 -0600 Subject: [PATCH 31/83] chore: bump assex (#42) --- crates/cheatcodes/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index e9bec123f2823..699243cacb03e 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,8 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", rev = "6f74915" } - +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", version = "0.1.0" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From 96f15fcdc5c7e709f0a5bdf4db7494d2938cb322 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Wed, 21 May 2025 11:03:15 -0600 Subject: [PATCH 32/83] feat: 100k ae gas limit (#43) --- crates/cheatcodes/src/credible.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index ac210469af24e..34534c8399cc8 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -77,7 +77,7 @@ impl Cheatcode for assertionExCall { // Prepare assertion store let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); - let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 3_000_000 }; + let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 100_000 }; let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); From f7f4c21af4733762e97ffce4a631b70995679af1 Mon Sep 17 00:00:00 2001 From: Jacob Stenum Czepluch Date: Tue, 3 Jun 2025 18:51:50 +0300 Subject: [PATCH 33/83] add one liner on Phoundry to readme (#45) --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5fc3620afbdab..949b23d30583b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# Phoundry + +### Phoundry is a minimalfork of Foundry that is customized to support the cheat codes used in the Credible Layer +
Foundry banner @@ -23,7 +27,7 @@ --- -### Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust. +### Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust Foundry consists of: @@ -349,7 +353,6 @@ shall be dual licensed as above, without any additional terms or conditions. [foundry-compilers]: https://github.com/foundry-rs/compilers [ethers-solc]: https://github.com/gakonst/ethers-rs/tree/master/ethers-solc/ [solady]: https://github.com/Vectorized/solady -[openzeppelin]: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/release-v5.1 [morpho-blue]: https://github.com/morpho-org/morpho-blue [solmate]: https://github.com/transmissions11/solmate/ [geb]: https://github.com/reflexer-labs/geb From 1759fab60e76b049ea63b90bf0c332b9ca6f3e8b Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Wed, 4 Jun 2025 20:28:54 +0200 Subject: [PATCH 34/83] chore: bump assex (#46) --- crates/anvil/server/Cargo.toml | 2 +- crates/cheatcodes/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/anvil/server/Cargo.toml b/crates/anvil/server/Cargo.toml index c8856939c21f3..394bcbe8a68e4 100644 --- a/crates/anvil/server/Cargo.toml +++ b/crates/anvil/server/Cargo.toml @@ -30,7 +30,7 @@ futures.workspace = true # ipc interprocess = { version = "2", optional = true, features = ["tokio"] } bytes = { workspace = true, optional = true } -tokio-util = { version = "0.7", features = ["codec"], optional = true } +tokio-util = { version = "0.7.15", features = ["codec"], optional = true } # misc serde_json.workspace = true diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 699243cacb03e..c6bec129da78b 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", version = "0.1.0" } +assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", version = "0.1.2" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From 2ad2abed0f8d6e913efdcb7952ca27a04fa3f4b4 Mon Sep 17 00:00:00 2001 From: formerly luehrsFred Date: Wed, 4 Jun 2025 21:12:42 +0200 Subject: [PATCH 35/83] chore: change links to https (#47) --- .gitmodules | 6 +++--- crates/cheatcodes/Cargo.toml | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 40e736c3a48e0..c4a84884ee1d8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "testdata/lib/credible-std"] - path = testdata/lib/credible-std - url = git@github.com:phylaxsystems/credible-std.git - branch = feat/update-assertion-interface +path = testdata/lib/credible-std +url = https://github.com/phylaxsystems/credible-std.git +branch = feat/update-assertion-interface diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index c6bec129da78b..44ba2efd8e441 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "ssh://git@github.com/phylaxsystems/assertion-executor.git", version = "0.1.2" } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", version = "0.1.2" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true @@ -75,4 +75,3 @@ tracing.workspace = true walkdir.workspace = true proptest.workspace = true serde.workspace = true - From a66bf6312c023dfc8c52dc25ad4c6d5d98045543 Mon Sep 17 00:00:00 2001 From: formerly luehrsFred Date: Wed, 4 Jun 2025 22:52:11 +0200 Subject: [PATCH 36/83] chore: update assertion executor to 0.1.3 (#48) --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 44ba2efd8e441..d529557ba2aca 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", version = "0.1.2" } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", version = "0.1.3" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From 0ca78ecfc3a63fec749a5437539fa688f43d42fd Mon Sep 17 00:00:00 2001 From: fredo Date: Wed, 4 Jun 2025 22:56:15 +0200 Subject: [PATCH 37/83] fix: use tag key in cargo.toml --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index d529557ba2aca..ef6710f64b351 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", version = "0.1.3" } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.3" } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From 4dbc7f4c420e4cd4576b9ca95c6aaee9a8713906 Mon Sep 17 00:00:00 2001 From: formerly luehrsFred Date: Thu, 5 Jun 2025 14:53:58 +0200 Subject: [PATCH 38/83] fix: disable default features (optimism) on assertion executor (#50) --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index ef6710f64b351..30befc6727f0a 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.3" } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.3", default-features = false } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From 0c341519aff482747963f255b26b8f89aef55546 Mon Sep 17 00:00:00 2001 From: fredo Date: Thu, 5 Jun 2025 17:15:49 +0200 Subject: [PATCH 39/83] chore: update assertion executor to 0.1.4 --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 30befc6727f0a..a040d991b9de0 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.3", default-features = false } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.4", default-features = false } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From 3992424f5790b26f201708120e1c653c48f3b33b Mon Sep 17 00:00:00 2001 From: formerly luehrsFred Date: Thu, 5 Jun 2025 17:57:02 +0200 Subject: [PATCH 40/83] chore: bump assertion executor to 0.1.5 (#51) --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index a040d991b9de0..b35043e0d21e5 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.4", default-features = false } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.5", default-features = false } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From d277e80eafce89facee8071e7c6b965e3cd76698 Mon Sep 17 00:00:00 2001 From: fredo Date: Thu, 5 Jun 2025 20:01:10 +0200 Subject: [PATCH 41/83] chore: update assertion executor to 0.1.6 --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index b35043e0d21e5..5b904edfed782 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.5", default-features = false } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.6", default-features = false } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true From b1c85ff963adae8dedc9542d898b366d88479298 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Tue, 10 Jun 2025 22:48:21 +0200 Subject: [PATCH 42/83] gregory/eng 690 bugphoundry missing error information (#52) * chore: fmt * chore: cleanup --- crates/cheatcodes/src/credible.rs | 63 ++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 34534c8399cc8..67f8c38d09ab9 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -119,7 +119,8 @@ impl Cheatcode for assertionExCall { // if transaction execution reverted, bail if !tx_validation.result_and_state.result.is_success() { - let decoded_error = decode_revert_error(&tx_validation.result_and_state.result); + let decoded_error = + decode_invalidated_assertion(&tx_validation.result_and_state.result); executor.console_log(ccx, &format!("Transaction reverted: {}", decoded_error.reason())); bail!("Transaction Reverted"); } @@ -158,7 +159,7 @@ impl Cheatcode for assertionExCall { "[selector {}:index {}]", assertion_fn.id.fn_selector, fn_selector_index ); - let revert = decode_revert_error(assertion_fn.as_result()); + let revert = decode_invalidated_assertion(assertion_fn.as_result()); (key, revert) }) .collect(); @@ -179,7 +180,57 @@ impl Cheatcode for assertionExCall { } } -fn decode_revert_error(revert: &ExecutionResult) -> Revert { - Revert::abi_decode(&revert.clone().into_output().unwrap_or_default(), false) - .unwrap_or(Revert::new(("Unknown Revert Reason".to_string(),))) -} \ No newline at end of file +fn decode_invalidated_assertion(execution_result: &ExecutionResult) -> Revert { + let result = execution_result; + match result { + ExecutionResult::Success{..} => Revert { + reason: "Tried to decode invalidated assertion, but result was success. This is a bug in phoundry. Please report to the Phylax team.".to_string(), + }, + ExecutionResult::Revert{output, ..} => { + Revert::abi_decode(output, true) + .unwrap_or(Revert::new(("Unknown Revert Reason".to_string(),))) + }, + ExecutionResult::Halt{reason, ..} => Revert { + reason: format!("Halt reason: {reason:#?}"), + }, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::Bytes; + use revm::primitives::{HaltReason, Output, SuccessReason}; + + #[test] + fn test_decode_revert_error_success() { + // Test case 1: When result is success + let result = ExecutionResult::Success { + gas_used: 0, + gas_refunded: 0, + logs: vec![], + output: Output::Call(Bytes::new()), + reason: SuccessReason::Return, + }; + let revert = decode_invalidated_assertion(&result); + assert_eq!(revert.reason(), "Tried to decode invalidated assertion, but result was success. This is a bug in phoundry. Please report to the Phylax team."); + } + + #[test] + fn test_decode_revert_error_revert() { + let revert_reason = "Something is a bit fky wuky"; + let revert_output = Revert::new((revert_reason.to_string(),)).abi_encode(); + let result = ExecutionResult::Revert { output: revert_output.into(), gas_used: 0 }; + let revert = decode_invalidated_assertion(&result); + assert_eq!(revert.reason(), revert_reason); + } + + #[test] + fn test_decode_revert_error_halt() { + let halt_reason = HaltReason::CallTooDeep; + let result = ExecutionResult::Halt { reason: halt_reason, gas_used: 0 }; + + let revert = decode_invalidated_assertion(&result); + assert_eq!(revert.reason(), "Halt reason: CallTooDeep"); + } +} From 0848fda0f582d05562e9abfae11c314645decb74 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Thu, 26 Jun 2025 05:27:28 -0600 Subject: [PATCH 43/83] fix: set gas_price to block basefee (#54) * fix: set gas_price to block basefee * fix: bump assertion executor to 0.1.7 * chore: bump assex to 0.1.8 --------- Co-authored-by: fredo --- crates/cheatcodes/Cargo.toml | 2 +- crates/cheatcodes/src/credible.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 5b904edfed782..631bcf72c2830 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.6", default-features = false } +assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.8", default-features = false } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 67f8c38d09ab9..02af84924d945 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -96,6 +96,7 @@ impl Cheatcode for assertionExCall { value: decoded_tx.value, data: decoded_tx.data, chain_id: Some(chain_id), + gas_price: ccx.ecx.env.block.basefee, ..Default::default() }; From 6cce6191b05f50c750b4226d7098a2c6f3ad0f9e Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Tue, 22 Jul 2025 20:40:56 +0700 Subject: [PATCH 44/83] feat: cheatcode refactor (#56) * feat: cheatcode refactor * chore: remove dead code about depth --- crates/cheatcodes/Cargo.toml | 3 +- crates/cheatcodes/spec/src/vm.rs | 17 +- crates/cheatcodes/src/credible.rs | 335 ++++++++++++++++++----------- crates/cheatcodes/src/inspector.rs | 85 +++++++- crates/cheatcodes/src/lib.rs | 2 +- 5 files changed, 300 insertions(+), 142 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 631bcf72c2830..1b0ecbc28ed48 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,8 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/assertion-executor.git", tag = "0.1.8", default-features = false } +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "d17125a", features = ["phoundry"]} + foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index c6db80849ee99..1b07dca3a2479 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -19,20 +19,11 @@ sol! { #[derive(Debug, Cheatcode)] // Keep this list small to avoid unnecessary bloat. #[sol(abi)] interface Vm { - /// Simple transaction struct for assertion execution testing - struct AssertionExTransaction { - /// The address of the sender - address from; - /// The address of the receiver - address to; - /// The value of the transaction - uint256 value; - /// The abi encoded calldata of the transaction - bytes data; - } - /// Gets the address for a given private key. + + // Used to execute assertion against the next call or contract creation. + // Will revert if the assertion is not triggered. #[cheatcode(group = Credible, safety = Safe)] - function assertionEx(bytes calldata tx, address assertionAdopter, bytes calldata assertionContract, string calldata assertionContractLabel) external; + function assertion(address adopter, bytes calldata createData, bytes4 fnSelector) external; // ======== Types ======== diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 02af84924d945..6638d74dc778d 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,18 +1,24 @@ -use crate::{Cheatcode, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; -use alloy_primitives::TxKind; -use alloy_sol_types::{Revert, SolError, SolValue}; +use crate::{inspector::Ecx, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; +use alloy_primitives::{Bytes, FixedBytes, TxKind}; +use alloy_sol_types::{Revert, SolError, SolEvent, SolValue}; use assertion_executor::{ - db::fork_db::ForkDb, + db::{fork_db::ForkDb, DatabaseCommit, DatabaseRef}, + primitives::{ + AccountInfo, Address, AssertionFunctionExecutionResult, Bytecode, ExecutionResult, TxEnv, + B256, U256, + }, store::{AssertionState, AssertionStore}, ExecutorConfig, }; -use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; -use revm::{ - primitives::{AccountInfo, Address, Bytecode, ExecutionResult, TxEnv, B256, U256}, - DatabaseCommit, DatabaseRef, + +use foundry_evm_core::{ + abi::console::ds::Console, + backend::{DatabaseError, DatabaseExt}, }; +use revm::context_interface::{ContextTr, JournalTr}; use std::{ - collections::HashMap, + cmp::max, + collections::HashSet, sync::{Arc, Mutex}, }; @@ -40,144 +46,227 @@ impl<'a> ThreadSafeDb<'a> { impl<'a> DatabaseRef for ThreadSafeDb<'a> { type Error = DatabaseError; - fn basic_ref(&self, address: Address) -> Result, Self::Error> { + fn basic_ref( + &self, + address: Address, + ) -> Result, ::Error> { self.db.lock().unwrap().basic(address) } - fn code_by_hash_ref(&self, code_hash: B256) -> Result { + fn code_by_hash_ref(&self, code_hash: B256) -> Result::Error> { self.db.lock().unwrap().code_by_hash(code_hash) } - fn storage_ref(&self, address: Address, index: U256) -> Result { + fn storage_ref( + &self, + address: Address, + index: U256, + ) -> Result::Error> { self.db.lock().unwrap().storage(address, index) } - fn block_hash_ref(&self, number: u64) -> Result { + fn block_hash_ref(&self, number: u64) -> Result::Error> { self.db.lock().unwrap().block_hash(number) } } -impl Cheatcode for assertionExCall { - fn apply_full(&self, ccx: &mut CheatsCtxt, executor: &mut dyn CheatcodesExecutor) -> Result { - let Self { - tx, - assertionAdopter: assertion_adopter, - assertionContract, - assertionContractLabel, - } = self; - - let spec_id = ccx.ecx.spec_id(); - let block = ccx.ecx.env.block.clone(); - let state = ccx.ecx.journaled_state.state.clone(); - let chain_id = ccx.ecx.env.cfg.chain_id; +impl Cheatcode for assertionCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { adopter, createData: create_data, fnSelector: fn_selector } = self; - // Setup assertion database - let db = ThreadSafeDb::new(ccx.ecx.db); + ensure!( + ccx.state.assertion.is_none(), + "you must call another function prior to setting another assertion" + ); + let assertion = Assertion { + adopter: *adopter, + create_data: create_data.to_vec(), + fn_selector: *fn_selector, + depth: ccx.ecx.journaled_state.depth(), + }; - // Prepare assertion store - let assertion_contract_bytecode = Bytecode::LegacyRaw(assertionContract.to_vec().into()); + ccx.state.assertion = Some(assertion); + Ok(Default::default()) + } +} +#[derive(Debug, Clone)] +pub struct Assertion { + pub adopter: Address, + pub create_data: Vec, + pub fn_selector: FixedBytes<4>, + pub depth: usize, +} - let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 100_000 }; +pub struct TxAttributes { + pub value: U256, + pub data: Bytes, + pub caller: Address, + pub kind: TxKind, +} - let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); +/// Used to handle assertion execution in inspector in calls after the cheatcode was called. +pub fn execute_assertion( + assertion: &Assertion, + tx_attributes: TxAttributes, + ecx: Ecx, + executor: &mut dyn CheatcodesExecutor, + cheats: &mut Cheatcodes, + is_create: bool, +) -> Result, crate::Error> { + let spec_id = ecx.cfg.spec; + let block = ecx.block.clone(); + let state = ecx.journaled_state.state.clone(); + let chain_id = ecx.cfg.chain_id; + + let nonce = ecx.db().basic(tx_attributes.caller).unwrap_or_default().unwrap_or_default().nonce; + // Setup assertion database + let db = ThreadSafeDb::new(ecx.db()); + + // Prepare assertion store + + let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 100_000 }; + + let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); + + let mut assertion_state = + AssertionState::new_active(assertion.create_data.clone().into(), &config) + .expect("Failed to create assertion state"); + + // Filter triggers for one fn selector + for fn_selectors in assertion_state.trigger_recorder.triggers.values_mut() { + if fn_selectors.contains(&assertion.fn_selector) { + *fn_selectors = HashSet::from_iter([assertion.fn_selector]); + } else { + *fn_selectors = HashSet::new(); + } + } - let assertion_state = - AssertionState::new_active(assertion_contract_bytecode.bytes(), &config) - .expect("Failed to create assertion state"); + store.insert(assertion.adopter, assertion_state).expect("Failed to store assertions"); + let tx_env = TxEnv { + caller: tx_attributes.caller, + gas_limit: block.gas_limit.try_into().unwrap_or(u64::MAX), + gas_price: block.basefee.into(), + chain_id: Some(chain_id), + value: tx_attributes.value, + data: tx_attributes.data, + kind: tx_attributes.kind, + nonce, + ..Default::default() + }; + + let mut assertion_executor = config.build(store); + + // Commit current journal state so that it is available for assertions and + // triggering tx + let mut fork_db = ForkDb::new(db.clone()); + fork_db.commit(state); + + // Odysseas: This is a hack to use the new unified codepath for validate_transaction_ext_db + // Effectively, we are applying the transaction in a clone of the currently running database + // which is then used by the fork_db. + // TODO: Remove this once we have a proper way to handle this. + let mut ext_db = revm::database::WrapDatabaseRef(fork_db.clone()); + + // Store assertions + let tx_validation = assertion_executor + .validate_transaction_ext_db(block.clone(), tx_env.clone(), &mut fork_db, &mut ext_db) + .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; + + ecx.journaled_state.inner.checkpoint(); + + if let Some(expected) = &mut cheats.expected_revert { + expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); + } - store.insert(*assertion_adopter, assertion_state).expect("Failed to store assertions"); + let mut inspector = executor.get_inspector(cheats); + // if transaction execution reverted, log the revert reason + if !tx_validation.result_and_state.result.is_success() { + inspector.console_log(&format!( + "Transaction reverted: {}", + decode_invalidated_assertion(&tx_validation.result_and_state.result).reason() + )); + } - let decoded_tx = AssertionExTransaction::abi_decode(tx, true)?; + // else get information about the assertion execution + let total_assertion_gas = tx_validation.total_assertions_gas(); + let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); + let tx_gas_used = tx_validation.result_and_state.result.gas_used(); - let tx_env = TxEnv { - caller: decoded_tx.from, - gas_limit: ccx.ecx.env.block.gas_limit.try_into().unwrap_or(u64::MAX), - transact_to: TxKind::Call(decoded_tx.to), - value: decoded_tx.value, - data: decoded_tx.data, - chain_id: Some(chain_id), - gas_price: ccx.ecx.env.block.basefee, - ..Default::default() - }; + if total_assertions_ran != 1 { + bail!("Expected 1 assertion to be executed, but {total_assertions_ran} were executed."); + } - let mut assertion_executor = config.build(db, store); - - // Commit current journal state so that it is available for assertions and - // triggering tx - let mut fork_db = ForkDb::new(assertion_executor.db.clone()); - fork_db.commit(state); - - // Odysseas: This is a hack to use the new unified codepath for validate_transaction_ext_db - // Effectively, we are applying the transaction in a clone of the currently running database - // which is then used by the fork_db. - // TODO: Remove this once we have a proper way to handle this. - let mut ext_db = revm::db::WrapDatabaseRef(fork_db.clone()); - - // Store assertions - let tx_validation = assertion_executor - .validate_transaction_ext_db(block, tx_env, &mut fork_db, &mut ext_db) - .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; - - // if transaction execution reverted, bail - if !tx_validation.result_and_state.result.is_success() { - let decoded_error = - decode_invalidated_assertion(&tx_validation.result_and_state.result); - executor.console_log(ccx, &format!("Transaction reverted: {}", decoded_error.reason())); - bail!("Transaction Reverted"); + //Expect is safe because we validate above that 1 assertion was ran. + let assertion_contract = tx_validation + .assertions_executions + .first() + .expect("Expected 1 assertion to be executed, but got 0"); + + let assertion_fn_result = assertion_contract + .assertion_fns_results + .first() + .expect("Expected 1 assertion to be executed, but got 0"); + + for log in assertion_fn_result.as_result().logs() { + if Some(&Console::log::SIGNATURE_HASH) == log.topics().first() { + let decoded_log = Console::log::decode_log(log); + if let Ok(log_data) = decoded_log { + inspector.console_log(&format!("{}", log_data.val)); + } } - // else get information about the assertion execution - let assertion_contract = tx_validation.assertions_executions.first().unwrap(); - let total_assertion_gas = tx_validation.total_assertions_gas(); - let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); - let tx_gas_used = tx_validation.result_and_state.result.gas_used(); - let mut assertion_gas_message = format!( - "Transaction gas cost: {tx_gas_used}\n Total Assertion gas cost: {total_assertion_gas}\n Total assertions ran: {total_assertions_ran}\n Assertion Functions gas cost\n " - ); + } - // Format individual assertion function results - for (fn_selector_index, assertion_fn) in - assertion_contract.assertion_fns_results.iter().enumerate() - { - assertion_gas_message.push_str(&format!( - " └─ [selector {}:index {}] gas cost: {}\n", - assertion_fn.id.fn_selector, - fn_selector_index, - assertion_fn.as_result().gas_used() - )); - } - executor.console_log(ccx, &assertion_gas_message); - - if !tx_validation.is_valid() { - let mut error_msg = format!("\n {assertionContractLabel} Enforced Assertions:\n"); - // Collect failed assertions - let reverted_assertions: HashMap<_, _> = assertion_contract - .assertion_fns_results - .iter() - .enumerate() - .filter(|(_, assertion_fn)| !assertion_fn.is_success()) - .map(|(fn_selector_index, assertion_fn)| { - let key = format!( - "[selector {}:index {}]", - assertion_fn.id.fn_selector, fn_selector_index - ); - let revert = decode_invalidated_assertion(assertion_fn.as_result()); - (key, revert) - }) - .collect(); - - // Format error messages - for (key, revert) in reverted_assertions { - error_msg.push_str(&format!( - " └─ {} - Revert Reason: {} \n", - key, - revert.reason() + let assertion_gas_message = format!( + "Transaction gas cost: {tx_gas_used}\n Assertion gas cost: {total_assertion_gas}\n " + ); + inspector.console_log(&assertion_gas_message); + + if !tx_validation.is_valid() { + match &assertion_fn_result.result { + AssertionFunctionExecutionResult::AssertionContractDeployFailure(result) => { + inspector.console_log(&format!( + "Assertion contract deploy failed: {}", + decode_invalidated_assertion(&result).reason() )); + let output = result.output().unwrap_or_default(); + return Err(crate::Error::from(output.clone())); + } + AssertionFunctionExecutionResult::AssertionExecutionResult(result) => { + inspector.console_log(&format!( + "Assertion function reverted: {}", + decode_invalidated_assertion(&result).reason() + )); + let output = result.output().unwrap_or_default(); + return Err(crate::Error::from(output.clone())); } - - executor.console_log(ccx, &error_msg); - bail!("Assertions Reverted"); } - Ok(Default::default()) + } else { + let journaled_state = &mut ecx.journaled_state.state; + for (address, account) in tx_validation.result_and_state.state { + let journaled_acct = journaled_state.get_mut(&address); + match journaled_acct { + Some(journaled_acct) => { + journaled_acct.info = account.info; + journaled_acct.status = journaled_acct.status.union(account.status); + for (index, value) in account.storage.iter() { + journaled_acct.storage.insert(*index, value.clone()); + } + } + None => { + journaled_state.insert(address, account); + } + } + } + } + + if is_create { + let address: Option
= + tx_validation.result_and_state.result.output().map(|output| { + Address::abi_decode(output).expect("Could not decode address from create output") + }); + Ok(address) + } else { + Ok(None) } } @@ -188,7 +277,7 @@ fn decode_invalidated_assertion(execution_result: &ExecutionResult) -> Revert { reason: "Tried to decode invalidated assertion, but result was success. This is a bug in phoundry. Please report to the Phylax team.".to_string(), }, ExecutionResult::Revert{output, ..} => { - Revert::abi_decode(output, true) + Revert::abi_decode(output) .unwrap_or(Revert::new(("Unknown Revert Reason".to_string(),))) }, ExecutionResult::Halt{reason, ..} => Revert { @@ -200,8 +289,8 @@ fn decode_invalidated_assertion(execution_result: &ExecutionResult) -> Revert { #[cfg(test)] mod tests { use super::*; - use alloy_primitives::Bytes; - use revm::primitives::{HaltReason, Output, SuccessReason}; + use assertion_executor::primitives::HaltReason; + use revm::context::result::{Output, SuccessReason}; #[test] fn test_decode_revert_error_success() { diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 4eebd3a7cbf00..6ed86ee98f2c4 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -409,6 +409,9 @@ pub struct Cheatcodes { /// Expected revert information pub expected_revert: Option, + /// Assertion information + pub assertion: Option, + /// Assume next call can revert and discard fuzz run if it does. pub assume_no_revert: Option, @@ -552,6 +555,7 @@ impl Cheatcodes { mocked_functions: Default::default(), expected_calls: Default::default(), expected_emits: Default::default(), + assertion: Default::default(), expected_creates: Default::default(), allowed_mem_writes: Default::default(), broadcast: Default::default(), @@ -1041,6 +1045,43 @@ impl Cheatcodes { }]); } + if let Some(assertion) = self.assertion.take() { + let tx_attributes = crate::credible::TxAttributes { + value: call.call_value(), + data: call.input.bytes(ecx), + caller: call.caller, + kind: TxKind::Call(call.target_address), + }; + + let call_outcome = match crate::credible::execute_assertion( + &assertion, + tx_attributes, + ecx, + executor, + self, + false, + ) { + Ok(_) => Some(CallOutcome { + result: InterpreterResult { + result: InstructionResult::Return, + output: Default::default(), + gas, + }, + memory_offset: call.return_memory_offset.clone(), + }), + Err(err) => Some(CallOutcome { + result: InterpreterResult { + result: InstructionResult::Revert, + output: err.abi_encode().into(), + gas, + }, + memory_offset: call.return_memory_offset.clone(), + }), + }; + + return call_outcome; + } + None } @@ -1220,8 +1261,8 @@ impl Inspector> for Cheatcodes { record_logs(&mut self.recorded_logs, &log); } - fn call(&mut self, ecx: Ecx, inputs: &mut CallInputs) -> Option { - Self::call_with_executor(self, ecx, inputs, &mut TransparentCheatcodesExecutor) + fn call(&mut self, ecx: Ecx, call: &mut CallInputs) -> Option { + Self::call_with_executor(self, ecx, call, &mut TransparentCheatcodesExecutor) } fn call_end(&mut self, ecx: Ecx, call: &CallInputs, outcome: &mut CallOutcome) { @@ -1266,10 +1307,10 @@ impl Inspector> for Cheatcodes { assume_no_revert.reverted_by = Some(call.target_address); } - // allow multiple cheatcode calls at the same depth let curr_depth = ecx.journaled_state.depth(); + // allow multiple cheatcode calls at the same depth if curr_depth <= assume_no_revert.depth && !cheatcode_call { - // Discard run if we're at the same depth as cheatcode, call reverted, and no + // discard run if we're at the same depth as cheatcode, call reverted, and no // specific reason was supplied if outcome.result.is_revert() { let assume_no_revert = std::mem::take(&mut self.assume_no_revert).unwrap(); @@ -1751,6 +1792,42 @@ impl Inspector> for Cheatcodes { depth: curr_depth as u64, }]); } + if let Some(assertion) = self.assertion.take() { + let tx_attributes = crate::credible::TxAttributes { + value: input.value(), + data: input.init_code(), + caller: input.caller(), + kind: TxKind::Create, + }; + + let call_outcome = match crate::credible::execute_assertion( + &assertion, + tx_attributes, + ecx, + &mut TransparentCheatcodesExecutor, + self, + true, + ) { + Ok(address) => Some(CreateOutcome { + result: InterpreterResult { + result: InstructionResult::Return, + output: Default::default(), + gas, + }, + address, + }), + Err(err) => Some(CreateOutcome { + result: InterpreterResult { + result: InstructionResult::Revert, + output: err.abi_encode().into(), + gas, + }, + address: None, + }), + }; + + return call_outcome; + } None } diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index 275aa4f4fe7b2..75850449d72b8 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -63,7 +63,7 @@ mod toml; mod utils; -mod credible; +pub mod credible; /// Cheatcode implementation. pub(crate) trait Cheatcode: CheatcodeDef + DynCheatcode { From 6d95b8b6a0214af2e884ebed0dce4123e9b40d29 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Thu, 24 Jul 2025 15:26:37 +0700 Subject: [PATCH 45/83] gregory/eng 896 feat add console logging inside assertion execution (#57) * feat: add console logging * chore: bump assex * chore: bump * chore: bump assex --- crates/cheatcodes/Cargo.toml | 3 ++- crates/cheatcodes/src/credible.rs | 17 ++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 1b0ecbc28ed48..f665c97fb2c50 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,8 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "d17125a", features = ["phoundry"]} +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "a7571bb", features = ["phoundry"]} +#assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 6638d74dc778d..9efb876335d09 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,6 +1,6 @@ use crate::{inspector::Ecx, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Bytes, FixedBytes, TxKind}; -use alloy_sol_types::{Revert, SolError, SolEvent, SolValue}; +use alloy_sol_types::{Revert, SolError, SolValue}; use assertion_executor::{ db::{fork_db::ForkDb, DatabaseCommit, DatabaseRef}, primitives::{ @@ -11,10 +11,7 @@ use assertion_executor::{ ExecutorConfig, }; -use foundry_evm_core::{ - abi::console::ds::Console, - backend::{DatabaseError, DatabaseExt}, -}; +use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; use revm::context_interface::{ContextTr, JournalTr}; use std::{ cmp::max, @@ -207,12 +204,10 @@ pub fn execute_assertion( .first() .expect("Expected 1 assertion to be executed, but got 0"); - for log in assertion_fn_result.as_result().logs() { - if Some(&Console::log::SIGNATURE_HASH) == log.topics().first() { - let decoded_log = Console::log::decode_log(log); - if let Ok(log_data) = decoded_log { - inspector.console_log(&format!("{}", log_data.val)); - } + if !assertion_fn_result.console_logs.is_empty() { + inspector.console_log("Assertion function logs: "); + for log in assertion_fn_result.console_logs.iter() { + inspector.console_log(log); } } From 8b2743788a67d34f56dc0d3f4969ad026facb2b0 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Mon, 28 Jul 2025 20:41:03 +0700 Subject: [PATCH 46/83] chore: make consistent (#58) --- crates/cheatcodes/src/credible.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 9efb876335d09..0d85d93fcf7e4 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -129,14 +129,18 @@ pub fn execute_assertion( AssertionState::new_active(assertion.create_data.clone().into(), &config) .expect("Failed to create assertion state"); + let mut trigger_types_to_remove = Vec::new(); // Filter triggers for one fn selector - for fn_selectors in assertion_state.trigger_recorder.triggers.values_mut() { + for (trigger_type, fn_selectors) in assertion_state.trigger_recorder.triggers.iter_mut() { if fn_selectors.contains(&assertion.fn_selector) { *fn_selectors = HashSet::from_iter([assertion.fn_selector]); } else { - *fn_selectors = HashSet::new(); + trigger_types_to_remove.push(trigger_type.clone()); } } + for trigger_type in trigger_types_to_remove { + assertion_state.trigger_recorder.triggers.remove(&trigger_type); + } store.insert(assertion.adopter, assertion_state).expect("Failed to store assertions"); let tx_env = TxEnv { From 2eb90ac17e9d035394aab236c33ac739d51f03da Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Wed, 6 Aug 2025 15:13:22 +0700 Subject: [PATCH 47/83] chore: fix triggers with return values (#59) * chore: fix regressions * Update crates/cheatcodes/src/credible.rs Co-authored-by: Frederik Signed-off-by: GregTheDev --------- Signed-off-by: GregTheDev Co-authored-by: Frederik --- crates/cheatcodes/src/credible.rs | 60 ++++++++++++------------------ crates/cheatcodes/src/inspector.rs | 28 ++------------ 2 files changed, 28 insertions(+), 60 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 0d85d93fcf7e4..e8d7c77d70165 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,6 +1,6 @@ use crate::{inspector::Ecx, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Bytes, FixedBytes, TxKind}; -use alloy_sol_types::{Revert, SolError, SolValue}; +use alloy_sol_types::{Revert, SolError}; use assertion_executor::{ db::{fork_db::ForkDb, DatabaseCommit, DatabaseRef}, primitives::{ @@ -108,8 +108,7 @@ pub fn execute_assertion( ecx: Ecx, executor: &mut dyn CheatcodesExecutor, cheats: &mut Cheatcodes, - is_create: bool, -) -> Result, crate::Error> { +) -> Result<(), crate::Error> { let spec_id = ecx.cfg.spec; let block = ecx.block.clone(); let state = ecx.journaled_state.state.clone(); @@ -173,12 +172,6 @@ pub fn execute_assertion( .validate_transaction_ext_db(block.clone(), tx_env.clone(), &mut fork_db, &mut ext_db) .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; - ecx.journaled_state.inner.checkpoint(); - - if let Some(expected) = &mut cheats.expected_revert { - expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); - } - let mut inspector = executor.get_inspector(cheats); // if transaction execution reverted, log the revert reason if !tx_validation.result_and_state.result.is_success() { @@ -194,6 +187,15 @@ pub fn execute_assertion( let tx_gas_used = tx_validation.result_and_state.result.gas_used(); if total_assertions_ran != 1 { + // If assertions were not executed, we need to update expect revert depth to + // allow for matching on this revert condition, as we will not execute against + // test evm in this case. + ecx.journaled_state.inner.checkpoint(); + + std::mem::drop(inspector); + if let Some(expected) = &mut cheats.expected_revert { + expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); + } bail!("Expected 1 assertion to be executed, but {total_assertions_ran} were executed."); } @@ -220,7 +222,19 @@ pub fn execute_assertion( ); inspector.console_log(&assertion_gas_message); + // Drop the inspector to avoid borrow checker issues + std::mem::drop(inspector); + if !tx_validation.is_valid() { + // If invalidated, we don't execute against test evm, so we must update expected depth + // for expect revert cheatcode. + ecx.journaled_state.inner.checkpoint(); + + if let Some(expected) = &mut cheats.expected_revert { + expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); + } + + let mut inspector = executor.get_inspector(cheats); match &assertion_fn_result.result { AssertionFunctionExecutionResult::AssertionContractDeployFailure(result) => { inspector.console_log(&format!( @@ -239,34 +253,8 @@ pub fn execute_assertion( return Err(crate::Error::from(output.clone())); } } - } else { - let journaled_state = &mut ecx.journaled_state.state; - for (address, account) in tx_validation.result_and_state.state { - let journaled_acct = journaled_state.get_mut(&address); - match journaled_acct { - Some(journaled_acct) => { - journaled_acct.info = account.info; - journaled_acct.status = journaled_acct.status.union(account.status); - for (index, value) in account.storage.iter() { - journaled_acct.storage.insert(*index, value.clone()); - } - } - None => { - journaled_state.insert(address, account); - } - } - } - } - - if is_create { - let address: Option
= - tx_validation.result_and_state.result.output().map(|output| { - Address::abi_decode(output).expect("Could not decode address from create output") - }); - Ok(address) - } else { - Ok(None) } + Ok(()) } fn decode_invalidated_assertion(execution_result: &ExecutionResult) -> Revert { diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 6ed86ee98f2c4..89717ac50ceda 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1053,22 +1053,14 @@ impl Cheatcodes { kind: TxKind::Call(call.target_address), }; - let call_outcome = match crate::credible::execute_assertion( + return match crate::credible::execute_assertion( &assertion, tx_attributes, ecx, executor, self, - false, ) { - Ok(_) => Some(CallOutcome { - result: InterpreterResult { - result: InstructionResult::Return, - output: Default::default(), - gas, - }, - memory_offset: call.return_memory_offset.clone(), - }), + Ok(_) => None, Err(err) => Some(CallOutcome { result: InterpreterResult { result: InstructionResult::Revert, @@ -1078,8 +1070,6 @@ impl Cheatcodes { memory_offset: call.return_memory_offset.clone(), }), }; - - return call_outcome; } None @@ -1800,22 +1790,14 @@ impl Inspector> for Cheatcodes { kind: TxKind::Create, }; - let call_outcome = match crate::credible::execute_assertion( + return match crate::credible::execute_assertion( &assertion, tx_attributes, ecx, &mut TransparentCheatcodesExecutor, self, - true, ) { - Ok(address) => Some(CreateOutcome { - result: InterpreterResult { - result: InstructionResult::Return, - output: Default::default(), - gas, - }, - address, - }), + Ok(_) => None, Err(err) => Some(CreateOutcome { result: InterpreterResult { result: InstructionResult::Revert, @@ -1825,8 +1807,6 @@ impl Inspector> for Cheatcodes { address: None, }), }; - - return call_outcome; } None From 5baf70ed9fd99f2fde2afb7571076e6ca93f83b2 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Thu, 7 Aug 2025 18:50:35 +0700 Subject: [PATCH 48/83] chore: bump assex (#60) --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index f665c97fb2c50..5839216328082 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "a7571bb", features = ["phoundry"]} +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "13ceefe", features = ["phoundry"]} #assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} foundry-cheatcodes-spec.workspace = true From 98ee064536682f153e538b99a7f27a8368bb1d78 Mon Sep 17 00:00:00 2001 From: GregTheDev Date: Sat, 9 Aug 2025 00:11:30 +0700 Subject: [PATCH 49/83] chore: bump assex (#61) --- crates/cheatcodes/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 5839216328082..01fb16b6e1a30 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,7 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "13ceefe", features = ["phoundry"]} +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "5b0b528", features = ["phoundry"]} #assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} foundry-cheatcodes-spec.workspace = true From 1edfa9f5c9b400e1f36ffd91d8b410f90bd9c146 Mon Sep 17 00:00:00 2001 From: Frederik Date: Wed, 20 Aug 2025 11:21:46 +0200 Subject: [PATCH 50/83] chore: bump assex with checkpoint fix (#62) --- crates/cheatcodes/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 01fb16b6e1a30..5d204f7e0823c 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,7 +22,9 @@ vergen = { workspace = true, default-features = false, features = [ ] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "5b0b528", features = ["phoundry"]} +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "40731c9", features = [ + "phoundry", +] } #assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} foundry-cheatcodes-spec.workspace = true From 0e2ea63fd4813dec782997ecaf61c126a6fccf1a Mon Sep 17 00:00:00 2001 From: Frederik Date: Mon, 3 Nov 2025 16:54:28 +0100 Subject: [PATCH 51/83] feat: change assertion gas limit to 300000 (#63) --- crates/cheatcodes/src/credible.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index e8d7c77d70165..76ace0b4f0dd2 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -120,7 +120,7 @@ pub fn execute_assertion( // Prepare assertion store - let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 100_000 }; + let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 300_000 }; let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); From 04fd8ffdfcd1b8335b85c9928a3963a9c666b41d Mon Sep 17 00:00:00 2001 From: mateo-mro <160488334+mateo-mro@users.noreply.github.com> Date: Tue, 2 Dec 2025 21:41:29 +0100 Subject: [PATCH 52/83] feat: adapt code to latest assex --- Cargo.lock | 752 +++++++++++++++++++++++++++-- Cargo.toml | 2 +- README.md | 1 + crates/anvil/server/Cargo.toml | 2 +- crates/cheatcodes/Cargo.toml | 8 +- crates/cheatcodes/spec/src/vm.rs | 4 +- crates/cheatcodes/src/credible.rs | 14 +- crates/cheatcodes/src/inspector.rs | 2 + 8 files changed, 725 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 874b12c3afad3..1a761c31e983e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,7 +38,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.8.31", ] [[package]] @@ -65,6 +65,34 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07655fedc35188f3c50ff8fc6ee45703ae14ef1bc7ae7d80e23a747012184e3" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-json-rpc", + "alloy-network", + "alloy-node-bindings", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", + "alloy-trie", +] + [[package]] name = "alloy-chains" version = "0.2.23" @@ -142,6 +170,19 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "alloy-core" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a651e1d9e50e6d0a78bd23cd08facb70459a94501c4036c7799a093e569a310" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + [[package]] name = "alloy-dyn-abi" version = "1.5.1" @@ -252,6 +293,27 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "alloy-evm" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01be36ba6f5e6e62563b369e03ca529eac46aea50677f84655084b4750816574" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-hardforks 0.4.5", + "alloy-primitives", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-sol-types", + "auto_impl", + "derive_more", + "op-alloy 0.22.4", + "op-revm", + "revm", + "thiserror 2.0.17", +] + [[package]] name = "alloy-evm" version = "0.25.2" @@ -260,7 +322,7 @@ checksum = "e6ccc4c702c840148af1ce784cc5c6ed9274a020ef32417c5b1dbeab8c317673" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-op-hardforks", "alloy-primitives", "alloy-rpc-types-engine", @@ -268,7 +330,7 @@ dependencies = [ "alloy-sol-types", "auto_impl", "derive_more", - "op-alloy", + "op-alloy 0.23.1", "op-revm", "revm", "thiserror 2.0.17", @@ -289,6 +351,19 @@ dependencies = [ "serde_with", ] +[[package]] +name = "alloy-hardforks" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165210652f71dfc094b051602bafd691f506c54050a174b1cba18fb5ef706a3" +dependencies = [ + "alloy-chains", + "alloy-eip2124", + "alloy-primitives", + "auto_impl", + "dyn-clone", +] + [[package]] name = "alloy-hardforks" version = "0.4.5" @@ -368,6 +443,27 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-node-bindings" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b000c0790644bd4effe719f4272f0023167567ca9534e4e071f6f18c4f7e44" +dependencies = [ + "alloy-genesis", + "alloy-hardforks 0.2.13", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "alloy-signer-local", + "k256", + "rand 0.8.5", + "serde_json", + "tempfile", + "thiserror 2.0.17", + "tracing", + "url", +] + [[package]] name = "alloy-op-evm" version = "0.25.2" @@ -376,11 +472,11 @@ checksum = "0f640da852f93ddaa3b9a602b7ca41d80e0023f77a67b68aaaf511c32f1fe0ce" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-op-hardforks", "alloy-primitives", "auto_impl", - "op-alloy", + "op-alloy 0.23.1", "op-revm", "revm", "thiserror 2.0.17", @@ -393,7 +489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f96fb2fce4024ada5b2c11d4076acf778a0d3e4f011c6dfd2ffce6d0fcf84ee9" dependencies = [ "alloy-chains", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-primitives", "auto_impl", ] @@ -441,9 +537,11 @@ dependencies = [ "alloy-json-rpc", "alloy-network", "alloy-network-primitives", + "alloy-node-bindings", "alloy-primitives", "alloy-pubsub", "alloy-rpc-client", + "alloy-rpc-types-anvil", "alloy-rpc-types-debug", "alloy-rpc-types-eth", "alloy-rpc-types-trace", @@ -552,6 +650,7 @@ checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", + "alloy-rpc-types-debug", "alloy-rpc-types-engine", "alloy-rpc-types-eth", "alloy-rpc-types-trace", @@ -1118,7 +1217,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-eip5792", "alloy-eips", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-genesis", "alloy-network", "alloy-op-evm", @@ -1158,8 +1257,8 @@ dependencies = [ "futures", "hyper", "itertools 0.14.0", - "op-alloy-consensus", - "op-alloy-rpc-types", + "op-alloy-consensus 0.23.1", + "op-alloy-rpc-types 0.23.1", "op-revm", "parking_lot", "rand 0.8.5", @@ -1558,6 +1657,79 @@ dependencies = [ "term", ] +[[package]] +name = "assertion-da-client" +version = "0.7.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=mateo%2Fupdate-revm#33c32700e4379cf5878b135f339907c83aa5ce11" +dependencies = [ + "alloy", + "assertion-da-core", + "http 1.4.0", + "reqwest", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "url", +] + +[[package]] +name = "assertion-da-core" +version = "0.7.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=mateo%2Fupdate-revm#33c32700e4379cf5878b135f339907c83aa5ce11" +dependencies = [ + "alloy", + "serde", +] + +[[package]] +name = "assertion-executor" +version = "0.7.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=mateo%2Fupdate-revm#33c32700e4379cf5878b135f339907c83aa5ce11" +dependencies = [ + "alloy", + "alloy-consensus", + "alloy-evm 0.24.2", + "alloy-network", + "alloy-network-primitives", + "alloy-node-bindings", + "alloy-primitives", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-rpc-types-anvil", + "alloy-signer", + "alloy-signer-local", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-ws", + "assertion-da-client", + "bincode", + "clap", + "dashmap", + "enum-as-inner", + "evm-glue", + "futures", + "metrics", + "moka", + "op-revm", + "parking_lot", + "rayon", + "revm", + "serde", + "serde_json", + "sled", + "tempfile", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tracing", + "url", + "zerocopy 0.7.35", +] + [[package]] name = "async-compression" version = "0.4.36" @@ -2164,6 +2336,15 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -2541,6 +2722,15 @@ dependencies = [ "serde", ] +[[package]] +name = "cache-advisor" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f89ab55ca4e6a46a0740a1c5346db1ad66e4a76598bbfa060dc3259935a7450" +dependencies = [ + "crossbeam-queue", +] + [[package]] name = "camino" version = "1.2.2" @@ -2589,7 +2779,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-eips", "alloy-ens", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-json-abi", "alloy-json-rpc", "alloy-network", @@ -3057,6 +3247,17 @@ version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" +[[package]] +name = "concurrent-map" +version = "5.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6542c565fbcba786db59307d7840f0bf5cd9e0aba6502755337e15f0e06fd65" +dependencies = [ + "ebr", + "serde", + "stack-map", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -3258,6 +3459,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -3733,6 +3943,15 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "ebr" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b1ea3b18359d566f360eaf811a2d69bc6c8eb6faaeecc8839975633860a076e" +dependencies = [ + "shared-local-state", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -3845,6 +4064,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "enum-ordinalize" version = "4.3.2" @@ -4045,6 +4276,15 @@ dependencies = [ "hex", ] +[[package]] +name = "evm-glue" +version = "0.1.0" +source = "git+https://git@github.com/Philogy/evm-glue.git?rev=6be3e8c89a7d193b591ca0415ec2a48b1540c01e#6be3e8c89a7d193b591ca0415ec2a48b1540c01e" +dependencies = [ + "hex", + "hex-literal", +] + [[package]] name = "evmole" version = "0.8.1" @@ -4100,6 +4340,12 @@ dependencies = [ "bytes", ] +[[package]] +name = "fault-injection" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3d175246dec3fddef3b1fcd57acdb023e4c562d032e9eccc5f246da3d7fed3" + [[package]] name = "fd-lock" version = "4.0.4" @@ -4210,13 +4456,28 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "forge" version = "1.5.1" dependencies = [ "alloy-chains", "alloy-dyn-abi", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-json-abi", "alloy-network", "alloy-primitives", @@ -4504,7 +4765,7 @@ dependencies = [ "alloy-consensus", "alloy-dyn-abi", "alloy-ens", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-genesis", "alloy-json-abi", "alloy-network", @@ -4515,6 +4776,7 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "alloy-sol-types", + "assertion-executor", "base64 0.22.1", "dialoguer", "ecdsa", @@ -4527,6 +4789,7 @@ dependencies = [ "foundry-evm-core", "foundry-evm-fuzz", "foundry-evm-traces", + "foundry-fork-db", "foundry-wallets", "itertools 0.14.0", "jsonpath_lib", @@ -4848,7 +5111,7 @@ name = "foundry-evm" version = "1.5.1" dependencies = [ "alloy-dyn-abi", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-json-abi", "alloy-primitives", "alloy-rpc-types", @@ -4894,9 +5157,9 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-dyn-abi", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-genesis", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-json-abi", "alloy-network", "alloy-op-evm", @@ -4974,7 +5237,7 @@ name = "foundry-evm-networks" version = "1.5.1" dependencies = [ "alloy-chains", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-primitives", "clap", "revm", @@ -5021,7 +5284,7 @@ checksum = "8df2fd495cf7337b247d960f90355329cc625fe27fe7da9fe5e598c42df21526" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -5063,7 +5326,7 @@ name = "foundry-primitives" version = "1.5.1" dependencies = [ "alloy-consensus", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-network", "alloy-primitives", "alloy-rlp", @@ -5071,8 +5334,8 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-serde", "derive_more", - "op-alloy-consensus", - "op-alloy-rpc-types", + "op-alloy-consensus 0.23.1", + "op-alloy-rpc-types 0.23.1", "op-revm", "revm", "serde", @@ -5166,6 +5429,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -5181,6 +5454,12 @@ dependencies = [ "libc", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "2.0.0" @@ -5487,7 +5766,7 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "zerocopy", + "zerocopy 0.8.31", ] [[package]] @@ -5569,6 +5848,12 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "hidapi-rusb" version = "1.3.3" @@ -5746,6 +6031,22 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.19" @@ -6038,6 +6339,16 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +[[package]] +name = "inline-array" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4213ac9a8f085582112110fbf2a49b64c4394e3c609dbcbcca6f5f33c009651" +dependencies = [ + "concurrent-map", + "serde", +] + [[package]] name = "inotify" version = "0.11.0" @@ -6781,6 +7092,40 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "moka" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid 1.19.0", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework 2.11.1", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk-context" version = "0.1.1" @@ -7135,17 +7480,48 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "op-alloy" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b13412d297c1f9341f678b763750b120a73ffe998fa54a94d6eda98449e7ca" +dependencies = [ + "op-alloy-consensus 0.22.4", + "op-alloy-network 0.22.4", + "op-alloy-provider 0.22.4", + "op-alloy-rpc-types 0.22.4", + "op-alloy-rpc-types-engine 0.22.4", +] + [[package]] name = "op-alloy" version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9b8fee21003dd4f076563de9b9d26f8c97840157ef78593cd7f262c5ca99848" dependencies = [ - "op-alloy-consensus", - "op-alloy-network", - "op-alloy-provider", - "op-alloy-rpc-types", - "op-alloy-rpc-types-engine", + "op-alloy-consensus 0.23.1", + "op-alloy-network 0.23.1", + "op-alloy-provider 0.23.1", + "op-alloy-rpc-types 0.23.1", + "op-alloy-rpc-types-engine 0.23.1", +] + +[[package]] +name = "op-alloy-consensus" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726da827358a547be9f1e37c2a756b9e3729cb0350f43408164794b370cad8ae" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth", + "alloy-serde", + "derive_more", + "serde", + "thiserror 2.0.17", ] [[package]] @@ -7173,6 +7549,22 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a79f352fc3893dcd670172e615afef993a41798a1d3fc0db88a3e60ef2e70ecc" +[[package]] +name = "op-alloy-network" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63f27e65be273ec8fcb0b6af0fd850b550979465ab93423705ceb3dfddbd2ab" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-signer", + "op-alloy-consensus 0.22.4", + "op-alloy-rpc-types 0.22.4", +] + [[package]] name = "op-alloy-network" version = "0.23.1" @@ -7185,8 +7577,23 @@ dependencies = [ "alloy-provider", "alloy-rpc-types-eth", "alloy-signer", - "op-alloy-consensus", - "op-alloy-rpc-types", + "op-alloy-consensus 0.23.1", + "op-alloy-rpc-types 0.23.1", +] + +[[package]] +name = "op-alloy-provider" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a71456699aa256dc20119736422ad9a44da8b9585036117afb936778122093b9" +dependencies = [ + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-engine", + "alloy-transport", + "async-trait", + "op-alloy-rpc-types-engine 0.22.4", ] [[package]] @@ -7201,7 +7608,26 @@ dependencies = [ "alloy-rpc-types-engine", "alloy-transport", "async-trait", - "op-alloy-rpc-types-engine", + "op-alloy-rpc-types-engine 0.23.1", +] + +[[package]] +name = "op-alloy-rpc-types" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562dd4462562c41f9fdc4d860858c40e14a25df7f983ae82047f15f08fce4d19" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "derive_more", + "op-alloy-consensus 0.22.4", + "serde", + "serde_json", + "thiserror 2.0.17", ] [[package]] @@ -7217,12 +7643,33 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-serde", "derive_more", - "op-alloy-consensus", + "op-alloy-consensus 0.23.1", "serde", "serde_json", "thiserror 2.0.17", ] +[[package]] +name = "op-alloy-rpc-types-engine" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f24b8cb66e4b33e6c9e508bf46b8ecafc92eadd0b93fedd306c0accb477657" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-engine", + "alloy-serde", + "derive_more", + "ethereum_ssz 0.9.1", + "ethereum_ssz_derive", + "op-alloy-consensus 0.22.4", + "serde", + "snap", + "thiserror 2.0.17", +] + [[package]] name = "op-alloy-rpc-types-engine" version = "0.23.1" @@ -7238,7 +7685,7 @@ dependencies = [ "derive_more", "ethereum_ssz 0.9.1", "ethereum_ssz_derive", - "op-alloy-consensus", + "op-alloy-consensus 0.23.1", "serde", "sha2", "snap", @@ -7267,12 +7714,50 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -7304,6 +7789,12 @@ dependencies = [ "sha2", ] +[[package]] +name = "pagetable" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b57830c885fc057ecbf2f1f99f0427c3d102cf2ee5e80a52c09948d45a460e" + [[package]] name = "parity-scale-codec" version = "3.7.5" @@ -7703,7 +8194,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy", + "zerocopy 0.8.31", ] [[package]] @@ -8134,6 +8625,19 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.8.5" @@ -8177,6 +8681,21 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.6.4" @@ -8256,6 +8775,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "recvmsg" version = "1.0.0" @@ -8347,6 +8875,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "reqwest" version = "0.12.26" @@ -8365,11 +8902,13 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", + "hyper-tls", "hyper-util", "js-sys", "log", "mime", "mime_guess", + "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -8381,6 +8920,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -8402,7 +8942,7 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-eips", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-genesis", "alloy-primitives", "alloy-trie", @@ -8426,7 +8966,7 @@ dependencies = [ "alloy-trie", "bytes", "modular-bitfield", - "op-alloy-consensus", + "op-alloy-consensus 0.23.1", "reth-codecs-derive", "reth-zstd-compressors", "serde", @@ -8487,7 +9027,7 @@ version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ "alloy-eip2124", - "alloy-hardforks", + "alloy-hardforks 0.4.5", "alloy-primitives", "auto_impl", "once_cell", @@ -8519,7 +9059,7 @@ source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab6077 dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-primitives", "auto_impl", "derive_more", @@ -8538,7 +9078,7 @@ name = "reth-execution-errors" version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ - "alloy-evm", + "alloy-evm 0.25.2", "alloy-primitives", "alloy-rlp", "nybbles", @@ -8553,7 +9093,7 @@ source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab6077 dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-primitives", "derive_more", "reth-ethereum-primitives", @@ -8592,7 +9132,7 @@ dependencies = [ "derive_more", "modular-bitfield", "once_cell", - "op-alloy-consensus", + "op-alloy-consensus 0.23.1", "reth-codecs", "revm-bytecode", "revm-primitives", @@ -8623,7 +9163,7 @@ version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ "alloy-consensus", - "alloy-evm", + "alloy-evm 0.25.2", "alloy-json-rpc", "alloy-network", "alloy-primitives", @@ -8726,7 +9266,7 @@ name = "reth-zstd-compressors" version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ - "zstd", + "zstd 0.13.3", ] [[package]] @@ -9202,7 +9742,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.5.1", ] [[package]] @@ -9445,6 +9985,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework" version = "3.5.1" @@ -9714,6 +10267,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-local-state" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a50ccb2f45251772ed15abfd1e5f10a305288187b1582ab2e4295b29bbb4929" +dependencies = [ + "parking_lot", +] + [[package]] name = "shell-words" version = "1.1.1" @@ -9816,6 +10378,33 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +[[package]] +name = "sled" +version = "1.0.0-alpha.124" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863ddb1887c62f8dad18635f6096876c648923e61962057058f92228fee2308f" +dependencies = [ + "bincode", + "cache-advisor", + "concurrent-map", + "crc32fast", + "crossbeam-channel", + "crossbeam-queue", + "ebr", + "fault-injection", + "fnv", + "fs2", + "inline-array", + "log", + "pagetable", + "parking_lot", + "rayon", + "serde", + "stack-map", + "tempdir", + "zstd 0.12.4", +] + [[package]] name = "small_btree" version = "0.1.0" @@ -10114,6 +10703,15 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "stack-map" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49d6d36fee60faad91e23603db2356677b58ec2429237b39d5c60c26868f37c" +dependencies = [ + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -10405,12 +11003,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0e973b34477b7823833469eb0f5a3a60370fef7a453e02d751b59180d0a5a05" +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand 0.4.6", + "remove_dir_all", +] + [[package]] name = "tempfile" version = "3.23.0" @@ -10689,6 +11303,16 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -12288,13 +12912,34 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + [[package]] name = "zerocopy" version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ - "zerocopy-derive", + "zerocopy-derive 0.8.31", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", ] [[package]] @@ -12426,13 +13071,32 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe 6.0.6", +] + [[package]] name = "zstd" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ - "zstd-safe", + "zstd-safe 7.2.4", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d940142e8d04c..dbeac987c0358 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -464,4 +464,4 @@ rexpect = { git = "https://github.com/rust-cli/rexpect", rev = "2ed0b1898d7edaf6 solar = { package = "solar-compiler", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } solar-interface = { package = "solar-interface", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } solar-ast = { package = "solar-ast", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } -solar-sema = { package = "solar-sema", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } \ No newline at end of file +solar-sema = { package = "solar-sema", git = "https://github.com/paradigmxyz/solar.git", rev = "1f28069" } diff --git a/README.md b/README.md index 949b23d30583b..f98a7d7e90ac8 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,7 @@ shall be dual licensed as above, without any additional terms or conditions. [foundry-compilers]: https://github.com/foundry-rs/compilers [ethers-solc]: https://github.com/gakonst/ethers-rs/tree/master/ethers-solc/ [solady]: https://github.com/Vectorized/solady +[openzeppelin]: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/release-v5.1 [morpho-blue]: https://github.com/morpho-org/morpho-blue [solmate]: https://github.com/transmissions11/solmate/ [geb]: https://github.com/reflexer-labs/geb diff --git a/crates/anvil/server/Cargo.toml b/crates/anvil/server/Cargo.toml index 394bcbe8a68e4..c8856939c21f3 100644 --- a/crates/anvil/server/Cargo.toml +++ b/crates/anvil/server/Cargo.toml @@ -30,7 +30,7 @@ futures.workspace = true # ipc interprocess = { version = "2", optional = true, features = ["tokio"] } bytes = { workspace = true, optional = true } -tokio-util = { version = "0.7.15", features = ["codec"], optional = true } +tokio-util = { version = "0.7", features = ["codec"], optional = true } # misc serde_json.workspace = true diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 5d204f7e0823c..ffa60e8656524 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -15,16 +15,12 @@ exclude.workspace = true workspace = true [build-dependencies] -vergen = { workspace = true, default-features = false, features = [ - "build", - "git", - "gitcl", -] } [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "40731c9", features = [ +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", branch = "mateo/update-revm", features = [ "phoundry", ] } +foundry-fork-db.workspace = true #assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} foundry-cheatcodes-spec.workspace = true diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 1b07dca3a2479..807733124b28d 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -20,8 +20,8 @@ sol! { #[sol(abi)] interface Vm { - // Used to execute assertion against the next call or contract creation. - // Will revert if the assertion is not triggered. + /// Used to execute assertion against the next call or contract creation. + /// Will revert if the assertion is not triggered. #[cheatcode(group = Credible, safety = Safe)] function assertion(address adopter, bytes calldata createData, bytes4 fnSelector) external; diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 76ace0b4f0dd2..ab6071f452b56 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,6 +1,7 @@ use crate::{inspector::Ecx, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Bytes, FixedBytes, TxKind}; use alloy_sol_types::{Revert, SolError}; +use foundry_fork_db::DatabaseError; use assertion_executor::{ db::{fork_db::ForkDb, DatabaseCommit, DatabaseRef}, primitives::{ @@ -11,7 +12,7 @@ use assertion_executor::{ ExecutorConfig, }; -use foundry_evm_core::backend::{DatabaseError, DatabaseExt}; +use foundry_evm_core::backend::{DatabaseExt}; use revm::context_interface::{ContextTr, JournalTr}; use std::{ cmp::max, @@ -86,6 +87,7 @@ impl Cheatcode for assertionCall { Ok(Default::default()) } } + #[derive(Debug, Clone)] pub struct Assertion { pub adopter: Address, @@ -114,18 +116,18 @@ pub fn execute_assertion( let state = ecx.journaled_state.state.clone(); let chain_id = ecx.cfg.chain_id; - let nonce = ecx.db().basic(tx_attributes.caller).unwrap_or_default().unwrap_or_default().nonce; + let nonce = ecx.db_mut().basic(tx_attributes.caller).unwrap_or_default().unwrap_or_default().nonce; // Setup assertion database - let db = ThreadSafeDb::new(ecx.db()); + let db = ThreadSafeDb::new(*ecx.db_mut()); // Prepare assertion store - let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: 300_000 }; + let config = ExecutorConfig { spec_id: spec_id.into(), chain_id, assertion_gas_limit: 300_000 }; let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); let mut assertion_state = - AssertionState::new_active(assertion.create_data.clone().into(), &config) + AssertionState::new_active(&Bytes::from_iter(assertion.create_data.clone()), &config) .expect("Failed to create assertion state"); let mut trigger_types_to_remove = Vec::new(); @@ -277,7 +279,7 @@ fn decode_invalidated_assertion(execution_result: &ExecutionResult) -> Revert { mod tests { use super::*; use assertion_executor::primitives::HaltReason; - use revm::context::result::{Output, SuccessReason}; + use revm::context_interface::result::{Output, SuccessReason}; #[test] fn test_decode_revert_error_success() { diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 89717ac50ceda..4d3e19585aa0c 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1068,6 +1068,8 @@ impl Cheatcodes { gas, }, memory_offset: call.return_memory_offset.clone(), + was_precompile_called: false, + precompile_call_logs: vec![], }), }; } From 4781cf0565bc779d48414a34a63704cba92b89b7 Mon Sep 17 00:00:00 2001 From: Mateo <160488334+mateo-mro@users.noreply.github.com> Date: Mon, 22 Dec 2025 12:43:54 +0100 Subject: [PATCH 53/83] feat: Bump assex version to 0.8.1 (#66) --- Cargo.lock | 13 +++++++------ crates/cheatcodes/Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a761c31e983e..9edc9c748b026 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1659,8 +1659,8 @@ dependencies = [ [[package]] name = "assertion-da-client" -version = "0.7.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=mateo%2Fupdate-revm#33c32700e4379cf5878b135f339907c83aa5ce11" +version = "0.9.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.0#b934f6d8367940cdb8b3565b3748d6aec0e59fb9" dependencies = [ "alloy", "assertion-da-core", @@ -1676,8 +1676,8 @@ dependencies = [ [[package]] name = "assertion-da-core" -version = "0.7.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=mateo%2Fupdate-revm#33c32700e4379cf5878b135f339907c83aa5ce11" +version = "0.9.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.0#b934f6d8367940cdb8b3565b3748d6aec0e59fb9" dependencies = [ "alloy", "serde", @@ -1685,8 +1685,8 @@ dependencies = [ [[package]] name = "assertion-executor" -version = "0.7.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=mateo%2Fupdate-revm#33c32700e4379cf5878b135f339907c83aa5ce11" +version = "0.9.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.0#b934f6d8367940cdb8b3565b3748d6aec0e59fb9" dependencies = [ "alloy", "alloy-consensus", @@ -1716,6 +1716,7 @@ dependencies = [ "moka", "op-revm", "parking_lot", + "rapidhash", "rayon", "revm", "serde", diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index ffa60e8656524..37b496b29c3d7 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -17,7 +17,7 @@ workspace = true [build-dependencies] [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", branch = "mateo/update-revm", features = [ +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", tag = "0.9.0", features = [ "phoundry", ] } foundry-fork-db.workspace = true From f5bf969814c44e6a54f8c7b0615abe02c69de787 Mon Sep 17 00:00:00 2001 From: Mateo <160488334+mateo-mro@users.noreply.github.com> Date: Mon, 22 Dec 2025 13:41:33 +0100 Subject: [PATCH 54/83] feat: Improve README with update upstream explanation (#70) --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index f98a7d7e90ac8..7933cc1c3ea08 100644 --- a/README.md +++ b/README.md @@ -338,6 +338,23 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. +## How to update upstream + +The default branch of this repository is `main`. + +To update the upstream repository, run the following commands: + +```terminal +git remote add upstream https://github.com/foundry-rs/foundry.git +git fetch upstream +git checkout main +# Backup branch +git checkout -b upstream-update +git checkout main +git rebase upstream/master +git push --force-with-lease origin main +``` + ## Acknowledgements - Foundry is a clean-room rewrite of the testing framework [DappTools][dapptools]. None of this would have been possible without the DappHub team's work over the years. From 2749a433bb31a5a7b0c55d7a78d9e4b686740fc4 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Mon, 22 Dec 2025 19:42:02 +0100 Subject: [PATCH 55/83] Odysseas/fix/errors (#68) * chore: implement fixes on rebase * fix: revert on gas overflow, but show full gas usage * fix: deny --- crates/cheatcodes/src/credible.rs | 231 ++++++++++++++++++++++-------- deny.toml | 30 +++- 2 files changed, 193 insertions(+), 68 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index ab6071f452b56..b2f73e1e9f783 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,18 +1,18 @@ -use crate::{inspector::Ecx, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*, inspector::Ecx}; use alloy_primitives::{Bytes, FixedBytes, TxKind}; -use alloy_sol_types::{Revert, SolError}; -use foundry_fork_db::DatabaseError; use assertion_executor::{ - db::{fork_db::ForkDb, DatabaseCommit, DatabaseRef}, + ExecutorConfig, + db::{DatabaseCommit, DatabaseRef, fork_db::ForkDb}, primitives::{ - AccountInfo, Address, AssertionFunctionExecutionResult, Bytecode, ExecutionResult, TxEnv, - B256, U256, + AccountInfo, Address, AssertionFunctionExecutionResult, B256, Bytecode, ExecutionResult, + TxEnv, U256, }, store::{AssertionState, AssertionStore}, - ExecutorConfig, }; +use foundry_evm_core::{ContextExt, decode::RevertDecoder}; +use foundry_fork_db::DatabaseError; -use foundry_evm_core::backend::{DatabaseExt}; +use foundry_evm_core::backend::DatabaseExt; use revm::context_interface::{ContextTr, JournalTr}; use std::{ cmp::max, @@ -103,6 +103,24 @@ pub struct TxAttributes { pub kind: TxKind, } +/// Maximum gas allowed for assertion execution (300k gas). +/// Assertions exceeding this limit will cause the test to fail. +const ASSERTION_GAS_LIMIT: u64 = 300_000; + +/// Checks if the assertion gas usage is within the allowed limit. +/// Returns a detailed log message if the limit is exceeded, None otherwise. +fn check_assertion_gas_limit(gas_used: u64) -> Option { + if gas_used > ASSERTION_GAS_LIMIT { + let over_by = gas_used - ASSERTION_GAS_LIMIT; + let over_percent = (over_by as f64 / ASSERTION_GAS_LIMIT as f64) * 100.0; + Some(format!( + "Assertion used {gas_used} gas, exceeding limit of {ASSERTION_GAS_LIMIT} by {over_by} ({over_percent:.1}% over)" + )) + } else { + None + } +} + /// Used to handle assertion execution in inspector in calls after the cheatcode was called. pub fn execute_assertion( assertion: &Assertion, @@ -116,32 +134,38 @@ pub fn execute_assertion( let state = ecx.journaled_state.state.clone(); let chain_id = ecx.cfg.chain_id; - let nonce = ecx.db_mut().basic(tx_attributes.caller).unwrap_or_default().unwrap_or_default().nonce; + let (db, journal, _) = ecx.as_db_env_and_journal(); + let nonce = journal + .load_account(db, tx_attributes.caller) + .map(|acc| acc.info.nonce) + .unwrap_or(0); // Setup assertion database let db = ThreadSafeDb::new(*ecx.db_mut()); // Prepare assertion store - let config = ExecutorConfig { spec_id: spec_id.into(), chain_id, assertion_gas_limit: 300_000 }; + let config = + ExecutorConfig { spec_id: spec_id.into(), chain_id, assertion_gas_limit: u64::MAX }; let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); + if assertion.create_data.is_empty() { + bail!("Assertion bytecode is empty"); + } + let mut assertion_state = AssertionState::new_active(&Bytes::from_iter(assertion.create_data.clone()), &config) .expect("Failed to create assertion state"); - let mut trigger_types_to_remove = Vec::new(); - // Filter triggers for one fn selector - for (trigger_type, fn_selectors) in assertion_state.trigger_recorder.triggers.iter_mut() { + // Filter triggers to only keep those matching our fn_selector + assertion_state.trigger_recorder.triggers.retain(|_, fn_selectors| { if fn_selectors.contains(&assertion.fn_selector) { *fn_selectors = HashSet::from_iter([assertion.fn_selector]); + true } else { - trigger_types_to_remove.push(trigger_type.clone()); + false } - } - for trigger_type in trigger_types_to_remove { - assertion_state.trigger_recorder.triggers.remove(&trigger_type); - } + }); store.insert(assertion.adopter, assertion_state).expect("Failed to store assertions"); let tx_env = TxEnv { @@ -169,18 +193,19 @@ pub fn execute_assertion( // TODO: Remove this once we have a proper way to handle this. let mut ext_db = revm::database::WrapDatabaseRef(fork_db.clone()); - // Store assertions + // Execute assertion validation let tx_validation = assertion_executor - .validate_transaction_ext_db(block.clone(), tx_env.clone(), &mut fork_db, &mut ext_db) + .validate_transaction_ext_db(block, tx_env, &mut fork_db, &mut ext_db) .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; let mut inspector = executor.get_inspector(cheats); // if transaction execution reverted, log the revert reason if !tx_validation.result_and_state.result.is_success() { inspector.console_log(&format!( - "Transaction reverted: {}", - decode_invalidated_assertion(&tx_validation.result_and_state.result).reason() + "Mock Transaction Revert Reason: {}", + decode_invalidated_assertion(&tx_validation.result_and_state.result) )); + bail!("Mock Transaction Reverted"); } // else get information about the assertion execution @@ -194,11 +219,17 @@ pub fn execute_assertion( // test evm in this case. ecx.journaled_state.inner.checkpoint(); + // Drop inspector first to release the borrow on cheats std::mem::drop(inspector); if let Some(expected) = &mut cheats.expected_revert { expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); } - bail!("Expected 1 assertion to be executed, but {total_assertions_ran} were executed."); + // Get a new inspector for logging + let mut inspector = executor.get_inspector(cheats); + inspector.console_log(&format!( + "Expected 1 assertion fn to be executed, but {total_assertions_ran} were executed." + )); + bail!("Assertion Fn number mismatch"); } //Expect is safe because we validate above that 1 assertion was ran. @@ -219,10 +250,9 @@ pub fn execute_assertion( } } - let assertion_gas_message = format!( - "Transaction gas cost: {tx_gas_used}\n Assertion gas cost: {total_assertion_gas}\n " - ); - inspector.console_log(&assertion_gas_message); + inspector.console_log(&format!( + "Transaction gas cost: {tx_gas_used}\n Assertion gas cost: {total_assertion_gas}" + )); // Drop the inspector to avoid borrow checker issues std::mem::drop(inspector); @@ -237,53 +267,56 @@ pub fn execute_assertion( } let mut inspector = executor.get_inspector(cheats); - match &assertion_fn_result.result { - AssertionFunctionExecutionResult::AssertionContractDeployFailure(result) => { - inspector.console_log(&format!( - "Assertion contract deploy failed: {}", - decode_invalidated_assertion(&result).reason() - )); - let output = result.output().unwrap_or_default(); - return Err(crate::Error::from(output.clone())); + let (msg, result) = match &assertion_fn_result.result { + AssertionFunctionExecutionResult::AssertionContractDeployFailure(r) => { + ("Assertion contract deploy failed", r) } - AssertionFunctionExecutionResult::AssertionExecutionResult(result) => { - inspector.console_log(&format!( - "Assertion function reverted: {}", - decode_invalidated_assertion(&result).reason() - )); - let output = result.output().unwrap_or_default(); - return Err(crate::Error::from(output.clone())); + AssertionFunctionExecutionResult::AssertionExecutionResult(r) => { + ("Assertion function reverted", r) } - } + }; + inspector.console_log(&format!("{msg}: {}", decode_invalidated_assertion(result))); + return Err(crate::Error::from(result.output().unwrap_or_default().clone())); + } + + if let Some(log_msg) = check_assertion_gas_limit(total_assertion_gas) { + let mut inspector = executor.get_inspector(cheats); + inspector.console_log(&log_msg); + bail!("Assertion exceeded gas limit"); } + Ok(()) } -fn decode_invalidated_assertion(execution_result: &ExecutionResult) -> Revert { - let result = execution_result; +/// Decodes revert data from an assertion execution result. +/// Uses foundry's RevertDecoder to handle all revert types: +/// - Error(string) from revert()/require() +/// - Panic(uint256) from assert()/overflow/etc +/// - Custom errors +/// - Raw bytes as fallback +fn decode_invalidated_assertion(result: &ExecutionResult) -> String { match result { - ExecutionResult::Success{..} => Revert { - reason: "Tried to decode invalidated assertion, but result was success. This is a bug in phoundry. Please report to the Phylax team.".to_string(), - }, - ExecutionResult::Revert{output, ..} => { - Revert::abi_decode(output) - .unwrap_or(Revert::new(("Unknown Revert Reason".to_string(),))) - }, - ExecutionResult::Halt{reason, ..} => Revert { - reason: format!("Halt reason: {reason:#?}"), - }, + ExecutionResult::Success { .. } => { + "Tried to decode invalidated assertion, but result was success. \ + This is a bug in phoundry. Please report to the Phylax team." + .to_string() + } + ExecutionResult::Revert { output, .. } => RevertDecoder::default().decode(output, None), + ExecutionResult::Halt { reason, .. } => { + format!("Halt reason: {reason:#?}") + } } } #[cfg(test)] mod tests { use super::*; + use alloy_sol_types::{Revert, SolError}; use assertion_executor::primitives::HaltReason; use revm::context_interface::result::{Output, SuccessReason}; #[test] fn test_decode_revert_error_success() { - // Test case 1: When result is success let result = ExecutionResult::Success { gas_used: 0, gas_refunded: 0, @@ -291,8 +324,8 @@ mod tests { output: Output::Call(Bytes::new()), reason: SuccessReason::Return, }; - let revert = decode_invalidated_assertion(&result); - assert_eq!(revert.reason(), "Tried to decode invalidated assertion, but result was success. This is a bug in phoundry. Please report to the Phylax team."); + let decoded = decode_invalidated_assertion(&result); + assert!(decoded.contains("bug in phoundry")); } #[test] @@ -300,16 +333,90 @@ mod tests { let revert_reason = "Something is a bit fky wuky"; let revert_output = Revert::new((revert_reason.to_string(),)).abi_encode(); let result = ExecutionResult::Revert { output: revert_output.into(), gas_used: 0 }; - let revert = decode_invalidated_assertion(&result); - assert_eq!(revert.reason(), revert_reason); + let decoded = decode_invalidated_assertion(&result); + assert_eq!(decoded, revert_reason); + } + + #[test] + fn test_decode_revert_panic() { + // Panic(uint256) with code 0x01 (assertion failed) + let panic_output = alloy_sol_types::Panic::from(0x01).abi_encode(); + let result = ExecutionResult::Revert { output: panic_output.into(), gas_used: 0 }; + let decoded = decode_invalidated_assertion(&result); + assert!(decoded.contains("Panic") || decoded.contains("panic")); + } + + #[test] + fn test_decode_revert_raw_bytes() { + // Raw bytes that don't match any known format + let raw_bytes = vec![0xde, 0xad, 0xbe, 0xef]; + let result = ExecutionResult::Revert { output: raw_bytes.into(), gas_used: 0 }; + let decoded = decode_invalidated_assertion(&result); + // Should contain hex representation + assert!(decoded.contains("deadbeef") || decoded.contains("custom error")); } #[test] fn test_decode_revert_error_halt() { let halt_reason = HaltReason::CallTooDeep; let result = ExecutionResult::Halt { reason: halt_reason, gas_used: 0 }; + let decoded = decode_invalidated_assertion(&result); + assert_eq!(decoded, "Halt reason: CallTooDeep"); + } + + #[test] + fn test_assertion_gas_limit_constant() { + // Ensure the gas limit is set to the expected value (300k) + assert_eq!(ASSERTION_GAS_LIMIT, 300_000); + } + + #[test] + fn test_check_gas_limit_under() { + // Gas usage under limit should return None + assert!(check_assertion_gas_limit(100_000).is_none()); + assert!(check_assertion_gas_limit(299_999).is_none()); + } + + #[test] + fn test_check_gas_limit_exact() { + // Gas usage exactly at limit should return None + assert!(check_assertion_gas_limit(300_000).is_none()); + } + + #[test] + fn test_check_gas_limit_over() { + // Gas usage over limit should return error message with details + let result = check_assertion_gas_limit(450_000); + assert!(result.is_some()); + let msg = result.unwrap(); + // Should contain: gas used, limit, absolute over, percentage + assert!(msg.contains("450000"), "should contain gas used"); + assert!(msg.contains("300000"), "should contain limit"); + assert!(msg.contains("150000"), "should contain absolute over amount"); + assert!(msg.contains("50.0%"), "should contain percentage over"); + } + + #[test] + fn test_check_gas_limit_over_small() { + // Just 1 gas over the limit + let result = check_assertion_gas_limit(300_001); + assert!(result.is_some()); + let msg = result.unwrap(); + assert!(msg.contains("300001")); + assert!(msg.contains("by 1")); + assert!(msg.contains("0.0%")); // 1/300000 ≈ 0.0003% + } + + #[test] + fn test_check_gas_limit_zero() { + // Zero gas should be fine + assert!(check_assertion_gas_limit(0).is_none()); + } - let revert = decode_invalidated_assertion(&result); - assert_eq!(revert.reason(), "Halt reason: CallTooDeep"); + #[test] + fn test_check_gas_limit_max() { + // Max u64 should definitely exceed + let result = check_assertion_gas_limit(u64::MAX); + assert!(result.is_some()); } } diff --git a/deny.toml b/deny.toml index dfe4f0128f313..08d1aa65335dd 100644 --- a/deny.toml +++ b/deny.toml @@ -9,6 +9,12 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. "RUSTSEC-2024-0437", + # https://rustsec.org/advisories/RUSTSEC-2023-0018 remove_dir_all vulnerability + # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. + "RUSTSEC-2023-0018", + # https://rustsec.org/advisories/RUSTSEC-2018-0017 tempdir deprecated + # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. + "RUSTSEC-2018-0017", ] # This section is considered when running `cargo deny check bans`. @@ -21,7 +27,11 @@ multiple-versions = "allow" wildcards = "allow" highlight = "all" # List of crates to deny -deny = [{ name = "openssl" }] +deny = [ + # openssl is banned but allowed when wrapped by native-tls + # (transitive dep from assertion-executor -> alloy -> reqwest -> native-tls) + { name = "openssl", wrappers = ["native-tls"] }, +] # Certain crates/versions that will be skipped when doing duplicate detection. skip = [] # Similarly to `skip` allows you to skip certain crates during duplicate @@ -69,6 +79,16 @@ exceptions = [ { allow = ["CC0-1.0"], name = "dunce" }, { allow = ["CC0-1.0"], name = "aurora-engine-modexp" }, ] + +# Crates from credible-sdk and evm-glue don't have license fields +# These are internal/trusted dependencies - ignore unlicensed crates from these sources +[licenses.private] +ignore = true +registries = [] +ignore-sources = [ + "https://github.com/phylaxsystems/credible-sdk", + "https://git@github.com/Philogy/evm-glue", +] # copyleft = "deny" # See note in unicode-ident's readme! @@ -95,16 +115,14 @@ unknown-registry = "warn" # in the allow list is encountered unknown-git = "deny" allow-git = [ - "https://github.com/alloy-rs/alloy", - "https://github.com/foundry-rs/compilers", - "https://github.com/foundry-rs/foundry-fork-db", - "https://github.com/paradigmxyz/revm-inspectors", "https://github.com/paradigmxyz/solar", - "https://github.com/bluealloy/revm", # Only for tests. "https://github.com/rust-cli/rexpect", # Tempo "https://github.com/tempoxyz/tempo", # Transitive dependency of Tempo "https://github.com/paradigmxyz/reth", + # Assertion executor and its dependencies + "https://github.com/phylaxsystems/credible-sdk", + "https://git@github.com/Philogy/evm-glue", ] From d186e89dfd2707b2ecf68145c1f96fd5f2932a03 Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Wed, 24 Dec 2025 12:19:36 +0100 Subject: [PATCH 56/83] fix: use new hashmap ephemeral (#71) * fix: use new hashmap ephemeral * chore: bump assertion executor * nit: mock transaction revert reason in revert msg --- Cargo.lock | 273 +++++------------------------- crates/cheatcodes/Cargo.toml | 4 +- crates/cheatcodes/src/credible.rs | 17 +- 3 files changed, 51 insertions(+), 243 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9edc9c748b026..15687e1dc6338 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,7 +38,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "version_check", - "zerocopy 0.8.31", + "zerocopy", ] [[package]] @@ -293,27 +293,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "alloy-evm" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01be36ba6f5e6e62563b369e03ca529eac46aea50677f84655084b4750816574" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-hardforks 0.4.5", - "alloy-primitives", - "alloy-rpc-types-engine", - "alloy-rpc-types-eth", - "alloy-sol-types", - "auto_impl", - "derive_more", - "op-alloy 0.22.4", - "op-revm", - "revm", - "thiserror 2.0.17", -] - [[package]] name = "alloy-evm" version = "0.25.2" @@ -330,7 +309,7 @@ dependencies = [ "alloy-sol-types", "auto_impl", "derive_more", - "op-alloy 0.23.1", + "op-alloy", "op-revm", "revm", "thiserror 2.0.17", @@ -472,11 +451,11 @@ checksum = "0f640da852f93ddaa3b9a602b7ca41d80e0023f77a67b68aaaf511c32f1fe0ce" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-op-hardforks", "alloy-primitives", "auto_impl", - "op-alloy 0.23.1", + "op-alloy", "op-revm", "revm", "thiserror 2.0.17", @@ -1217,7 +1196,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-eip5792", "alloy-eips", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-genesis", "alloy-network", "alloy-op-evm", @@ -1257,8 +1236,8 @@ dependencies = [ "futures", "hyper", "itertools 0.14.0", - "op-alloy-consensus 0.23.1", - "op-alloy-rpc-types 0.23.1", + "op-alloy-consensus", + "op-alloy-rpc-types", "op-revm", "parking_lot", "rand 0.8.5", @@ -1659,8 +1638,8 @@ dependencies = [ [[package]] name = "assertion-da-client" -version = "0.9.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.0#b934f6d8367940cdb8b3565b3748d6aec0e59fb9" +version = "0.9.2" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.2#ed8c0fa7d9cdbbc4abc1e6031c959b46c52a2a2e" dependencies = [ "alloy", "assertion-da-core", @@ -1676,8 +1655,8 @@ dependencies = [ [[package]] name = "assertion-da-core" -version = "0.9.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.0#b934f6d8367940cdb8b3565b3748d6aec0e59fb9" +version = "0.9.2" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.2#ed8c0fa7d9cdbbc4abc1e6031c959b46c52a2a2e" dependencies = [ "alloy", "serde", @@ -1685,23 +1664,20 @@ dependencies = [ [[package]] name = "assertion-executor" -version = "0.9.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.0#b934f6d8367940cdb8b3565b3748d6aec0e59fb9" +version = "0.9.2" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.2#ed8c0fa7d9cdbbc4abc1e6031c959b46c52a2a2e" dependencies = [ "alloy", "alloy-consensus", - "alloy-evm 0.24.2", + "alloy-evm", "alloy-network", "alloy-network-primitives", "alloy-node-bindings", "alloy-primitives", "alloy-provider", - "alloy-pubsub", - "alloy-rpc-client", "alloy-rpc-types", "alloy-rpc-types-anvil", "alloy-signer", - "alloy-signer-local", "alloy-sol-types", "alloy-transport", "alloy-transport-ws", @@ -1710,12 +1686,9 @@ dependencies = [ "clap", "dashmap", "enum-as-inner", - "evm-glue", "futures", "metrics", - "moka", "op-revm", - "parking_lot", "rapidhash", "rayon", "revm", @@ -1725,10 +1698,7 @@ dependencies = [ "tempfile", "thiserror 2.0.17", "tokio", - "tokio-util", "tracing", - "url", - "zerocopy 0.7.35", ] [[package]] @@ -4277,15 +4247,6 @@ dependencies = [ "hex", ] -[[package]] -name = "evm-glue" -version = "0.1.0" -source = "git+https://git@github.com/Philogy/evm-glue.git?rev=6be3e8c89a7d193b591ca0415ec2a48b1540c01e#6be3e8c89a7d193b591ca0415ec2a48b1540c01e" -dependencies = [ - "hex", - "hex-literal", -] - [[package]] name = "evmole" version = "0.8.1" @@ -4766,7 +4727,7 @@ dependencies = [ "alloy-consensus", "alloy-dyn-abi", "alloy-ens", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-genesis", "alloy-json-abi", "alloy-network", @@ -5112,7 +5073,7 @@ name = "foundry-evm" version = "1.5.1" dependencies = [ "alloy-dyn-abi", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-json-abi", "alloy-primitives", "alloy-rpc-types", @@ -5158,7 +5119,7 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-dyn-abi", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-genesis", "alloy-hardforks 0.4.5", "alloy-json-abi", @@ -5238,7 +5199,7 @@ name = "foundry-evm-networks" version = "1.5.1" dependencies = [ "alloy-chains", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-primitives", "clap", "revm", @@ -5327,7 +5288,7 @@ name = "foundry-primitives" version = "1.5.1" dependencies = [ "alloy-consensus", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-network", "alloy-primitives", "alloy-rlp", @@ -5335,8 +5296,8 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-serde", "derive_more", - "op-alloy-consensus 0.23.1", - "op-alloy-rpc-types 0.23.1", + "op-alloy-consensus", + "op-alloy-rpc-types", "op-revm", "revm", "serde", @@ -5767,7 +5728,7 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "zerocopy 0.8.31", + "zerocopy", ] [[package]] @@ -5849,12 +5810,6 @@ dependencies = [ "arrayvec", ] -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - [[package]] name = "hidapi-rusb" version = "1.3.3" @@ -7093,23 +7048,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "moka" -version = "0.12.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a" -dependencies = [ - "crossbeam-channel", - "crossbeam-epoch", - "crossbeam-utils", - "equivalent", - "parking_lot", - "portable-atomic", - "smallvec", - "tagptr", - "uuid 1.19.0", -] - [[package]] name = "native-tls" version = "0.2.14" @@ -7481,48 +7419,17 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "op-alloy" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b13412d297c1f9341f678b763750b120a73ffe998fa54a94d6eda98449e7ca" -dependencies = [ - "op-alloy-consensus 0.22.4", - "op-alloy-network 0.22.4", - "op-alloy-provider 0.22.4", - "op-alloy-rpc-types 0.22.4", - "op-alloy-rpc-types-engine 0.22.4", -] - [[package]] name = "op-alloy" version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9b8fee21003dd4f076563de9b9d26f8c97840157ef78593cd7f262c5ca99848" dependencies = [ - "op-alloy-consensus 0.23.1", - "op-alloy-network 0.23.1", - "op-alloy-provider 0.23.1", - "op-alloy-rpc-types 0.23.1", - "op-alloy-rpc-types-engine 0.23.1", -] - -[[package]] -name = "op-alloy-consensus" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726da827358a547be9f1e37c2a756b9e3729cb0350f43408164794b370cad8ae" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-network", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", - "derive_more", - "serde", - "thiserror 2.0.17", + "op-alloy-consensus", + "op-alloy-network", + "op-alloy-provider", + "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", ] [[package]] @@ -7550,22 +7457,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a79f352fc3893dcd670172e615afef993a41798a1d3fc0db88a3e60ef2e70ecc" -[[package]] -name = "op-alloy-network" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63f27e65be273ec8fcb0b6af0fd850b550979465ab93423705ceb3dfddbd2ab" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-provider", - "alloy-rpc-types-eth", - "alloy-signer", - "op-alloy-consensus 0.22.4", - "op-alloy-rpc-types 0.22.4", -] - [[package]] name = "op-alloy-network" version = "0.23.1" @@ -7578,23 +7469,8 @@ dependencies = [ "alloy-provider", "alloy-rpc-types-eth", "alloy-signer", - "op-alloy-consensus 0.23.1", - "op-alloy-rpc-types 0.23.1", -] - -[[package]] -name = "op-alloy-provider" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71456699aa256dc20119736422ad9a44da8b9585036117afb936778122093b9" -dependencies = [ - "alloy-network", - "alloy-primitives", - "alloy-provider", - "alloy-rpc-types-engine", - "alloy-transport", - "async-trait", - "op-alloy-rpc-types-engine 0.22.4", + "op-alloy-consensus", + "op-alloy-rpc-types", ] [[package]] @@ -7609,26 +7485,7 @@ dependencies = [ "alloy-rpc-types-engine", "alloy-transport", "async-trait", - "op-alloy-rpc-types-engine 0.23.1", -] - -[[package]] -name = "op-alloy-rpc-types" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562dd4462562c41f9fdc4d860858c40e14a25df7f983ae82047f15f08fce4d19" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "derive_more", - "op-alloy-consensus 0.22.4", - "serde", - "serde_json", - "thiserror 2.0.17", + "op-alloy-rpc-types-engine", ] [[package]] @@ -7644,33 +7501,12 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-serde", "derive_more", - "op-alloy-consensus 0.23.1", + "op-alloy-consensus", "serde", "serde_json", "thiserror 2.0.17", ] -[[package]] -name = "op-alloy-rpc-types-engine" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f24b8cb66e4b33e6c9e508bf46b8ecafc92eadd0b93fedd306c0accb477657" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-engine", - "alloy-serde", - "derive_more", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", - "op-alloy-consensus 0.22.4", - "serde", - "snap", - "thiserror 2.0.17", -] - [[package]] name = "op-alloy-rpc-types-engine" version = "0.23.1" @@ -7686,7 +7522,7 @@ dependencies = [ "derive_more", "ethereum_ssz 0.9.1", "ethereum_ssz_derive", - "op-alloy-consensus 0.23.1", + "op-alloy-consensus", "serde", "sha2", "snap", @@ -8195,7 +8031,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.31", + "zerocopy", ] [[package]] @@ -8943,7 +8779,7 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-eips", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-genesis", "alloy-primitives", "alloy-trie", @@ -8967,7 +8803,7 @@ dependencies = [ "alloy-trie", "bytes", "modular-bitfield", - "op-alloy-consensus 0.23.1", + "op-alloy-consensus", "reth-codecs-derive", "reth-zstd-compressors", "serde", @@ -9060,7 +8896,7 @@ source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab6077 dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-primitives", "auto_impl", "derive_more", @@ -9079,7 +8915,7 @@ name = "reth-execution-errors" version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ - "alloy-evm 0.25.2", + "alloy-evm", "alloy-primitives", "alloy-rlp", "nybbles", @@ -9094,7 +8930,7 @@ source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab6077 dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-primitives", "derive_more", "reth-ethereum-primitives", @@ -9133,7 +8969,7 @@ dependencies = [ "derive_more", "modular-bitfield", "once_cell", - "op-alloy-consensus 0.23.1", + "op-alloy-consensus", "reth-codecs", "revm-bytecode", "revm-primitives", @@ -9164,7 +9000,7 @@ version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ "alloy-consensus", - "alloy-evm 0.25.2", + "alloy-evm", "alloy-json-rpc", "alloy-network", "alloy-primitives", @@ -11004,12 +10840,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0e973b34477b7823833469eb0f5a3a60370fef7a453e02d751b59180d0a5a05" -[[package]] -name = "tagptr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" - [[package]] name = "tap" version = "1.0.1" @@ -12913,34 +12743,13 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - [[package]] name = "zerocopy" version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ - "zerocopy-derive 0.8.31", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", + "zerocopy-derive", ] [[package]] diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 37b496b29c3d7..4f8beadc44a69 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -17,11 +17,11 @@ workspace = true [build-dependencies] [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", tag = "0.9.0", features = [ +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", tag = "0.9.2", features = [ "phoundry", ] } foundry-fork-db.workspace = true -#assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} +# assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index b2f73e1e9f783..16d34873bad0a 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -20,6 +20,8 @@ use std::{ sync::{Arc, Mutex}, }; +use revm::primitives::eip7825::TX_GAS_LIMIT_CAP; + /// Wrapper around DatabaseExt to make it thread-safe #[derive(Clone)] struct ThreadSafeDb<'a> { @@ -135,19 +137,17 @@ pub fn execute_assertion( let chain_id = ecx.cfg.chain_id; let (db, journal, _) = ecx.as_db_env_and_journal(); - let nonce = journal - .load_account(db, tx_attributes.caller) - .map(|acc| acc.info.nonce) - .unwrap_or(0); + let nonce = + journal.load_account(db, tx_attributes.caller).map(|acc| acc.info.nonce).unwrap_or(0); // Setup assertion database let db = ThreadSafeDb::new(*ecx.db_mut()); // Prepare assertion store let config = - ExecutorConfig { spec_id: spec_id.into(), chain_id, assertion_gas_limit: u64::MAX }; + ExecutorConfig { spec_id: spec_id.into(), chain_id, assertion_gas_limit: TX_GAS_LIMIT_CAP }; - let store = AssertionStore::new_ephemeral().expect("Failed to create assertion store"); + let store = AssertionStore::new_ephemeral(); if assertion.create_data.is_empty() { bail!("Assertion bytecode is empty"); @@ -201,11 +201,10 @@ pub fn execute_assertion( let mut inspector = executor.get_inspector(cheats); // if transaction execution reverted, log the revert reason if !tx_validation.result_and_state.result.is_success() { - inspector.console_log(&format!( - "Mock Transaction Revert Reason: {}", + bail!(format!( + "Mock Transaction Reverted: {}", decode_invalidated_assertion(&tx_validation.result_and_state.result) )); - bail!("Mock Transaction Reverted"); } // else get information about the assertion execution From 9c0a77d5b7a482f45cac2fe84ce9c9491aac704a Mon Sep 17 00:00:00 2001 From: makemake Date: Mon, 5 Jan 2026 16:03:07 +0100 Subject: [PATCH 57/83] fix: fail error message text, respect EIP gas limit for txs (#73) * fix: assertion gas limit to block gas limit * fix: surface overshooting the limit * fix: enforce `TX_GAS_LIMIT_CAP` for `tx_gas_limit` * fix: revert error message for assertion fn run * feat: disable block gas limit check * fix: ci * feat: revert gas clamping --------- Co-authored-by: Odysseas.eth --- crates/cheatcodes/src/credible.rs | 17 ++++++----------- crates/cli/src/opts/global.rs | 5 +---- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 16d34873bad0a..be929462fe839 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -143,9 +143,7 @@ pub fn execute_assertion( let db = ThreadSafeDb::new(*ecx.db_mut()); // Prepare assertion store - - let config = - ExecutorConfig { spec_id: spec_id.into(), chain_id, assertion_gas_limit: TX_GAS_LIMIT_CAP }; + let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: TX_GAS_LIMIT_CAP }; let store = AssertionStore::new_ephemeral(); @@ -168,9 +166,11 @@ pub fn execute_assertion( }); store.insert(assertion.adopter, assertion_state).expect("Failed to store assertions"); + // transaction gas limit should respect new hardfork rules of max 16m gas + let tx_gas_limit = block.gas_limit.min(TX_GAS_LIMIT_CAP); let tx_env = TxEnv { caller: tx_attributes.caller, - gas_limit: block.gas_limit.try_into().unwrap_or(u64::MAX), + gas_limit: tx_gas_limit, gas_price: block.basefee.into(), chain_id: Some(chain_id), value: tx_attributes.value, @@ -223,12 +223,7 @@ pub fn execute_assertion( if let Some(expected) = &mut cheats.expected_revert { expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); } - // Get a new inspector for logging - let mut inspector = executor.get_inspector(cheats); - inspector.console_log(&format!( - "Expected 1 assertion fn to be executed, but {total_assertions_ran} were executed." - )); - bail!("Assertion Fn number mismatch"); + bail!("Expected 1 assertion to be executed, but {total_assertions_ran} were executed."); } //Expect is safe because we validate above that 1 assertion was ran. @@ -244,7 +239,7 @@ pub fn execute_assertion( if !assertion_fn_result.console_logs.is_empty() { inspector.console_log("Assertion function logs: "); - for log in assertion_fn_result.console_logs.iter() { + for log in &assertion_fn_result.console_logs { inspector.console_log(log); } } diff --git a/crates/cli/src/opts/global.rs b/crates/cli/src/opts/global.rs index 7d24db8daf563..5cc478513724e 100644 --- a/crates/cli/src/opts/global.rs +++ b/crates/cli/src/opts/global.rs @@ -1,8 +1,5 @@ use clap::{ArgAction, Parser}; -use foundry_common::{ - shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity}, - version::{IS_NIGHTLY_VERSION, NIGHTLY_VERSION_WARNING_MESSAGE}, -}; +use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity}; use serde::{Deserialize, Serialize}; /// Global arguments for the CLI. From acdd46999759ebfe0b20c934ea92b134d141cdba Mon Sep 17 00:00:00 2001 From: Mateo <160488334+mateo-mro@users.noreply.github.com> Date: Fri, 9 Jan 2026 17:26:28 +0100 Subject: [PATCH 58/83] Fix CI (#74) --- .github/scripts/matrices.py | 4 ++-- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/docker-publish.yml | 2 +- .github/workflows/docs.yml | 4 ++-- deny.toml | 6 ++++++ 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/scripts/matrices.py b/.github/scripts/matrices.py index b60ea7048884d..727fa08893881 100755 --- a/.github/scripts/matrices.py +++ b/.github/scripts/matrices.py @@ -68,10 +68,10 @@ def __init__( profile = os.environ.get("PROFILE") is_pr = os.environ.get("EVENT_NAME") == "pull_request" t_linux_x86 = Target( - "depot-ubuntu-latest-16", "x86_64-unknown-linux-gnu", "linux-amd64" + "ubuntu-latest-16", "x86_64-unknown-linux-gnu", "linux-amd64" ) t_linux_arm = Target( - "depot-ubuntu-latest-arm-16", "aarch64-unknown-linux-gnu", "linux-aarch64" + "ubuntu-latest-arm-16", "aarch64-unknown-linux-gnu", "linux-aarch64" ) t_macos = Target("depot-macos-latest", "aarch64-apple-darwin", "macosx-aarch64") t_windows = Target("depot-windows-latest-16", "x86_64-pc-windows-msvc", "windows-amd64") diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08f9b1a118fa2..e1bce518ef020 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: secrets: inherit doctest: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -50,7 +50,7 @@ jobs: - run: cargo test --workspace --doc typos: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -61,7 +61,7 @@ jobs: - uses: crate-ci/typos@2d0ce569feab1f8752f1dde43cc2f2aa53236e06 # v1 shellcheck: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 5 permissions: contents: read @@ -74,7 +74,7 @@ jobs: run: ./.github/scripts/shellcheck.sh clippy: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -94,7 +94,7 @@ jobs: RUSTFLAGS: -Dwarnings rustfmt: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -109,7 +109,7 @@ jobs: - run: cargo fmt --all --check forge-fmt: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -128,7 +128,7 @@ jobs: run: ./.github/scripts/format.sh --check crate-checks: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 369875f9373b3..8f052baf01ac6 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -30,7 +30,7 @@ env: jobs: build: name: build and push - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest permissions: contents: read id-token: write diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 04a99b63626ee..3191e3debefbb 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,7 +19,7 @@ env: jobs: docs: - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -49,7 +49,7 @@ jobs: deploy-docs: if: github.ref_name == 'master' && github.event_name == 'push' needs: [docs] - runs-on: depot-ubuntu-latest + runs-on: ubuntu-latest timeout-minutes: 30 permissions: pages: write diff --git a/deny.toml b/deny.toml index 08d1aa65335dd..cb3f06295e88e 100644 --- a/deny.toml +++ b/deny.toml @@ -9,9 +9,15 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. "RUSTSEC-2024-0437", + # https://rustsec.org/advisories/RUSTSEC-2025-0141 bincode is unmaintained, need to transition all deps to wincode first + "RUSTSEC-2025-0141", + # https://rustsec.org/advisories/RUSTSEC-2026-0002 lru unused directly: + "RUSTSEC-2026-0002", # https://rustsec.org/advisories/RUSTSEC-2023-0018 remove_dir_all vulnerability # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. "RUSTSEC-2023-0018", + # https://rustsec.org/advisories/RUSTSEC-2025-0137 `reciprocal_mg10` OOB, unused + "RUSTSEC-2025-0137", # https://rustsec.org/advisories/RUSTSEC-2018-0017 tempdir deprecated # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. "RUSTSEC-2018-0017", From 85b466882d790fca8403734453bba6a89a3b306b Mon Sep 17 00:00:00 2001 From: "odysseas.eth" Date: Sat, 17 Jan 2026 00:12:31 +0100 Subject: [PATCH 59/83] Fix assertion tx env gas fields (#76) * Fix assertion tx env gas fields * Use call gas limit in assertion tx env --------- Signed-off-by: odysseas.eth --- crates/cheatcodes/src/credible.rs | 91 ++++++++++++++++++++++++------ crates/cheatcodes/src/inspector.rs | 2 + 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index be929462fe839..003794bbff7be 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -103,6 +103,7 @@ pub struct TxAttributes { pub data: Bytes, pub caller: Address, pub kind: TxKind, + pub gas_limit: u64, } /// Maximum gas allowed for assertion execution (300k gas). @@ -123,6 +124,24 @@ fn check_assertion_gas_limit(gas_used: u64) -> Option { } } +fn build_tx_env( + tx_attributes: TxAttributes, + base_tx_env: &TxEnv, + chain_id: u64, + nonce: u64, +) -> TxEnv { + let tx_gas_limit = tx_attributes.gas_limit.min(TX_GAS_LIMIT_CAP); + let mut tx_env = base_tx_env.clone(); + tx_env.caller = tx_attributes.caller; + tx_env.gas_limit = tx_gas_limit; + tx_env.chain_id = Some(chain_id); + tx_env.value = tx_attributes.value; + tx_env.data = tx_attributes.data; + tx_env.kind = tx_attributes.kind; + tx_env.nonce = nonce; + tx_env +} + /// Used to handle assertion execution in inspector in calls after the cheatcode was called. pub fn execute_assertion( assertion: &Assertion, @@ -135,10 +154,12 @@ pub fn execute_assertion( let block = ecx.block.clone(); let state = ecx.journaled_state.state.clone(); let chain_id = ecx.cfg.chain_id; + let base_tx_env = ecx.tx.clone(); - let (db, journal, _) = ecx.as_db_env_and_journal(); - let nonce = - journal.load_account(db, tx_attributes.caller).map(|acc| acc.info.nonce).unwrap_or(0); + let nonce = { + let (db, journal, _) = ecx.as_db_env_and_journal(); + journal.load_account(db, tx_attributes.caller).map(|acc| acc.info.nonce).unwrap_or(0) + }; // Setup assertion database let db = ThreadSafeDb::new(*ecx.db_mut()); @@ -166,19 +187,8 @@ pub fn execute_assertion( }); store.insert(assertion.adopter, assertion_state).expect("Failed to store assertions"); - // transaction gas limit should respect new hardfork rules of max 16m gas - let tx_gas_limit = block.gas_limit.min(TX_GAS_LIMIT_CAP); - let tx_env = TxEnv { - caller: tx_attributes.caller, - gas_limit: tx_gas_limit, - gas_price: block.basefee.into(), - chain_id: Some(chain_id), - value: tx_attributes.value, - data: tx_attributes.data, - kind: tx_attributes.kind, - nonce, - ..Default::default() - }; + + let tx_env = build_tx_env(tx_attributes, &base_tx_env, chain_id, nonce); let mut assertion_executor = config.build(store); @@ -358,6 +368,55 @@ mod tests { assert_eq!(decoded, "Halt reason: CallTooDeep"); } + #[test] + fn test_build_tx_env_uses_base_gas_fields() { + let base_tx_env = TxEnv { + gas_limit: 50_000, + gas_price: 123, + gas_priority_fee: Some(7), + tx_type: 2, + ..Default::default() + }; + let tx_attributes = TxAttributes { + value: U256::from(1), + data: Bytes::from(vec![0x01, 0x02]), + caller: Address::from([0x11; 20]), + kind: TxKind::Call(Address::from([0x22; 20])), + gas_limit: 40_000, + }; + let tx_env = build_tx_env(tx_attributes, &base_tx_env, 1, 9); + + assert_eq!(tx_env.gas_limit, 40_000); + assert_eq!(tx_env.gas_price, 123); + assert_eq!(tx_env.gas_priority_fee, Some(7)); + assert_eq!(tx_env.tx_type, 2); + assert_eq!(tx_env.chain_id, Some(1)); + assert_eq!(tx_env.nonce, 9); + assert_eq!(tx_env.caller, Address::from([0x11; 20])); + assert_eq!(tx_env.value, U256::from(1)); + assert_eq!(tx_env.data, Bytes::from(vec![0x01, 0x02])); + assert_eq!(tx_env.kind, TxKind::Call(Address::from([0x22; 20]))); + } + + #[test] + fn test_build_tx_env_caps_gas_limit() { + let base_tx_env = TxEnv { + gas_limit: TX_GAS_LIMIT_CAP.saturating_add(1), + gas_price: 1, + ..Default::default() + }; + let tx_attributes = TxAttributes { + value: U256::ZERO, + data: Bytes::new(), + caller: Address::from([0x33; 20]), + kind: TxKind::Call(Address::from([0x44; 20])), + gas_limit: TX_GAS_LIMIT_CAP.saturating_add(1), + }; + let tx_env = build_tx_env(tx_attributes, &base_tx_env, 1, 0); + + assert_eq!(tx_env.gas_limit, TX_GAS_LIMIT_CAP); + } + #[test] fn test_assertion_gas_limit_constant() { // Ensure the gas limit is set to the expected value (300k) diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 4d3e19585aa0c..6eac8e3ab48db 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1051,6 +1051,7 @@ impl Cheatcodes { data: call.input.bytes(ecx), caller: call.caller, kind: TxKind::Call(call.target_address), + gas_limit: call.gas_limit, }; return match crate::credible::execute_assertion( @@ -1790,6 +1791,7 @@ impl Inspector> for Cheatcodes { data: input.init_code(), caller: input.caller(), kind: TxKind::Create, + gas_limit: input.gas_limit(), }; return match crate::credible::execute_assertion( From e161ddce390f75346afe4f2e0052125bf12588d9 Mon Sep 17 00:00:00 2001 From: makemake Date: Fri, 6 Feb 2026 16:32:46 +0100 Subject: [PATCH 60/83] feat: assex tracing (#78) * feat: add assertion tracing support * fix: improve readability * chore: use latest assex --- Cargo.lock | 12 ++-- crates/cheatcodes/Cargo.toml | 7 +-- crates/cheatcodes/src/credible.rs | 87 +++++++++++++++++++++------- crates/cheatcodes/src/inspector.rs | 19 +++++- crates/evm/traces/src/decoder/mod.rs | 36 ++++++++++++ crates/forge/src/cmd/test/mod.rs | 15 ++++- crates/forge/src/result.rs | 11 +++- 7 files changed, 153 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15687e1dc6338..bc5ac8832eb1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1638,8 +1638,8 @@ dependencies = [ [[package]] name = "assertion-da-client" -version = "0.9.2" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.2#ed8c0fa7d9cdbbc4abc1e6031c959b46c52a2a2e" +version = "1.0.7" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=5ace6939c7027f1ba0bcf6f8751904dd4ca4f986#5ace6939c7027f1ba0bcf6f8751904dd4ca4f986" dependencies = [ "alloy", "assertion-da-core", @@ -1655,8 +1655,8 @@ dependencies = [ [[package]] name = "assertion-da-core" -version = "0.9.2" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.2#ed8c0fa7d9cdbbc4abc1e6031c959b46c52a2a2e" +version = "1.0.7" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=5ace6939c7027f1ba0bcf6f8751904dd4ca4f986#5ace6939c7027f1ba0bcf6f8751904dd4ca4f986" dependencies = [ "alloy", "serde", @@ -1664,8 +1664,8 @@ dependencies = [ [[package]] name = "assertion-executor" -version = "0.9.2" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?tag=0.9.2#ed8c0fa7d9cdbbc4abc1e6031c959b46c52a2a2e" +version = "1.0.7" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=5ace6939c7027f1ba0bcf6f8751904dd4ca4f986#5ace6939c7027f1ba0bcf6f8751904dd4ca4f986" dependencies = [ "alloy", "alloy-consensus", diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 4f8beadc44a69..26aa9fcc28478 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -17,11 +17,10 @@ workspace = true [build-dependencies] [dependencies] -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", tag = "0.9.2", features = [ - "phoundry", -] } foundry-fork-db.workspace = true -# assertion-executor = { path = "../../../credible-sdk/crates/assertion-executor", features = ["phoundry"]} +# sdk version 1.0.7 with custom inspector commit +# done to not have cyclical version bumps between sdk and phoundry +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "5ace6939c7027f1ba0bcf6f8751904dd4ca4f986", features = ["phoundry"] } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 003794bbff7be..9253f3c63de39 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -5,11 +5,12 @@ use assertion_executor::{ db::{DatabaseCommit, DatabaseRef, fork_db::ForkDb}, primitives::{ AccountInfo, Address, AssertionFunctionExecutionResult, B256, Bytecode, ExecutionResult, - TxEnv, U256, + TxEnv, TxValidationResult, U256, }, store::{AssertionState, AssertionStore}, }; use foundry_evm_core::{ContextExt, decode::RevertDecoder}; +use foundry_evm_traces::{TraceMode, TracingInspector, TracingInspectorConfig}; use foundry_fork_db::DatabaseError; use foundry_evm_core::backend::DatabaseExt; @@ -22,28 +23,38 @@ use std::{ use revm::primitives::eip7825::TX_GAS_LIMIT_CAP; -/// Wrapper around DatabaseExt to make it thread-safe +/// Wrapper around DatabaseExt to make it thread-safe and 'static. +/// Uses a leaked reference internally to satisfy 'static bounds required by +/// the inspector API. This is safe because the wrapper is only used within +/// a single function scope and the original database outlives this usage. #[derive(Clone)] -struct ThreadSafeDb<'a> { - db: Arc>, +struct ThreadSafeDb { + // Im fine with leaking this because it only lives for the duration + // of assex execution + db: Arc>, } -impl std::fmt::Debug for ThreadSafeDb<'_> { +impl std::fmt::Debug for ThreadSafeDb { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "ThreadSafeDb") } } -/// Separate implementation block for constructor and helper methods -impl<'a> ThreadSafeDb<'a> { - /// Creates a new thread-safe database wrapper - pub fn new(db: &'a mut dyn DatabaseExt) -> Self { - Self { db: Arc::new(Mutex::new(db)) } +impl ThreadSafeDb { + /// Creates a new thread-safe database wrapper by leaking the reference. + /// # Safety + /// The caller must ensure the original database outlives all uses of this wrapper. + pub fn new(db: &mut dyn DatabaseExt) -> Self { + // SAFETY: We transmute the lifetime to 'static. This is safe because: + // 1. ThreadSafeDb is only used within execute_assertion's scope + // 2. The original ecx.db_mut() outlives this entire function + // 3. We don't store ThreadSafeDb beyond this function's execution + let static_ref: &'static mut dyn DatabaseExt = unsafe { std::mem::transmute(db) }; + Self { db: Arc::new(Mutex::new(static_ref)) } } } -/// Keep DatabaseRef implementation separate -impl<'a> DatabaseRef for ThreadSafeDb<'a> { +impl DatabaseRef for ThreadSafeDb { type Error = DatabaseError; fn basic_ref( @@ -155,13 +166,12 @@ pub fn execute_assertion( let state = ecx.journaled_state.state.clone(); let chain_id = ecx.cfg.chain_id; let base_tx_env = ecx.tx.clone(); + let verbosity = cheats.config.evm_opts.verbosity; let nonce = { let (db, journal, _) = ecx.as_db_env_and_journal(); journal.load_account(db, tx_attributes.caller).map(|acc| acc.info.nonce).unwrap_or(0) }; - // Setup assertion database - let db = ThreadSafeDb::new(*ecx.db_mut()); // Prepare assertion store let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: TX_GAS_LIMIT_CAP }; @@ -192,8 +202,10 @@ pub fn execute_assertion( let mut assertion_executor = config.build(store); - // Commit current journal state so that it is available for assertions and - // triggering tx + // Setup assertion database with 'static lifetime (via transmute in ThreadSafeDb::new) + let db = ThreadSafeDb::new(*ecx.db_mut()); + + // Commit current journal state so that it is available for assertions and triggering tx let mut fork_db = ForkDb::new(db.clone()); fork_db.commit(state); @@ -203,10 +215,37 @@ pub fn execute_assertion( // TODO: Remove this once we have a proper way to handle this. let mut ext_db = revm::database::WrapDatabaseRef(fork_db.clone()); - // Execute assertion validation - let tx_validation = assertion_executor - .validate_transaction_ext_db(block, tx_env, &mut fork_db, &mut ext_db) - .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; + // Minimum verbosity for tracing (matches Foundry's -vvv) + const TRACING_VERBOSITY: u8 = 3; + + // Execute assertion validation with optional tracing based on verbosity + let (tx_validation, tracing_inspectors): (TxValidationResult, Option>) = + if verbosity >= TRACING_VERBOSITY { + // Create tracing inspector configured based on verbosity + let tracing_config = TraceMode::Call + .with_verbosity(verbosity) + .into_config() + .unwrap_or_else(TracingInspectorConfig::default_parity); + let tracing_inspector = TracingInspector::new(tracing_config); + + let result_with_inspectors = assertion_executor + .validate_transaction_with_inspector( + block, + &tx_env, + &mut fork_db, + &mut ext_db, + tracing_inspector, + ) + .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; + + (result_with_inspectors.result, Some(result_with_inspectors.inspectors)) + } else { + // No tracing - use the standard path + let result = assertion_executor + .validate_transaction_ext_db(block, &tx_env, &mut fork_db, &mut ext_db) + .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; + (result, None) + }; let mut inspector = executor.get_inspector(cheats); // if transaction execution reverted, log the revert reason @@ -270,6 +309,14 @@ pub fn execute_assertion( expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); } + if let Some(inspectors) = tracing_inspectors { + let traces = inspectors + .into_iter() + .map(|tracing_inspector| tracing_inspector.into_traces()) + .filter(|arena| !arena.nodes().is_empty()); + cheats.push_assertion_traces(traces); + } + let mut inspector = executor.get_inspector(cheats); let (msg, result) = match &assertion_fn_result.result { AssertionFunctionExecutionResult::AssertionContractDeployFailure(r) => { diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 6eac8e3ab48db..1a24b7ed5d8e1 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -44,7 +44,7 @@ use foundry_evm_core::{ evm::{FoundryEvm, new_evm_with_existing_context}, }; use foundry_evm_traces::{ - TracingInspector, TracingInspectorConfig, identifier::SignaturesIdentifier, + CallTraceArena, TracingInspector, TracingInspectorConfig, identifier::SignaturesIdentifier, }; use foundry_wallets::wallet_multi::MultiWallet; use itertools::Itertools; @@ -506,6 +506,9 @@ pub struct Cheatcodes { /// Ignored traces. pub ignored_traces: IgnoredTraces, + /// Assertion traces collected during assertion execution. + assertion_traces: Vec, + /// Addresses with arbitrary storage. pub arbitrary_storage: Option, @@ -572,6 +575,7 @@ impl Cheatcodes { intercept_next_create_call: Default::default(), test_runner: Default::default(), ignored_traces: Default::default(), + assertion_traces: Default::default(), arbitrary_storage: Default::default(), deprecated: Default::default(), wallets: Default::default(), @@ -603,6 +607,19 @@ impl Cheatcodes { self.wallets = Some(wallets); } + /// Stores assertion traces collected during execution. + pub fn push_assertion_traces(&mut self, traces: I) + where + I: IntoIterator, + { + self.assertion_traces.extend(traces); + } + + /// Drains assertion traces for inclusion in test output. + pub fn take_assertion_traces(&mut self) -> Vec { + std::mem::take(&mut self.assertion_traces) + } + /// Adds a delegation to the active delegations list. pub fn add_delegation(&mut self, authorization: SignedAuthorization) { self.active_delegations.push(authorization); diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 4f377fe03c510..51570c239db8f 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -546,6 +546,17 @@ impl CallTraceDecoder { decoded[1] = DynSolValue::String("".to_string()); Some(decoded.iter().map(format_token).collect()) } + "assertion" => { + if self.verbosity >= 5 { + None + } else { + let mut decoded = func.abi_decode_input(&data[SELECTOR_LEN..]).ok()?; + if decoded.len() >= 2 { + decoded[1] = DynSolValue::String("".to_string()); + } + Some(decoded.iter().map(format_token).collect()) + } + } "parseJson" | "parseJsonUint" | "parseJsonUintArray" | @@ -1256,4 +1267,29 @@ mod tests { assert_eq!(result, expected, "Output case failed for: {function_signature}"); } } + + #[test] + fn test_assertion_bytecode_redacted() { + let decoder = CallTraceDecoder::new(); + let function = Function::parse("assertion(address,bytes,bytes4)").unwrap(); + let address = Address::repeat_byte(0x11); + + let mut selector_word = [0u8; 32]; + selector_word[..4].copy_from_slice(&[0x12, 0x34, 0x56, 0x78]); + let selector = B256::from(selector_word); + + let data = function + .abi_encode_input(&[ + DynSolValue::Address(address), + DynSolValue::Bytes(vec![0xde, 0xad, 0xbe, 0xef]), + DynSolValue::FixedBytes(selector, 4), + ]) + .unwrap(); + + let decoded = decoder.decode_cheatcode_inputs(&function, &data).expect("decoded inputs"); + assert_eq!(decoded.len(), 3); + assert_eq!(decoded[0], format_token(&DynSolValue::Address(address))); + assert_eq!(decoded[1], "\"\""); + assert_eq!(decoded[2], format_token(&DynSolValue::FixedBytes(selector, 4))); + } } diff --git a/crates/forge/src/cmd/test/mod.rs b/crates/forge/src/cmd/test/mod.rs index a37a422e6688b..889d839c3f27a 100644 --- a/crates/forge/src/cmd/test/mod.rs +++ b/crates/forge/src/cmd/test/mod.rs @@ -6,7 +6,7 @@ use crate::{ multi_runner::matches_artifact, result::{SuiteResult, TestOutcome, TestStatus}, traces::{ - CallTraceDecoderBuilder, InternalTraceMode, TraceKind, + CallTraceDecoderBuilder, InternalTraceMode, SparsedTraceArena, TraceKind, debug::{ContractSources, DebugTraceIdentifier}, decode_trace_arena, folded_stack_trace, identifier::SignaturesIdentifier, @@ -53,6 +53,16 @@ use std::{ }; use yansi::Paint; +fn assertion_trace_header(arena: &SparsedTraceArena) -> Option { + let signature = + arena.nodes().first()?.trace.decoded.as_ref()?.call_data.as_ref()?.signature.as_str(); + if !signature.starts_with("assertionCall") { + return None; + } + let name = signature.trim_end_matches("()"); + Some(format!("Assertion trace: {name}")) +} + mod filter; mod summary; use crate::{result::TestKind, traces::render_trace_arena_inner}; @@ -661,6 +671,9 @@ impl TestArgs { prune_trace_depth(arena, trace_depth); } + if let Some(header) = assertion_trace_header(arena) { + decoded_traces.push(header); + } decoded_traces.push(render_trace_arena_inner(arena, false, verbosity > 4)); } } diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index 7a0f42846f4c1..de8fc5554a799 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -17,7 +17,7 @@ use foundry_evm::{ decode::SkipReason, executors::{RawCallResult, invariant::InvariantMetrics}, fuzz::{CounterExample, FuzzCase, FuzzFixtures, FuzzTestResult}, - traces::{CallTraceArena, CallTraceDecoder, TraceKind, Traces}, + traces::{CallTraceArena, CallTraceDecoder, SparsedTraceArena, TraceKind, Traces}, }; use serde::{Deserialize, Serialize}; use std::{ @@ -574,7 +574,14 @@ impl TestResult { self.duration = Duration::default(); self.gas_report_traces = Vec::new(); - if let Some(cheatcodes) = raw_call_result.cheatcodes { + if let Some(mut cheatcodes) = raw_call_result.cheatcodes { + let assertion_traces = cheatcodes.take_assertion_traces(); + if !assertion_traces.is_empty() { + self.traces.extend(assertion_traces.into_iter().map(|arena| { + (TraceKind::Execution, SparsedTraceArena { arena, ignored: Default::default() }) + })); + } + self.breakpoints = cheatcodes.breakpoints; self.gas_snapshots = cheatcodes.gas_snapshots; self.deprecated_cheatcodes = cheatcodes.deprecated; From a67a48ebb07e2ddba83e6f9d4770d6a755c204a7 Mon Sep 17 00:00:00 2001 From: makemake Date: Wed, 11 Feb 2026 13:12:17 +0100 Subject: [PATCH 61/83] fix: always trace, proper assertion section (#79) * fix: do tracing regardless * fix: assertion traces section * feat: seprate trigger call --- crates/cheatcodes/src/credible.rs | 22 +++++--- crates/cheatcodes/src/inspector.rs | 16 ++++++ crates/evm/traces/src/lib.rs | 18 +++++++ crates/forge/src/cmd/test/mod.rs | 84 +++++++++++++++++++++++++----- crates/forge/src/result.rs | 12 ++++- crates/script/src/execute.rs | 2 + 6 files changed, 131 insertions(+), 23 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 9253f3c63de39..c172cb971c88c 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -247,6 +247,20 @@ pub fn execute_assertion( (result, None) }; + if let Some(inspectors) = tracing_inspectors { + let mut inspectors = inspectors.into_iter(); + if let Some(trigger_inspector) = inspectors.next() { + let trigger_traces = std::iter::once(trigger_inspector.into_traces()) + .filter(|arena| !arena.nodes().is_empty()); + cheats.push_assertion_trigger_traces(trigger_traces); + } + + let traces = inspectors + .map(|tracing_inspector| tracing_inspector.into_traces()) + .filter(|arena| !arena.nodes().is_empty()); + cheats.push_assertion_traces(traces); + } + let mut inspector = executor.get_inspector(cheats); // if transaction execution reverted, log the revert reason if !tx_validation.result_and_state.result.is_success() { @@ -309,14 +323,6 @@ pub fn execute_assertion( expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); } - if let Some(inspectors) = tracing_inspectors { - let traces = inspectors - .into_iter() - .map(|tracing_inspector| tracing_inspector.into_traces()) - .filter(|arena| !arena.nodes().is_empty()); - cheats.push_assertion_traces(traces); - } - let mut inspector = executor.get_inspector(cheats); let (msg, result) = match &assertion_fn_result.result { AssertionFunctionExecutionResult::AssertionContractDeployFailure(r) => { diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 1a24b7ed5d8e1..89a7a8e12cc78 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -508,6 +508,8 @@ pub struct Cheatcodes { /// Assertion traces collected during assertion execution. assertion_traces: Vec, + /// Trigger call traces collected during assertion execution. + assertion_trigger_traces: Vec, /// Addresses with arbitrary storage. pub arbitrary_storage: Option, @@ -576,6 +578,7 @@ impl Cheatcodes { test_runner: Default::default(), ignored_traces: Default::default(), assertion_traces: Default::default(), + assertion_trigger_traces: Default::default(), arbitrary_storage: Default::default(), deprecated: Default::default(), wallets: Default::default(), @@ -615,11 +618,24 @@ impl Cheatcodes { self.assertion_traces.extend(traces); } + /// Stores trigger call traces collected during assertion execution. + pub fn push_assertion_trigger_traces(&mut self, traces: I) + where + I: IntoIterator, + { + self.assertion_trigger_traces.extend(traces); + } + /// Drains assertion traces for inclusion in test output. pub fn take_assertion_traces(&mut self) -> Vec { std::mem::take(&mut self.assertion_traces) } + /// Drains trigger call traces for inclusion in test output. + pub fn take_assertion_trigger_traces(&mut self) -> Vec { + std::mem::take(&mut self.assertion_trigger_traces) + } + /// Adds a delegation to the active delegations list. pub fn add_delegation(&mut self, authorization: SignedAuthorization) { self.active_delegations.push(authorization); diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 301454d43eeab..9d7df90324b3c 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -230,6 +230,8 @@ pub enum TraceKind { Deployment, Setup, Execution, + AssertionTrigger, + Assertion, } impl TraceKind { @@ -256,6 +258,22 @@ impl TraceKind { pub fn is_execution(self) -> bool { matches!(self, Self::Execution) } + + /// Returns `true` if the trace kind is [`AssertionTrigger`]. + /// + /// [`AssertionTrigger`]: TraceKind::AssertionTrigger + #[must_use] + pub fn is_assertion_trigger(self) -> bool { + matches!(self, Self::AssertionTrigger) + } + + /// Returns `true` if the trace kind is [`Assertion`]. + /// + /// [`Assertion`]: TraceKind::Assertion + #[must_use] + pub fn is_assertion(self) -> bool { + matches!(self, Self::Assertion) + } } /// Given a list of traces and artifacts, it returns a map connecting address to abi diff --git a/crates/forge/src/cmd/test/mod.rs b/crates/forge/src/cmd/test/mod.rs index 889d839c3f27a..16ee40a93f946 100644 --- a/crates/forge/src/cmd/test/mod.rs +++ b/crates/forge/src/cmd/test/mod.rs @@ -53,14 +53,19 @@ use std::{ }; use yansi::Paint; -fn assertion_trace_header(arena: &SparsedTraceArena) -> Option { - let signature = - arena.nodes().first()?.trace.decoded.as_ref()?.call_data.as_ref()?.signature.as_str(); - if !signature.starts_with("assertionCall") { - return None; +fn label_assertion_trace(arena: &mut SparsedTraceArena) { + let Some(assertion_addr) = arena.nodes().first().map(|node| node.trace.address) else { + return; + }; + + for node in arena.nodes_mut() { + if node.trace.address == assertion_addr + && let Some(decoded) = node.trace.decoded.as_mut() + && decoded.label.is_none() + { + decoded.label = Some("Assertion".to_string()); + } } - let name = signature.trim_end_matches("()"); - Some(format!("Assertion trace: {name}")) } mod filter; @@ -644,6 +649,8 @@ impl TestArgs { // Identify addresses and decode traces. let mut decoded_traces = Vec::with_capacity(result.traces.len()); + let mut decoded_trigger_traces = Vec::new(); + let mut decoded_assertion_traces = Vec::new(); for (kind, arena) in &mut result.traces { if identify_addresses { decoder.identify(arena, &mut identifier); @@ -658,6 +665,12 @@ impl TestArgs { TraceKind::Execution => { (verbosity == 3 && result.status.is_failure()) || verbosity >= 4 } + TraceKind::AssertionTrigger => { + (verbosity == 3 && result.status.is_failure()) || verbosity >= 4 + } + TraceKind::Assertion => { + (verbosity == 3 && result.status.is_failure()) || verbosity >= 4 + } TraceKind::Setup => { (verbosity == 4 && result.status.is_failure()) || verbosity >= 5 } @@ -671,17 +684,60 @@ impl TestArgs { prune_trace_depth(arena, trace_depth); } - if let Some(header) = assertion_trace_header(arena) { - decoded_traces.push(header); + if matches!(kind, TraceKind::Assertion) { + label_assertion_trace(arena); + decoded_assertion_traces.push(render_trace_arena_inner( + arena, + false, + verbosity > 4, + )); + } else if matches!(kind, TraceKind::AssertionTrigger) { + decoded_trigger_traces.push(render_trace_arena_inner( + arena, + false, + verbosity > 4, + )); + } else { + decoded_traces.push(render_trace_arena_inner( + arena, + false, + verbosity > 4, + )); } - decoded_traces.push(render_trace_arena_inner(arena, false, verbosity > 4)); } } - if !silent && show_traces && !decoded_traces.is_empty() { - sh_println!("Traces:")?; - for trace in &decoded_traces { - sh_println!("{trace}")?; + if !silent + && show_traces + && (!decoded_traces.is_empty() + || !decoded_trigger_traces.is_empty() + || !decoded_assertion_traces.is_empty()) + { + if !decoded_traces.is_empty() { + sh_println!("Traces:")?; + for trace in &decoded_traces { + sh_println!("{trace}")?; + } + } + + if !decoded_trigger_traces.is_empty() { + if !decoded_traces.is_empty() { + sh_println!()?; + } + sh_println!("Trigger Call:")?; + for trace in &decoded_trigger_traces { + sh_println!("{trace}")?; + } + } + + if !decoded_assertion_traces.is_empty() { + if !decoded_traces.is_empty() || !decoded_trigger_traces.is_empty() { + sh_println!()?; + } + sh_println!("Assertion Traces:")?; + for trace in &decoded_assertion_traces { + sh_println!("{trace}")?; + } } } diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index de8fc5554a799..d842e2040384d 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -575,10 +575,20 @@ impl TestResult { self.gas_report_traces = Vec::new(); if let Some(mut cheatcodes) = raw_call_result.cheatcodes { + let assertion_trigger_traces = cheatcodes.take_assertion_trigger_traces(); + if !assertion_trigger_traces.is_empty() { + self.traces.extend(assertion_trigger_traces.into_iter().map(|arena| { + ( + TraceKind::AssertionTrigger, + SparsedTraceArena { arena, ignored: Default::default() }, + ) + })); + } + let assertion_traces = cheatcodes.take_assertion_traces(); if !assertion_traces.is_empty() { self.traces.extend(assertion_traces.into_iter().map(|arena| { - (TraceKind::Execution, SparsedTraceArena { arena, ignored: Default::default() }) + (TraceKind::Assertion, SparsedTraceArena { arena, ignored: Default::default() }) })); } diff --git a/crates/script/src/execute.rs b/crates/script/src/execute.rs index e9bcb8e813700..e8dcf63ed7426 100644 --- a/crates/script/src/execute.rs +++ b/crates/script/src/execute.rs @@ -429,6 +429,8 @@ impl PreSimulationState { let should_include = match kind { TraceKind::Setup => verbosity >= 5, TraceKind::Execution => verbosity > 3, + TraceKind::AssertionTrigger => verbosity > 3, + TraceKind::Assertion => verbosity > 3, _ => false, } || !result.success; From a86d84bfa11aacfd5d16074cfb7dddcc13c6c6e5 Mon Sep 17 00:00:00 2001 From: Mateo <160488334+mateo-mro@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:20:51 +0100 Subject: [PATCH 62/83] feat(phoundry): Add function for pretty traces (#80) --- crates/evm/traces/src/lib.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 9d7df90324b3c..4f4528505b5af 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -187,6 +187,22 @@ pub fn render_trace_arena(arena: &SparsedTraceArena) -> String { render_trace_arena_inner(arena, false, false) } +/// Render a collection of call traces to a string with ANSI colors always enabled. +/// +/// Use this when rendering traces outside of a TTY context (e.g. server-side) where +/// `shell::color_choice()` would default to `Never`. +pub fn render_trace_arena_with_colors( + arena: &SparsedTraceArena, + with_storage_changes: bool, +) -> String { + let mut w = TraceWriter::new(Vec::::new()) + .color_cheatcodes(true) + .use_colors(revm_inspectors::ColorChoice::Always) + .with_storage_changes(with_storage_changes); + w.write_arena(&arena.resolve_arena()).expect("Failed to write traces"); + String::from_utf8(w.into_writer()).expect("trace writer wrote invalid UTF-8") +} + /// Prunes trace depth if depth is provided as an argument pub fn prune_trace_depth(arena: &mut CallTraceArena, depth: usize) { for node in arena.nodes_mut() { From 590665961dac7064c7ccacfca3fd033ed00d9108 Mon Sep 17 00:00:00 2001 From: Mateo <160488334+mateo-mro@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:31:36 +0200 Subject: [PATCH 63/83] feat(cheatcodes): make assertion-executor optional behind `credible` feature (#81) --- .github/workflows/docker-publish.yml | 2 +- .github/workflows/release.yml | 2 +- crates/anvil/Cargo.toml | 1 + crates/cast/Cargo.toml | 1 + crates/cheatcodes/Cargo.toml | 6 +++++- crates/cheatcodes/src/inspector.rs | 6 +++++- crates/cheatcodes/src/lib.rs | 17 +++++++++++++++++ crates/chisel/Cargo.toml | 1 + crates/evm/evm/Cargo.toml | 4 ++++ crates/forge/Cargo.toml | 1 + deny.toml | 16 ++++++++++++++-- 11 files changed, 51 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8f052baf01ac6..5c5b4f5b442e5 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -25,7 +25,7 @@ env: # Keep in sync with `release.yml`. RUST_PROFILE: maxperf - RUST_FEATURES: aws-kms,gcp-kms,turnkey,cli,asm-keccak,js-tracer + RUST_FEATURES: aws-kms,gcp-kms,turnkey,cli,asm-keccak,js-tracer,credible jobs: build: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8d4b0826159d1..e7ac9bff2e350 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ env: # Keep in sync with `docker-publish.yml`. RUST_PROFILE: maxperf - RUST_FEATURES: aws-kms,gcp-kms,turnkey,cli,asm-keccak,js-tracer + RUST_FEATURES: aws-kms,gcp-kms,turnkey,cli,asm-keccak,js-tracer,credible LAST_STABLE_VERSION: "v1.5.0" diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 537668d6b465a..60cc81bed8901 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -135,3 +135,4 @@ cmd = [ "tokio/signal", ] js-tracer = ["revm-inspectors/js-tracer"] +credible = ["foundry-evm/credible"] diff --git a/crates/cast/Cargo.toml b/crates/cast/Cargo.toml index 434039f99823f..3a01de1159543 100644 --- a/crates/cast/Cargo.toml +++ b/crates/cast/Cargo.toml @@ -103,3 +103,4 @@ aws-kms = ["foundry-wallets/aws-kms"] gcp-kms = ["foundry-wallets/gcp-kms"] turnkey = ["foundry-wallets/turnkey"] isolate-by-default = ["foundry-config/isolate-by-default"] +credible = ["foundry-evm/credible"] diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 26aa9fcc28478..39914f37f67a6 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -14,13 +14,17 @@ exclude.workspace = true [lints] workspace = true +[features] +default = [] +credible = ["dep:assertion-executor"] + [build-dependencies] [dependencies] foundry-fork-db.workspace = true # sdk version 1.0.7 with custom inspector commit # done to not have cyclical version bumps between sdk and phoundry -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "5ace6939c7027f1ba0bcf6f8751904dd4ca4f986", features = ["phoundry"] } +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "5ace6939c7027f1ba0bcf6f8751904dd4ca4f986", features = ["phoundry"], optional = true } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 89a7a8e12cc78..c21be7c4ba155 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -409,7 +409,8 @@ pub struct Cheatcodes { /// Expected revert information pub expected_revert: Option, - /// Assertion information + /// Assertion information (only available with `credible` feature) + #[cfg(feature = "credible")] pub assertion: Option, /// Assume next call can revert and discard fuzz run if it does. @@ -560,6 +561,7 @@ impl Cheatcodes { mocked_functions: Default::default(), expected_calls: Default::default(), expected_emits: Default::default(), + #[cfg(feature = "credible")] assertion: Default::default(), expected_creates: Default::default(), allowed_mem_writes: Default::default(), @@ -1078,6 +1080,7 @@ impl Cheatcodes { }]); } + #[cfg(feature = "credible")] if let Some(assertion) = self.assertion.take() { let tx_attributes = crate::credible::TxAttributes { value: call.call_value(), @@ -1818,6 +1821,7 @@ impl Inspector> for Cheatcodes { depth: curr_depth as u64, }]); } + #[cfg(feature = "credible")] if let Some(assertion) = self.assertion.take() { let tx_attributes = crate::credible::TxAttributes { value: input.value(), diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index 75850449d72b8..6ad3690a93162 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -63,8 +63,25 @@ mod toml; mod utils; +#[cfg(feature = "credible")] pub mod credible; +/// Stub implementation when the `credible` feature is disabled. +/// `vm.assertion()` is kept in the ABI but reverts with a clear error at runtime. +#[cfg(not(feature = "credible"))] +mod credible_stub { + use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; + + impl Cheatcode for assertionCall { + fn apply_stateful(&self, _ccx: &mut CheatsCtxt) -> Result { + bail!( + "vm.assertion() requires Phylax-built forge with the `credible` feature enabled. \ + Install from: https://github.com/phylaxsystems/phoundry" + ) + } + } +} + /// Cheatcode implementation. pub(crate) trait Cheatcode: CheatcodeDef + DynCheatcode { /// Applies this cheatcode to the given state. diff --git a/crates/chisel/Cargo.toml b/crates/chisel/Cargo.toml index 7f6e9fb54685c..45947a9c68d25 100644 --- a/crates/chisel/Cargo.toml +++ b/crates/chisel/Cargo.toml @@ -69,3 +69,4 @@ asm-keccak = ["alloy-primitives/asm-keccak"] jemalloc = ["foundry-cli/jemalloc"] mimalloc = ["foundry-cli/mimalloc"] tracy-allocator = ["foundry-cli/tracy-allocator"] +credible = ["foundry-evm/credible"] diff --git a/crates/evm/evm/Cargo.toml b/crates/evm/evm/Cargo.toml index b3e9553f40304..f9cc16596b504 100644 --- a/crates/evm/evm/Cargo.toml +++ b/crates/evm/evm/Cargo.toml @@ -13,6 +13,10 @@ repository.workspace = true [lints] workspace = true +[features] +default = [] +credible = ["foundry-cheatcodes/credible"] + [dependencies] foundry-cheatcodes.workspace = true foundry-common.workspace = true diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index 53b5243d54b38..de80ae7f9334a 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -122,3 +122,4 @@ aws-kms = ["dep:foundry-wallets", "foundry-wallets/aws-kms"] gcp-kms = ["dep:foundry-wallets", "foundry-wallets/gcp-kms"] turnkey = ["dep:foundry-wallets", "foundry-wallets/turnkey"] isolate-by-default = ["foundry-config/isolate-by-default"] +credible = ["foundry-evm/credible"] diff --git a/deny.toml b/deny.toml index cb3f06295e88e..3e477868150bd 100644 --- a/deny.toml +++ b/deny.toml @@ -11,8 +11,6 @@ ignore = [ "RUSTSEC-2024-0437", # https://rustsec.org/advisories/RUSTSEC-2025-0141 bincode is unmaintained, need to transition all deps to wincode first "RUSTSEC-2025-0141", - # https://rustsec.org/advisories/RUSTSEC-2026-0002 lru unused directly: - "RUSTSEC-2026-0002", # https://rustsec.org/advisories/RUSTSEC-2023-0018 remove_dir_all vulnerability # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. "RUSTSEC-2023-0018", @@ -21,6 +19,20 @@ ignore = [ # https://rustsec.org/advisories/RUSTSEC-2018-0017 tempdir deprecated # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. "RUSTSEC-2018-0017", + # aws-lc-sys vulnerabilities — transitive dep via rustls. Upgrade blocked by alloy pinning aws-lc-rs. + "RUSTSEC-2026-0044", + "RUSTSEC-2026-0045", + "RUSTSEC-2026-0046", + "RUSTSEC-2026-0047", + "RUSTSEC-2026-0048", + # https://rustsec.org/advisories/RUSTSEC-2026-0007 bytes integer overflow — awaiting upstream update + "RUSTSEC-2026-0007", + # https://rustsec.org/advisories/RUSTSEC-2026-0097 rand unsoundness with custom logger — awaiting upstream update + "RUSTSEC-2026-0097", + # https://rustsec.org/advisories/RUSTSEC-2026-0049 rustls-webpki CRL bypass — awaiting upstream update + "RUSTSEC-2026-0049", + # https://rustsec.org/advisories/RUSTSEC-2026-0009 time DoS via stack exhaustion — awaiting upstream update + "RUSTSEC-2026-0009", ] # This section is considered when running `cargo deny check bans`. From 9289aae52324675d4e6b2f053e2970075c6e3c96 Mon Sep 17 00:00:00 2001 From: Mateo <160488334+mateo-mro@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:43:30 +0200 Subject: [PATCH 64/83] chore(cheatcodes): bump assertion-executor to latest rev (#82) --- Cargo.lock | 117 +++++------------------------------ crates/cheatcodes/Cargo.toml | 5 +- 2 files changed, 18 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc5ac8832eb1d..7dcf9d5202a73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,34 +65,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "alloy" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07655fedc35188f3c50ff8fc6ee45703ae14ef1bc7ae7d80e23a747012184e3" -dependencies = [ - "alloy-consensus", - "alloy-contract", - "alloy-core", - "alloy-eips", - "alloy-genesis", - "alloy-json-rpc", - "alloy-network", - "alloy-node-bindings", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-serde", - "alloy-signer", - "alloy-signer-local", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", - "alloy-trie", -] - [[package]] name = "alloy-chains" version = "0.2.23" @@ -170,19 +142,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "alloy-core" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a651e1d9e50e6d0a78bd23cd08facb70459a94501c4036c7799a093e569a310" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-rlp", - "alloy-sol-types", -] - [[package]] name = "alloy-dyn-abi" version = "1.5.1" @@ -301,7 +260,7 @@ checksum = "e6ccc4c702c840148af1ce784cc5c6ed9274a020ef32417c5b1dbeab8c317673" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-op-hardforks", "alloy-primitives", "alloy-rpc-types-engine", @@ -330,19 +289,6 @@ dependencies = [ "serde_with", ] -[[package]] -name = "alloy-hardforks" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165210652f71dfc094b051602bafd691f506c54050a174b1cba18fb5ef706a3" -dependencies = [ - "alloy-chains", - "alloy-eip2124", - "alloy-primitives", - "auto_impl", - "dyn-clone", -] - [[package]] name = "alloy-hardforks" version = "0.4.5" @@ -422,27 +368,6 @@ dependencies = [ "serde", ] -[[package]] -name = "alloy-node-bindings" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b000c0790644bd4effe719f4272f0023167567ca9534e4e071f6f18c4f7e44" -dependencies = [ - "alloy-genesis", - "alloy-hardforks 0.2.13", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "alloy-signer-local", - "k256", - "rand 0.8.5", - "serde_json", - "tempfile", - "thiserror 2.0.17", - "tracing", - "url", -] - [[package]] name = "alloy-op-evm" version = "0.25.2" @@ -468,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f96fb2fce4024ada5b2c11d4076acf778a0d3e4f011c6dfd2ffce6d0fcf84ee9" dependencies = [ "alloy-chains", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-primitives", "auto_impl", ] @@ -516,11 +441,9 @@ dependencies = [ "alloy-json-rpc", "alloy-network", "alloy-network-primitives", - "alloy-node-bindings", "alloy-primitives", "alloy-pubsub", "alloy-rpc-client", - "alloy-rpc-types-anvil", "alloy-rpc-types-debug", "alloy-rpc-types-eth", "alloy-rpc-types-trace", @@ -629,7 +552,6 @@ checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug", "alloy-rpc-types-engine", "alloy-rpc-types-eth", "alloy-rpc-types-trace", @@ -1638,10 +1560,10 @@ dependencies = [ [[package]] name = "assertion-da-client" -version = "1.0.7" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=5ace6939c7027f1ba0bcf6f8751904dd4ca4f986#5ace6939c7027f1ba0bcf6f8751904dd4ca4f986" +version = "1.3.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa#3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa" dependencies = [ - "alloy", + "alloy-primitives", "assertion-da-core", "http 1.4.0", "reqwest", @@ -1655,38 +1577,32 @@ dependencies = [ [[package]] name = "assertion-da-core" -version = "1.0.7" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=5ace6939c7027f1ba0bcf6f8751904dd4ca4f986#5ace6939c7027f1ba0bcf6f8751904dd4ca4f986" +version = "1.3.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa#3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa" dependencies = [ - "alloy", + "alloy-primitives", "serde", ] [[package]] name = "assertion-executor" -version = "1.0.7" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=5ace6939c7027f1ba0bcf6f8751904dd4ca4f986#5ace6939c7027f1ba0bcf6f8751904dd4ca4f986" +version = "1.3.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa#3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa" dependencies = [ - "alloy", "alloy-consensus", "alloy-evm", "alloy-network", "alloy-network-primitives", - "alloy-node-bindings", "alloy-primitives", "alloy-provider", "alloy-rpc-types", - "alloy-rpc-types-anvil", "alloy-signer", "alloy-sol-types", - "alloy-transport", - "alloy-transport-ws", "assertion-da-client", "bincode", - "clap", + "bumpalo", "dashmap", "enum-as-inner", - "futures", "metrics", "op-revm", "rapidhash", @@ -1695,7 +1611,6 @@ dependencies = [ "serde", "serde_json", "sled", - "tempfile", "thiserror 2.0.17", "tokio", "tracing", @@ -2750,7 +2665,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-eips", "alloy-ens", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-json-abi", "alloy-json-rpc", "alloy-network", @@ -4439,7 +4354,7 @@ version = "1.5.1" dependencies = [ "alloy-chains", "alloy-dyn-abi", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-json-abi", "alloy-network", "alloy-primitives", @@ -5121,7 +5036,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-evm", "alloy-genesis", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-json-abi", "alloy-network", "alloy-op-evm", @@ -5246,7 +5161,7 @@ checksum = "8df2fd495cf7337b247d960f90355329cc625fe27fe7da9fe5e598c42df21526" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -8864,7 +8779,7 @@ version = "1.9.3" source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" dependencies = [ "alloy-eip2124", - "alloy-hardforks 0.4.5", + "alloy-hardforks", "alloy-primitives", "auto_impl", "once_cell", diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 39914f37f67a6..cdbcf384bb3c9 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,9 +22,8 @@ credible = ["dep:assertion-executor"] [dependencies] foundry-fork-db.workspace = true -# sdk version 1.0.7 with custom inspector commit -# done to not have cyclical version bumps between sdk and phoundry -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "5ace6939c7027f1ba0bcf6f8751904dd4ca4f986", features = ["phoundry"], optional = true } +# pinned to avoid cyclical version bumps between sdk and phoundry +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa", features = ["phoundry"], optional = true } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true From f83bad912a9dba7bf0371def1e70bb1896048356 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:03:16 +0200 Subject: [PATCH 65/83] chore(release): apply fixes for v1.7.0 (#14487) * Improve CI action (#14484) * fix(config): warn instead of erroring on unknown FOUNDRY_PROFILE (#14486) * fix(config): warn instead of erroring on unknown FOUNDRY_PROFILE When the selected profile (via `FOUNDRY_PROFILE` or otherwise) does not exist in `foundry.toml`, fall back to the default profile and emit a `Warning::UnknownProfile` instead of returning a hard error. This matches the lenient behaviour used for nested lib configs and keeps commands like `FOUNDRY_PROFILE=ci forge build` working when `[profile.ci]` happens to be missing. Amp-Thread-ID: https://ampcode.com/threads/T-019dd43e-e2d0-723e-bc03-03b0467dc68e Co-authored-by: Amp * fix fmt --------- Co-authored-by: Amp --------- Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Amp --- .github/workflows/release.yml | 9 ++++----- crates/config/src/lib.rs | 29 ++++++++++++++++++----------- crates/config/src/warning.rs | 12 ++++++++++++ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fc1d6923da812..682c9214284f6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -198,11 +198,10 @@ jobs: - name: cross setup if: contains(matrix.target, 'musl') - uses: taiki-e/cache-cargo-install-action@f9eed3e4680f27610dc6d8c67be1b88593f7dade # v3.0.6 - with: - git: https://github.com/cross-rs/cross - rev: baf457efc2555225af47963475bd70e8d2f5993f - tool: cross + run: | + cargo install cross --locked \ + --git https://github.com/cross-rs/cross \ + --rev baf457efc2555225af47963475bd70e8d2f5993f - name: Build binaries env: diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 4934503ea66c4..3b60ebb4f324e 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -847,12 +847,15 @@ impl Config { // Check if the selected profile exists. if config.profiles.contains(&selected_profile) { config.profile = selected_profile; - } else if strict_profile { - return Err(ExtractConfigError::new(Error::from(format!( - "selected profile `{selected_profile}` does not exist" - )))); } else { - // Fall back to default profile for nested lib configs. + // Fall back to the default profile. In strict mode (top-level loads), emit a warning + // so users are informed when an unknown profile (e.g. via `FOUNDRY_PROFILE`) is + // selected; the silent fallback is reserved for nested lib configs. + if strict_profile { + config + .warnings + .push(Warning::UnknownProfile { profile: selected_profile.to_string() }); + } config.profile = Self::DEFAULT_PROFILE; } @@ -7024,9 +7027,9 @@ mod tests { }); } - // Test for issue #12844: FOUNDRY_PROFILE=nonexistent should fail + // Test for issue #12844: FOUNDRY_PROFILE=nonexistent should warn and fall back to default. #[test] - fn fails_on_unknown_profile() { + fn warns_on_unknown_profile() { figment::Jail::expect_with(|jail| { jail.create_file( "foundry.toml", @@ -7037,11 +7040,15 @@ mod tests { )?; jail.set_env("FOUNDRY_PROFILE", "nonexistent"); - let err = Config::load().expect_err("expected unknown profile to fail"); - let err_msg = err.to_string(); + let cfg = Config::load().expect("expected unknown profile to fall back to default"); + assert_eq!(cfg.profile, Config::DEFAULT_PROFILE); assert!( - err_msg.contains("selected profile `nonexistent` does not exist"), - "Expected error about nonexistent profile, got: {err_msg}" + cfg.warnings.iter().any(|w| matches!( + w, + crate::Warning::UnknownProfile { profile } if profile == "nonexistent" + )), + "Expected UnknownProfile warning, got: {:?}", + cfg.warnings ); Ok(()) diff --git a/crates/config/src/warning.rs b/crates/config/src/warning.rs index 1c1518f5d7cc7..32a1183208892 100644 --- a/crates/config/src/warning.rs +++ b/crates/config/src/warning.rs @@ -64,6 +64,12 @@ pub enum Warning { /// The config file where the key was found source: String, }, + /// The selected profile (via `FOUNDRY_PROFILE` or otherwise) does not exist in the config. + /// Falls back to the default profile. + UnknownProfile { + /// The selected profile that does not exist + profile: String, + }, } impl fmt::Display for Warning { @@ -117,6 +123,12 @@ impl fmt::Display for Warning { "Found unknown `{key}` config key in section `{section}` defined in {source}." ) } + Self::UnknownProfile { profile } => { + write!( + f, + "Selected profile `{profile}` does not exist; falling back to the default profile." + ) + } } } } From 4072e48705af9d93e3c0f6e29e93b5e9a40caed8 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Fri, 8 May 2026 09:44:24 +0200 Subject: [PATCH 66/83] chore(release): v1.7.1 (#14640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(cheatcodes): fix solc 0.8.35 error keyword warning (#14509) fix(cheatcodes): avoid solc error keyword warning (cherry picked from commit f0bd9bb7e830cdfd1ae8736f22aede4b6c8f256f) * chore: bump compiler version to 0.8.35 for tests (#14524) * bump compiler version for tests * fix CI: update gas snapshots and bump svm-rs to 0.5.25 Amp-Thread-ID: https://ampcode.com/threads/T-019dddbd-7f28-72cc-965b-d5a23ecb37ce Co-authored-by: Amp * make fmt Amp-Thread-ID: https://ampcode.com/threads/T-019dddbd-7f28-72cc-965b-d5a23ecb37ce Co-authored-by: Amp * fix: add blockTimestamp to LegacyTransactionResult for testRpcTransactionByHash DRPC now returns a blockTimestamp field, which shifts ABI decoding offsets and breaks the test. Amp-Thread-ID: https://ampcode.com/threads/T-019dddbd-7f28-72cc-965b-d5a23ecb37ce Co-authored-by: Amp --------- Co-authored-by: Amp (cherry picked from commit 470d04883f3532397d72dad9ea58bd667ace6e3b) * fix(ci): use `PATH_USD` fallback fee token in Mail templates (#14546) (cherry picked from commit e8d0d899d3ca5b57fe9630d8eb15b7aa2cb865cc) * fix(forge): ignore ETH_RPC_URL for test forking (#14555) Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> (cherry picked from commit 6c9bbeae19511f618024d904c1f7aff38a2cb846) * fix(cli): fix jsonwebtoken panic (#14562) `cast` panicked with this message coming from jsonwebtoken: ``` Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'rust_crypto' and 'aws_lc_rs' features is enabled. See the documentation of the CryptoProvider type for more information. ``` This seemingly was introduced with the bump of jsonwebtoken to 10. Now it requires you to pick one backend used by default controlled by the compile time cargo features or call `CryptoProvider::install_default()` at the beginning. I realized that probably it would be better to just select the feature and I picked `aws_lc_rs` as it seems to be increasingly a default and we already are using the C toolchain. Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> (cherry picked from commit 6e40f568f23ad36cb3ee8592b56a3ae7541211a7) * ci: sign release archives, docker images, and publish SBOMs (#14563) - release.yml: emit per-archive sha256 + SPDX SBOM (Syft), cosign keyless sign-blob of the archive, and use actions/attest@v4 for both build provenance and SBOM attestations. Upload all artifacts to the draft release. - docker-publish.yml: enable BuildKit SBOM, capture the build digest, cosign keyless sign each pushed tag, and publish a Sigstore-signed SLSA provenance attestation via actions/attest with push-to-registry. - SECURITY.md: document how external users verify archives and the docker image (gh attestation, cosign, plain sha256, buildx imagetools). - README.md: link to the new verification section. (cherry picked from commit 3e7f0ed66a059ef685c0bf70d53275a5e1f186d2) * fix(ci): increase permissions for the enhanced attestation writing (#14584) * increase permissions for artifact writing * apply write permissions to release-docker (cherry picked from commit 1fd6466f96e4f52cea01093ae0f5772ddf3a6795) * fix(forge): encode Tempo creates as AA calls (#14585) (cherry picked from commit 8b44ae6f92bea125e868d18a476bd7b0efda4d97) * fix(cli): fix release version strings for immutable tags, bump to 1.7.1 (#14496) * Fix release version metadata for immutable tags Amp-Thread-ID: https://ampcode.com/threads/T-019dd617-b29f-7409-8523-9858a1504f17 Co-authored-by: Amp * Derive nightly release suffix from commit SHA Amp-Thread-ID: https://ampcode.com/threads/T-019dd617-b29f-7409-8523-9858a1504f17 Co-authored-by: Amp * Apply suggestion from @zerosnacks * Apply suggestion from @zerosnacks * Apply suggestion from @zerosnacks * bump to v1.7.1 * avoid appending whole sha hash, not necessary, handle version cmp correctly. after v1.7.1 release we need to bump to v1.7.2 for nightlies following it to compare correctly * Make foundryVersionCmp tolerate new version format and add tests - Strip both pre-release ('-nightly', '-dev') and build metadata ('+..') from SEMVER_VERSION before comparison so the cheatcode keeps working for tagged releases (which have no '-' separator). - Extract strip_semver_metadata helper and add Rust unit tests covering all SEMVER_VERSION shapes, version_cmp ordering, and parse_version rejection of pre-release/build/garbage input. - Extend the Solidity test suite for vm.getFoundryVersion()/foundryVersionCmp/foundryVersionAtLeast: validate MAJOR.MINOR.PATCH parseability, build profile value, cmp/atLeast invariant, and error paths for invalid user-supplied versions. Amp-Thread-ID: https://ampcode.com/threads/T-019dd971-fcb7-7149-9680-f0134130844c Co-authored-by: Amp * fix(test): drop view from solidity tests using assert helpers and fix fmt - assertTrue/assertEq aren't view, so testGetFoundryVersionBuildProfile and testFoundryVersionCmpAndAtLeastAreConsistent can't be view either. - Collapse the buildType assertion onto one line to satisfy forge fmt. Amp-Thread-ID: https://ampcode.com/threads/T-019dd971-fcb7-7149-9680-f0134130844c Co-authored-by: Amp * test(version): assert build profile is non-empty instead of debug|release The dist profile (used for distributed release binaries) is also valid; just require non-empty so any future profile works. Amp-Thread-ID: https://ampcode.com/threads/T-019dd971-fcb7-7149-9680-f0134130844c Co-authored-by: Amp * Normalize nightly- to nightly in release_version Ensures tarball and Docker nightly artifacts produce the same version string. The commit identifier is already included in the SemVer build metadata (after `+`), so collapsing `nightly-` to `nightly` avoids duplicating the SHA in the pre-release tag. Co-authored-by: Amp Amp-Thread-ID: https://ampcode.com/threads/T-019df79e-d4c9-707c-85eb-2efbf59160b3 --------- Co-authored-by: Centaur AI Co-authored-by: Amp Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: zerosnacks (cherry picked from commit a70d4aa77d87374cf167fa97087855051ade4bdf) * fix(evm): query `state_snapshot.storage` in `ForkDbStateSnapshot::storage_ref` (#14007) * fix(evm): query `state_snapshot.storage` in `ForkDbStateSnapshot::storage_ref` * test(evm): cover `ForkDbStateSnapshot::storage_ref` snapshot lookup (cherry picked from commit fa5429abb300bc27cee58efb6855cf8befa7b2ab) * fix(cast): consistent `--json` output for `keychain` subcommands (#14590) - `keychain rl`: wrap remaining limit in `{"remaining":"..."}` object instead of emitting a bare JSON string - `keychain policy add-call`: emit `{"status":"already_present","target":"..."}` when the rule already exists, instead of plain text - `send_keychain_tx`: wrap sponsor hash in `{"sponsor_hash":"0x..."}` object when --tempo.print-sponsor-hash is used with --json Add CLI tests covering the rl and sponsor-hash JSON output shapes. (cherry picked from commit 79167192198a997ce757fe4cc58b91f825c59f86) * fix(cheatcodes): transfer value for payable mock calls (#14547) * test: updated tests * fix: execute value transfer * test: improve * imp: review item * test: vm.prank test * imp: moved mocked-call handling after prank application --------- Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> (cherry picked from commit f2e09d2df1b48b37ca83e9c47880ed1e47413cc6) * fix(forge): `--fuzz-seed` parameter is not effective in `forge coverage` (#14610) fix --fuzz-seed not effective in forge coverage (cherry picked from commit bd9cf5510fc36f2128c36106c6737a6980f6f5ae) * fix(cheatcodes): enforce `expectRevert` reverter address for CREATE frames (#14615) * fix(cheatcodes): enforce `expectRevert` reverter address for CREATE frames The reverter address argument to `vm.expectRevert` was silently ignored when the innermost reverting frame was a CREATE (top-level or nested), because create_end never populated `expected_revert.reverted_by`. Mirror call_end's logic in create_end: when the outcome reverts and a reverter address is expected, record outcome.address (revm guarantees this is Some(would-be address) whenever the constructor executed). Adds positive regression tests for top-level and nested-CREATE reverts, and a negative regression test asserting wrong-reverter now fails. Co-authored-by: Amp * improve coverage * add Derek's suggested test cases * fix: forge fmt for ExpectRevert.t.sol Amp-Thread-ID: https://ampcode.com/threads/T-019dfdc5-5414-70b6-9f49-cb5797a37a29 Co-authored-by: Amp --------- Co-authored-by: Amp Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> (cherry picked from commit 85cd75c0acd4dff4257fd4bdd8bac2c0a6733119) * fix(cheatcodes): preserve reverts with `expectEmit` (#14619) * test: added regression test * fix: re-order revert handling * refactor: simplify * lint: fmt * polish: tighten comment, extend test with revert reason and custom error Amp-Thread-ID: https://ampcode.com/threads/T-019dfd96-7a03-7249-8c10-af20ee2729f5 Co-authored-by: Amp --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: Amp (cherry picked from commit 2e8ae6c606ebe37d3e5f42a38f777da2e947e3d6) * fix(evm): preserve `CREATE` address on revert in isolation mode (#14637) (cherry picked from commit 9584c6c4379ec5a9f8d02578081deb748325051e) * chore(clippy): fix for_kv_map and useless_borrows_in_formatting (#14554) * chore(clippy): fix for_kv_map and useless_borrows_in_formatting Amp-Thread-ID: https://ampcode.com/threads/T-019df0f9-62e7-74b8-bd5e-da2acce678fb Co-authored-by: Amp * chore(clippy): drop redundant borrows in cheatcodes assert formatters Amp-Thread-ID: https://ampcode.com/threads/T-019df0f9-62e7-74b8-bd5e-da2acce678fb Co-authored-by: Amp --------- Co-authored-by: Amp (cherry picked from commit 84d38735051f48cabdf7c152542f107110651560) * fix(ext): bump forge-std commit in external integration tests (#14504) bump forge commit (cherry picked from commit 024820cc43edd20cedce4a317967543ee9389728) * chore(tests): bump forge-std version (#14510) chore: bump forge-std version used for tests Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> (cherry picked from commit 5766929d7621e06678cb0dd3b9680c694ee431dc) * fix(config): suppress spurious unknown-key warning for `network` (#14534) * fix(config): suppress spurious unknown-key warning for `network` The `network` field in `NetworkConfigs` had `skip_serializing_if = "Option::is_none"`, so it was missing from the serialized default `Config`. The warnings provider builds its allowed-keys set from that serialized default, so a valid `network = "tempo"` entry in foundry.toml triggered: Warning: Found unknown `network` config for profile `default` defined in foundry.toml. Replace `skip_serializing_if` with `#[serde(default)]` so `network` appears (as null) in the default config and is recognized as a known profile key. TOML output is unchanged (None is omitted by toml-rs); only the JSON snapshot in `test_default_config` needed updating. Amp-Thread-ID: https://ampcode.com/threads/T-019ddec8-2f04-7255-b8bf-70c1ce2a996d Co-authored-by: Amp * test(config): add regression tests for network/tempo unknown-key warnings Cover both the new `network = "tempo"` form and the legacy `tempo = true` alias to ensure neither triggers UnknownKey warnings. Amp-Thread-ID: https://ampcode.com/threads/T-019ddec8-2f04-7255-b8bf-70c1ce2a996d Co-authored-by: Amp * fix(config): canonicalize network field on serialization Previously, with `network = "tempo"` set, `forge config` would emit both: network = "tempo" tempo = false which is misleading — the legacy boolean alias contradicts the resolved network. Conversely, with `tempo = true` (legacy), the output omitted `network` entirely, hiding the actual resolved network. Make `NetworkConfigs` use a custom `Serialize` impl that: - Always emits the *resolved* network as the canonical `network = "..."` field. - Never emits the legacy `tempo` / `optimism` boolean aliases (they are still accepted as deserialize-only aliases for backward compatibility). - Continues to emit `celo` and `bypass_prevrandao` as before. This ensures consistent output regardless of input form: network = "tempo" (canonical) → network = "tempo" tempo = true (legacy) → network = "tempo" optimism = true (legacy) → network = "optimism" Both legacy keys are added to `BACKWARD_COMPATIBLE_KEYS` in the warnings provider so they don't trigger unknown-key warnings on input. Test snapshots updated accordingly. Amp-Thread-ID: https://ampcode.com/threads/T-019ddec8-2f04-7255-b8bf-70c1ce2a996d Co-authored-by: Amp * style: cargo fmt Amp-Thread-ID: https://ampcode.com/threads/T-019ddec8-2f04-7255-b8bf-70c1ce2a996d Co-authored-by: Amp --------- Co-authored-by: Amp (cherry picked from commit 95bf1015fcd1f774aec149b6684bc25bbff978a7) * feat(forge): use network = "tempo" and add rpc_endpoints in tempo template (#14528) * feat(forge): use network = "tempo" and add rpc_endpoints in tempo template Amp-Thread-ID: https://ampcode.com/threads/T-019dddff-1855-752f-b136-bd0465462ac8 Co-authored-by: Amp * feat(forge): add eth_rpc_url = "tempo" to tempo template Amp-Thread-ID: https://ampcode.com/threads/T-019dddff-1855-752f-b136-bd0465462ac8 Co-authored-by: Amp * style: cargo fmt Amp-Thread-ID: https://ampcode.com/threads/T-019dddff-1855-752f-b136-bd0465462ac8 Co-authored-by: Amp * fix: drop eth_rpc_url from tempo template (would silently fork all tests) Amp-Thread-ID: https://ampcode.com/threads/T-019dddff-1855-752f-b136-bd0465462ac8 Co-authored-by: Amp * refactor: build tempo template foundry.toml in a single toml serialize Amp-Thread-ID: https://ampcode.com/threads/T-019dddff-1855-752f-b136-bd0465462ac8 Co-authored-by: Amp --------- Co-authored-by: Amp (cherry picked from commit 323bceb203a19c971b63892b27e5eff25b221b5a) * ci(tempo): align ci-tempo workflow with master, drop fork-schedule test step Backport of CI Tempo workflow updates (#14501, #14537, #14556) so the v1.7.1 release branch matches master: - Devnet checks run on PR and push (re-enabled) - Devnet wallet tests run on PR and push - Testnet/mainnet checks moved to nightly schedule only - Nightly failure issue creation The 'Check Tempo fork schedule compatibility' step is intentionally omitted: the underlying tempo::tests::test_fork_schedule_parses_configured_rpcs test was added in #14485 (Tempo deps bump) which is not part of v1.7.1. Amp-Thread-ID: https://ampcode.com/threads/T-019e01cd-cea5-72e8-8338-5f0594e06335 Co-authored-by: Amp --------- Co-authored-by: figtracer Co-authored-by: Amp Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> Co-authored-by: Sergei Shulepov Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com> Co-authored-by: Centaur AI Co-authored-by: zerosnacks Co-authored-by: Nikki Co-authored-by: srdtrk <59252793+srdtrk@users.noreply.github.com> Co-authored-by: lazymio Co-authored-by: stevencartavia <112043913+stevencartavia@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md | 10 ++ .github/workflows/ci-tempo.yml | 91 +++++++---- .github/workflows/docker-publish.yml | 30 ++++ .github/workflows/release.yml | 78 +++++++++- Cargo.lock | 83 +++++----- Cargo.toml | 2 +- README.md | 2 + SECURITY.md | 109 +++++++++++++ crates/anvil/src/eth/pool/transactions.rs | 4 +- crates/cast/src/cmd/keychain.rs | 2 +- crates/cast/src/cmd/wallet/mod.rs | 13 +- crates/cast/src/lib.rs | 2 +- crates/cheatcodes/assets/cheatcodes.json | 116 +++++++------- crates/cheatcodes/spec/src/vm.rs | 116 +++++++------- crates/cheatcodes/src/inspector.rs | 145 ++++++++++++------ crates/cheatcodes/src/test/assert.rs | 14 +- crates/cheatcodes/src/version.rs | 67 +++++++- crates/chisel/src/executor.rs | 6 +- crates/cli/src/opts/evm.rs | 11 ++ crates/cli/src/opts/rpc.rs | 53 +++++++ crates/cli/src/opts/rpc_common.rs | 26 ++-- crates/common/Cargo.toml | 2 +- crates/common/build.rs | 20 ++- crates/common/src/contracts.rs | 2 +- crates/config/src/lib.rs | 83 ++++++++-- crates/config/src/providers/warnings.rs | 5 +- crates/doc/src/writer/as_doc.rs | 4 +- crates/evm/core/src/decode.rs | 4 +- crates/evm/core/src/fork/database.rs | 53 +++++-- crates/evm/evm/src/executors/invariant/mod.rs | 2 +- crates/evm/evm/src/inspectors/stack.rs | 11 ++ crates/evm/fuzz/src/lib.rs | 2 +- crates/evm/networks/src/lib.rs | 37 ++++- crates/fmt/src/state/mod.rs | 2 +- crates/forge/assets/tempo/MailTemplate.s.sol | 2 +- crates/forge/assets/tempo/MailTemplate.t.sol | 2 +- crates/forge/src/cmd/coverage.rs | 7 +- crates/forge/src/cmd/create.rs | 7 +- crates/forge/src/cmd/snapshot.rs | 7 +- crates/forge/src/cmd/test/mod.rs | 4 +- crates/forge/src/cmd/test/summary.rs | 4 +- crates/forge/src/gas_report.rs | 2 +- crates/forge/src/runner.rs | 2 +- crates/forge/tests/cli/cmd.rs | 123 ++++++++------- crates/forge/tests/cli/config.rs | 3 +- crates/forge/tests/cli/ext_integration.rs | 2 +- crates/forge/tests/cli/failure_assertions.rs | 7 +- crates/forge/tests/cli/script.rs | 2 +- .../tests/cli/test_cmd/invariant/common.rs | 2 +- .../forge/tests/cli/test_cmd/invariant/mod.rs | 12 +- crates/forge/tests/cli/test_cmd/repros.rs | 60 ++++++++ .../tests/fixtures/ExpectRevertFailures.t.sol | 57 +++++++ crates/script/src/verify.rs | 2 +- crates/test-utils/src/util.rs | 2 +- foundryup/README.md | 4 +- testdata/default/cheats/ExpectRevert.t.sol | 85 ++++++++++ testdata/default/cheats/Fork2.t.sol | 1 + .../default/cheats/GetFoundryVersion.t.sol | 51 ++++++ testdata/default/cheats/MockCall.t.sol | 41 ++++- testdata/default/cheats/MockCalls.t.sol | 4 + testdata/forge-std-rev | 2 +- testdata/utils/Vm.sol | 116 +++++++------- 62 files changed, 1348 insertions(+), 472 deletions(-) create mode 100644 .github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md diff --git a/.github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md b/.github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md new file mode 100644 index 0000000000000..8f72899c63611 --- /dev/null +++ b/.github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md @@ -0,0 +1,10 @@ +--- +title: "bug: tempo nightly workflow failed" +labels: P-high, T-bug +--- + +The nightly Tempo workflow (mainnet and testnet checks) has failed. This indicates a regression in Foundry's Tempo support or an issue with the Tempo mainnet/testnet endpoints. + +Check the [tempo nightly workflow page]({{ env.WORKFLOW_URL }}) for details. + +This issue was raised by the workflow at `.github/workflows/ci-tempo.yml`. diff --git a/.github/workflows/ci-tempo.yml b/.github/workflows/ci-tempo.yml index 06451b8428ea6..f594f52ea84e7 100644 --- a/.github/workflows/ci-tempo.yml +++ b/.github/workflows/ci-tempo.yml @@ -6,6 +6,8 @@ on: push: branches: [master] pull_request: + schedule: + - cron: "0 2 * * *" # Run daily at 2 AM UTC (offset from other nightlies) workflow_dispatch: inputs: network: @@ -59,36 +61,28 @@ jobs: cargo build --profile dev --locked -p forge -p cast -p anvil -p chisel echo "${{ github.workspace }}/target/debug" >> "$GITHUB_PATH" - # TODO: re-enable once devnet is up and stable - # - name: Run Tempo check on devnet - # if: | - # github.event_name == 'pull_request' || - # github.event.inputs.network == 'devnet' || - # github.event.inputs.network == 'all' - # env: - # ETH_RPC_URL: ${{ secrets.TEMPO_DEVNET_RPC_URL }} - # SCRIPTS: ${{ github.event.inputs.scripts || 'both' }} - # run: | - # if [ "$SCRIPTS" = "check" ] || [ "$SCRIPTS" = "both" ]; then - # ./.github/scripts/tempo-check.sh - # fi - # if [ "$SCRIPTS" = "deploy" ] || [ "$SCRIPTS" = "both" ]; then - # ./.github/scripts/tempo-deploy.sh - # fi - - # TODO: re-enable once devnet is up and stable - # - name: Run Tempo wallet tests on devnet - # if: | - # github.event_name == 'pull_request' || - # github.event.inputs.network == 'devnet' || - # github.event.inputs.network == 'all' - # env: - # ETH_RPC_URL: ${{ secrets.TEMPO_DEVNET_RPC_URL }} - # run: ./.github/scripts/tempo-wallet.sh + - name: Run Tempo check on mainnet + if: | + github.event_name == 'schedule' || + github.event.inputs.network == 'mainnet' || + github.event.inputs.network == 'all' + env: + ETH_RPC_URL: ${{ secrets.TEMPO_MAINNET_RPC_URL }} + TEMPO_FEE_TOKEN: "0x20c0000000000000000000000000000000000000" + VERIFIER_URL: ${{ secrets.VERIFIER_URL }} + PRIVATE_KEY: ${{ secrets.THROW_AWAY_MAINNET_PKEY }} + SCRIPTS: ${{ github.event.inputs.scripts || 'both' }} + run: | + if [ "$SCRIPTS" = "check" ] || [ "$SCRIPTS" = "both" ]; then + ./.github/scripts/tempo-check.sh + fi + if [ "$SCRIPTS" = "deploy" ] || [ "$SCRIPTS" = "both" ]; then + ./.github/scripts/tempo-deploy.sh + fi - name: Run Tempo check on testnet if: | - github.event_name == 'pull_request' || + github.event_name == 'schedule' || github.event.inputs.network == 'testnet' || github.event.inputs.network == 'all' env: @@ -103,15 +97,14 @@ jobs: ./.github/scripts/tempo-deploy.sh fi - - name: Run Tempo check on mainnet + - name: Run Tempo check on devnet if: | - github.event.inputs.network == 'mainnet' || + github.event_name == 'push' || + github.event_name == 'pull_request' || + github.event.inputs.network == 'devnet' || github.event.inputs.network == 'all' env: - ETH_RPC_URL: ${{ secrets.TEMPO_MAINNET_RPC_URL }} - TEMPO_FEE_TOKEN: "0x20c0000000000000000000000000000000000000" - VERIFIER_URL: ${{ secrets.VERIFIER_URL }} - PRIVATE_KEY: ${{ secrets.THROW_AWAY_MAINNET_PKEY }} + ETH_RPC_URL: ${{ secrets.TEMPO_DEVNET_RPC_URL }} SCRIPTS: ${{ github.event.inputs.scripts || 'both' }} run: | if [ "$SCRIPTS" = "check" ] || [ "$SCRIPTS" = "both" ]; then @@ -120,3 +113,35 @@ jobs: if [ "$SCRIPTS" = "deploy" ] || [ "$SCRIPTS" = "both" ]; then ./.github/scripts/tempo-deploy.sh fi + + - name: Run Tempo wallet tests on devnet + if: | + github.event_name == 'push' || + github.event_name == 'pull_request' || + github.event.inputs.network == 'devnet' || + github.event.inputs.network == 'all' + env: + ETH_RPC_URL: ${{ secrets.TEMPO_DEVNET_RPC_URL }} + run: ./.github/scripts/tempo-wallet.sh + + # If the nightly run fails, this will create an issue to signal so. + issue: + name: Open an issue + runs-on: ubuntu-latest + needs: [tempo-check] + if: failure() && github.event_name == 'schedule' + permissions: + contents: read + issues: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_URL: | + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + update_existing: true + filename: .github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index b97a99d5310a4..6120735657ee6 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -32,6 +32,8 @@ jobs: name: build and push runs-on: depot-ubuntu-latest permissions: + attestations: write + artifact-metadata: write contents: read id-token: write packages: write @@ -92,6 +94,7 @@ jobs: uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1 - name: Build and push Foundry image + id: build uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0 with: build-args: | @@ -106,3 +109,30 @@ jobs: platforms: linux/amd64,linux/arm64 push: true no-cache: true + sbom: true + provenance: mode=max + + - name: Install cosign + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + + - name: Sign image with cosign (keyless) + env: + DOCKER_TAGS: ${{ steps.docker_tagging.outputs.docker_tags }} + DIGEST: ${{ steps.build.outputs.digest }} + shell: bash + run: | + set -euo pipefail + IFS=',' read -r -a tags <<< "$DOCKER_TAGS" + for tag in "${tags[@]}"; do + # Strip any tag suffix and pin to immutable digest, then sign. + ref="${tag%%:*}@${DIGEST}" + printf 'Signing %s\n' "$ref" + cosign sign --yes "$ref" + done + + - name: Image build provenance attestation + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.build.outputs.digest }} + push-to-registry: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 682c9214284f6..38fa791fb655f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,7 @@ jobs: - name: Build changelog id: build_changelog - uses: mikepenz/release-changelog-builder-action@bcae7115752d4ed746ff92feb666574428a79415 # v6.2 + uses: mikepenz/release-changelog-builder-action@bcae7115752d4ed746ff92feb666574428a79415 # v6.2.1 with: configuration: "./.github/changelog.json" fromTag: ${{ steps.release_info.outputs.from_tag || '' }} @@ -117,6 +117,8 @@ jobs: needs: prepare uses: ./.github/workflows/docker-publish.yml permissions: + attestations: write + artifact-metadata: write contents: read id-token: write packages: write @@ -129,9 +131,10 @@ jobs: # way, GitHub's immutable-releases setting seals the release at publish. release: permissions: - id-token: write - contents: write attestations: write + artifact-metadata: write + contents: write + id-token: write name: release ${{ matrix.target }} (${{ matrix.runner }}) runs-on: ${{ matrix.runner }} timeout-minutes: 240 @@ -264,6 +267,38 @@ jobs: printf "file_name=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" >> "$GITHUB_OUTPUT" fi printf "foundry_attestation=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.attestation.txt" >> "$GITHUB_OUTPUT" + printf "foundry_sbom=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.spdx.json" >> "$GITHUB_OUTPUT" + printf "foundry_checksum=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.sha256" >> "$GITHUB_OUTPUT" + printf "foundry_signature=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.sigstore.json" >> "$GITHUB_OUTPUT" + + - name: Generate archive checksum + env: + FILE_NAME: ${{ steps.artifacts.outputs.file_name }} + FOUNDRY_CHECKSUM: ${{ steps.artifacts.outputs.foundry_checksum }} + shell: bash + run: | + set -euo pipefail + if command -v sha256sum >/dev/null 2>&1; then + sha256sum "$FILE_NAME" > "$FOUNDRY_CHECKSUM" + else + shasum -a 256 "$FILE_NAME" > "$FOUNDRY_CHECKSUM" + fi + cat "$FOUNDRY_CHECKSUM" + + - name: Install Syft + uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 + + - name: Generate SBOM (SPDX) + env: + FOUNDRY_SBOM: ${{ steps.artifacts.outputs.foundry_sbom }} + VERSION_NAME: ${{ (env.IS_NIGHTLY == 'true' && 'nightly') || needs.prepare.outputs.tag_name }} + shell: bash + run: | + set -euo pipefail + syft scan dir:. \ + --source-name foundry \ + --source-version "$VERSION_NAME" \ + -o spdx-json="$FOUNDRY_SBOM" - name: Upload build artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -292,15 +327,37 @@ jobs: tar -czvf "foundry_man_${VERSION_NAME}.tar.gz" forge.1.gz cast.1.gz anvil.1.gz chisel.1.gz printf 'foundry_man=%s\n' "foundry_man_${VERSION_NAME}.tar.gz" >> "$GITHUB_OUTPUT" - - name: Binaries attestation + - name: Binaries and archive provenance attestation id: attestation - uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 with: subject-path: | ${{ env.anvil_bin_path }} ${{ env.cast_bin_path }} ${{ env.chisel_bin_path }} ${{ env.forge_bin_path }} + ${{ steps.artifacts.outputs.file_name }} + + - name: Archive SBOM attestation + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 + with: + subject-path: ${{ steps.artifacts.outputs.file_name }} + sbom-path: ${{ steps.artifacts.outputs.foundry_sbom }} + + - name: Install cosign + uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + + - name: Sign archive with cosign (keyless) + env: + FILE_NAME: ${{ steps.artifacts.outputs.file_name }} + FOUNDRY_SIGNATURE: ${{ steps.artifacts.outputs.foundry_signature }} + shell: bash + run: | + set -euo pipefail + cosign sign-blob \ + --yes \ + --bundle "$FOUNDRY_SIGNATURE" \ + "$FILE_NAME" - name: Record attestation URL env: @@ -321,11 +378,20 @@ jobs: TAG_NAME: ${{ needs.prepare.outputs.tag_name }} FILE_NAME: ${{ steps.artifacts.outputs.file_name }} FOUNDRY_ATTESTATION: ${{ steps.artifacts.outputs.foundry_attestation }} + FOUNDRY_SBOM: ${{ steps.artifacts.outputs.foundry_sbom }} + FOUNDRY_CHECKSUM: ${{ steps.artifacts.outputs.foundry_checksum }} + FOUNDRY_SIGNATURE: ${{ steps.artifacts.outputs.foundry_signature }} FOUNDRY_MAN: ${{ steps.man.outputs.foundry_man }} shell: bash run: | set -euo pipefail - files=("$FILE_NAME" "$FOUNDRY_ATTESTATION") + files=( + "$FILE_NAME" + "$FOUNDRY_ATTESTATION" + "$FOUNDRY_SBOM" + "$FOUNDRY_CHECKSUM" + "$FOUNDRY_SIGNATURE" + ) if [[ -n "${FOUNDRY_MAN:-}" ]]; then files+=("$FOUNDRY_MAN") fi diff --git a/Cargo.lock b/Cargo.lock index 71d56653d7a20..11655f3ad966a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1223,7 +1223,7 @@ dependencies = [ [[package]] name = "anvil" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -1297,7 +1297,7 @@ dependencies = [ [[package]] name = "anvil-core" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "anvil-rpc" -version = "1.6.0" +version = "1.7.1" dependencies = [ "serde", "serde_json", @@ -1329,7 +1329,7 @@ dependencies = [ [[package]] name = "anvil-server" -version = "1.6.0" +version = "1.7.1" dependencies = [ "anvil-rpc", "async-trait", @@ -2745,7 +2745,7 @@ dependencies = [ [[package]] name = "cast" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -2876,7 +2876,7 @@ dependencies = [ [[package]] name = "chisel" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -4608,7 +4608,7 @@ checksum = "932dcfbd51320af5f27f1ba02d2e567dec332cac7d2c221ba45d8e767264c4dc" [[package]] name = "forge" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -4690,7 +4690,7 @@ dependencies = [ [[package]] name = "forge-doc" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-primitives", "derive_more", @@ -4714,7 +4714,7 @@ dependencies = [ [[package]] name = "forge-fmt" -version = "1.6.0" +version = "1.7.1" dependencies = [ "foundry-common", "foundry-config", @@ -4728,7 +4728,7 @@ dependencies = [ [[package]] name = "forge-lint" -version = "1.6.0" +version = "1.7.1" dependencies = [ "eyre", "foundry-common", @@ -4742,7 +4742,7 @@ dependencies = [ [[package]] name = "forge-script" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -4790,7 +4790,7 @@ dependencies = [ [[package]] name = "forge-script-sequence" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-network", "alloy-primitives", @@ -4806,7 +4806,7 @@ dependencies = [ [[package]] name = "forge-sol-macro-gen" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -4821,7 +4821,7 @@ dependencies = [ [[package]] name = "forge-verify" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -4867,7 +4867,7 @@ dependencies = [ [[package]] name = "foundry-bench" -version = "1.6.0" +version = "1.7.1" dependencies = [ "chrono", "clap", @@ -4902,7 +4902,7 @@ dependencies = [ [[package]] name = "foundry-cheatcodes" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -4955,7 +4955,7 @@ dependencies = [ [[package]] name = "foundry-cheatcodes-spec" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-sol-types", "foundry-macros", @@ -4966,7 +4966,7 @@ dependencies = [ [[package]] name = "foundry-cli" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-dyn-abi", @@ -5018,7 +5018,7 @@ dependencies = [ [[package]] name = "foundry-cli-markdown" -version = "1.6.0" +version = "1.7.1" dependencies = [ "clap", "pretty_assertions", @@ -5026,7 +5026,7 @@ dependencies = [ [[package]] name = "foundry-common" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -5096,7 +5096,7 @@ dependencies = [ [[package]] name = "foundry-common-fmt" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -5219,7 +5219,7 @@ dependencies = [ [[package]] name = "foundry-config" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-primitives", @@ -5259,7 +5259,7 @@ dependencies = [ [[package]] name = "foundry-debugger" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-primitives", "crossterm", @@ -5277,7 +5277,7 @@ dependencies = [ [[package]] name = "foundry-evm" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -5314,7 +5314,7 @@ dependencies = [ [[package]] name = "foundry-evm-abi" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -5326,7 +5326,7 @@ dependencies = [ [[package]] name = "foundry-evm-core" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -5378,7 +5378,7 @@ dependencies = [ [[package]] name = "foundry-evm-coverage" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-primitives", "eyre", @@ -5394,7 +5394,7 @@ dependencies = [ [[package]] name = "foundry-evm-fuzz" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -5419,7 +5419,7 @@ dependencies = [ [[package]] name = "foundry-evm-hardforks" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-hardforks", @@ -5434,7 +5434,7 @@ dependencies = [ [[package]] name = "foundry-evm-networks" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-eips 2.0.1", @@ -5450,11 +5450,11 @@ dependencies = [ [[package]] name = "foundry-evm-sancov" -version = "1.6.0" +version = "1.7.1" [[package]] name = "foundry-evm-traces" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -5511,7 +5511,7 @@ dependencies = [ [[package]] name = "foundry-linking" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-primitives", "foundry-compilers", @@ -5522,7 +5522,7 @@ dependencies = [ [[package]] name = "foundry-macros" -version = "1.6.0" +version = "1.7.1" dependencies = [ "proc-macro-error2", "proc-macro2", @@ -5532,7 +5532,7 @@ dependencies = [ [[package]] name = "foundry-primitives" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-consensus", "alloy-evm", @@ -5573,7 +5573,7 @@ dependencies = [ [[package]] name = "foundry-test-utils" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-primitives", @@ -6843,6 +6843,7 @@ version = "10.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" dependencies = [ + "aws-lc-rs", "base64 0.22.1", "getrandom 0.2.17", "js-sys", @@ -7811,7 +7812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b685c8311c9171d1bd2895222965d25616b2de2cb5819dd3504ed9250df9fecd" dependencies = [ "ahash", - "hashbrown 0.17.0", + "hashbrown 0.16.1", "parking_lot", "stable_deref_trait", ] @@ -11177,9 +11178,9 @@ dependencies = [ [[package]] name = "svm-rs" -version = "0.5.24" +version = "0.5.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230df06b463c7251e4d1b39b1b3e6f25a9b3a42630179053a1e5f919e6e15534" +checksum = "4572dd9845e37ca0293acb5fe591a7f61b51f1b7b62d3dc6fb8e99e2664f3755" dependencies = [ "const-hex", "dirs", @@ -11196,9 +11197,9 @@ dependencies = [ [[package]] name = "svm-rs-builds" -version = "0.5.24" +version = "0.5.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b271921143e5b12947a526de464db02b00363919d582a7ea712374840f928328" +checksum = "74224f62f19c1309caa071de7c1c9c1ad1d7551d2f881af4046f3d71880c820a" dependencies = [ "const-hex", "semver 1.0.28", diff --git a/Cargo.toml b/Cargo.toml index c27286e7d6ba0..5f2bc033bf885 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ members = [ resolver = "2" [workspace.package] -version = "1.6.0" +version = "1.7.1" edition = "2024" rust-version = "1.89" authors = ["Foundry Contributors"] diff --git a/README.md b/README.md index c9f0a45c57b0a..90cd1d8a7865e 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ foundryup See the [installation guide](https://getfoundry.sh/getting-started/installation) for more details. +To verify a downloaded release archive or container image, see [Verifying Releases](./SECURITY.md#verifying-releases). + ## Getting Started Initialize a new project, build and test: diff --git a/SECURITY.md b/SECURITY.md index d84327cc18e91..6296066db5e73 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,3 +3,112 @@ ## Reporting a Vulnerability Contact [security@tempo.xyz](mailto:security@tempo.xyz). + +## Verifying Releases + +Every official Foundry release ships with multiple, independent integrity +artifacts. All signing is keyless via [Sigstore](https://www.sigstore.dev/) — +no Foundry-managed key material is involved, and every signature is recorded +in the public [Rekor](https://docs.sigstore.dev/logging/overview/) transparency +log. The signing identity is the GitHub Actions OIDC token of this repository's +`release.yml` / `docker-publish.yml` workflows. + +### Per-release artifacts + +For each `foundry___.{tar.gz,zip}` archive on the +[releases page](https://github.com/foundry-rs/foundry/releases), the same +release also publishes: + +| Suffix | Purpose | +| --- | --- | +| `.sha256` | SHA-256 checksum of the archive (`sha256sum` format) | +| `.sigstore.json` | Cosign keyless signature bundle (cert + signature + Rekor proof) over the archive | +| `.spdx.json` | SPDX 2.3 SBOM of the source workspace used for the build | +| `.attestation.txt` | URL of the GitHub artifact-attestation summary | + +In addition, GitHub stores SLSA build-provenance and SBOM attestations against +the archive's digest; these are queryable via `gh attestation` without +downloading anything else. + +### Verifying an archive + +Pick whichever toolchain you have available — they verify the same signatures. + +#### Option 1: GitHub CLI (simplest) + +```bash +gh attestation verify foundry_v1.4.0_linux_amd64.tar.gz \ + --repo foundry-rs/foundry +``` + +This computes the file's digest, fetches the matching attestation from GitHub, +and verifies the Sigstore signature plus the SLSA provenance predicate. Add +`--signer-workflow foundry-rs/foundry/.github/workflows/release.yml` to also +require the workflow identity. + +To verify the SBOM attestation specifically: + +```bash +gh attestation verify foundry_v1.4.0_linux_amd64.tar.gz \ + --repo foundry-rs/foundry \ + --predicate-type 'https://spdx.dev/Document/v2.3' +``` + +#### Option 2: Cosign (offline-friendly) + +Download the archive and its `.sigstore.json` bundle from the release page, +then: + +```bash +cosign verify-blob \ + --bundle foundry_v1.4.0_linux_amd64.sigstore.json \ + --certificate-identity-regexp '^https://github.com/foundry-rs/foundry/\.github/workflows/release\.yml@.*' \ + --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \ + foundry_v1.4.0_linux_amd64.tar.gz +``` + +For nightly builds the certificate identity points at `refs/heads/master` +instead of a tag; the regex above matches both. + +#### Option 3: Plain checksum (integrity only) + +```bash +sha256sum -c foundry_v1.4.0_linux_amd64.sha256 # GNU coreutils +shasum -a 256 -c foundry_v1.4.0_linux_amd64.sha256 # macOS +``` + +This proves the bytes match what was uploaded, but says nothing about who +uploaded them. Combine with one of the verifications above for end-to-end +trust. + +### Verifying the Docker image + +Container signatures and attestations are pushed as OCI referrers to GHCR, so +no separate files need to be downloaded. + +```bash +# Cosign keyless signature on the image +cosign verify ghcr.io/foundry-rs/foundry:v1.4.0 \ + --certificate-identity-regexp '^https://github.com/foundry-rs/foundry/\.github/workflows/(release|docker-publish)\.yml@.*' \ + --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' + +# SLSA build-provenance attestation +gh attestation verify oci://ghcr.io/foundry-rs/foundry:v1.4.0 \ + --repo foundry-rs/foundry + +# Inspect the buildx-attached SBOM and provenance +docker buildx imagetools inspect ghcr.io/foundry-rs/foundry:v1.4.0 \ + --format '{{ json .SBOM }}' +docker buildx imagetools inspect ghcr.io/foundry-rs/foundry:v1.4.0 \ + --format '{{ json .Provenance }}' +``` + +To pin to an immutable digest (recommended for reproducible deployments): + +```bash +docker pull ghcr.io/foundry-rs/foundry:v1.4.0 +DIGEST=$(docker buildx imagetools inspect ghcr.io/foundry-rs/foundry:v1.4.0 --format '{{ .Manifest.Digest }}') +cosign verify "ghcr.io/foundry-rs/foundry@${DIGEST}" \ + --certificate-identity-regexp '^https://github.com/foundry-rs/foundry/\.github/workflows/(release|docker-publish)\.yml@.*' \ + --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' +``` diff --git a/crates/anvil/src/eth/pool/transactions.rs b/crates/anvil/src/eth/pool/transactions.rs index df65822e1eab3..5280987483dd7 100644 --- a/crates/anvil/src/eth/pool/transactions.rs +++ b/crates/anvil/src/eth/pool/transactions.rs @@ -123,10 +123,10 @@ impl PoolTransaction { impl fmt::Debug for PoolTransaction { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { write!(fmt, "Transaction {{ ")?; - write!(fmt, "hash: {:?}, ", &self.pending_transaction.hash())?; + write!(fmt, "hash: {:?}, ", self.pending_transaction.hash())?; write!(fmt, "requires: [{}], ", hex_fmt_many(self.requires.iter()))?; write!(fmt, "provides: [{}], ", hex_fmt_many(self.provides.iter()))?; - write!(fmt, "raw tx: {:?}", &self.pending_transaction)?; + write!(fmt, "raw tx: {:?}", self.pending_transaction)?; write!(fmt, "}}")?; Ok(()) } diff --git a/crates/cast/src/cmd/keychain.rs b/crates/cast/src/cmd/keychain.rs index 8b7d80786dfad..c952b58369e1c 100644 --- a/crates/cast/src/cmd/keychain.rs +++ b/crates/cast/src/cmd/keychain.rs @@ -646,7 +646,7 @@ async fn run_remaining_limit( }; if shell::is_json() { - sh_println!("{}", serde_json::to_string(&remaining.to_string())?)?; + sh_println!("{}", serde_json::json!({ "remaining": remaining.to_string() }))?; } else { sh_println!("{remaining}")?; } diff --git a/crates/cast/src/cmd/wallet/mod.rs b/crates/cast/src/cmd/wallet/mod.rs index 8e0dd8dd3ed8c..b2378d8bfdc58 100644 --- a/crates/cast/src/cmd/wallet/mod.rs +++ b/crates/cast/src/cmd/wallet/mod.rs @@ -779,8 +779,7 @@ flag to set your key via: )?; let address = wallet.address(); let success_message = format!( - "`{}` keystore was saved successfully. Address: {:?}", - &account_name, address, + "`{account_name}` keystore was saved successfully. Address: {address:?}", ); sh_println!("{}", success_message.green())?; } @@ -815,7 +814,7 @@ flag to set your key via: format!("Failed to remove keystore file at {}", keystore_path.display()) })?; - let success_message = format!("`{}` keystore was removed successfully.", &name); + let success_message = format!("`{name}` keystore was removed successfully."); sh_println!("{}", success_message.green())?; } Self::PrivateKey { @@ -886,8 +885,7 @@ flag to set your key via: let private_key = B256::from_slice(&wallet.credential().to_bytes()); - let success_message = - format!("{}'s private key is: {}", &account_name, private_key); + let success_message = format!("{account_name}'s private key is: {private_key}"); sh_println!("{}", success_message.green())?; } @@ -945,10 +943,9 @@ flag to set your key via: Some(&account_name), )?; + let address = wallet.address(); let success_message = format!( - "Password for keystore `{}` was changed successfully. Address: {:?}", - &account_name, - wallet.address(), + "Password for keystore `{account_name}` was changed successfully. Address: {address:?}", ); sh_println!("{}", success_message.green())?; } diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index ce5572acebc13..3f446b1fbedf0 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -246,7 +246,7 @@ impl + Clone + Unpin, N: Network> Cast { let mut s = vec![format!("gas used: {}", access_list.gas_used), "access list:".to_string()]; for al in access_list.access_list.0 { - s.push(format!("- address: {}", &al.address.to_checksum(None))); + s.push(format!("- address: {}", al.address.to_checksum(None))); if !al.storage_keys.is_empty() { s.push(" keys:".to_string()); for key in al.storage_keys { diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 7d6cb9e481502..94974301df8ac 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -864,7 +864,7 @@ "func": { "id": "assertApproxEqAbsDecimal_1", "description": "Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqAbsDecimal(uint256,uint256,uint256,uint256,string)", @@ -904,7 +904,7 @@ "func": { "id": "assertApproxEqAbsDecimal_3", "description": "Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqAbsDecimal(int256,int256,uint256,uint256,string)", @@ -944,7 +944,7 @@ "func": { "id": "assertApproxEqAbs_1", "description": "Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.\nIncludes error message into revert string on failure.", - "declaration": "function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure;", + "declaration": "function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqAbs(uint256,uint256,uint256,string)", @@ -984,7 +984,7 @@ "func": { "id": "assertApproxEqAbs_3", "description": "Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.\nIncludes error message into revert string on failure.", - "declaration": "function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure;", + "declaration": "function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqAbs(int256,int256,uint256,string)", @@ -1024,7 +1024,7 @@ "func": { "id": "assertApproxEqRelDecimal_1", "description": "Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.\n`maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqRelDecimal(uint256,uint256,uint256,uint256,string)", @@ -1064,7 +1064,7 @@ "func": { "id": "assertApproxEqRelDecimal_3", "description": "Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.\n`maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqRelDecimal(int256,int256,uint256,uint256,string)", @@ -1104,7 +1104,7 @@ "func": { "id": "assertApproxEqRel_1", "description": "Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.\n`maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%\nIncludes error message into revert string on failure.", - "declaration": "function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) external pure;", + "declaration": "function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqRel(uint256,uint256,uint256,string)", @@ -1144,7 +1144,7 @@ "func": { "id": "assertApproxEqRel_3", "description": "Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.\n`maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%\nIncludes error message into revert string on failure.", - "declaration": "function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) external pure;", + "declaration": "function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertApproxEqRel(int256,int256,uint256,string)", @@ -1184,7 +1184,7 @@ "func": { "id": "assertEqDecimal_1", "description": "Asserts that two `uint256` values are equal, formatting them with decimals in failure message.\nIncludes error message into revert string on failure.", - "declaration": "function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEqDecimal(uint256,uint256,uint256,string)", @@ -1224,7 +1224,7 @@ "func": { "id": "assertEqDecimal_3", "description": "Asserts that two `int256` values are equal, formatting them with decimals in failure message.\nIncludes error message into revert string on failure.", - "declaration": "function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEqDecimal(int256,int256,uint256,string)", @@ -1264,7 +1264,7 @@ "func": { "id": "assertEq_1", "description": "Asserts that two `bool` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(bool left, bool right, string calldata error) external pure;", + "declaration": "function assertEq(bool left, bool right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(bool,bool,string)", @@ -1304,7 +1304,7 @@ "func": { "id": "assertEq_11", "description": "Asserts that two `string` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(string calldata left, string calldata right, string calldata error) external pure;", + "declaration": "function assertEq(string calldata left, string calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(string,string,string)", @@ -1344,7 +1344,7 @@ "func": { "id": "assertEq_13", "description": "Asserts that two `bytes` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure;", + "declaration": "function assertEq(bytes calldata left, bytes calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(bytes,bytes,string)", @@ -1384,7 +1384,7 @@ "func": { "id": "assertEq_15", "description": "Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(bool[],bool[],string)", @@ -1424,7 +1424,7 @@ "func": { "id": "assertEq_17", "description": "Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(uint256[],uint256[],string)", @@ -1464,7 +1464,7 @@ "func": { "id": "assertEq_19", "description": "Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(int256[],int256[],string)", @@ -1524,7 +1524,7 @@ "func": { "id": "assertEq_21", "description": "Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(address[] calldata left, address[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(address[],address[],string)", @@ -1564,7 +1564,7 @@ "func": { "id": "assertEq_23", "description": "Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(bytes32[],bytes32[],string)", @@ -1604,7 +1604,7 @@ "func": { "id": "assertEq_25", "description": "Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(string[] calldata left, string[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(string[],string[],string)", @@ -1644,7 +1644,7 @@ "func": { "id": "assertEq_27", "description": "Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;", + "declaration": "function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(bytes[],bytes[],string)", @@ -1664,7 +1664,7 @@ "func": { "id": "assertEq_3", "description": "Asserts that two `uint256` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(uint256 left, uint256 right, string calldata error) external pure;", + "declaration": "function assertEq(uint256 left, uint256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(uint256,uint256,string)", @@ -1704,7 +1704,7 @@ "func": { "id": "assertEq_5", "description": "Asserts that two `int256` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(int256 left, int256 right, string calldata error) external pure;", + "declaration": "function assertEq(int256 left, int256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(int256,int256,string)", @@ -1744,7 +1744,7 @@ "func": { "id": "assertEq_7", "description": "Asserts that two `address` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(address left, address right, string calldata error) external pure;", + "declaration": "function assertEq(address left, address right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(address,address,string)", @@ -1784,7 +1784,7 @@ "func": { "id": "assertEq_9", "description": "Asserts that two `bytes32` values are equal and includes error message into revert string on failure.", - "declaration": "function assertEq(bytes32 left, bytes32 right, string calldata error) external pure;", + "declaration": "function assertEq(bytes32 left, bytes32 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertEq(bytes32,bytes32,string)", @@ -1824,7 +1824,7 @@ "func": { "id": "assertFalse_1", "description": "Asserts that the given condition is false and includes error message into revert string on failure.", - "declaration": "function assertFalse(bool condition, string calldata error) external pure;", + "declaration": "function assertFalse(bool condition, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertFalse(bool,string)", @@ -1864,7 +1864,7 @@ "func": { "id": "assertGeDecimal_1", "description": "Compares two `uint256` values. Expects first value to be greater than or equal to second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGeDecimal(uint256,uint256,uint256,string)", @@ -1904,7 +1904,7 @@ "func": { "id": "assertGeDecimal_3", "description": "Compares two `int256` values. Expects first value to be greater than or equal to second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGeDecimal(int256,int256,uint256,string)", @@ -1944,7 +1944,7 @@ "func": { "id": "assertGe_1", "description": "Compares two `uint256` values. Expects first value to be greater than or equal to second.\nIncludes error message into revert string on failure.", - "declaration": "function assertGe(uint256 left, uint256 right, string calldata error) external pure;", + "declaration": "function assertGe(uint256 left, uint256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGe(uint256,uint256,string)", @@ -1984,7 +1984,7 @@ "func": { "id": "assertGe_3", "description": "Compares two `int256` values. Expects first value to be greater than or equal to second.\nIncludes error message into revert string on failure.", - "declaration": "function assertGe(int256 left, int256 right, string calldata error) external pure;", + "declaration": "function assertGe(int256 left, int256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGe(int256,int256,string)", @@ -2024,7 +2024,7 @@ "func": { "id": "assertGtDecimal_1", "description": "Compares two `uint256` values. Expects first value to be greater than second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGtDecimal(uint256,uint256,uint256,string)", @@ -2064,7 +2064,7 @@ "func": { "id": "assertGtDecimal_3", "description": "Compares two `int256` values. Expects first value to be greater than second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGtDecimal(int256,int256,uint256,string)", @@ -2104,7 +2104,7 @@ "func": { "id": "assertGt_1", "description": "Compares two `uint256` values. Expects first value to be greater than second.\nIncludes error message into revert string on failure.", - "declaration": "function assertGt(uint256 left, uint256 right, string calldata error) external pure;", + "declaration": "function assertGt(uint256 left, uint256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGt(uint256,uint256,string)", @@ -2144,7 +2144,7 @@ "func": { "id": "assertGt_3", "description": "Compares two `int256` values. Expects first value to be greater than second.\nIncludes error message into revert string on failure.", - "declaration": "function assertGt(int256 left, int256 right, string calldata error) external pure;", + "declaration": "function assertGt(int256 left, int256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertGt(int256,int256,string)", @@ -2184,7 +2184,7 @@ "func": { "id": "assertLeDecimal_1", "description": "Compares two `uint256` values. Expects first value to be less than or equal to second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLeDecimal(uint256,uint256,uint256,string)", @@ -2224,7 +2224,7 @@ "func": { "id": "assertLeDecimal_3", "description": "Compares two `int256` values. Expects first value to be less than or equal to second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLeDecimal(int256,int256,uint256,string)", @@ -2264,7 +2264,7 @@ "func": { "id": "assertLe_1", "description": "Compares two `uint256` values. Expects first value to be less than or equal to second.\nIncludes error message into revert string on failure.", - "declaration": "function assertLe(uint256 left, uint256 right, string calldata error) external pure;", + "declaration": "function assertLe(uint256 left, uint256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLe(uint256,uint256,string)", @@ -2304,7 +2304,7 @@ "func": { "id": "assertLe_3", "description": "Compares two `int256` values. Expects first value to be less than or equal to second.\nIncludes error message into revert string on failure.", - "declaration": "function assertLe(int256 left, int256 right, string calldata error) external pure;", + "declaration": "function assertLe(int256 left, int256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLe(int256,int256,string)", @@ -2344,7 +2344,7 @@ "func": { "id": "assertLtDecimal_1", "description": "Compares two `uint256` values. Expects first value to be less than second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLtDecimal(uint256,uint256,uint256,string)", @@ -2384,7 +2384,7 @@ "func": { "id": "assertLtDecimal_3", "description": "Compares two `int256` values. Expects first value to be less than second.\nFormats values with decimals in failure message. Includes error message into revert string on failure.", - "declaration": "function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLtDecimal(int256,int256,uint256,string)", @@ -2424,7 +2424,7 @@ "func": { "id": "assertLt_1", "description": "Compares two `uint256` values. Expects first value to be less than second.\nIncludes error message into revert string on failure.", - "declaration": "function assertLt(uint256 left, uint256 right, string calldata error) external pure;", + "declaration": "function assertLt(uint256 left, uint256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLt(uint256,uint256,string)", @@ -2464,7 +2464,7 @@ "func": { "id": "assertLt_3", "description": "Compares two `int256` values. Expects first value to be less than second.\nIncludes error message into revert string on failure.", - "declaration": "function assertLt(int256 left, int256 right, string calldata error) external pure;", + "declaration": "function assertLt(int256 left, int256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertLt(int256,int256,string)", @@ -2504,7 +2504,7 @@ "func": { "id": "assertNotEqDecimal_1", "description": "Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.\nIncludes error message into revert string on failure.", - "declaration": "function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEqDecimal(uint256,uint256,uint256,string)", @@ -2544,7 +2544,7 @@ "func": { "id": "assertNotEqDecimal_3", "description": "Asserts that two `int256` values are not equal, formatting them with decimals in failure message.\nIncludes error message into revert string on failure.", - "declaration": "function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;", + "declaration": "function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEqDecimal(int256,int256,uint256,string)", @@ -2584,7 +2584,7 @@ "func": { "id": "assertNotEq_1", "description": "Asserts that two `bool` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(bool left, bool right, string calldata error) external pure;", + "declaration": "function assertNotEq(bool left, bool right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(bool,bool,string)", @@ -2624,7 +2624,7 @@ "func": { "id": "assertNotEq_11", "description": "Asserts that two `string` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(string calldata left, string calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(string calldata left, string calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(string,string,string)", @@ -2664,7 +2664,7 @@ "func": { "id": "assertNotEq_13", "description": "Asserts that two `bytes` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(bytes calldata left, bytes calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(bytes,bytes,string)", @@ -2704,7 +2704,7 @@ "func": { "id": "assertNotEq_15", "description": "Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(bool[],bool[],string)", @@ -2744,7 +2744,7 @@ "func": { "id": "assertNotEq_17", "description": "Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(uint256[],uint256[],string)", @@ -2784,7 +2784,7 @@ "func": { "id": "assertNotEq_19", "description": "Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(int256[],int256[],string)", @@ -2844,7 +2844,7 @@ "func": { "id": "assertNotEq_21", "description": "Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(address[] calldata left, address[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(address[],address[],string)", @@ -2884,7 +2884,7 @@ "func": { "id": "assertNotEq_23", "description": "Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(bytes32[],bytes32[],string)", @@ -2924,7 +2924,7 @@ "func": { "id": "assertNotEq_25", "description": "Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(string[] calldata left, string[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(string[],string[],string)", @@ -2964,7 +2964,7 @@ "func": { "id": "assertNotEq_27", "description": "Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;", + "declaration": "function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(bytes[],bytes[],string)", @@ -2984,7 +2984,7 @@ "func": { "id": "assertNotEq_3", "description": "Asserts that two `uint256` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(uint256 left, uint256 right, string calldata error) external pure;", + "declaration": "function assertNotEq(uint256 left, uint256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(uint256,uint256,string)", @@ -3024,7 +3024,7 @@ "func": { "id": "assertNotEq_5", "description": "Asserts that two `int256` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(int256 left, int256 right, string calldata error) external pure;", + "declaration": "function assertNotEq(int256 left, int256 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(int256,int256,string)", @@ -3064,7 +3064,7 @@ "func": { "id": "assertNotEq_7", "description": "Asserts that two `address` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(address left, address right, string calldata error) external pure;", + "declaration": "function assertNotEq(address left, address right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(address,address,string)", @@ -3104,7 +3104,7 @@ "func": { "id": "assertNotEq_9", "description": "Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.", - "declaration": "function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure;", + "declaration": "function assertNotEq(bytes32 left, bytes32 right, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertNotEq(bytes32,bytes32,string)", @@ -3144,7 +3144,7 @@ "func": { "id": "assertTrue_1", "description": "Asserts that the given condition is true and includes error message into revert string on failure.", - "declaration": "function assertTrue(bool condition, string calldata error) external pure;", + "declaration": "function assertTrue(bool condition, string calldata err) external pure;", "visibility": "external", "mutability": "pure", "signature": "assertTrue(bool,string)", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 65f181f6b0e35..7c2e0741704b3 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -1243,7 +1243,7 @@ interface Vm { /// Asserts that the given condition is true and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertTrue(bool condition, string calldata error) external pure; + function assertTrue(bool condition, string calldata err) external pure; /// Asserts that the given condition is false. #[cheatcode(group = Testing, safety = Safe)] @@ -1251,7 +1251,7 @@ interface Vm { /// Asserts that the given condition is false and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertFalse(bool condition, string calldata error) external pure; + function assertFalse(bool condition, string calldata err) external pure; /// Asserts that two `bool` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1259,7 +1259,7 @@ interface Vm { /// Asserts that two `bool` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(bool left, bool right, string calldata error) external pure; + function assertEq(bool left, bool right, string calldata err) external pure; /// Asserts that two `uint256` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1267,7 +1267,7 @@ interface Vm { /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(uint256 left, uint256 right, string calldata error) external pure; + function assertEq(uint256 left, uint256 right, string calldata err) external pure; /// Asserts that two `int256` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1275,7 +1275,7 @@ interface Vm { /// Asserts that two `int256` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(int256 left, int256 right, string calldata error) external pure; + function assertEq(int256 left, int256 right, string calldata err) external pure; /// Asserts that two `address` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1283,7 +1283,7 @@ interface Vm { /// Asserts that two `address` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(address left, address right, string calldata error) external pure; + function assertEq(address left, address right, string calldata err) external pure; /// Asserts that two `bytes32` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1291,7 +1291,7 @@ interface Vm { /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertEq(bytes32 left, bytes32 right, string calldata err) external pure; /// Asserts that two `string` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1299,7 +1299,7 @@ interface Vm { /// Asserts that two `string` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(string calldata left, string calldata right, string calldata error) external pure; + function assertEq(string calldata left, string calldata right, string calldata err) external pure; /// Asserts that two `bytes` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1307,7 +1307,7 @@ interface Vm { /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertEq(bytes calldata left, bytes calldata right, string calldata err) external pure; /// Asserts that two arrays of `bool` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1315,7 +1315,7 @@ interface Vm { /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `uint256 values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1323,7 +1323,7 @@ interface Vm { /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `int256` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1331,7 +1331,7 @@ interface Vm { /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `address` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1339,7 +1339,7 @@ interface Vm { /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertEq(address[] calldata left, address[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes32` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1347,7 +1347,7 @@ interface Vm { /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `string` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1355,7 +1355,7 @@ interface Vm { /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertEq(string[] calldata left, string[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes` values are equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1363,7 +1363,7 @@ interface Vm { /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. #[cheatcode(group = Testing, safety = Safe)] @@ -1372,7 +1372,7 @@ interface Vm { /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. #[cheatcode(group = Testing, safety = Safe)] @@ -1381,7 +1381,7 @@ interface Vm { /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `bool` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1389,7 +1389,7 @@ interface Vm { /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(bool left, bool right, string calldata error) external pure; + function assertNotEq(bool left, bool right, string calldata err) external pure; /// Asserts that two `uint256` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1397,7 +1397,7 @@ interface Vm { /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; + function assertNotEq(uint256 left, uint256 right, string calldata err) external pure; /// Asserts that two `int256` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1405,7 +1405,7 @@ interface Vm { /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(int256 left, int256 right, string calldata error) external pure; + function assertNotEq(int256 left, int256 right, string calldata err) external pure; /// Asserts that two `address` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1413,7 +1413,7 @@ interface Vm { /// Asserts that two `address` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(address left, address right, string calldata error) external pure; + function assertNotEq(address left, address right, string calldata err) external pure; /// Asserts that two `bytes32` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1421,7 +1421,7 @@ interface Vm { /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertNotEq(bytes32 left, bytes32 right, string calldata err) external pure; /// Asserts that two `string` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1429,7 +1429,7 @@ interface Vm { /// Asserts that two `string` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; + function assertNotEq(string calldata left, string calldata right, string calldata err) external pure; /// Asserts that two `bytes` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1437,7 +1437,7 @@ interface Vm { /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertNotEq(bytes calldata left, bytes calldata right, string calldata err) external pure; /// Asserts that two arrays of `bool` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1445,7 +1445,7 @@ interface Vm { /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `uint256` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1453,7 +1453,7 @@ interface Vm { /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `int256` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1461,7 +1461,7 @@ interface Vm { /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `address` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1469,7 +1469,7 @@ interface Vm { /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertNotEq(address[] calldata left, address[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes32` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1477,7 +1477,7 @@ interface Vm { /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `string` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1485,7 +1485,7 @@ interface Vm { /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertNotEq(string[] calldata left, string[] calldata right, string calldata err) external pure; /// Asserts that two arrays of `bytes` values are not equal. #[cheatcode(group = Testing, safety = Safe)] @@ -1493,7 +1493,7 @@ interface Vm { /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. #[cheatcode(group = Testing, safety = Safe)] @@ -1502,7 +1502,7 @@ interface Vm { /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. #[cheatcode(group = Testing, safety = Safe)] @@ -1511,7 +1511,7 @@ interface Vm { /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. #[cheatcode(group = Testing, safety = Safe)] @@ -1520,7 +1520,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be greater than second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGt(uint256 left, uint256 right, string calldata error) external pure; + function assertGt(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than second. #[cheatcode(group = Testing, safety = Safe)] @@ -1529,7 +1529,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be greater than second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGt(int256 left, int256 right, string calldata error) external pure; + function assertGt(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. @@ -1539,7 +1539,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. @@ -1549,7 +1549,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. #[cheatcode(group = Testing, safety = Safe)] @@ -1558,7 +1558,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGe(uint256 left, uint256 right, string calldata error) external pure; + function assertGe(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. #[cheatcode(group = Testing, safety = Safe)] @@ -1567,7 +1567,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGe(int256 left, int256 right, string calldata error) external pure; + function assertGe(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. @@ -1577,7 +1577,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. @@ -1587,7 +1587,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than second. #[cheatcode(group = Testing, safety = Safe)] @@ -1596,7 +1596,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be less than second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLt(uint256 left, uint256 right, string calldata error) external pure; + function assertLt(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than second. #[cheatcode(group = Testing, safety = Safe)] @@ -1605,7 +1605,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be less than second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLt(int256 left, int256 right, string calldata error) external pure; + function assertLt(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. @@ -1615,7 +1615,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. @@ -1625,7 +1625,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. #[cheatcode(group = Testing, safety = Safe)] @@ -1634,7 +1634,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLe(uint256 left, uint256 right, string calldata error) external pure; + function assertLe(uint256 left, uint256 right, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. #[cheatcode(group = Testing, safety = Safe)] @@ -1643,7 +1643,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLe(int256 left, int256 right, string calldata error) external pure; + function assertLe(int256 left, int256 right, string calldata err) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. @@ -1653,7 +1653,7 @@ interface Vm { /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. @@ -1663,7 +1663,7 @@ interface Vm { /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. #[cheatcode(group = Testing, safety = Safe)] @@ -1672,7 +1672,7 @@ interface Vm { /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata err) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. #[cheatcode(group = Testing, safety = Safe)] @@ -1681,7 +1681,7 @@ interface Vm { /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata err) external pure; /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. /// Formats values with decimals in failure message. @@ -1696,7 +1696,7 @@ interface Vm { uint256 right, uint256 maxDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. @@ -1712,7 +1712,7 @@ interface Vm { int256 right, uint256 maxDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. @@ -1724,7 +1724,7 @@ interface Vm { /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) external pure; + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata err) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% @@ -1735,7 +1735,7 @@ interface Vm { /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Includes error message into revert string on failure. #[cheatcode(group = Testing, safety = Safe)] - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) external pure; + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata err) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% @@ -1757,7 +1757,7 @@ interface Vm { uint256 right, uint256 maxPercentDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. @@ -1780,7 +1780,7 @@ interface Vm { int256 right, uint256 maxPercentDelta, uint256 decimals, - string calldata error + string calldata err ) external pure; /// Returns true if the current Foundry version is greater than or equal to the given version. diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index b22f76714dd0f..27545c1b6cd33 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -856,42 +856,6 @@ impl Cheatcodes { } } - // Handle mocked calls - if let Some(mocks) = self.mocked_calls.get_mut(&call.bytecode_address) { - let ctx = MockCallDataContext { - calldata: call.input.bytes(ecx), - value: call.transfer_value(), - }; - - if let Some(return_data_queue) = match mocks.get_mut(&ctx) { - Some(queue) => Some(queue), - None => mocks - .iter_mut() - .find(|(mock, _)| { - call.input.bytes(ecx).get(..mock.calldata.len()) == Some(&mock.calldata[..]) - && mock.value.is_none_or(|value| Some(value) == call.transfer_value()) - }) - .map(|(_, v)| v), - } && let Some(return_data) = if return_data_queue.len() == 1 { - // If the mocked calls stack has a single element in it, don't empty it - return_data_queue.front().map(|x| x.to_owned()) - } else { - // Else, we pop the front element - return_data_queue.pop_front() - } { - return Some(CallOutcome { - result: InterpreterResult { - result: return_data.ret_type, - output: return_data.data, - gas, - }, - memory_offset: call.return_memory_offset.clone(), - was_precompile_called: true, - precompile_call_logs: vec![], - }); - } - } - // Apply our prank if let Some(prank) = &self.get_prank(curr_depth) { // Apply delegate call, `call.caller`` will not equal `prank.prank_caller` @@ -932,6 +896,72 @@ impl Cheatcodes { } } + // Handle mocked calls + if let Some(mocks) = self.mocked_calls.get_mut(&call.bytecode_address) { + let ctx = MockCallDataContext { + calldata: call.input.bytes(ecx), + value: call.transfer_value(), + }; + + if let Some(return_data_queue) = match mocks.get_mut(&ctx) { + Some(queue) => Some(queue), + None => mocks + .iter_mut() + .find(|(mock, _)| { + call.input.bytes(ecx).get(..mock.calldata.len()) == Some(&mock.calldata[..]) + && mock.value.is_none_or(|value| Some(value) == call.transfer_value()) + }) + .map(|(_, v)| v), + } && let Some(return_data) = return_data_queue.front().map(|x| x.to_owned()) + { + if let Some(value) = call.transfer_value() { + let checkpoint = ecx.journal_mut().checkpoint(); + match ecx.journal_mut().transfer_loaded( + call.transfer_from(), + call.transfer_to(), + value, + ) { + None => { + if return_data.ret_type.is_ok() { + ecx.journal_mut().checkpoint_commit(); + } else { + ecx.journal_mut().checkpoint_revert(checkpoint); + } + } + Some(err) => { + ecx.journal_mut().checkpoint_revert(checkpoint); + return Some(CallOutcome { + result: InterpreterResult { + result: err.into(), + output: Bytes::new(), + gas, + }, + memory_offset: call.return_memory_offset.clone(), + was_precompile_called: false, + precompile_call_logs: vec![], + }); + } + } + } + + // If the mocked calls stack has a single element in it, don't empty it + if return_data_queue.len() > 1 { + return_data_queue.pop_front(); + } + + return Some(CallOutcome { + result: InterpreterResult { + result: return_data.ret_type, + output: return_data.data, + gas, + }, + memory_offset: call.return_memory_offset.clone(), + was_precompile_called: true, + precompile_call_logs: vec![], + }); + } + } + // Apply EIP-2930 access list self.apply_accesslist(ecx); @@ -1497,6 +1527,21 @@ impl Inspector> for Cheatcode } } + // this will ensure we don't have false positives when trying to diagnose reverts in fork + // mode + let diag = self.fork_revert_diagnostic.take(); + + // If the call already reverted, preserve that primary failure and skip post-call + // expect* validation so it cannot overwrite the original revert. + if outcome.result.is_revert() { + // if there's a revert and a previous call was diagnosed as fork related revert then we + // can return a better error here + if let Some(err) = diag { + outcome.result.output = Error::encode(err.to_error_msg(&self.labels)); + } + return; + } + // At the end of the call, // we need to check if we've found all the emits. // We know we've found all the expected emits in the right order @@ -1574,19 +1619,6 @@ impl Inspector> for Cheatcode self.expected_emits.clear() } - // this will ensure we don't have false positives when trying to diagnose reverts in fork - // mode - let diag = self.fork_revert_diagnostic.take(); - - // if there's a revert and a previous call was diagnosed as fork related revert then we can - // return a better error here - if outcome.result.is_revert() - && let Some(err) = diag - { - outcome.result.output = Error::encode(err.to_error_msg(&self.labels)); - return; - } - // try to diagnose reverts in multi-fork mode where a call is made to an address that does // not exist if let TxKind::Call(test_contract) = ecx.tx().kind() { @@ -1867,10 +1899,23 @@ impl Inspector> for Cheatcode } // Handle expected reverts - if let Some(expected_revert) = &self.expected_revert + if let Some(expected_revert) = &mut self.expected_revert && curr_depth <= expected_revert.depth && matches!(expected_revert.kind, ExpectedRevertKind::Default) { + // Mirror the logic in `call_end`: when an expected reverter address is set + // and we don't yet have one (or we're matching multiple reverts), record the + // would-be deployed address as the reverter. revm guarantees `outcome.address` + // is `Some(_)` whenever the constructor actually ran (including the revert + // case); it is only `None` for pre-frame rejection (depth/balance/nonce), + // for which a reverter address is meaningless. + if outcome.result.is_revert() + && expected_revert.reverter.is_some() + && (expected_revert.reverted_by.is_none() || expected_revert.count > 1) + && let Some(addr) = outcome.address + { + expected_revert.reverted_by = Some(addr); + } let mut expected_revert = std::mem::take(&mut self.expected_revert).unwrap(); return match revert_handlers::handle_expect_revert( false, diff --git a/crates/cheatcodes/src/test/assert.rs b/crates/cheatcodes/src/test/assert.rs index 632ba8e04245b..12d625768a0c9 100644 --- a/crates/cheatcodes/src/test/assert.rs +++ b/crates/cheatcodes/src/test/assert.rs @@ -164,7 +164,7 @@ impl EqRelAssertionError { format_units_uint(&f.left, decimals), format_units_uint(&f.right, decimals), format_delta_percent(&f.max_delta), - &f.real_delta, + f.real_delta, ), Self::Overflow => self.to_string(), } @@ -179,7 +179,7 @@ impl EqRelAssertionError { format_units_int(&f.left, decimals), format_units_int(&f.right, decimals), format_delta_percent(&f.max_delta), - &f.real_delta, + f.real_delta, ), Self::Overflow => self.to_string(), } @@ -222,9 +222,9 @@ fn handle_assertion_result_mono( /// Implements [crate::Cheatcode] for pairs of cheatcodes. /// /// Accepts a list of pairs of cheatcodes, where the first cheatcode is the one that doesn't contain -/// a custom error message, and the second one contains it at `error` field. +/// a custom error message, and the second one contains it at `err` field. /// -/// Passed `args` are the common arguments for both cheatcode structs (excluding `error` field). +/// Passed `args` are the common arguments for both cheatcode structs (excluding `err` field). /// /// Macro also accepts an optional closure that formats the error returned by the assertion. macro_rules! impl_assertions { @@ -267,10 +267,12 @@ macro_rules! impl_assertions { ccx: &mut CheatsCtxt<'_, '_, FEN>, executor: &mut dyn CheatcodesExecutor, ) -> Result { - let Self { $($arg,)* error } = self; + let Self { $($arg,)* err } = self; match $body { Ok(()) => Ok(Default::default()), - Err(err) => handle_assertion_result(ccx, executor, err, $error_formatter, Some(error)) + Err(assertion_err) => { + handle_assertion_result(ccx, executor, assertion_err, $error_formatter, Some(err)) + } } } } diff --git a/crates/cheatcodes/src/version.rs b/crates/cheatcodes/src/version.rs index fb722c2814baa..2b8f81518a621 100644 --- a/crates/cheatcodes/src/version.rs +++ b/crates/cheatcodes/src/version.rs @@ -20,7 +20,14 @@ impl Cheatcode for foundryVersionAtLeastCall { } fn foundry_version_cmp(version: &str) -> Result { - version_cmp(SEMVER_VERSION.split('-').next().unwrap(), version) + version_cmp(strip_semver_metadata(SEMVER_VERSION), version) +} + +/// Strips pre-release (e.g. `-nightly`, `-dev`) and build metadata +/// (e.g. `+..`) from a version string +/// so we compare on `MAJOR.MINOR.PATCH` only. +fn strip_semver_metadata(version: &str) -> &str { + version.split(['-', '+']).next().unwrap() } fn version_cmp(version_a: &str, version_b: &str) -> Result { @@ -42,3 +49,61 @@ fn parse_version(version: &str) -> Result { } Ok(version) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn strips_build_metadata_only() { + // Tagged release: `1.7.1+..` + assert_eq!(strip_semver_metadata("1.7.1+abc1234567.1737036656.release"), "1.7.1"); + } + + #[test] + fn strips_pre_release_and_build_metadata() { + // Nightly: `1.7.1-nightly+..` + assert_eq!(strip_semver_metadata("1.7.1-nightly+abc1234567.1737036656.release"), "1.7.1"); + // Dev: `1.7.1-dev+..` + assert_eq!(strip_semver_metadata("1.7.1-dev+abc1234567.1737036656.debug"), "1.7.1"); + } + + #[test] + fn strips_plain_version() { + assert_eq!(strip_semver_metadata("1.7.1"), "1.7.1"); + } + + #[test] + fn version_cmp_orders_correctly() { + assert_eq!(version_cmp("1.7.1", "1.7.1").unwrap(), Ordering::Equal); + assert_eq!(version_cmp("1.7.1", "1.7.0").unwrap(), Ordering::Greater); + assert_eq!(version_cmp("1.7.1", "1.7.2").unwrap(), Ordering::Less); + assert_eq!(version_cmp("1.7.1", "0.0.1").unwrap(), Ordering::Greater); + assert_eq!(version_cmp("1.7.1", "99.0.0").unwrap(), Ordering::Less); + } + + #[test] + fn parse_version_rejects_pre_release_and_build_metadata() { + // User-supplied versions must be plain `MAJOR.MINOR.PATCH`. + assert!(parse_version("1.7.1-nightly").is_err()); + assert!(parse_version("1.7.1+abc").is_err()); + assert!(parse_version("not-a-version").is_err()); + assert!(parse_version("1.7.1").is_ok()); + } + + #[test] + fn cmp_works_against_full_semver_version_strings() { + // Simulate comparing each shape of `SEMVER_VERSION` against a user-supplied version. + for current in [ + "1.7.1+abc1234567.1737036656.release", + "1.7.1-nightly+abc1234567.1737036656.release", + "1.7.1-dev+abc1234567.1737036656.debug", + "1.7.1", + ] { + let stripped = strip_semver_metadata(current); + assert_eq!(version_cmp(stripped, "1.7.1").unwrap(), Ordering::Equal); + assert_eq!(version_cmp(stripped, "1.7.0").unwrap(), Ordering::Greater); + assert_eq!(version_cmp(stripped, "1.7.2").unwrap(), Ordering::Less); + } + } +} diff --git a/crates/chisel/src/executor.rs b/crates/chisel/src/executor.rs index da2c7f4caff02..8d8122e05868e 100644 --- a/crates/chisel/src/executor.rs +++ b/crates/chisel/src/executor.rs @@ -384,8 +384,8 @@ fn format_event_definition(event_definition: &pt::EventDefinition) -> Result Result>() diff --git a/crates/cli/src/opts/evm.rs b/crates/cli/src/opts/evm.rs index 87f14e2039606..4fc437c7232f8 100644 --- a/crates/cli/src/opts/evm.rs +++ b/crates/cli/src/opts/evm.rs @@ -307,6 +307,17 @@ mod tests { assert_eq!(val, &Value::from(1000u64)); } + #[test] + fn rpc_url_arg_does_not_read_eth_rpc_url_env() { + use clap::CommandFactory; + + let command = EvmArgs::command(); + let rpc_url = + command.get_arguments().find(|arg| arg.get_id() == "rpc_url").expect("rpc_url arg"); + + assert!(rpc_url.get_env().is_none()); + } + #[test] fn can_parse_chain_id() { let args = EvmArgs { diff --git a/crates/cli/src/opts/rpc.rs b/crates/cli/src/opts/rpc.rs index 8c37860446683..3438b57ed054a 100644 --- a/crates/cli/src/opts/rpc.rs +++ b/crates/cli/src/opts/rpc.rs @@ -66,8 +66,20 @@ impl figment::Provider for RpcOpts { impl RpcOpts { /// Returns the RPC endpoint. pub fn url<'a>(&'a self, config: Option<&'a Config>) -> Result>> { + self.url_with_env(config, std::env::var("ETH_RPC_URL").ok()) + } + + fn url_with_env<'a>( + &'a self, + config: Option<&'a Config>, + env_url: Option, + ) -> Result>> { if self.flashbots { Ok(Some(Cow::Borrowed(FLASHBOTS_URL))) + } else if let Some(url) = self.common.rpc_url.as_deref() { + Ok(Some(Cow::Borrowed(url))) + } else if let Some(url) = env_url { + Ok(Some(Cow::Owned(url))) } else { self.common.url(config) } @@ -85,6 +97,9 @@ impl RpcOpts { pub fn dict(&self) -> Dict { let mut dict = self.common.dict(); + if let Ok(Some(url)) = self.url(None) { + dict.insert("eth_rpc_url".into(), url.into_owned().into()); + } if self.flashbots { dict.insert("eth_rpc_url".into(), FLASHBOTS_URL.into()); } @@ -199,6 +214,7 @@ impl figment::Provider for EthereumOpts { #[cfg(test)] mod tests { use super::*; + use clap::CommandFactory; #[test] fn parse_etherscan_opts() { @@ -223,4 +239,41 @@ mod tests { let id: u64 = chain_id.deserialize().expect("chain_id should deserialize as u64"); assert_eq!(id, 9745); } + + #[test] + fn rpc_url_arg_does_not_read_eth_rpc_url_env() { + let command = RpcOpts::command(); + let rpc_url = + command.get_arguments().find(|arg| arg.get_id() == "rpc_url").expect("rpc_url arg"); + + assert!(rpc_url.get_env().is_none()); + } + + #[test] + fn rpc_url_resolves_eth_rpc_url_env() { + let args = RpcOpts::default(); + let url = args + .url_with_env(None, Some("http://127.0.0.1:8545".to_string())) + .expect("url") + .expect("url"); + + assert_eq!(url.as_ref(), "http://127.0.0.1:8545"); + } + + #[test] + fn explicit_rpc_url_takes_precedence_over_eth_rpc_url_env() { + let args = RpcOpts { + common: RpcCommonOpts { + rpc_url: Some("http://127.0.0.1:8546".to_string()), + ..Default::default() + }, + ..Default::default() + }; + let url = args + .url_with_env(None, Some("http://127.0.0.1:8545".to_string())) + .expect("url") + .expect("url"); + + assert_eq!(url.as_ref(), "http://127.0.0.1:8546"); + } } diff --git a/crates/cli/src/opts/rpc_common.rs b/crates/cli/src/opts/rpc_common.rs index 05b98582fa88f..9c6285857f8cf 100644 --- a/crates/cli/src/opts/rpc_common.rs +++ b/crates/cli/src/opts/rpc_common.rs @@ -13,14 +13,10 @@ use serde::Serialize; use std::borrow::Cow; /// Common RPC-related options shared across CLI commands. -/// -/// This struct holds fields that both [`super::RpcOpts`] (cast) and -/// [`super::EvmArgs`] (forge/script) need, eliminating duplication and -/// making the two structs composable. #[derive(Clone, Debug, Default, Serialize, Parser)] pub struct RpcCommonOpts { /// The RPC endpoint. - #[arg(short, long, visible_alias = "fork-url", env = "ETH_RPC_URL")] + #[arg(short, long, visible_alias = "fork-url", value_name = "URL")] #[serde(rename = "eth_rpc_url", skip_serializing_if = "Option::is_none")] pub rpc_url: Option, @@ -80,12 +76,7 @@ impl figment::Provider for RpcCommonOpts { impl RpcCommonOpts { /// Returns the RPC endpoint URL, resolving from CLI args or config. pub fn url<'a>(&'a self, config: Option<&'a Config>) -> Result>> { - let url = match (self.rpc_url.as_deref(), config) { - (Some(url), _) => Some(Cow::Borrowed(url)), - (None, Some(config)) => config.get_rpc_url().transpose()?, - (None, None) => None, - }; - Ok(url) + resolve_rpc_url(self.rpc_url.as_deref(), config) } /// Builds a figment-compatible dictionary from these options. @@ -112,3 +103,16 @@ impl RpcCommonOpts { dict } } + +/// Resolves an RPC URL from an explicit CLI value or config. +pub fn resolve_rpc_url<'a>( + rpc_url: Option<&'a str>, + config: Option<&'a Config>, +) -> Result>> { + let url = match (rpc_url, config) { + (Some(url), _) => Some(Cow::Borrowed(url)), + (None, Some(config)) => config.get_rpc_url().transpose()?, + (None, None) => None, + }; + Ok(url) +} diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 51115fb4a0bae..2d7f721d3789b 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -34,7 +34,7 @@ alloy-signer.workspace = true alloy-pubsub.workspace = true alloy-rpc-client.workspace = true alloy-rpc-types = { workspace = true, features = ["eth", "engine"] } -alloy-rpc-types-engine = { workspace = true, features = ["jwt"] } +alloy-rpc-types-engine = { workspace = true, features = ["jwt-aws-lc-rs"] } alloy-sol-types.workspace = true alloy-transport-ipc.workspace = true alloy-transport-ws.workspace = true diff --git a/crates/common/build.rs b/crates/common/build.rs index d89e23be850f4..9afa01b5757ef 100644 --- a/crates/common/build.rs +++ b/crates/common/build.rs @@ -15,16 +15,13 @@ fn main() -> Result<(), Box> { let sha_short = &sha[..10]; let tag_name = try_env_var("TAG_NAME").unwrap_or_else(|| String::from("dev")); - let is_nightly = tag_name.contains("nightly"); - let version_suffix = if is_nightly { "nightly" } else { &tag_name }; + let version = release_version(&env_var("CARGO_PKG_VERSION"), &tag_name); + let is_nightly = tag_name.starts_with("nightly"); if is_nightly { println!("cargo:rustc-env=FOUNDRY_IS_NIGHTLY_VERSION=true"); } - let pkg_version = env_var("CARGO_PKG_VERSION"); - let version = format!("{pkg_version}-{version_suffix}"); - // `PROFILE` captures only release or debug. Get the actual name from the out directory. let out_dir = PathBuf::from(env_var("OUT_DIR")); let profile = out_dir.components().rev().nth(3).unwrap().as_os_str().to_str().unwrap(); @@ -87,6 +84,19 @@ fn env_var(name: &str) -> String { try_env_var(name).unwrap() } +fn release_version(pkg_version: &str, tag_name: &str) -> String { + if let Some(version) = tag_name.strip_prefix('v') { + return version.to_owned(); + } + + // Normalize `nightly-` to `nightly` so tarball and Docker nightly + // artifacts produce the same version string. The commit identifier is + // already included in the SemVer build metadata (after `+`). + let normalized = if tag_name.starts_with("nightly-") { "nightly" } else { tag_name }; + + format!("{pkg_version}-{normalized}") +} + fn try_env_var(name: &str) -> Option { println!("cargo:rerun-if-env-changed={name}"); std::env::var(name).ok() diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index 895b16b3b4532..12d2aea5b1287 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -411,7 +411,7 @@ impl ContractsByArtifact { let mut funcs = BTreeMap::new(); let mut events = BTreeMap::new(); let mut errors_abi = JsonAbi::new(); - for (_name, contract) in self.iter() { + for contract in self.values() { for func in contract.abi.functions() { funcs.insert(func.selector(), func.clone()); } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 3b60ebb4f324e..a980b1c017ea3 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -2864,19 +2864,35 @@ impl BasicConfig { /// /// This serializes to a table with the name of the profile pub fn to_string_pretty(&self) -> Result { - let mut value = toml::Value::try_from(self)?; + let mut profile_body = toml::Value::try_from(self)?; if let Some(ref network) = self.network - && let toml::Value::Table(ref mut table) = value + && let toml::Value::Table(ref mut table) = profile_body { - table.insert(network.clone(), toml::Value::Boolean(true)); + table.insert("network".to_string(), toml::Value::String(network.clone())); + } + + let mut profile_section = toml::value::Table::new(); + profile_section.insert(self.profile.to_string(), profile_body); + + let mut document = toml::value::Table::new(); + document.insert("profile".to_string(), toml::Value::Table(profile_section)); + + if self.network.as_deref() == Some("tempo") { + let mut endpoints = toml::value::Table::new(); + endpoints.insert( + "tempo".to_string(), + toml::Value::String("https://rpc.tempo.xyz/".to_string()), + ); + endpoints.insert( + "moderato".to_string(), + toml::Value::String("https://rpc.moderato.tempo.xyz/".to_string()), + ); + document.insert("rpc_endpoints".to_string(), toml::Value::Table(endpoints)); } - let s = toml::to_string_pretty(&value)?; + + let body = toml::to_string_pretty(&toml::Value::Table(document))?; Ok(format!( - "\ -[profile.{}] -{s} -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options\n", - self.profile + "{body}\n# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options\n" )) } } @@ -6681,6 +6697,55 @@ mod tests { }); } + #[test] + fn no_unknown_key_warning_for_network_field() { + // Regression test: `network` is a flattened `Option` field of `NetworkConfigs`. It must + // not trigger an unknown-key warning, regardless of whether it is set. + figment::Jail::expect_with(|jail| { + jail.create_file( + "foundry.toml", + r#" + [profile.default] + network = "tempo" + "#, + )?; + + let cfg = Config::load().unwrap(); + assert!( + !cfg.warnings.iter().any( + |w| matches!(w, crate::Warning::UnknownKey { key, .. } if key == "network") + ), + "did not expect UnknownKey warning for `network`, got: {:?}", + cfg.warnings + ); + Ok(()) + }); + } + + #[test] + fn no_unknown_key_warning_for_legacy_tempo_alias() { + // Regression test: the legacy `tempo = true` alias must keep working without warnings. + figment::Jail::expect_with(|jail| { + jail.create_file( + "foundry.toml", + r#" + [profile.default] + tempo = true + "#, + )?; + + let cfg = Config::load().unwrap(); + assert!( + !cfg.warnings + .iter() + .any(|w| matches!(w, crate::Warning::UnknownKey { key, .. } if key == "tempo")), + "did not expect UnknownKey warning for `tempo`, got: {:?}", + cfg.warnings + ); + Ok(()) + }); + } + #[test] fn fails_on_ambiguous_version_in_compilation_restrictions() { figment::Jail::expect_with(|jail| { diff --git a/crates/config/src/providers/warnings.rs b/crates/config/src/providers/warnings.rs index 930066b29cf73..ff1d0b35def47 100644 --- a/crates/config/src/providers/warnings.rs +++ b/crates/config/src/providers/warnings.rs @@ -38,7 +38,10 @@ const DOC_KEYS: &[&str] = &["out", "title", "book", "homepage", "repository", "p const RESERVED_KEYS: &[&str] = &["extends"]; /// Keys kept for backward compatibility that should not trigger unknown key warnings. -const BACKWARD_COMPATIBLE_KEYS: &[&str] = &["solc_version"]; +/// +/// `tempo` and `optimism` are legacy aliases for `network = "tempo"` / `network = "optimism"` — +/// still accepted on input but no longer serialized in the default config. +const BACKWARD_COMPATIBLE_KEYS: &[&str] = &["solc_version", "tempo", "optimism"]; /// Generate warnings for unknown sections and deprecated keys pub struct WarningsProvider

{ diff --git a/crates/doc/src/writer/as_doc.rs b/crates/doc/src/writer/as_doc.rs index 1502322ac87f4..c4cc5bd07a234 100644 --- a/crates/doc/src/writer/as_doc.rs +++ b/crates/doc/src/writer/as_doc.rs @@ -75,8 +75,8 @@ impl AsDoc for CommentsRef<'_> { writer.writeln_raw(format!( "{}{}: {}", if customs.len() == 1 { "" } else { "- " }, - &c.tag, - &c.value + c.tag, + c.value ))?; writer.writeln()?; } diff --git a/crates/evm/core/src/decode.rs b/crates/evm/core/src/decode.rs index 0cfd56a44219c..b836023a968b7 100644 --- a/crates/evm/core/src/decode.rs +++ b/crates/evm/core/src/decode.rs @@ -223,8 +223,8 @@ fn trimmed_hex(s: &[u8]) -> String { } else { format!( "{}…{} ({} bytes)", - &hex::encode(&s[..n / 2]), - &hex::encode(&s[s.len() - n / 2..]), + hex::encode(&s[..n / 2]), + hex::encode(&s[s.len() - n / 2..]), s.len(), ) } diff --git a/crates/evm/core/src/fork/database.rs b/crates/evm/core/src/fork/database.rs index aefa0e2ee9741..2284823047ca6 100644 --- a/crates/evm/core/src/fork/database.rs +++ b/crates/evm/core/src/fork/database.rs @@ -212,13 +212,18 @@ pub struct ForkDbStateSnapshot { } impl ForkDbStateSnapshot { - fn get_storage(&self, address: Address, index: U256) -> Option { - self.local - .cache - .accounts - .get(&address) - .and_then(|account| account.storage.get(&index)) - .copied() + /// Lookup storage in `state_snapshot`, then fall back to the backend (remote RPC). + fn storage_from_snapshot_or_backend( + &self, + address: Address, + index: U256, + ) -> Result { + // Check state_snapshot.storage first (data fetched by SharedBackend / disk cache). + if let Some(val) = self.state_snapshot.storage.get(&address).and_then(|s| s.get(&index)) { + return Ok(*val); + } + // Fall back to the underlying backend (SharedBackend → remote RPC). + DatabaseRef::storage_ref(&self.local, address, index) } } @@ -250,15 +255,9 @@ impl DatabaseRef for ForkDbStateSnapshot { match self.local.cache.accounts.get(&address) { Some(account) => match account.storage.get(&index) { Some(entry) => Ok(*entry), - None => match self.get_storage(address, index) { - None => DatabaseRef::storage_ref(&self.local, address, index), - Some(storage) => Ok(storage), - }, - }, - None => match self.get_storage(address, index) { - None => DatabaseRef::storage_ref(&self.local, address, index), - Some(storage) => Ok(storage), + None => self.storage_from_snapshot_or_backend(address, index), }, + None => self.storage_from_snapshot_or_backend(address, index), } } @@ -303,4 +302,28 @@ mod tests { assert!(loaded.is_some()); assert_eq!(loaded.unwrap(), info); } + + /// Verifies that `ForkDbStateSnapshot::storage_ref` reads from `state_snapshot.storage` + /// when the slot is missing from `local.cache.accounts`. Without this lookup the call + /// would fall through to the backend and return the unrelated remote value. + #[tokio::test(flavor = "multi_thread")] + async fn fork_db_state_snapshot_reads_storage_from_snapshot() { + let rpc = foundry_test_utils::rpc::next_http_rpc_endpoint(); + let provider = get_http_provider(rpc.clone()); + let meta = BlockchainDbMeta::new(BlockEnv::default(), rpc); + let db = BlockchainDb::new(meta, None); + let backend = SharedBackend::spawn_backend(Arc::new(provider), db, None).await; + + let address = Address::random(); + let slot = U256::from(42u64); + let expected = U256::from(0xdeadbeefu64); + + let mut state_snapshot = StateSnapshot::default(); + state_snapshot.storage.entry(address).or_default().insert(slot, expected); + + let snapshot = ForkDbStateSnapshot { local: CacheDB::new(backend), state_snapshot }; + + let got = DatabaseRef::storage_ref(&snapshot, address, slot).unwrap(); + assert_eq!(got, expected); + } } diff --git a/crates/evm/evm/src/executors/invariant/mod.rs b/crates/evm/evm/src/executors/invariant/mod.rs index 27d8e6a0ed588..e02cdbc393ee6 100644 --- a/crates/evm/evm/src/executors/invariant/mod.rs +++ b/crates/evm/evm/src/executors/invariant/mod.rs @@ -736,7 +736,7 @@ impl<'a, FEN: FoundryEvmNetwork> InvariantExecutor<'a, FEN> { if !msg.is_empty() { msg.push_str(", "); } - msg.push_str(&format!("{}", &corpus_manager.metrics)); + msg.push_str(&format!("{}", corpus_manager.metrics)); } progress.set_message(msg); } diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index addaddc180efd..2a3bce3dac89e 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -1291,6 +1291,15 @@ impl Inspector> && !self.in_inner_context && ecx.journal().depth() == 1 { + // In isolation mode, transact_inner returns None for the address on revert; pre-compute + // the would-be deployed address so create_end can enforce expected_revert reverter + // checks. + let precomputed_address = ecx + .journal() + .evm_state() + .get(&create.caller()) + .map(|acc| create.caller().create(acc.info.nonce)); + let (result, address) = self.transact_inner( ecx, TxKind::Create, @@ -1299,6 +1308,8 @@ impl Inspector> create.gas_limit(), create.value(), ); + let address = + address.or_else(|| if result.is_revert() { precomputed_address } else { None }); return Some(CreateOutcome { result, address }); } diff --git a/crates/evm/fuzz/src/lib.rs b/crates/evm/fuzz/src/lib.rs index 44d71fb6deee3..e64d7abc5add3 100644 --- a/crates/evm/fuzz/src/lib.rs +++ b/crates/evm/fuzz/src/lib.rs @@ -229,7 +229,7 @@ impl fmt::Display for BaseCounterExample { if let Some(sig) = &self.signature { write!(f, "calldata={sig}")? } else { - write!(f, "calldata={}", &self.calldata)? + write!(f, "calldata={}", self.calldata)? } if let Some(args) = &self.args { diff --git a/crates/evm/networks/src/lib.rs b/crates/evm/networks/src/lib.rs index 4672deff353d0..303b9ca8b7a13 100644 --- a/crates/evm/networks/src/lib.rs +++ b/crates/evm/networks/src/lib.rs @@ -59,22 +59,25 @@ impl From for NetworkVariant { } } -#[derive(Clone, Debug, Default, Parser, Serialize, Deserialize, Copy, PartialEq, Eq)] +#[derive(Clone, Debug, Default, Parser, Deserialize, Copy, PartialEq, Eq)] pub struct NetworkConfigs { /// Enable a specific network family. #[arg(help_heading = "Networks", long, short, num_args = 1, value_name = "NETWORK", value_enum, conflicts_with_all = ["celo", "optimism", "tempo"])] - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] network: Option, /// Enable Celo network features. #[arg(help_heading = "Networks", long, conflicts_with_all = ["network", "optimism", "tempo"])] celo: bool, /// Enable Optimism network features (deprecated: use --network optimism). #[arg(long, hide = true, conflicts_with_all = ["network", "celo", "tempo"])] - // Skipped from configs (forge) as there is no feature to be added yet. - #[serde(skip)] + // Deserialize-only legacy alias: accepted in foundry.toml but never serialized — the + // canonical form is `network = "optimism"`. + #[serde(default)] optimism: bool, /// Enable Tempo network features (deprecated: use --network tempo). #[arg(long, hide = true, conflicts_with_all = ["network", "celo", "optimism"])] + // Deserialize-only legacy alias: accepted in foundry.toml but never serialized — the + // canonical form is `network = "tempo"`. #[serde(default)] tempo: bool, /// Whether to bypass prevrandao. @@ -83,6 +86,21 @@ pub struct NetworkConfigs { bypass_prevrandao: bool, } +// Custom `Serialize` impl: always emits the *resolved* network as the canonical +// `network = "..."` field, and never emits the legacy `tempo` / `optimism` aliases. This avoids +// confusing output like `network = "tempo"` next to `tempo = false`, and ensures `tempo = true` +// in foundry.toml round-trips as `network = "tempo"`. +impl Serialize for NetworkConfigs { + fn serialize(&self, serializer: S) -> Result { + use serde::ser::SerializeStruct; + let mut s = serializer.serialize_struct("NetworkConfigs", 3)?; + s.serialize_field("network", &self.resolved_network())?; + s.serialize_field("celo", &self.celo)?; + s.serialize_field("bypass_prevrandao", &self.bypass_prevrandao)?; + s.end() + } +} + impl NetworkConfigs { pub fn with_optimism() -> Self { Self { network: Some(NetworkVariant::Optimism), optimism: true, ..Default::default() } @@ -311,6 +329,17 @@ mod tests { assert!(cfg.is_tempo()); } + #[test] + fn serde_serializes_legacy_alias_as_canonical_network() { + // Legacy `tempo = true` should serialize as the canonical `network = "tempo"`, + // and the legacy `tempo` / `optimism` keys must not appear in the output. + let cfg = NetworkConfigs { tempo: true, ..Default::default() }; + let json = serde_json::to_value(cfg).unwrap(); + assert_eq!(json["network"], serde_json::json!("tempo")); + assert!(json.get("tempo").is_none(), "legacy `tempo` key should not be serialized"); + assert!(json.get("optimism").is_none(), "legacy `optimism` key should not be serialized"); + } + #[test] fn serde_new_network_field_deserialized() { let json_tempo = r#"{"network": "tempo", "celo": false, "bypass_prevrandao": false}"#; diff --git a/crates/fmt/src/state/mod.rs b/crates/fmt/src/state/mod.rs index 89a9bf152c8c2..4b986017b71dd 100644 --- a/crates/fmt/src/state/mod.rs +++ b/crates/fmt/src/state/mod.rs @@ -711,7 +711,7 @@ impl<'sess> State<'sess, '_> { // Merge the lines and let the wrapper handle breaking if needed let merged_line = format!( "{current_line} {next_content}", - next_content = &next_line[prefix.len()..].trim_start() + next_content = next_line[prefix.len()..].trim_start() ); result.push(merged_line); diff --git a/crates/forge/assets/tempo/MailTemplate.s.sol b/crates/forge/assets/tempo/MailTemplate.s.sol index 27512efe4d5ec..45006f7cd0e06 100644 --- a/crates/forge/assets/tempo/MailTemplate.s.sol +++ b/crates/forge/assets/tempo/MailTemplate.s.sol @@ -14,7 +14,7 @@ contract MailScript is Script { function run(string memory salt) public { vm.startBroadcast(); - address feeToken = vm.envOr("TEMPO_FEE_TOKEN", StdTokens.ALPHA_USD_ADDRESS); + address feeToken = vm.envOr("TEMPO_FEE_TOKEN", StdTokens.PATH_USD_ADDRESS); StdPrecompiles.TIP_FEE_MANAGER.setUserToken(feeToken); ITIP20 token = ITIP20( diff --git a/crates/forge/assets/tempo/MailTemplate.t.sol b/crates/forge/assets/tempo/MailTemplate.t.sol index b1749db5df0bf..19760303860a1 100644 --- a/crates/forge/assets/tempo/MailTemplate.t.sol +++ b/crates/forge/assets/tempo/MailTemplate.t.sol @@ -17,7 +17,7 @@ contract MailTest is Test { address public constant BOB = address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); function setUp() public virtual { - address feeToken = vm.envOr("TEMPO_FEE_TOKEN", StdTokens.ALPHA_USD_ADDRESS); + address feeToken = vm.envOr("TEMPO_FEE_TOKEN", StdTokens.PATH_USD_ADDRESS); StdPrecompiles.TIP_FEE_MANAGER.setUserToken(feeToken); token = ITIP20( diff --git a/crates/forge/src/cmd/coverage.rs b/crates/forge/src/cmd/coverage.rs index ea034bce87185..b8ce2a9b945b1 100644 --- a/crates/forge/src/cmd/coverage.rs +++ b/crates/forge/src/cmd/coverage.rs @@ -87,8 +87,11 @@ impl CoverageArgs { config = self.load_config()?; } - // Set fuzz seed so coverage reports are deterministic - config.fuzz.seed = Some(U256::from_be_bytes(STATIC_FUZZ_SEED)); + // Default to a static fuzz seed so coverage reports are deterministic, + // but allow the user to override it via `--fuzz-seed` or `[fuzz] seed` in config. + if config.fuzz.seed.is_none() { + config.fuzz.seed = Some(U256::from_be_bytes(STATIC_FUZZ_SEED)); + } let (paths, mut output) = { let (project, output) = self.build(&config)?; diff --git a/crates/forge/src/cmd/create.rs b/crates/forge/src/cmd/create.rs index 765bb64f95fdd..98564ec01ea67 100644 --- a/crates/forge/src/cmd/create.rs +++ b/crates/forge/src/cmd/create.rs @@ -408,15 +408,18 @@ impl CreateArgs { // Apply user-provided gas, fee, nonce, and Tempo options. self.tx.apply::(&mut deployer.tx, is_legacy); - // For keychain mode, set key_id and nonce_key before gas estimation. // Convert the CREATE into an AA-compatible call entry since Tempo AA // transactions use a `calls` list instead of `to`+`input`. + if chain.is_tempo() { + deployer.tx.convert_create_to_call(); + } + + // For keychain mode, set key_id and nonce_key before gas estimation. if let Some((_, ref ak)) = tempo_keychain { deployer.tx.set_key_id(ak.key_address); if deployer.tx.nonce_key().is_none() { deployer.tx.set_nonce_key(U256::ZERO); } - deployer.tx.convert_create_to_call(); } // Fetch defaults from provider for values not specified by user. diff --git a/crates/forge/src/cmd/snapshot.rs b/crates/forge/src/cmd/snapshot.rs index c8dc2ba72aae1..7c6fb51ce3266 100644 --- a/crates/forge/src/cmd/snapshot.rs +++ b/crates/forge/src/cmd/snapshot.rs @@ -99,8 +99,11 @@ impl GasSnapshotArgs { } pub async fn run(mut self) -> Result<()> { - // Set fuzz seed so gas snapshots are deterministic - self.test.fuzz_seed = Some(U256::from_be_bytes(STATIC_FUZZ_SEED)); + // Default to a static fuzz seed so gas snapshots are deterministic, + // but allow the user to override it via `--fuzz-seed`. + if self.test.fuzz_seed.is_none() { + self.test.fuzz_seed = Some(U256::from_be_bytes(STATIC_FUZZ_SEED)); + } let outcome = self.test.compile_and_run().await?; outcome.ensure_ok(false)?; diff --git a/crates/forge/src/cmd/test/mod.rs b/crates/forge/src/cmd/test/mod.rs index da300c429e37e..67294bc997f70 100644 --- a/crates/forge/src/cmd/test/mod.rs +++ b/crates/forge/src/cmd/test/mod.rs @@ -905,7 +905,7 @@ impl TestArgs { if let Some(gas_report) = gas_report { let finalized = gas_report.finalize(); - sh_println!("{}", &finalized)?; + sh_println!("{finalized}")?; outcome.gas_report = Some(finalized); } @@ -915,7 +915,7 @@ impl TestArgs { if self.summary && !outcome.results.is_empty() { let summary_report = TestSummaryReport::new(self.detailed, outcome.clone()); - sh_println!("{}", &summary_report)?; + sh_println!("{summary_report}")?; } // Reattach the task. diff --git a/crates/forge/src/cmd/test/summary.rs b/crates/forge/src/cmd/test/summary.rs index f8a72272af53c..a0123e896d0bf 100644 --- a/crates/forge/src/cmd/test/summary.rs +++ b/crates/forge/src/cmd/test/summary.rs @@ -25,9 +25,9 @@ impl TestSummaryReport { impl Display for TestSummaryReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { if shell::is_json() { - writeln!(f, "{}", &self.format_json_output(&self.is_detailed, &self.outcome))?; + writeln!(f, "{}", self.format_json_output(&self.is_detailed, &self.outcome))?; } else { - writeln!(f, "\n{}", &self.format_table_output(&self.is_detailed, &self.outcome))?; + writeln!(f, "\n{}", self.format_table_output(&self.is_detailed, &self.outcome))?; } Ok(()) } diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index 6c93dc03b28b5..58b11d98874ed 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -146,7 +146,7 @@ impl GasReport { impl Display for GasReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { if shell::is_json() { - writeln!(f, "{}", &self.format_json_output())?; + writeln!(f, "{}", self.format_json_output())?; } else { for (name, contract) in &self.contracts { if contract.functions.is_empty() { diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index d924c416759a2..353d8b1f55cde 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -826,7 +826,7 @@ impl<'a, FEN: FoundryEvmNetwork> FunctionRunner<'a, FEN> { ); if let Some(ref progress) = progress { - progress.set_prefix(format!("{}\n{warn}\n", &func.name)); + progress.set_prefix(format!("{}\n{warn}\n", func.name)); } else { let _ = sh_warn!("{warn}"); } diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index d3f1503faf569..6e0acebc67225 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -916,11 +916,18 @@ Installing tempo-std in [..] (url: https://github.com/tempoxyz/tempo-std, tag: N assert!(prj.root().join("foundry.toml").exists()); - // Verify foundry.toml contains `tempo = true` so subsequent commands auto-detect the network. + // Verify foundry.toml contains `network = "tempo"` so subsequent commands auto-detect the + // network. let foundry_toml = std::fs::read_to_string(prj.root().join("foundry.toml")).unwrap(); assert!( - foundry_toml.contains("tempo = true"), - "foundry.toml should contain `tempo = true`, got:\n{foundry_toml}" + foundry_toml.contains("network = \"tempo\""), + "foundry.toml should contain `network = \"tempo\"`, got:\n{foundry_toml}" + ); + assert!( + foundry_toml.contains("[rpc_endpoints]") + && foundry_toml.contains("tempo = \"https://rpc.tempo.xyz/\"") + && foundry_toml.contains("moderato = \"https://rpc.moderato.tempo.xyz/\""), + "foundry.toml should contain tempo rpc_endpoints, got:\n{foundry_toml}" ); assert!(prj.root().join("lib/forge-std").exists()); @@ -1816,7 +1823,7 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -1830,7 +1837,7 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -1844,7 +1851,7 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -1863,7 +1870,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -1879,7 +1886,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -1895,7 +1902,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -1921,7 +1928,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -1935,7 +1942,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -1949,7 +1956,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -1968,7 +1975,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -1984,7 +1991,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2000,7 +2007,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2026,7 +2033,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2040,7 +2047,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -2054,7 +2061,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2073,7 +2080,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2089,7 +2096,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2105,7 +2112,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2134,7 +2141,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2148,7 +2155,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -2162,7 +2169,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2181,7 +2188,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2197,7 +2204,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2213,7 +2220,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2246,7 +2253,7 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2265,7 +2272,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2293,7 +2300,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2312,7 +2319,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2340,7 +2347,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -2359,7 +2366,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2395,7 +2402,7 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -2409,7 +2416,7 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2428,7 +2435,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2444,7 +2451,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2476,7 +2483,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2490,7 +2497,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -2509,7 +2516,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2525,7 +2532,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2565,7 +2572,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2579,7 +2586,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133219 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| @@ -2593,7 +2600,7 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133015 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| @@ -2622,7 +2629,7 @@ Warning: ContractThree is listed in both 'gas_reports' and 'gas_reports_ignore'. { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -2638,7 +2645,7 @@ Warning: ContractThree is listed in both 'gas_reports' and 'gas_reports_ignore'. { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 133243, + "gas": 133219, "size": 395 }, "functions": { @@ -2654,7 +2661,7 @@ Warning: ContractThree is listed in both 'gas_reports' and 'gas_reports_ignore'. { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 133027, + "gas": 133015, "size": 394 }, "functions": { @@ -3106,7 +3113,7 @@ contract NestedDeploy is Test { +============================================================================================+ | Deployment Cost | Deployment Size | | | | | |-------------------------------------------+-----------------+-----+--------+-----+---------| -| 328961 | 1163 | | | | | +| 328949 | 1163 | | | | | |-------------------------------------------+-----------------+-----+--------+-----+---------| | | | | | | | |-------------------------------------------+-----------------+-----+--------+-----+---------| @@ -3161,7 +3168,7 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) { "contract": "test/NestedDeployTest.sol:Parent", "deployment": { - "gas": 328961, + "gas": 328949, "size": 1163 }, "functions": { @@ -3918,7 +3925,7 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { +=======================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| -| 156813 | 509 | | | | | +| 156801 | 509 | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| @@ -3942,7 +3949,7 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { |-----------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------+-----------------+--------+--------+--------+---------| -| setUp | 218902 | 218902 | 218902 | 218902 | 1 | +| setUp | 218890 | 218890 | 218890 | 218890 | 1 | |-----------------------------------------+-----------------+--------+--------+--------+---------| | test_Increment | 51847 | 51847 | 51847 | 51847 | 1 | ╰-----------------------------------------+-----------------+--------+--------+--------+---------╯ @@ -3960,7 +3967,7 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) | src/Counter.sol:Counter Contract | | | | | | |----------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 156813 | 509 | | | | | +| 156801 | 509 | | | | | | | | | | | | | Function Name | Min | Avg | Median | Max | # Calls | | increment | 43482 | 43482 | 43482 | 43482 | 1 | @@ -3973,7 +3980,7 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) | 1544498 | 7573 | | | | | | | | | | | | | Function Name | Min | Avg | Median | Max | # Calls | -| setUp | 218902 | 218902 | 218902 | 218902 | 1 | +| setUp | 218890 | 218890 | 218890 | 218890 | 1 | | test_Increment | 51847 | 51847 | 51847 | 51847 | 1 | @@ -3990,7 +3997,7 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) { "contract": "src/Counter.sol:Counter", "deployment": { - "gas": 156813, + "gas": 156801, "size": 509 }, "functions": { @@ -4026,10 +4033,10 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) "functions": { "setUp()": { "calls": 1, - "min": 218902, - "mean": 218902, - "median": 218902, - "max": 218902 + "min": 218890, + "mean": 218890, + "median": 218890, + "max": 218890 }, "test_Increment()": { "calls": 1, diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index dca88ad1c2f63..0eeb3757982e9 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -112,7 +112,6 @@ create2_deployer = "0x4e59b44847b379578588920ca78fbf26c0b4956c" assertions_revert = true legacy_assertions = false celo = false -tempo = false bypass_prevrandao = false transaction_timeout = 120 additional_compiler_profiles = [] @@ -1437,8 +1436,8 @@ forgetest_init!(test_default_config, |prj, cmd| { "soldeer": null, "assertions_revert": true, "legacy_assertions": false, + "network": null, "celo": false, - "tempo": false, "bypass_prevrandao": false, "transaction_timeout": 120, "additional_compiler_profiles": [], diff --git a/crates/forge/tests/cli/ext_integration.rs b/crates/forge/tests/cli/ext_integration.rs index fbd84739635c5..b4ad3c2d0afc6 100644 --- a/crates/forge/tests/cli/ext_integration.rs +++ b/crates/forge/tests/cli/ext_integration.rs @@ -6,7 +6,7 @@ use foundry_test_utils::util::ExtTester; // #[test] fn forge_std() { - ExtTester::new("foundry-rs", "forge-std", "b69e66b0ff79924d487d49bf7fb47c9ec326acba") + ExtTester::new("foundry-rs", "forge-std", "8987040ede9553cea20c95ad40d0455930f9c8e0") // Skip fork tests. .args(["--nmc", "Fork"]) .verbosity(2) diff --git a/crates/forge/tests/cli/failure_assertions.rs b/crates/forge/tests/cli/failure_assertions.rs index 48a17c723b261..77d5a5e84cfbb 100644 --- a/crates/forge/tests/cli/failure_assertions.rs +++ b/crates/forge/tests/cli/failure_assertions.rs @@ -70,8 +70,13 @@ Suite result: FAILED. 0 passed; 7 failed; 0 skipped; [ELAPSED] .stdout_eq( r#"No files changed, compilation skipped ... +[FAIL: Reverter != expected reverter: [..] != 0x000000000000000000000000000000000000dEaD] testShouldFailExpectPartialRevertWrongReverterTopLevelCreate() ([GAS]) +[FAIL: Reverter != expected reverter: [..] != [..]] testShouldFailExpectRevertNestedCreateInnerAddress() ([GAS]) +[FAIL: Reverter != expected reverter: [..] != 0x000000000000000000000000000000000000dEaD] testShouldFailExpectRevertWithBytesWrongReverterTopLevelCreate() ([GAS]) +[FAIL: Reverter != expected reverter: [..] != 0x000000000000000000000000000000000000dEaD] testShouldFailExpectRevertWrongReverterNestedCreate() ([GAS]) +[FAIL: Reverter != expected reverter: [..] != 0x000000000000000000000000000000000000dEaD] testShouldFailExpectRevertWrongReverterTopLevelCreate() ([GAS]) [FAIL: next call did not revert as expected] testShouldFailExpectRevertsNotOnImmediateNextCall() ([GAS]) -Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] +Suite result: FAILED. 0 passed; 6 failed; 0 skipped; [ELAPSED] ... "#, ); diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index 242a0ebb4267f..031d80f0cf071 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -3241,7 +3241,7 @@ contract CounterScript is Script { error: the following required arguments were not provided: --broadcast -Usage: [..] script --broadcast --verify --rpc-url [ARGS]... +Usage: [..] script --broadcast --verify --rpc-url [ARGS]... For more information, try '--help'. diff --git a/crates/forge/tests/cli/test_cmd/invariant/common.rs b/crates/forge/tests/cli/test_cmd/invariant/common.rs index fefd95def0412..107b387bb0ec5 100644 --- a/crates/forge/tests/cli/test_cmd/invariant/common.rs +++ b/crates/forge/tests/cli/test_cmd/invariant/common.rs @@ -2670,7 +2670,7 @@ contract InvariantWarp is Test { [FAIL: max time] [Sequence] (original: 3, shrunk: 1) vm.warp(block.timestamp + 656868); - vm.prank(0x00000000000000000000000000000000000012d2); + vm.prank(0x00000000000000000000000000000000000012d1); Warp(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f).increment(); invariant_warp() (runs: 0, calls: 0, reverts: 2) ... diff --git a/crates/forge/tests/cli/test_cmd/invariant/mod.rs b/crates/forge/tests/cli/test_cmd/invariant/mod.rs index 723b5bd789c8b..bbe65f2f2f2fa 100644 --- a/crates/forge/tests/cli/test_cmd/invariant/mod.rs +++ b/crates/forge/tests/cli/test_cmd/invariant/mod.rs @@ -422,9 +422,9 @@ Failing tests: Encountered 1 failing test in test/InvariantSequenceLenTest.t.sol:InvariantSequenceLenTest [FAIL: invariant increment failure] [Sequence] (original: 3, shrunk: 3) - sender=0x00000000000000000000000000000000000014aD addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=increment() args=[] + sender=0x0000000000000000000000000000000000001490 addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=increment() args=[] sender=0x8ef7F804bAd9183981A366EA618d9D47D3124649 addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=increment() args=[] - sender=0x00000000000000000000000000000000000016Ac addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=setNumber(uint256) args=[284406551521730736391345481857560031052359183671404042152984097777 [2.844e65]] + sender=0x00000000000000000000000000000000000016C5 addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=setNumber(uint256) args=[284406551521730736391345481857560031052359183671404042152984097777 [2.844e65]] invariant_increment() (runs: 0, calls: 0, reverts: 0) Encountered a total of 1 failing tests, 0 tests succeeded @@ -448,11 +448,11 @@ Failing tests: Encountered 1 failing test in test/InvariantSequenceLenTest.t.sol:InvariantSequenceLenTest [FAIL: invariant increment failure] [Sequence] (original: 3, shrunk: 3) - vm.prank(0x00000000000000000000000000000000000014aD); + vm.prank(0x0000000000000000000000000000000000001490); Counter(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f).increment(); vm.prank(0x8ef7F804bAd9183981A366EA618d9D47D3124649); Counter(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f).increment(); - vm.prank(0x00000000000000000000000000000000000016Ac); + vm.prank(0x00000000000000000000000000000000000016C5); Counter(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f).setNumber(284406551521730736391345481857560031052359183671404042152984097777); invariant_increment() (runs: 0, calls: 0, reverts: 0) @@ -476,9 +476,9 @@ Failing tests: Encountered 1 failing test in test/InvariantSequenceLenTest.t.sol:InvariantSequenceLenTest [FAIL: invariant increment failure] [Sequence] (original: 3, shrunk: 3) - sender=0x00000000000000000000000000000000000014aD addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=increment() args=[] + sender=0x0000000000000000000000000000000000001490 addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=increment() args=[] sender=0x8ef7F804bAd9183981A366EA618d9D47D3124649 addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=increment() args=[] - sender=0x00000000000000000000000000000000000016Ac addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=setNumber(uint256) args=[284406551521730736391345481857560031052359183671404042152984097777 [2.844e65]] + sender=0x00000000000000000000000000000000000016C5 addr=[src/Counter.sol:Counter]0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f calldata=setNumber(uint256) args=[284406551521730736391345481857560031052359183671404042152984097777 [2.844e65]] invariant_increment() (runs: 1, calls: 1, reverts: 1) Encountered a total of 1 failing tests, 0 tests succeeded diff --git a/crates/forge/tests/cli/test_cmd/repros.rs b/crates/forge/tests/cli/test_cmd/repros.rs index 32bfe6a98a9fd..3803385b496ab 100644 --- a/crates/forge/tests/cli/test_cmd/repros.rs +++ b/crates/forge/tests/cli/test_cmd/repros.rs @@ -783,6 +783,66 @@ ParserError: Source "Missing.sol" not found: File not found. Searched the follow "#]]); }); +// https://github.com/foundry-rs/foundry/issues/10463 +forgetest_init!(issue_10463, |prj, cmd| { + prj.add_test( + "Issue10463.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract Issue10463Test is Test { + event Foo(); + + error CustomError(uint256 code); + + function revertingBefore(bool shouldRevert) external { + if (shouldRevert) revert(); + emit Foo(); + } + + function revertingWithReason() external pure { + revert("revert reason"); + } + + function revertingWithCustomError() external pure { + revert CustomError(42); + } + + function testExpectEmitPreservesRevertWhenCallRevertsBeforeLog() public { + vm.expectEmit(); + emit Foo(); + + this.revertingBefore(true); + } + + function testExpectEmitPreservesRevertReason() public { + vm.expectEmit(); + emit Foo(); + + this.revertingWithReason(); + } + + function testExpectEmitPreservesCustomError() public { + vm.expectEmit(); + emit Foo(); + + this.revertingWithCustomError(); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +... +Ran 3 tests for test/Issue10463.t.sol:Issue10463Test +[FAIL: CustomError(42)] testExpectEmitPreservesCustomError() ([GAS]) +[FAIL: revert reason] testExpectEmitPreservesRevertReason() ([GAS]) +[FAIL: EvmError: Revert] testExpectEmitPreservesRevertWhenCallRevertsBeforeLog() ([GAS]) +Suite result: FAILED. 0 passed; 3 failed; 0 skipped; [ELAPSED] +... +"#]]); +}); + // https://github.com/foundry-rs/foundry/issues/12803 // Test gas underflow prevention on Cancun (no EIP-7702 gas floor) forgetest_init!(issue_12803_cancun, |prj, cmd| { diff --git a/crates/forge/tests/fixtures/ExpectRevertFailures.t.sol b/crates/forge/tests/fixtures/ExpectRevertFailures.t.sol index 7e482c6673155..838183a1b0b5e 100644 --- a/crates/forge/tests/fixtures/ExpectRevertFailures.t.sol +++ b/crates/forge/tests/fixtures/ExpectRevertFailures.t.sol @@ -233,6 +233,63 @@ contract ExpectRevertWithReverterFailureTest is DSTest { aContract.doNotRevert(); aContract.callAndRevert(); } + + // + // Regression: must fail because 0xdead is not the actual reverter when a + // top-level CREATE constructor reverts directly. + function testShouldFailExpectRevertWrongReverterTopLevelCreate() public { + vm.expectRevert(address(0xdead)); + new DContract(); + } + + // + // Regression: must fail because the reverter address argument is enforced + // even when an exact-bytes pattern is also supplied for a top-level CREATE. + function testShouldFailExpectRevertWithBytesWrongReverterTopLevelCreate() public { + vm.expectRevert(abi.encodePacked("Reverted by DContract"), address(0xdead)); + new DContract(); + } + + // + // Regression: must fail because the reverter address argument is enforced + // for `expectPartialRevert(bytes4, address)` against a top-level CREATE. + function testShouldFailExpectPartialRevertWrongReverterTopLevelCreate() public { + vm.expectPartialRevert(bytes4(keccak256("Error(string)")), address(0xdead)); + new DContract(); + } + + // + // Regression: must fail when the innermost reverting frame is a nested + // CREATE and the reverter address argument does not match the would-be + // deployed address of the failed deployment. + function testShouldFailExpectRevertWrongReverterNestedCreate() public { + vm.expectRevert(address(0xdead)); + new NestedDContractCreator(); + } + + // + // Regression: documents the intended semantics for nested CREATEs — the + // matched reverter is the *outer* would-be-deployed address (the contract + // whose deployment failed), NOT the innermost reverting CREATE's address. + // Supplying the inner address must fail. + function testShouldFailExpectRevertNestedCreateInnerAddress() public { + // Outer = NestedDContractCreator at this contract's next nonce. + // Inner = DContract created from inside the outer constructor (deployer + // is the outer, nonce 1). + address outer = + vm.computeCreateAddress(address(this), vm.getNonce(address(this))); + address inner = vm.computeCreateAddress(outer, 1); + vm.expectRevert(inner); + new NestedDContractCreator(); + } +} + +// Used by `testShouldFailExpectRevertWrongReverterNestedCreate`: a contract whose +// constructor directly creates another contract that reverts. +contract NestedDContractCreator { + constructor() { + new DContract(); + } } contract ExpectRevertCountFailureTest is DSTest { diff --git a/crates/script/src/verify.rs b/crates/script/src/verify.rs index ef10a1ce94082..fe1e9345fa23c 100644 --- a/crates/script/src/verify.rs +++ b/crates/script/src/verify.rs @@ -129,7 +129,7 @@ impl VerifyBundle { path: Some(artifact.source.to_string_lossy().to_string()), name: artifact .name - .strip_suffix(&format!(".{}", &artifact.profile)) + .strip_suffix(&format!(".{}", artifact.profile)) .unwrap_or_else(|| &artifact.name) .to_string(), }; diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index d22e12736d832..48489e43e34d9 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -30,7 +30,7 @@ static TEMPLATE_LOCK: LazyLock = LazyLock::new(|| env::temp_dir().join("foundry-forge-test-template.lock")); /// The default Solc version used when compiling tests. -pub const SOLC_VERSION: &str = "0.8.33"; +pub const SOLC_VERSION: &str = "0.8.35"; /// Another Solc version used when compiling tests. /// diff --git a/foundryup/README.md b/foundryup/README.md index 29e91378929cc..2cf61f8725227 100644 --- a/foundryup/README.md +++ b/foundryup/README.md @@ -30,10 +30,10 @@ To install the latest **nightly** version: foundryup --install nightly ``` -To install a specific version (e.g. `v1.6.0`): +To install a specific version (e.g. `v1.7.0`): ```sh -foundryup --install v1.6.0 +foundryup --install v1.7.0 ``` To **list** all **versions** installed: diff --git a/testdata/default/cheats/ExpectRevert.t.sol b/testdata/default/cheats/ExpectRevert.t.sol index 839d97962aa94..ae0c8ed844f5d 100644 --- a/testdata/default/cheats/ExpectRevert.t.sol +++ b/testdata/default/cheats/ExpectRevert.t.sol @@ -305,6 +305,91 @@ contract ExpectRevertWithReverterTest is Test { vm.expectRevert(address(cContract)); aContract.createDContractThroughCContract(); } + + // + // Regression: when the next operation is a top-level CREATE whose constructor + // reverts directly, the reverter address argument must be enforced (it used to + // be silently ignored). The matched reverter is the would-be-deployed address. + function testExpectRevertsWithReverterTopLevelCreate() public { + address expected = vm.computeCreateAddress(address(this), vm.getNonce(address(this))); + vm.expectRevert(expected); + new DContract(); + + expected = vm.computeCreateAddress(address(this), vm.getNonce(address(this))); + vm.expectRevert(abi.encodePacked("Reverted by DContract"), expected); + new DContract(); + } + + // + // Regression: when the next operation is a top-level CREATE whose constructor + // synchronously creates another contract that reverts (i.e. innermost frame is + // a CREATE), the matched reverter is the outer would-be-deployed address (the + // contract whose deployment failed). + function testExpectRevertsWithReverterNestedCreate() public { + address expected = vm.computeCreateAddress(address(this), vm.getNonce(address(this))); + vm.expectRevert(expected); + new NestedDContractCreator(); + } + + // + // Regression: `expectPartialRevert(bytes4, address)` overload must enforce + // the reverter address argument when matching a top-level CREATE revert. + function testExpectPartialRevertWithReverterTopLevelCreate() public { + address expected = vm.computeCreateAddress(address(this), vm.getNonce(address(this))); + // `Reverted by DContract` triggers Solidity's `Error(string)` selector. + vm.expectPartialRevert(bytes4(keccak256("Error(string)")), expected); + new DContract(); + } + + // + // Regression: `expectRevert(bytes4, address)` (exact 4-byte selector + reverter) + // overload must enforce the reverter address argument for a top-level CREATE. + function testExpectRevertWithBytes4SelectorAndReverterTopLevelCreate() public { + address expected = vm.computeCreateAddress(address(this), vm.getNonce(address(this))); + vm.expectRevert(DCustomErrorContract.CustomError.selector, expected); + new DCustomErrorContract(); + } + + // + // Regression: `expectRevert(address, uint64)` count-bearing overload must + // exercise the `count > 1` branch in `create_end`. Use CREATE2 with the same + // salt so both deploys would resolve to the same would-be address (each + // constructor reverts so no contract is ever actually placed there). + function testExpectRevertsWithReverterCountTopLevelCreate2() public { + bytes32 salt = bytes32(uint256(0x42)); + address expected = vm.computeCreate2Address(salt, keccak256(type(DContract).creationCode), address(this)); + vm.expectRevert(expected, 2); + new DContract{salt: salt}(); + new DContract{salt: salt}(); + } + + // + // Regression: CREATE2 deploys must also enforce the reverter address argument. + function testExpectRevertsWithReverterTopLevelCreate2() public { + bytes32 salt = bytes32(uint256(0xC0FFEE)); + address expected = vm.computeCreate2Address(salt, keccak256(type(DContract).creationCode), address(this)); + vm.expectRevert(expected); + new DContract{salt: salt}(); + } +} + +// Used by `testExpectRevertsWithReverterNestedCreate`: a contract whose constructor +// directly creates another contract that reverts. +contract NestedDContractCreator { + constructor() { + new DContract(); + } +} + +// Used by `testExpectRevertWithBytes4SelectorAndReverterTopLevelCreate`: constructor +// reverts with a parameter-less custom error so the full revert data is exactly the +// 4-byte selector. +contract DCustomErrorContract { + error CustomError(); + + constructor() { + revert CustomError(); + } } contract ExpectRevertCount is Test { diff --git a/testdata/default/cheats/Fork2.t.sol b/testdata/default/cheats/Fork2.t.sol index 0941e508483fd..d83c0480b7e72 100644 --- a/testdata/default/cheats/Fork2.t.sol +++ b/testdata/default/cheats/Fork2.t.sol @@ -325,6 +325,7 @@ contract ForkTest is Test { struct LegacyTransactionResult { bytes32 blockHash; bytes blockNumber; + bytes blockTimestamp; bytes chainId; address from; bytes gas; diff --git a/testdata/default/cheats/GetFoundryVersion.t.sol b/testdata/default/cheats/GetFoundryVersion.t.sol index 6139b8b6b6a5e..f01b7cdd7d213 100644 --- a/testdata/default/cheats/GetFoundryVersion.t.sol +++ b/testdata/default/cheats/GetFoundryVersion.t.sol @@ -84,4 +84,55 @@ contract GetFoundryVersionTest is Test { // Should return true for past versions assertTrue(vm.foundryVersionAtLeast("0.2.0")); } + + /// Returns the `MAJOR.MINOR.PATCH` prefix of `vm.getFoundryVersion()`, + /// stripping any pre-release suffix (`-nightly`, `-dev`, …) and the + /// `+..` build metadata. + function _semverPrefix() internal view returns (string memory) { + string[] memory plusSplit = vm.split(vm.getFoundryVersion(), "+"); + require(plusSplit.length == 2, "Invalid version format: Missing '+' separator"); + string[] memory dashSplit = vm.split(plusSplit[0], "-"); + return dashSplit[0]; + } + + function testGetFoundryVersionMajorMinorPatchIsParseable() public view { + // The MAJOR.MINOR.PATCH prefix must always be three numeric components, + // regardless of build kind (tagged release / nightly / dev). + string[] memory parts = vm.split(_semverPrefix(), "."); + require(parts.length == 3, "Invalid semver prefix: expected MAJOR.MINOR.PATCH"); + // Each component must parse as a uint (this reverts on garbage). + vm.parseUint(parts[0]); + vm.parseUint(parts[1]); + vm.parseUint(parts[2]); + } + + function testGetFoundryVersionBuildProfile() public view { + // The build profile must be present and non-empty (e.g. "debug", "release", "dist", …). + string[] memory plusSplit = vm.split(vm.getFoundryVersion(), "+"); + string[] memory metadataComponents = vm.split(plusSplit[1], "."); + require(bytes(metadataComponents[2]).length > 0, "Build profile is empty"); + } + + function testFoundryVersionCmpAndAtLeastAreConsistent() public { + // `foundryVersionAtLeast(v)` must equal `foundryVersionCmp(v) >= 0` for any input. + string[3] memory probes = ["0.0.1", _semverPrefix(), "99.0.0"]; + for (uint256 i = 0; i < probes.length; i++) { + assertEq(vm.foundryVersionAtLeast(probes[i]), vm.foundryVersionCmp(probes[i]) >= 0); + } + } + + function testFoundryVersionCmpRejectsPreRelease() public { + vm._expectCheatcodeRevert(); + vm.foundryVersionCmp("1.0.0-nightly"); + } + + function testFoundryVersionCmpRejectsBuildMetadata() public { + vm._expectCheatcodeRevert(); + vm.foundryVersionCmp("1.0.0+abc1234567.1700000000.release"); + } + + function testFoundryVersionCmpRejectsInvalidVersion() public { + vm._expectCheatcodeRevert(); + vm.foundryVersionCmp("not-a-version"); + } } diff --git a/testdata/default/cheats/MockCall.t.sol b/testdata/default/cheats/MockCall.t.sol index e2ac74d6f70fa..d8019ab4f6ee8 100644 --- a/testdata/default/cheats/MockCall.t.sol +++ b/testdata/default/cheats/MockCall.t.sol @@ -158,6 +158,35 @@ contract MockCallTest is Test { assertEq(mock.pay{value: 50}(1), 100); } + function testMockCallWithValueTransfersBalance() public { + Mock mock = new Mock(); + uint256 value = 10; + vm.deal(address(this), value); + + vm.mockCall(address(mock), value, abi.encodeWithSelector(mock.pay.selector), abi.encode(10)); + + assertEq(address(mock).balance, 0); + assertEq(mock.pay{value: value}(1), 10); + assertEq(address(mock).balance, value); + assertEq(address(this).balance, 0); + } + + function testMockCallWithValueTransfersPrankedSenderBalance() public { + Mock mock = new Mock(); + address sender = address(0xBEEF); + uint256 value = 10; + vm.deal(address(this), 0); + vm.deal(sender, value); + + vm.mockCall(address(mock), value, abi.encodeWithSelector(mock.pay.selector), abi.encode(10)); + + vm.prank(sender); + assertEq(mock.pay{value: value}(1), 10); + assertEq(address(mock).balance, value); + assertEq(address(this).balance, 0); + assertEq(sender.balance, 0); + } + function testMockCallWithValueCalldataPrecedence() public { Mock mock = new Mock(); @@ -279,17 +308,25 @@ contract MockCallRevertTest is Test { function testMockCallRevertWithValue() public { Mock mock = new Mock(); + uint256 value = 10; + vm.deal(address(this), value); - vm.mockCallRevert(address(mock), 10, abi.encodeWithSelector(mock.pay.selector), ERROR_MESSAGE); + vm.mockCallRevert(address(mock), value, abi.encodeWithSelector(mock.pay.selector), ERROR_MESSAGE); assertEq(mock.pay(1), 1); assertEq(mock.pay(2), 2); - try mock.pay{value: 10}(1) { + uint256 initSenderBalance = address(this).balance; + uint256 initTargetBalance = address(mock).balance; + + try mock.pay{value: value}(1) { revert(); } catch (bytes memory err) { require(keccak256(err) == keccak256(ERROR_MESSAGE)); } + + assertEq(address(this).balance, initSenderBalance); + assertEq(address(mock).balance, initTargetBalance); } function testMockCallResetsMockCallRevert() public { diff --git a/testdata/default/cheats/MockCalls.t.sol b/testdata/default/cheats/MockCalls.t.sol index e0f5eef151db6..777543f28e361 100644 --- a/testdata/default/cheats/MockCalls.t.sol +++ b/testdata/default/cheats/MockCalls.t.sol @@ -28,13 +28,17 @@ contract MockCallsTest is Test { mocks[0] = abi.encode(2 ether); mocks[1] = abi.encode(1 ether); mocks[2] = abi.encode(6.423 ether); + vm.deal(address(this), 3 ether); vm.mockCalls(mockErc20, 1 ether, data, mocks); (, bytes memory ret1) = mockErc20.call{value: 1 ether}(data); assertEq(abi.decode(ret1, (uint256)), 2 ether); + assertEq(mockErc20.balance, 1 ether); (, bytes memory ret2) = mockErc20.call{value: 1 ether}(data); assertEq(abi.decode(ret2, (uint256)), 1 ether); + assertEq(mockErc20.balance, 2 ether); (, bytes memory ret3) = mockErc20.call{value: 1 ether}(data); assertEq(abi.decode(ret3, (uint256)), 6.423 ether); + assertEq(mockErc20.balance, 3 ether); } function testMockCalls() public { diff --git a/testdata/forge-std-rev b/testdata/forge-std-rev index b1716a0a12950..977c31eec5512 100644 --- a/testdata/forge-std-rev +++ b/testdata/forge-std-rev @@ -1 +1 @@ -8987040ede9553cea20c95ad40d0455930f9c8e0 \ No newline at end of file +620536fa5277db4e3fd46772d5cbc1ea0696fb43 \ No newline at end of file diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index d9f9b52821f52..e488a1820453e 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -36,121 +36,121 @@ interface Vm { function addr(uint256 privateKey) external pure returns (address keyAddr); function allowCheatcodes(address account) external; function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; - function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata err) external pure; function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata err) external pure; function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) external pure; - function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) external pure; - function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; - function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) external pure; + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata err) external pure; function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) external pure; + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata err) external pure; function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertEq(bool left, bool right) external pure; - function assertEq(bool left, bool right, string calldata error) external pure; + function assertEq(bool left, bool right, string calldata err) external pure; function assertEq(string calldata left, string calldata right) external pure; - function assertEq(string calldata left, string calldata right, string calldata error) external pure; + function assertEq(string calldata left, string calldata right, string calldata err) external pure; function assertEq(bytes calldata left, bytes calldata right) external pure; - function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertEq(bytes calldata left, bytes calldata right, string calldata err) external pure; function assertEq(bool[] calldata left, bool[] calldata right) external pure; - function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; - function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; function assertEq(int256[] calldata left, int256[] calldata right) external pure; - function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; function assertEq(uint256 left, uint256 right) external pure; function assertEq(address[] calldata left, address[] calldata right) external pure; - function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertEq(address[] calldata left, address[] calldata right, string calldata err) external pure; function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; - function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; function assertEq(string[] calldata left, string[] calldata right) external pure; - function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertEq(string[] calldata left, string[] calldata right, string calldata err) external pure; function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; - function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; - function assertEq(uint256 left, uint256 right, string calldata error) external pure; + function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; + function assertEq(uint256 left, uint256 right, string calldata err) external pure; function assertEq(int256 left, int256 right) external pure; - function assertEq(int256 left, int256 right, string calldata error) external pure; + function assertEq(int256 left, int256 right, string calldata err) external pure; function assertEq(address left, address right) external pure; - function assertEq(address left, address right, string calldata error) external pure; + function assertEq(address left, address right, string calldata err) external pure; function assertEq(bytes32 left, bytes32 right) external pure; - function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertEq(bytes32 left, bytes32 right, string calldata err) external pure; function assertFalse(bool condition) external pure; - function assertFalse(bool condition, string calldata error) external pure; + function assertFalse(bool condition, string calldata err) external pure; function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertGe(uint256 left, uint256 right) external pure; - function assertGe(uint256 left, uint256 right, string calldata error) external pure; + function assertGe(uint256 left, uint256 right, string calldata err) external pure; function assertGe(int256 left, int256 right) external pure; - function assertGe(int256 left, int256 right, string calldata error) external pure; + function assertGe(int256 left, int256 right, string calldata err) external pure; function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertGt(uint256 left, uint256 right) external pure; - function assertGt(uint256 left, uint256 right, string calldata error) external pure; + function assertGt(uint256 left, uint256 right, string calldata err) external pure; function assertGt(int256 left, int256 right) external pure; - function assertGt(int256 left, int256 right, string calldata error) external pure; + function assertGt(int256 left, int256 right, string calldata err) external pure; function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertLe(uint256 left, uint256 right) external pure; - function assertLe(uint256 left, uint256 right, string calldata error) external pure; + function assertLe(uint256 left, uint256 right, string calldata err) external pure; function assertLe(int256 left, int256 right) external pure; - function assertLe(int256 left, int256 right, string calldata error) external pure; + function assertLe(int256 left, int256 right, string calldata err) external pure; function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertLt(uint256 left, uint256 right) external pure; - function assertLt(uint256 left, uint256 right, string calldata error) external pure; + function assertLt(uint256 left, uint256 right, string calldata err) external pure; function assertLt(int256 left, int256 right) external pure; - function assertLt(int256 left, int256 right, string calldata error) external pure; + function assertLt(int256 left, int256 right, string calldata err) external pure; function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertNotEq(bool left, bool right) external pure; - function assertNotEq(bool left, bool right, string calldata error) external pure; + function assertNotEq(bool left, bool right, string calldata err) external pure; function assertNotEq(string calldata left, string calldata right) external pure; - function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; + function assertNotEq(string calldata left, string calldata right, string calldata err) external pure; function assertNotEq(bytes calldata left, bytes calldata right) external pure; - function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertNotEq(bytes calldata left, bytes calldata right, string calldata err) external pure; function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; - function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; - function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; - function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; function assertNotEq(uint256 left, uint256 right) external pure; function assertNotEq(address[] calldata left, address[] calldata right) external pure; - function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertNotEq(address[] calldata left, address[] calldata right, string calldata err) external pure; function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; - function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; function assertNotEq(string[] calldata left, string[] calldata right) external pure; - function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertNotEq(string[] calldata left, string[] calldata right, string calldata err) external pure; function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; - function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; - function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; + function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; + function assertNotEq(uint256 left, uint256 right, string calldata err) external pure; function assertNotEq(int256 left, int256 right) external pure; - function assertNotEq(int256 left, int256 right, string calldata error) external pure; + function assertNotEq(int256 left, int256 right, string calldata err) external pure; function assertNotEq(address left, address right) external pure; - function assertNotEq(address left, address right, string calldata error) external pure; + function assertNotEq(address left, address right, string calldata err) external pure; function assertNotEq(bytes32 left, bytes32 right) external pure; - function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertNotEq(bytes32 left, bytes32 right, string calldata err) external pure; function assertTrue(bool condition) external pure; - function assertTrue(bool condition, string calldata error) external pure; + function assertTrue(bool condition, string calldata err) external pure; function assume(bool condition) external pure; function assumeNoRevert() external pure; function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure; From 3bae0a73b2e0638463102be516d8823a8ddb1ab2 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 13:16:23 +0200 Subject: [PATCH 67/83] ci: configure git auth via GH_TOKEN for private cargo deps --- .github/workflows/ci.yml | 12 ++++++++++++ .github/workflows/test.yml | 3 +++ 2 files changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1bce518ef020..13b7ec040f36a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,10 @@ jobs: - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Configure git for private cargo deps + env: + GH_TOKEN: ${{ github.token }} + run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - run: cargo test --workspace --doc typos: @@ -89,6 +93,10 @@ jobs: - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Configure git for private cargo deps + env: + GH_TOKEN: ${{ github.token }} + run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - run: cargo clippy --workspace --all-targets --all-features env: RUSTFLAGS: -Dwarnings @@ -145,6 +153,10 @@ jobs: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Configure git for private cargo deps + env: + GH_TOKEN: ${{ github.token }} + run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - run: cargo hack check deny: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eaa46c8e79f7c..9d8e39939ac29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -111,10 +111,13 @@ jobs: - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 - name: Setup Git config + env: + GH_TOKEN: ${{ github.token }} run: | git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" git config --global url."https://github.com/".insteadOf "git@github.com:" + git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - name: Test env: SVM_TARGET_PLATFORM: ${{ matrix.svm_target_platform }} From 18000b6f0fd637af9e2596fc95426f037d653469 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 13:21:54 +0200 Subject: [PATCH 68/83] deps: track credible-sdk ENG-3169 branch for assertion-executor --- crates/cheatcodes/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 632c597bba70c..f7313a99f4372 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -22,8 +22,8 @@ credible = ["dep:assertion-executor"] [dependencies] foundry-fork-db.workspace = true -# pinned to avoid cyclical version bumps between sdk and phoundry -assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", rev = "3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa", features = ["phoundry"], optional = true } +# tracks the credible-sdk ENG-3169 rebase branch during the revm/alloy bump +assertion-executor = { git = "https://github.com/phylaxsystems/credible-sdk.git", branch = "lea/eng-3169-featcredible-sdk-update-revm-and-alloy-dependencies", features = ["phoundry"], optional = true } foundry-cheatcodes-spec.workspace = true foundry-common.workspace = true From 77d43e6e1abefe6c78aca8c9673c1700c1b3be87 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 13:26:52 +0200 Subject: [PATCH 69/83] ci: extend GH_TOKEN git auth to forge-fmt, docs, and inline deny job --- .github/workflows/ci.yml | 19 ++++++++++++++++++- .github/workflows/docs.yml | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13b7ec040f36a..2600878cff595 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,6 +131,10 @@ jobs: - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Configure git for private cargo deps + env: + GH_TOKEN: ${{ github.token }} + run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - name: forge fmt shell: bash run: ./.github/scripts/format.sh --check @@ -160,9 +164,22 @@ jobs: - run: cargo hack check deny: - uses: ithacaxyz/ci/.github/workflows/deny.yml@9c8d0dc20e7ad02455d3fdab2378a05f29907630 # main + runs-on: ubuntu-latest + timeout-minutes: 15 permissions: contents: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - name: Configure git for private cargo deps + env: + GH_TOKEN: ${{ github.token }} + run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" + - uses: taiki-e/install-action@763e3324d4fd026c9bd284c504378585777a87d5 # v2 + with: + tool: cargo-deny + - run: cargo deny --all-features check codeql: name: analyze (${{ matrix.language }}) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index af3fee514e613..3da8de9acc0f8 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,6 +30,10 @@ jobs: with: toolchain: nightly - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 + - name: Configure git for private cargo deps + env: + GH_TOKEN: ${{ github.token }} + run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - name: Build documentation run: cargo doc --workspace --all-features --no-deps --document-private-items --locked env: From 9e19ffcbd7f4ae60e5462769d66890f9fa6c3e11 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 13:36:23 +0200 Subject: [PATCH 70/83] ci: use GitHub App token for cross-repo cargo auth + drop tempo CI workflows --- .github/workflows/bump-tempo.yml | 59 ------------- .github/workflows/ci-mpp.yml | 60 ------------- .github/workflows/ci-tempo.yml | 147 ------------------------------- .github/workflows/ci.yml | 45 ++++++++-- .github/workflows/docs.yml | 9 +- .github/workflows/test.yml | 9 +- 6 files changed, 56 insertions(+), 273 deletions(-) delete mode 100644 .github/workflows/bump-tempo.yml delete mode 100644 .github/workflows/ci-mpp.yml delete mode 100644 .github/workflows/ci-tempo.yml diff --git a/.github/workflows/bump-tempo.yml b/.github/workflows/bump-tempo.yml deleted file mode 100644 index ffbd68d772d81..0000000000000 --- a/.github/workflows/bump-tempo.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Bump Tempo Dependencies - -permissions: {} - -on: - schedule: - # Run daily at 00:00 UTC - - cron: "0 0 * * *" - workflow_dispatch: - -jobs: - bump-tempo: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - - name: Bump tempo dependencies - id: bump - env: - GH_TOKEN: ${{ github.token }} - run: ./.github/scripts/bump-tempo.sh - - - name: Create Pull Request - if: steps.bump.outputs.updated == 'true' - env: - GH_TOKEN: ${{ github.token }} - LATEST_REV: ${{ steps.bump.outputs.latest_rev }} - CHANGELOG_FILE: ${{ steps.bump.outputs.changelog }} - run: | - BRANCH_NAME="deps/bump-tempo-${LATEST_REV:0:7}" - - # Skip if a PR already exists for this branch - EXISTING_PR=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number') - if [[ -n "$EXISTING_PR" ]]; then - echo "PR #${EXISTING_PR} already exists for ${BRANCH_NAME}, skipping." - exit 0 - fi - - # Configure git - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - # Create and push branch (force-push in case a stale branch exists from a prior failed run) - git checkout -b "$BRANCH_NAME" - git add Cargo.toml Cargo.lock - git commit -m "chore(deps): bump tempo dependencies to ${LATEST_REV:0:7}" - git push --force-with-lease origin "$BRANCH_NAME" - - # Create PR - gh pr create \ - --title "chore(deps): bump tempo dependencies to ${LATEST_REV:0:7}" \ - --body-file "$CHANGELOG_FILE" \ - --base main \ - --head "$BRANCH_NAME" diff --git a/.github/workflows/ci-mpp.yml b/.github/workflows/ci-mpp.yml deleted file mode 100644 index 3a608b6500a90..0000000000000 --- a/.github/workflows/ci-mpp.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: CI MPP - -permissions: {} - -on: - push: - branches: [master] - pull_request: - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - RUSTC_WRAPPER: "sccache" - -jobs: - mpp-check: - runs-on: depot-ubuntu-latest - timeout-minutes: 60 - permissions: - contents: read - steps: - # Checkout the repository - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: stable - - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - - # Build and install binaries - - name: Build and install Foundry binaries - run: | - cargo build --profile dev --locked -p forge -p cast -p anvil -p chisel - echo "${{ github.workspace }}/target/debug" >> "$GITHUB_PATH" - - - name: Run MPP e2e test - env: - TEMPO_PRIVATE_KEY: ${{ secrets.TEMPO_PRIVATE_KEY }} - TEMPO_KEYS_TOML_B64: ${{ secrets.TEMPO_KEYS_TOML_B64 }} - MPP_API_KEY: ${{ secrets.MPP_API_KEY }} - MPP_DEPOSIT: "1000000" - TEMPO_AUTO_FUND: "1" - run: | - if [ -n "${TEMPO_PRIVATE_KEY:-}" ]; then - echo "::notice::Using TEMPO_PRIVATE_KEY for MPP e2e" - elif [ -n "${TEMPO_KEYS_TOML_B64:-}" ]; then - mkdir -p ~/.tempo/wallet - echo "$TEMPO_KEYS_TOML_B64" | tr -d '[:space:]' | base64 -d > ~/.tempo/wallet/keys.toml - else - echo "::warning::TEMPO_PRIVATE_KEY or TEMPO_KEYS_TOML_B64 secret not set, skipping MPP e2e" - exit 0 - fi - ./.github/scripts/tempo-mpp.sh "$(which cast | xargs dirname)" diff --git a/.github/workflows/ci-tempo.yml b/.github/workflows/ci-tempo.yml deleted file mode 100644 index f594f52ea84e7..0000000000000 --- a/.github/workflows/ci-tempo.yml +++ /dev/null @@ -1,147 +0,0 @@ -name: CI Tempo - -permissions: {} - -on: - push: - branches: [master] - pull_request: - schedule: - - cron: "0 2 * * *" # Run daily at 2 AM UTC (offset from other nightlies) - workflow_dispatch: - inputs: - network: - description: "Tempo network to check" - required: true - type: choice - options: - - testnet - - devnet - - mainnet - - all - scripts: - description: "Which scripts to run" - required: false - type: choice - default: "both" - options: - - check - - deploy - - both - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - RUSTC_WRAPPER: "sccache" - -jobs: - tempo-check: - runs-on: depot-ubuntu-latest - timeout-minutes: 60 - permissions: - contents: read - steps: - # Checkout the repository - - uses: actions/checkout@v6 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: stable - - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - - # Build and install binaries - - name: Build and install Foundry binaries - run: | - cargo build --profile dev --locked -p forge -p cast -p anvil -p chisel - echo "${{ github.workspace }}/target/debug" >> "$GITHUB_PATH" - - - name: Run Tempo check on mainnet - if: | - github.event_name == 'schedule' || - github.event.inputs.network == 'mainnet' || - github.event.inputs.network == 'all' - env: - ETH_RPC_URL: ${{ secrets.TEMPO_MAINNET_RPC_URL }} - TEMPO_FEE_TOKEN: "0x20c0000000000000000000000000000000000000" - VERIFIER_URL: ${{ secrets.VERIFIER_URL }} - PRIVATE_KEY: ${{ secrets.THROW_AWAY_MAINNET_PKEY }} - SCRIPTS: ${{ github.event.inputs.scripts || 'both' }} - run: | - if [ "$SCRIPTS" = "check" ] || [ "$SCRIPTS" = "both" ]; then - ./.github/scripts/tempo-check.sh - fi - if [ "$SCRIPTS" = "deploy" ] || [ "$SCRIPTS" = "both" ]; then - ./.github/scripts/tempo-deploy.sh - fi - - - name: Run Tempo check on testnet - if: | - github.event_name == 'schedule' || - github.event.inputs.network == 'testnet' || - github.event.inputs.network == 'all' - env: - ETH_RPC_URL: ${{ secrets.TEMPO_TESTNET_RPC_URL }} - VERIFIER_URL: ${{ secrets.VERIFIER_URL }} - SCRIPTS: ${{ github.event.inputs.scripts || 'both' }} - run: | - if [ "$SCRIPTS" = "check" ] || [ "$SCRIPTS" = "both" ]; then - ./.github/scripts/tempo-check.sh - fi - if [ "$SCRIPTS" = "deploy" ] || [ "$SCRIPTS" = "both" ]; then - ./.github/scripts/tempo-deploy.sh - fi - - - name: Run Tempo check on devnet - if: | - github.event_name == 'push' || - github.event_name == 'pull_request' || - github.event.inputs.network == 'devnet' || - github.event.inputs.network == 'all' - env: - ETH_RPC_URL: ${{ secrets.TEMPO_DEVNET_RPC_URL }} - SCRIPTS: ${{ github.event.inputs.scripts || 'both' }} - run: | - if [ "$SCRIPTS" = "check" ] || [ "$SCRIPTS" = "both" ]; then - ./.github/scripts/tempo-check.sh - fi - if [ "$SCRIPTS" = "deploy" ] || [ "$SCRIPTS" = "both" ]; then - ./.github/scripts/tempo-deploy.sh - fi - - - name: Run Tempo wallet tests on devnet - if: | - github.event_name == 'push' || - github.event_name == 'pull_request' || - github.event.inputs.network == 'devnet' || - github.event.inputs.network == 'all' - env: - ETH_RPC_URL: ${{ secrets.TEMPO_DEVNET_RPC_URL }} - run: ./.github/scripts/tempo-wallet.sh - - # If the nightly run fails, this will create an issue to signal so. - issue: - name: Open an issue - runs-on: ubuntu-latest - needs: [tempo-check] - if: failure() && github.event_name == 'schedule' - permissions: - contents: read - issues: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WORKFLOW_URL: | - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - with: - update_existing: true - filename: .github/TEMPO_NIGHTLY_FAILURE_TEMPLATE.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2600878cff595..f7a12110a6c76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,9 +47,16 @@ jobs: - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Configure git for private cargo deps env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - run: cargo test --workspace --doc @@ -93,9 +100,16 @@ jobs: - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Configure git for private cargo deps env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - run: cargo clippy --workspace --all-targets --all-features env: @@ -131,9 +145,16 @@ jobs: - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Configure git for private cargo deps env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - name: forge fmt shell: bash @@ -157,9 +178,16 @@ jobs: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Configure git for private cargo deps env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - run: cargo hack check @@ -172,9 +200,16 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Configure git for private cargo deps env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - uses: taiki-e/install-action@763e3324d4fd026c9bd284c504378585777a87d5 # v2 with: diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3da8de9acc0f8..a18a7f2805dfd 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,9 +30,16 @@ jobs: with: toolchain: nightly - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Configure git for private cargo deps env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" - name: Build documentation run: cargo doc --workspace --all-features --no-deps --document-private-items --locked diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9d8e39939ac29..b9861afb5760b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -110,9 +110,16 @@ jobs: ${{ runner.os }}-foundry-${{ matrix.name }}- - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - name: Generate GitHub App token (cross-repo cargo auth) + id: app-token + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.4 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} - name: Setup Git config env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" From 9d08cdf47ec9fea170350d04f50ff7a98d439991 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 17:15:13 +0200 Subject: [PATCH 71/83] fix phoundry revm 38 compile blockers --- Cargo.lock | 5006 ++++++++++++++++++-------- Cargo.toml | 1 + crates/cheatcodes/src/inspector.rs | 1033 +++--- crates/cheatcodes/src/lib.rs | 6 +- crates/evm/core/src/backend/mod.rs | 673 ++-- crates/evm/traces/src/decoder/mod.rs | 15 +- 6 files changed, 4457 insertions(+), 2277 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dcf9d5202a73..3e99055403f4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common 0.1.7", + "generic-array", +] + [[package]] name = "aes" version = "0.8.4" @@ -25,7 +35,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -65,31 +75,84 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8010fc7e9e8643ef4e758cdccf3eef26734594aedf88a9d5ed35e51837d42ef" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-contract", + "alloy-core", + "alloy-eips 2.0.4", + "alloy-genesis 2.0.4", + "alloy-network", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde 2.0.4", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", + "alloy-trie", +] + [[package]] name = "alloy-chains" -version = "0.2.23" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35d744058a9daa51a8cf22a3009607498fcf82d3cf4c5444dd8056cdf651f471" +checksum = "84e0378e959aa6a885897522080a990e80eb317f1e9a222a604492ea50e13096" dependencies = [ "alloy-primitives", "alloy-rlp", "num_enum", "serde", - "strum 0.27.2", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f16daaf7e1f95f62c6c3bf8a3fc3d78b08ae9777810c0bb5e94966c7cd57ef0" +dependencies = [ + "alloy-eips 1.8.3", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 1.8.3", + "alloy-trie", + "alloy-tx-macros 1.8.3", + "auto_impl", + "borsh", + "c-kzg", + "derive_more", + "either", + "k256", + "once_cell", + "rand 0.8.5", + "secp256k1 0.30.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.18", ] [[package]] name = "alloy-consensus" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" +checksum = "e3d64da86c616b5092ea64eea648f311bbd58630a0b384c42d699175d6f9122b" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "alloy-trie", - "alloy-tx-macros", + "alloy-tx-macros 2.0.4", "auto_impl", "borsh", "c-kzg", @@ -102,51 +165,79 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-consensus-any" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "118998d9015332ab1b4720ae1f1e3009491966a0349938a1f43ff45a8a4c6299" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 1.8.3", + "serde", ] [[package]] name = "alloy-consensus-any" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" +checksum = "8fd98696ca3617d3a9ba1a6f2011880cbfd5618228dab6400c9f8bca457859a8" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-contract" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d39c80ffc806f27a76ed42f3351a455f3dc4f81d6ff92c8aad2cf36b7d3a34" +checksum = "de3df0aadc569a8b277808a7d0ad0e421180654ea36a3c59e9ed2bb968c9a1cd" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-json-abi", "alloy-network", - "alloy-network-primitives", + "alloy-network-primitives 2.0.4", "alloy-primitives", "alloy-provider", "alloy-pubsub", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-sol-types", "alloy-transport", "futures", "futures-util", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "alloy-core" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", ] [[package]] name = "alloy-dyn-abi" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d48a9101f4a67c22fae57489f1ddf3057b8ab4a368d8eac3be088b6e9d9c9d9" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -158,7 +249,7 @@ dependencies = [ "proptest", "serde", "serde_json", - "winnow", + "winnow 0.7.14", ] [[package]] @@ -171,7 +262,7 @@ dependencies = [ "alloy-rlp", "crc", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -188,12 +279,12 @@ dependencies = [ [[package]] name = "alloy-eip5792" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb56700a502913fa9d40367e8f8c77720b043447c7763305f4ab582d713e36d" +checksum = "1ceb16e7fe5a95825305f218ccd356665f848831f94ce2bbf55339bf5d21e88a" dependencies = [ "alloy-primitives", - "alloy-serde", + "alloy-serde 2.0.4", "serde", "serde_json", ] @@ -210,79 +301,149 @@ dependencies = [ "k256", "serde", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-eip7928" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b827a6d7784fe3eb3489d40699407a4cdcce74271421a01bdffe60cf573bb16" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "once_cell", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "alloy-eips" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ef28c9fdad22d4eec52d894f5f2673a0895f1e5ef196734568e68c0f6caca8" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-eip7928", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 1.8.3", + "auto_impl", + "borsh", + "c-kzg", + "derive_more", + "either", + "serde", + "serde_with", + "sha2 0.10.9", ] [[package]] name = "alloy-eips" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" +checksum = "64c0456f5f7a4497e9342d20f528e30f5288ddfa0d6a012bd5044afee46cd8a0" dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", + "alloy-eip7928", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "auto_impl", "borsh", "c-kzg", "derive_more", "either", - "ethereum_ssz 0.9.1", + "ethereum_ssz", "ethereum_ssz_derive", "serde", "serde_with", - "sha2", - "thiserror 2.0.17", + "sha2 0.10.9", ] [[package]] name = "alloy-ens" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a171486ee60b6f98e12451b1eddd1458bc21571f3829f75fcf12bb16ae48e59" +checksum = "d5638cbbffb318d440fdb009de019090d8d117dae40de9d10cdb29891ea59eb9" dependencies = [ "alloy-contract", "alloy-primitives", "alloy-provider", "alloy-sol-types", "async-trait", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-evm" -version = "0.25.2" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ccc4c702c840148af1ce784cc5c6ed9274a020ef32417c5b1dbeab8c317673" +checksum = "7f092eb6af80456e4ab41c9722e777d791335bc9c00b11bc3db7bf29a432dfd0" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-hardforks", - "alloy-op-hardforks", "alloy-primitives", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", + "alloy-sol-types", + "auto_impl", + "derive_more", + "revm", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "alloy-evm" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ceeea6dcbbcd4e546b27700763a6f6c3b3fee30054209884f521078b6fda4f" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-hardforks", + "alloy-primitives", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth 2.0.4", "alloy-sol-types", "auto_impl", "derive_more", - "op-alloy", - "op-revm", "revm", - "thiserror 2.0.17", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "alloy-genesis" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf9480307b09d22876efb67d30cadd9013134c21f3a17ec9f93fd7536d38024" +dependencies = [ + "alloy-eips 1.8.3", + "alloy-primitives", + "alloy-serde 1.8.3", + "alloy-trie", + "borsh", + "serde", + "serde_with", ] [[package]] name = "alloy-genesis" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba4b1be0988c11f0095a2380aa596e35533276b8fa6c9e06961bbfe0aebcac5" +checksum = "a71ff8b55d2b8aa05259f474cae7dea0e4991724dc18936b81cb23ec492a0c2a" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "alloy-primitives", - "alloy-serde", + "alloy-serde 2.0.4", "alloy-trie", "borsh", "serde", @@ -291,22 +452,23 @@ dependencies = [ [[package]] name = "alloy-hardforks" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9a33550fc21fd77a3f8b63e99969d17660eec8dcc50a95a80f7c9964f7680b" +checksum = "83ba208044232d14d4adbfa77e57d6329f51bc1acc21f5667bb7db72d88a0831" dependencies = [ "alloy-chains", "alloy-eip2124", "alloy-primitives", "auto_impl", "dyn-clone", + "serde", ] [[package]] name = "alloy-json-abi" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9914c147bb9b25f440eca68a31dc29f5c22298bfa7754aa802965695384122b0" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -316,34 +478,34 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" +checksum = "19e352478b756bad5d7203148e4b461861282ea2ded3da406ba24868b52cd098" dependencies = [ "alloy-primitives", "alloy-sol-types", "http 1.4.0", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-network" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" +checksum = "ed08ae169869e08370ed121612e0d3dadac33d1a256e9f2465926b23f0bd7d95" dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-consensus-any 2.0.4", + "alloy-eips 2.0.4", "alloy-json-rpc", - "alloy-network-primitives", + "alloy-network-primitives 2.0.4", "alloy-primitives", "alloy-rpc-types-any", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "alloy-signer", "alloy-sol-types", "async-trait", @@ -352,57 +514,69 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-network-primitives" -version = "1.1.3" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" +checksum = "eb82711d59a43fdfd79727c99f270b974c784ec4eb5728a0d0d22f26716c87ef" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", - "alloy-serde", + "alloy-serde 1.8.3", "serde", ] [[package]] -name = "alloy-op-evm" -version = "0.25.2" +name = "alloy-network-primitives" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f640da852f93ddaa3b9a602b7ca41d80e0023f77a67b68aaaf511c32f1fe0ce" +checksum = "02e6c7ad28afe348a9a9c5624b67ee5b3607b8de98d5816b3056ecdfa6fa2697" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-evm", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives", + "alloy-serde 2.0.4", + "serde", +] + +[[package]] +name = "alloy-op-evm" +version = "0.31.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", "alloy-op-hardforks", "alloy-primitives", "auto_impl", "op-alloy", "op-revm", "revm", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-op-hardforks" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f96fb2fce4024ada5b2c11d4076acf778a0d3e4f011c6dfd2ffce6d0fcf84ee9" +version = "0.4.7" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ "alloy-chains", "alloy-hardforks", "alloy-primitives", "auto_impl", + "serde", ] [[package]] name = "alloy-primitives" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db950a29746be9e2f2c6288c8bd7a6202a81f999ce109a2933d2379970ec0fa" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", "arbitrary", @@ -411,9 +585,9 @@ dependencies = [ "const-hex", "derive_more", "foldhash 0.2.0", - "getrandom 0.3.4", + "getrandom 0.4.2", "hashbrown 0.16.1", - "indexmap 2.12.1", + "indexmap 2.14.0", "itoa", "k256", "keccak-asm", @@ -426,26 +600,26 @@ dependencies = [ "rustc-hash", "serde", "sha3", - "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" +checksum = "93a7c17472b55482d4734154c2f5ed13f72e03f6752cebb927f6a2d8b52e646c" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-json-rpc", "alloy-network", - "alloy-network-primitives", + "alloy-network-primitives 2.0.4", "alloy-primitives", "alloy-pubsub", "alloy-rpc-client", + "alloy-rpc-types-anvil", "alloy-rpc-types-debug", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", "alloy-signer", @@ -461,13 +635,13 @@ dependencies = [ "either", "futures", "futures-utils-wasm", - "lru 0.13.0", + "lru", "parking_lot", - "pin-project 1.1.10", - "reqwest", + "pin-project", + "reqwest 0.13.3", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -476,9 +650,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd4c64eb250a18101d22ae622357c6b505e158e9165d4c7974d59082a600c5e" +checksum = "a8d86958b02bca85103d64fa60d7b364a8b017c6e40f2b02c3f50ca22964a738" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -498,9 +672,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -509,20 +683,20 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "alloy-rpc-client" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" +checksum = "5beb5c2fe6b960c8e8b038e69fd502a90a2e930afa4770efb748b163b0767729" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -532,8 +706,8 @@ dependencies = [ "alloy-transport-ipc", "alloy-transport-ws", "futures", - "pin-project 1.1.10", - "reqwest", + "pin-project", + "reqwest 0.13.3", "serde", "serde_json", "tokio", @@ -546,66 +720,72 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" +checksum = "4ee1257a278f6d293e05c5162c5940a1561b1aa85ded0028b464c81de37ebfa5" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", + "alloy-rpc-types-debug", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-rpc-types-anvil" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ce4c24e416bd0f17fceeb2f26cd8668df08fe19e1dc02f9d41c3b8ed1e93e0" +checksum = "df32156f085e74eac942b6103744be49b817c302341aaa8cb0c1c88dc29228d9" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-rpc-types-any" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" +checksum = "6a234bfbdf7a76c3d13808f729af5321852de3dedcaa6fc6d5f54787aaf54c6a" dependencies = [ - "alloy-consensus-any", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-consensus-any 2.0.4", + "alloy-network-primitives 2.0.4", + "alloy-primitives", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "serde", + "serde_json", ] [[package]] name = "alloy-rpc-types-beacon" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16633087e23d8d75161c3a59aa183203637b817a5a8d2f662f612ccb6d129af0" +checksum = "296450f5e76bece0116c939b9437b0421a5da9c5d40031bf4cf9b38d3d94e475" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rpc-types-engine", "derive_more", "serde", "serde_json", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-debug" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4936f579d9d10eae01772b2ab3497f9d568684f05f26f8175e12f9a1a2babc33" +checksum = "0ab075ac1c25bcf697f133b7cd92e2fb26afe213e872ef79fdf77f0d7bcb3793" dependencies = [ "alloy-primitives", + "alloy-rlp", "derive_more", "serde", "serde_with", @@ -613,76 +793,108 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c60bdce3be295924122732b7ecd0b2495ce4790bedc5370ca7019c08ad3f26e" +checksum = "73b12366c96f4013e1aeebc96c6b56e5f33f07853c42ea2f485045c0c157a4a1" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "derive_more", - "ethereum_ssz 0.9.1", + "ethereum_ssz", "ethereum_ssz_derive", "jsonwebtoken", "rand 0.8.5", "serde", - "strum 0.27.2", + "strum", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c095f92c4e1ff4981d89e9aa02d5f98c762a1980ab66bec49c44be11349da2" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-consensus-any 1.8.3", + "alloy-eips 1.8.3", + "alloy-network-primitives 1.8.3", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 1.8.3", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-eth" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" +checksum = "56a282daf869eeb7383d3d5c2deb35b0b3fb45ecb329513af4090fc61245ee18" dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-network-primitives", + "alloy-consensus 2.0.4", + "alloy-consensus-any 2.0.4", + "alloy-eips 2.0.4", + "alloy-network-primitives 2.0.4", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "alloy-sol-types", "itertools 0.14.0", "serde", "serde_json", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-trace" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef206a4b8d436fbb7cf2e6a61c692d11df78f9382becc3c9a283bd58e64f0583" +checksum = "6184b5d14152b68b0bb8beb621339d94f0b761a37958bb365fbf7c00922125c2" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-rpc-types-txpool" -version = "1.1.3" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00b631c361e7c7baaf4f1f5a9877730f3507fed2acb9d4b34841b8184b2ec28" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "serde", +] + +[[package]] +name = "alloy-serde" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb5a795264a02222f9534435b8f40dcbd88de8e9d586647884aae24f389ebf2" +checksum = "11ece63b89294b8614ab3f483560c08d016930f842bf36da56bf0b764a15c11e" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", "serde", + "serde_json", ] [[package]] name = "alloy-serde" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" +checksum = "a0eada2558e921b39dfcead33c487364df9b31374f5733c1c9d2c891c4529933" dependencies = [ "alloy-primitives", "serde", @@ -691,9 +903,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" +checksum = "41eb29f7a8adcd8941fbb8e134022a133e6f8dfd345f2e3b7109599f8a7dca08" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -703,16 +915,16 @@ dependencies = [ "either", "elliptic-curve", "k256", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "alloy-signer-aws" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc8784b7567d5cfdad7450c5c71ddbdc12b288b82ea559be7a5363c28f774210" +checksum = "1258987fbc82716b5153ec7bb95a8a295e7640871b8f03d8ec7c4000dc80c215" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", "alloy-primitives", "alloy-signer", @@ -721,17 +933,17 @@ dependencies = [ "aws-sdk-kms", "k256", "spki", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-signer-gcp" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70059cb6f08c225be3840f8104573fd9342ca29117a735ea09ed8ee1be09fb9f" +checksum = "7ffc2a49bca5b73c6964711b57452f6c36a6bcb7f845ab7e9ad05b5a828d0161" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", "alloy-primitives", "alloy-signer", @@ -739,17 +951,17 @@ dependencies = [ "gcloud-sdk", "k256", "spki", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-signer-ledger" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a54e01fb2228c993c9ef7735043bb22c88a84502628fae820d6469c3bebddb84" +checksum = "94e11ddaddfb98c1ddce737dc440225565b0ae0987ac9ad5e59a85db5904878c" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-network", "alloy-primitives", @@ -758,18 +970,18 @@ dependencies = [ "async-trait", "coins-ledger", "futures-util", - "semver 1.0.27", - "thiserror 2.0.17", + "semver 1.0.28", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-signer-local" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" +checksum = "bef839e7ce9b59aa60fa9a175e97986c6145c888d643b0f1fb0a3e7b8e56a2e2" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", "alloy-primitives", "alloy-signer", @@ -779,81 +991,81 @@ dependencies = [ "eth-keystore", "k256", "rand 0.8.5", - "thiserror 2.0.17", + "thiserror 2.0.18", "zeroize", ] [[package]] name = "alloy-signer-trezor" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119c750dd3d2158c57ab14711dca06cd6dc5db657bd16e6ab46ed11112187958" +checksum = "44eb341d0013784da6a39e5bbdc11b95d6744993b12a1c3fd55df795a850dd42" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", "alloy-primitives", "alloy-signer", "async-trait", - "semver 1.0.27", - "thiserror 2.0.17", + "semver 1.0.28", + "thiserror 2.0.18", "tracing", "trezor-client", ] [[package]] name = "alloy-signer-turnkey" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd65beb3a838bff2e528e2ac4f0cf14f55893c4f0bc67c8339f2752b3d144022" +checksum = "82ff16b4166fb90bbe79bd1e49244824fb3cadc6b8cd11e9c8a002c1f8c07492" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", "alloy-primitives", "alloy-signer", "async-trait", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "turnkey_client", ] [[package]] name = "alloy-sol-macro" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b96d5f5890605ba9907ce1e2158e2701587631dc005bfa582cf92dd6f21147" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8247b7cca5cde556e93f8b3882b01dbd272f527836049083d240c57bf7b4c15" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.12.1", + "indexmap 2.14.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "sha3", + "syn 2.0.117", "syn-solidity", - "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd54f38512ac7bae10bbc38480eefb1b9b398ca2ce25db9cc0c048c6411c4f1" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ "alloy-json-abi", "const-hex", @@ -863,25 +1075,25 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b09815b44899564566d4d56613d14fa9a274b1043a021f00468568752f449" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" dependencies = [ "serde", - "winnow", + "winnow 0.7.14", ] [[package]] name = "alloy-sol-types" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1038284171df8bfd48befc0c7b78f667a7e2be162f45f07bd1c378078ebe58" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -891,9 +1103,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" +checksum = "3ac7a80c0bac3e44559d53d002e34c461dc2f23262b42cafec019bc70551abbe" dependencies = [ "alloy-json-rpc", "auto_impl", @@ -904,7 +1116,7 @@ dependencies = [ "parking_lot", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tower", "tracing", @@ -914,13 +1126,14 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" +checksum = "eed3ed3300a998f88639ed619fdbbd88bd82865e00c6a8ecb796c99eb12358f6" dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest", + "itertools 0.14.0", + "reqwest 0.13.3", "serde_json", "tower", "tracing", @@ -929,9 +1142,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8db249779ebc20dc265920c7e706ed0d31dbde8627818d1cbde60919b875bb0" +checksum = "1075d9d30fd4d71e50000fd4afb19ed2664ceab20c2a29f3889a6e988329e02d" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -939,7 +1152,7 @@ dependencies = [ "bytes", "futures", "interprocess", - "pin-project 1.1.10", + "pin-project", "serde", "serde_json", "tokio", @@ -949,9 +1162,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.1.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad2344a12398d7105e3722c9b7a7044ea837128e11d453604dec6e3731a86e2" +checksum = "0e3bff84b2b2a46eb34cc522dc3f889a2867c70be90a377421429b662b3ec4ce" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -960,50 +1173,50 @@ dependencies = [ "rustls", "serde_json", "tokio", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite 0.28.0", "tracing", + "url", "ws_stream_wasm", ] [[package]] name = "alloy-trie" -version = "0.9.1" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +checksum = "3f14b5d9b2c2173980202c6ff470d96e7c5e202c65a9f67884ad565226df7fbb" dependencies = [ "alloy-primitives", "alloy-rlp", - "arrayvec", "derive_more", "nybbles", "serde", "smallvec", + "thiserror 2.0.18", "tracing", ] [[package]] name = "alloy-tx-macros" -version = "1.1.3" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" +checksum = "d69722eddcdf1ce096c3ab66cf8116999363f734eb36fe94a148f4f71c85da84" dependencies = [ - "darling 0.21.3", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] -name = "ammonia" -version = "4.1.2" +name = "alloy-tx-macros" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" +checksum = "99fce0350197dcd4ba4e9a7dd43915d908c0eb0e7352755791709a705e1c76b6" dependencies = [ - "cssparser", - "html5ever", - "maplit", - "tendril", - "url", + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -1110,16 +1323,15 @@ dependencies = [ [[package]] name = "anvil" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-contract", "alloy-dyn-abi", - "alloy-eip5792", - "alloy-eips", - "alloy-evm", - "alloy-genesis", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", + "alloy-genesis 2.0.4", "alloy-network", "alloy-op-evm", "alloy-primitives", @@ -1128,8 +1340,8 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types", "alloy-rpc-types-beacon", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "alloy-signer", "alloy-signer-local", "alloy-sol-types", @@ -1144,7 +1356,7 @@ dependencies = [ "clap", "clap_complete", "ctrlc", - "ethereum_ssz 0.10.0", + "ethereum_ssz", "eyre", "fdlimit", "flate2", @@ -1158,19 +1370,25 @@ dependencies = [ "futures", "hyper", "itertools 0.14.0", - "op-alloy-consensus", + "op-alloy-consensus 0.24.0", "op-alloy-rpc-types", "op-revm", "parking_lot", "rand 0.8.5", "rand 0.9.2", - "reqwest", + "reqwest 0.13.3", "revm", "revm-inspectors", "serde", "serde_json", "tempfile", - "thiserror 2.0.17", + "tempo-alloy", + "tempo-chainspec", + "tempo-evm", + "tempo-precompiles", + "tempo-primitives", + "tempo-revm", + "thiserror 2.0.18", "tokio", "tracing", "tracing-subscriber 0.3.22", @@ -1179,16 +1397,17 @@ dependencies = [ [[package]] name = "anvil-core" -version = "1.5.1" +version = "1.7.1" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-eip5792", - "alloy-eips", + "alloy-eips 2.0.4", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rpc-types", - "alloy-serde", + "alloy-serde 2.0.4", "bytes", "foundry-common", "foundry-evm", @@ -1197,12 +1416,12 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "anvil-rpc" -version = "1.5.1" +version = "1.7.1" dependencies = [ "serde", "serde_json", @@ -1210,7 +1429,7 @@ dependencies = [ [[package]] name = "anvil-server" -version = "1.5.1" +version = "1.7.1" dependencies = [ "anvil-rpc", "async-trait", @@ -1220,10 +1439,10 @@ dependencies = [ "futures", "interprocess", "parking_lot", - "pin-project 1.1.10", + "pin-project", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio-util", "tower-http", "tracing", @@ -1231,9 +1450,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" @@ -1374,7 +1593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1412,7 +1631,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1501,7 +1720,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1547,6 +1766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" dependencies = [ "serde", + "zeroize", ] [[package]] @@ -1560,16 +1780,16 @@ dependencies = [ [[package]] name = "assertion-da-client" -version = "1.3.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa#3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa" +version = "1.4.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=lea%2Feng-3169-featcredible-sdk-update-revm-and-alloy-dependencies#7812d7d33e20f176ce64bfa4111003b9fb0ccbc2" dependencies = [ "alloy-primitives", "assertion-da-core", "http 1.4.0", - "reqwest", + "reqwest 0.12.26", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "url", @@ -1577,8 +1797,8 @@ dependencies = [ [[package]] name = "assertion-da-core" -version = "1.3.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa#3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa" +version = "1.4.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=lea%2Feng-3169-featcredible-sdk-update-revm-and-alloy-dependencies#7812d7d33e20f176ce64bfa4111003b9fb0ccbc2" dependencies = [ "alloy-primitives", "serde", @@ -1586,13 +1806,14 @@ dependencies = [ [[package]] name = "assertion-executor" -version = "1.3.0" -source = "git+https://github.com/phylaxsystems/credible-sdk.git?rev=3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa#3387cf96ff9a04869445ea0d20cd5a29f1a0ddfa" +version = "1.4.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=lea%2Feng-3169-featcredible-sdk-update-revm-and-alloy-dependencies#7812d7d33e20f176ce64bfa4111003b9fb0ccbc2" dependencies = [ - "alloy-consensus", - "alloy-evm", + "alloy-chains", + "alloy-consensus 2.0.4", + "alloy-evm 0.34.0", "alloy-network", - "alloy-network-primitives", + "alloy-network-primitives 2.0.4", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -1601,17 +1822,23 @@ dependencies = [ "assertion-da-client", "bincode", "bumpalo", + "bytes", "dashmap", + "eip-common", "enum-as-inner", "metrics", "op-revm", "rapidhash", "rayon", + "reth-db", + "reth-db-api 1.11.2", + "reth-libmdbx", "revm", "serde", "serde_json", "sled", - "thiserror 2.0.17", + "strum", + "thiserror 2.0.18", "tokio", "tracing", ] @@ -1657,7 +1884,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1668,7 +1895,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1721,7 +1948,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1774,19 +2001,20 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.15.2" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ "aws-lc-sys", + "untrusted 0.7.1", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.35.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" dependencies = [ "cc", "cmake", @@ -1924,7 +2152,7 @@ dependencies = [ "http 0.2.12", "http 1.4.0", "percent-encoding", - "sha2", + "sha2 0.10.9", "time", "tracing", ] @@ -2155,12 +2383,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "az" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" - [[package]] name = "backtrace" version = "0.3.76" @@ -2231,6 +2453,24 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.117", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -2290,6 +2530,30 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake3" +version = "1.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", + "zeroize", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -2299,6 +2563,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block2" version = "0.6.2" @@ -2330,7 +2603,7 @@ dependencies = [ "boa_interner", "boa_macros", "boa_string", - "indexmap 2.12.1", + "indexmap 2.14.0", "num-bigint", "rustc-hash", ] @@ -2362,7 +2635,7 @@ dependencies = [ "futures-lite", "hashbrown 0.16.1", "icu_normalizer", - "indexmap 2.12.1", + "indexmap 2.14.0", "intrusive-collections", "itertools 0.14.0", "num-bigint", @@ -2382,7 +2655,7 @@ dependencies = [ "tag_ptr", "tap", "thin-vec", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "xsum", ] @@ -2408,7 +2681,7 @@ dependencies = [ "boa_gc", "boa_macros", "hashbrown 0.16.1", - "indexmap 2.12.1", + "indexmap 2.14.0", "once_cell", "phf 0.13.1", "rustc-hash", @@ -2425,7 +2698,7 @@ dependencies = [ "cow-utils", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -2463,9 +2736,9 @@ dependencies = [ [[package]] name = "bon" -version = "3.8.1" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1" +checksum = "f47dbe92550676ee653353c310dfb9cf6ba17ee70396e1f7cf0a2020ad49b2fe" dependencies = [ "bon-macros", "rustversion", @@ -2473,17 +2746,17 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.8.1" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645" +checksum = "519bd3116aeeb42d5372c29d982d16d0170d3d4a5ed85fc7dd91642ffff3c67c" dependencies = [ - "darling 0.21.3", + "darling 0.20.11", "ident_case", "prettyplease", "proc-macro2", "quote", "rustversion", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2506,7 +2779,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2521,7 +2794,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "sha2", + "sha2 0.10.9", "tinyvec", ] @@ -2565,7 +2838,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2576,9 +2849,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2595,9 +2868,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "2.1.5" +version = "2.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" +checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" dependencies = [ "blst", "cc", @@ -2643,28 +2916,23 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "thiserror 1.0.69", ] -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - [[package]] name = "cast" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-contract", "alloy-dyn-abi", - "alloy-eips", + "alloy-eips 2.0.4", "alloy-ens", + "alloy-evm 0.33.3", "alloy-hardforks", "alloy-json-abi", "alloy-json-rpc", @@ -2674,7 +2942,7 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types", "alloy-rpc-types-beacon", - "alloy-serde", + "alloy-serde 2.0.4", "alloy-signer", "alloy-signer-local", "alloy-sol-types", @@ -2696,22 +2964,27 @@ dependencies = [ "foundry-config", "foundry-debugger", "foundry-evm", - "foundry-primitives", + "foundry-evm-networks", "foundry-test-utils", "foundry-wallets", "futures", "itertools 0.14.0", + "op-alloy-consensus 0.24.0", "op-alloy-flz", + "op-alloy-network", "rand 0.8.5", "rand 0.9.2", "rayon", "regex", "revm", "rpassword", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "tempfile", + "tempo-alloy", + "tempo-contracts", + "tempo-primitives", "tokio", "tracing", "yansi", @@ -2744,6 +3017,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -2756,9 +3038,33 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + [[package]] name = "chisel" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -2776,10 +3082,10 @@ dependencies = [ "foundry-solang-parser", "foundry-test-utils", "itertools 0.14.0", - "reqwest", + "reqwest 0.13.3", "rexpect", "rustyline", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "solar-compiler", @@ -2838,8 +3144,20 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", + "zeroize", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", ] [[package]] @@ -2905,7 +3223,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2922,7 +3240,7 @@ checksum = "85a8ab73a1c02b0c15597b22e09c7dc36e63b2f601f9d1e83ac0c3decd38b1ae" dependencies = [ "nix 0.29.0", "terminfo", - "thiserror 2.0.17", + "thiserror 2.0.18", "which", "windows-sys 0.59.0", ] @@ -2959,6 +3277,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5417da527aa9bf6a1e10a781231effd1edd3ee82f27d5f8529ac9b279babce96" + [[package]] name = "coins-bip32" version = "0.12.0" @@ -2971,7 +3295,7 @@ dependencies = [ "hmac", "k256", "serde", - "sha2", + "sha2 0.10.9", "thiserror 1.0.69", ] @@ -2987,7 +3311,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", - "sha2", + "sha2 0.10.9", "thiserror 1.0.69", ] @@ -3005,22 +3329,21 @@ dependencies = [ "generic-array", "ripemd", "serde", - "sha2", + "sha2 0.10.9", "sha3", "thiserror 1.0.69", ] [[package]] name = "coins-ledger" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9bc0994d0aa0f4ade5f3a9baf4a8d936f250278c85a1124b401860454246ab" +checksum = "c707b8909cef367cd04a11b0d71d65ab34a625d295a07869dd2fff2ca95bf688" dependencies = [ "async-trait", "byteorder", "cfg-if", "const-hex", - "getrandom 0.2.16", "hidapi-rusb", "js-sys", "log", @@ -3072,7 +3395,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3091,7 +3414,7 @@ version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b03b7db8e0b4b2fdad6c551e634134e99ec000e5c8c3b6856c65e8bbaded7a3b" dependencies = [ - "crossterm 0.29.0", + "crossterm", "unicode-segmentation", "unicode-width 0.2.0", ] @@ -3102,11 +3425,134 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" +[[package]] +name = "commonware-codec" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f06e32817f35fb517ceb6102d984f9a85fde85666c96f053638e323b8597f2f7" +dependencies = [ + "bytes", + "cfg-if", + "commonware-macros", + "paste", + "rand 0.8.5", + "rand_chacha 0.3.1", + "thiserror 2.0.18", +] + +[[package]] +name = "commonware-cryptography" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f09b55dd5510c3b7613a573606a41961c2788709ffde053d4e644bec0bff2c" +dependencies = [ + "anyhow", + "aws-lc-rs", + "blake3", + "blst", + "bytes", + "cfg-if", + "chacha20poly1305", + "commonware-codec", + "commonware-macros", + "commonware-math", + "commonware-parallel", + "commonware-utils", + "crc-fast", + "ctutils", + "ecdsa", + "ed25519-consensus", + "getrandom 0.2.16", + "num-rational", + "num-traits", + "p256", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "sha2 0.10.9", + "thiserror 2.0.18", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "commonware-macros" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd313d9299e13bf995999c7a0ed8cc570eef6cd0972fcffc6e2c682cfba6663" +dependencies = [ + "commonware-macros-impl", + "tokio", +] + +[[package]] +name = "commonware-macros-impl" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc385e646d91b5397c93816985421878d627839834f7cf85a8da2ac9f8b98b7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", + "toml 0.9.10+spec-1.1.0", +] + +[[package]] +name = "commonware-math" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d834ed8bf601e113b9cd2ba284dd0e95adf558933dc727f52f8879434cb286" +dependencies = [ + "bytes", + "commonware-codec", + "commonware-macros", + "commonware-parallel", + "commonware-utils", + "rand_core 0.6.4", +] + +[[package]] +name = "commonware-parallel" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db29306a40279ad54d06b42c623a05fbb5333546b5003c921796bc856b423106" +dependencies = [ + "cfg-if", + "commonware-macros", + "rayon", +] + +[[package]] +name = "commonware-utils" +version = "2026.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf66d7b5c89489d71b0669bda2e014e7c9ffcdf65629ae31886efe5361b1179" +dependencies = [ + "bytes", + "cfg-if", + "commonware-codec", + "commonware-macros", + "futures", + "getrandom 0.2.16", + "hashbrown 0.16.1", + "num-bigint", + "num-integer", + "num-rational", + "num-traits", + "parking_lot", + "pin-project", + "rand 0.8.5", + "thiserror 2.0.18", + "tokio", + "zeroize", +] + [[package]] name = "compact_str" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" dependencies = [ "castaway", "cfg-if", @@ -3196,7 +3642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -3207,6 +3653,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "const_format" version = "0.2.35" @@ -3227,6 +3679,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + [[package]] name = "convert_case" version = "0.10.0" @@ -3287,6 +3745,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -3302,6 +3769,16 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc-fast" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75b2483e97a5a7da73ac68a05b629f9c53cff58d8ed1c77866079e18b00dba5" +dependencies = [ + "digest 0.10.7", + "spin", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -3360,22 +3837,6 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crossterm" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" -dependencies = [ - "bitflags 2.10.0", - "crossterm_winapi", - "mio", - "parking_lot", - "rustix 0.38.44", - "signal-hook", - "signal-hook-mio", - "winapi", -] - [[package]] name = "crossterm" version = "0.29.0" @@ -3388,7 +3849,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix 1.1.2", + "rustix", "signal-hook", "signal-hook-mio", "winapi", @@ -3428,30 +3889,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] [[package]] -name = "cssparser" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "phf 0.11.3", - "smallvec", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" +name = "crypto-common" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "quote", - "syn 2.0.111", + "hybrid-array", ] [[package]] @@ -3474,6 +3922,54 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "ctutils" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758e5ed90be3c8abff7f9a6f37ab7f6d8c59c2210d448b81f3f508134aec84e4" +dependencies = [ + "cmov", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "fiat-crypto", + "rustc_version 0.4.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + [[package]] name = "darling" version = "0.20.11" @@ -3494,6 +3990,16 @@ dependencies = [ "darling_macro 0.21.3", ] +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + [[package]] name = "darling_core" version = "0.20.11" @@ -3505,7 +4011,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3515,12 +4021,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ "ident_case", "proc-macro2", "quote", "serde", "strsim", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3531,7 +4050,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3542,7 +4061,18 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.117", ] [[package]] @@ -3557,6 +4087,7 @@ dependencies = [ "lock_api", "once_cell", "parking_lot_core", + "serde", ] [[package]] @@ -3571,7 +4102,7 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", + "const-oid 0.9.6", "pem-rfc7468", "zeroize", ] @@ -3605,7 +4136,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3616,7 +4147,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3637,7 +4168,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3647,29 +4178,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.111", + "syn 2.0.117", "unicode-xid", ] @@ -3690,6 +4221,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.9.0" @@ -3705,12 +4242,23 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "const-oid 0.10.2", + "crypto-common 0.2.2", +] + [[package]] name = "dirs" version = "6.0.0" @@ -3729,7 +4277,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3752,7 +4300,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3782,21 +4330,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" -[[package]] -name = "dtoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" -dependencies = [ - "dtoa", -] - [[package]] name = "dunce" version = "1.0.5" @@ -3826,7 +4359,7 @@ checksum = "1ec431cd708430d5029356535259c5d645d60edd3d39c54e5eea9782d46caa7d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3853,6 +4386,21 @@ dependencies = [ "spki", ] +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "thiserror 1.0.69", + "zeroize", +] + [[package]] name = "educe" version = "0.6.0" @@ -3862,7 +4410,23 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", +] + +[[package]] +name = "ego-tree" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b04dc5a38e4f151a79d9f2451ae6037fb6eaf5cba34771f44781f80e508498e3" + +[[package]] +name = "eip-common" +version = "1.4.0" +source = "git+https://github.com/phylaxsystems/credible-sdk.git?branch=lea%2Feng-3169-featcredible-sdk-update-revm-and-alloy-dependencies#7812d7d33e20f176ce64bfa4111003b9fb0ccbc2" +dependencies = [ + "alloy-eips 2.0.4", + "alloy-primitives", + "revm", ] [[package]] @@ -3959,7 +4523,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3979,7 +4543,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4028,7 +4592,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4055,7 +4619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -4080,7 +4644,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "sha3", "thiserror 1.0.69", "uuid 0.8.2", @@ -4099,21 +4663,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "ethereum_ssz" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dcddb2554d19cde19b099fadddde576929d7a4d0c1cd3512d1fd95cf174375c" -dependencies = [ - "alloy-primitives", - "ethereum_serde_utils", - "itertools 0.13.0", - "serde", - "serde_derive", - "smallvec", - "typenum", -] - [[package]] name = "ethereum_ssz" version = "0.10.0" @@ -4131,14 +4680,14 @@ dependencies = [ [[package]] name = "ethereum_ssz_derive" -version = "0.9.1" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a657b6b3b7e153637dc6bdc6566ad9279d9ee11a15b12cfb24a2e04360637e9f" +checksum = "daf022360bdbe9456eda5f35718a50476d5b2a0d51a97ed4eae27420737a6fba" dependencies = [ - "darling 0.20.11", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4154,9 +4703,9 @@ dependencies = [ [[package]] name = "evm-disassembler" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded685d9f07315ff689ba56e7d84e6f1e782db19b531a46c34061a733bba7258" +checksum = "ace07bd9e99c61333fa7b95b264f0f814bdfc4ec6714f67ffd8e703b25edb2be" dependencies = [ "eyre", "hex", @@ -4170,7 +4719,7 @@ checksum = "6b62c02aa0474cf6c68610ee424dc5feddbe004ea48632c14d237fefa3d893a3" dependencies = [ "alloy-dyn-abi", "alloy-primitives", - "indexmap 2.12.1", + "indexmap 2.14.0", ] [[package]] @@ -4183,6 +4732,18 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fast-float2" version = "0.2.3" @@ -4230,8 +4791,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.1.2", - "windows-sys 0.59.0", + "rustix", + "windows-sys 0.52.0", ] [[package]] @@ -4255,17 +4816,22 @@ dependencies = [ ] [[package]] -name = "figment" -version = "0.10.19" +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "figment2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +checksum = "87d63dee16df12076c7770919713c0b92f4e1c85eac828dc2ade0b6c998f016b" dependencies = [ "atomic", "parking_lot", - "pear", "serde", "tempfile", - "toml 0.8.23", + "toml_edit 0.25.11+spec-1.1.0", "uncased", "version_check", ] @@ -4288,6 +4854,27 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixed-map" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ed19add84e8cb9e8cc5f7074de0324247149ffef0b851e215fb0edc50c229b" +dependencies = [ + "fixed-map-derive", + "serde", +] + +[[package]] +name = "fixed-map-derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dc7a9cb3326bafb80642c5ce99b39a2c0702d4bfa8ee8a3e773791a6cbe2407" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "fixedbitset" version = "0.5.7" @@ -4334,33 +4921,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "font-awesome-as-a-crate" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "b40fbe89eb7639971503bf5f17bd31c41338e8f92e03c5744d07f2e03d43f679" [[package]] name = "forge" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-hardforks", "alloy-json-abi", "alloy-network", "alloy-primitives", "alloy-provider", - "alloy-rpc-types", - "alloy-serde", "alloy-signer", "alloy-signer-local", "alloy-transport", @@ -4402,25 +4979,29 @@ dependencies = [ "path-slash", "proptest", "quick-junit", + "rand 0.9.2", "rayon", "regex", - "reqwest", + "reqwest 0.13.3", "revm", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "similar", "similar-asserts", "solar-compiler", "soldeer-commands", - "strum 0.27.2", + "soldeer-core", + "strum", "svm-rs", "tempfile", - "thiserror 2.0.17", + "tempo-alloy", + "thiserror 2.0.18", "tokio", "toml_edit 0.24.0+spec-1.1.0", "tower-http", "tracing", + "url", "watchexec", "watchexec-events", "watchexec-signals", @@ -4429,7 +5010,7 @@ dependencies = [ [[package]] name = "forge-doc" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-primitives", "derive_more", @@ -4440,20 +5021,20 @@ dependencies = [ "foundry-config", "foundry-solang-parser", "itertools 0.14.0", - "mdbook", + "mdbook-driver", "rayon", "regex", "serde", "serde_json", "solar-compiler", - "thiserror 2.0.17", + "thiserror 2.0.18", "toml 0.9.10+spec-1.1.0", "tracing", ] [[package]] name = "forge-fmt" -version = "1.5.1" +version = "1.7.1" dependencies = [ "foundry-common", "foundry-config", @@ -4467,7 +5048,7 @@ dependencies = [ [[package]] name = "forge-lint" -version = "1.5.1" +version = "1.7.1" dependencies = [ "eyre", "foundry-common", @@ -4476,23 +5057,23 @@ dependencies = [ "heck", "rayon", "solar-compiler", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "forge-script" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", - "alloy-eips", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", "alloy-json-abi", "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rpc-types", - "alloy-serde", "alloy-signer", "clap", "dialoguer", @@ -4507,6 +5088,7 @@ dependencies = [ "foundry-config", "foundry-debugger", "foundry-evm", + "foundry-evm-networks", "foundry-linking", "foundry-wallets", "futures", @@ -4514,11 +5096,13 @@ dependencies = [ "itertools 0.14.0", "parking_lot", "revm-inspectors", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "tempfile", - "thiserror 2.0.17", + "tempo-alloy", + "tempo-primitives", + "thiserror 2.0.18", "tokio", "tracing", "yansi", @@ -4526,7 +5110,7 @@ dependencies = [ [[package]] name = "forge-script-sequence" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-network", "alloy-primitives", @@ -4542,7 +5126,7 @@ dependencies = [ [[package]] name = "forge-sol-macro-gen" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -4552,14 +5136,16 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "forge-verify" -version = "1.5.1" +version = "1.7.1" dependencies = [ + "alloy-consensus 2.0.4", "alloy-dyn-abi", + "alloy-evm 0.33.3", "alloy-json-abi", "alloy-primitives", "alloy-provider", @@ -4578,9 +5164,9 @@ dependencies = [ "futures", "itertools 0.14.0", "regex", - "reqwest", + "reqwest 0.13.3", "revm", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "tempfile", @@ -4601,7 +5187,7 @@ dependencies = [ [[package]] name = "foundry-bench" -version = "1.5.1" +version = "1.7.1" dependencies = [ "chrono", "clap", @@ -4618,32 +5204,32 @@ dependencies = [ [[package]] name = "foundry-block-explorers" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff814624bb21bfe43b70fb736ab39527b405d04cdc94d90b7e182fba28b25ec7" +checksum = "786287256b3da26184e25d66685d33fd208d0b6e2098895cf7e880f3ce18eca1" dependencies = [ "alloy-chains", "alloy-json-abi", "alloy-primitives", "foundry-compilers", - "reqwest", - "semver 1.0.27", + "reqwest 0.13.3", + "semver 1.0.28", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] [[package]] name = "foundry-cheatcodes" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-ens", - "alloy-evm", - "alloy-genesis", + "alloy-evm 0.33.3", + "alloy-genesis 2.0.4", "alloy-json-abi", "alloy-network", "alloy-primitives", @@ -4657,6 +5243,7 @@ dependencies = [ "base64 0.22.1", "dialoguer", "ecdsa", + "ed25519-consensus", "eyre", "forge-script-sequence", "foundry-cheatcodes-spec", @@ -4678,11 +5265,11 @@ dependencies = [ "rand 0.9.2", "revm", "revm-inspectors", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "solar-compiler", - "thiserror 2.0.17", + "thiserror 2.0.18", "toml 0.9.10+spec-1.1.0", "tracing", "walkdir", @@ -4690,7 +5277,7 @@ dependencies = [ [[package]] name = "foundry-cheatcodes-spec" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-sol-types", "foundry-macros", @@ -4701,16 +5288,18 @@ dependencies = [ [[package]] name = "foundry-cli" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-dyn-abi", - "alloy-eips", + "alloy-eips 2.0.4", "alloy-ens", "alloy-json-abi", + "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rlp", + "alloy-signer", "cfg-if", "clap", "clap_complete", @@ -4719,11 +5308,12 @@ dependencies = [ "dotenvy", "dunce", "eyre", - "foundry-block-explorers", + "foundry-cli-markdown", "foundry-common", "foundry-compilers", "foundry-config", "foundry-evm", + "foundry-evm-networks", "foundry-wallets", "futures", "indicatif", @@ -4737,8 +5327,9 @@ dependencies = [ "serde_json", "solar-compiler", "strsim", - "strum 0.27.2", + "strum", "tempfile", + "tempo-primitives", "tikv-jemallocator", "tokio", "tracing", @@ -4747,26 +5338,35 @@ dependencies = [ "yansi", ] +[[package]] +name = "foundry-cli-markdown" +version = "1.7.1" +dependencies = [ + "clap", + "pretty_assertions", +] + [[package]] name = "foundry-common" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", - "alloy-eips", + "alloy-eips 2.0.4", "alloy-json-abi", "alloy-json-rpc", "alloy-network", "alloy-primitives", "alloy-provider", "alloy-pubsub", + "alloy-rlp", "alloy-rpc-client", "alloy-rpc-types", - "alloy-serde", + "alloy-rpc-types-engine", + "alloy-signer", "alloy-sol-types", "alloy-transport", - "alloy-transport-http", "alloy-transport-ipc", "alloy-transport-ws", "anstream", @@ -4776,58 +5376,75 @@ dependencies = [ "ciborium", "clap", "comfy-table", + "dirs", "dunce", "eyre", "flate2", "foundry-block-explorers", "foundry-common-fmt", "foundry-compilers", + "foundry-config", + "foundry-wallets", + "futures", "itertools 0.14.0", "jiff", + "mpp", "num-format", + "op-alloy-network", + "op-alloy-rpc-types", "path-slash", "regex", - "reqwest", + "reqwest 0.13.3", "revm", - "semver 1.0.27", + "rustls", + "semver 1.0.28", "serde", "serde_json", "solar-compiler", - "thiserror 2.0.17", + "tempfile", + "tempo-alloy", + "tempo-primitives", + "thiserror 2.0.18", "tokio", + "tokio-tungstenite 0.28.0", + "toml 0.9.10+spec-1.1.0", "tower", "tracing", "url", - "vergen", + "vergen-gitcl", "walkdir", "yansi", ] [[package]] name = "foundry-common-fmt" -version = "1.5.1" +version = "1.7.1" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-network", "alloy-primitives", "alloy-rpc-types", - "alloy-serde", + "alloy-serde 2.0.4", "chrono", + "comfy-table", "eyre", "foundry-macros", + "op-alloy-consensus 0.24.0", + "op-alloy-rpc-types", "revm", "serde", "serde_json", "similar-asserts", + "tempo-alloy", "yansi", ] [[package]] name = "foundry-compilers" -version = "0.19.10" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366854900404df2e7dce32662bdf76e442ec2001b72eb3f15cb1af7f6c2c3501" +checksum = "8a46823427db611c6b97506ee8f26b4424058366abcc9a97ac5c4c3419798518" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4841,25 +5458,25 @@ dependencies = [ "path-slash", "rand 0.9.2", "rayon", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", - "sha2", + "sha2 0.11.0", "solar-compiler", "svm-rs", "svm-rs-builds", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", - "winnow", + "winnow 0.7.14", "yansi", ] [[package]] name = "foundry-compilers-artifacts" -version = "0.19.10" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d46ae5cbaccf86b1019194309398b04bb65ab9cfb07c8e4ca2e79a95bbc85f" +checksum = "c29c6a49e82684909549e8e3a63a9dea4c92dfeb1b5b3a5e3ad683db42324ac3" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -4867,9 +5484,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.19.10" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0265397f148271a9e5733c9598685181ce3f3d0b878187220fb9ec98c208ef7d" +checksum = "02d3e554932001133f433473b3bdb37c74b4a648750ab61cd7966e7db0ead16d" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -4878,47 +5495,45 @@ dependencies = [ "path-slash", "rayon", "regex", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "yansi", ] [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.19.10" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c5e38bda9f97e2a3b36a08f24ea1bf343c90f5c8398bd07ebf48a6ed65d8cf" +checksum = "583168b6df6b73cc3de8d205a922dca58a9c0b4c2774f6b115b3ff7e79d23900" dependencies = [ "alloy-json-abi", "alloy-primitives", "foundry-compilers-artifacts-solc", "foundry-compilers-core", - "path-slash", - "semver 1.0.27", + "semver 1.0.28", "serde", ] [[package]] name = "foundry-compilers-core" -version = "0.19.10" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4f2dda845ce5933e70dcd6dd5b3edfb953d3dcf764bd64f96a31d0de56d6d8" +checksum = "b9f80dd5d9f3ed065e412ecef2da3904ea21708d53f79fac29a3547c10ae947f" dependencies = [ "alloy-primitives", - "cfg-if", "dunce", "fs_extra", "path-slash", "regex", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "svm-rs", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "walkdir", "xxhash-rust", @@ -4926,7 +5541,7 @@ dependencies = [ [[package]] name = "foundry-config" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", "alloy-primitives", @@ -4934,9 +5549,10 @@ dependencies = [ "dirs", "dunce", "eyre", - "figment", + "figment2", "foundry-block-explorers", "foundry-compilers", + "foundry-evm-hardforks", "foundry-evm-networks", "glob", "globset", @@ -4946,9 +5562,7 @@ dependencies = [ "path-slash", "rayon", "regex", - "reqwest", - "revm", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "similar-asserts", @@ -4956,7 +5570,7 @@ dependencies = [ "solar-compiler", "soldeer-core", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", "toml 0.9.10+spec-1.1.0", "toml_edit 0.24.0+spec-1.1.0", "tracing", @@ -4967,10 +5581,10 @@ dependencies = [ [[package]] name = "foundry-debugger" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-primitives", - "crossterm 0.29.0", + "crossterm", "eyre", "foundry-common", "foundry-compilers", @@ -4985,10 +5599,9 @@ dependencies = [ [[package]] name = "foundry-evm" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", - "alloy-evm", "alloy-json-abi", "alloy-primitives", "alloy-rpc-types", @@ -5001,23 +5614,29 @@ dependencies = [ "foundry-evm-core", "foundry-evm-coverage", "foundry-evm-fuzz", + "foundry-evm-hardforks", "foundry-evm-networks", + "foundry-evm-sancov", "foundry-evm-traces", "indicatif", "parking_lot", "proptest", + "rayon", "revm", "revm-inspectors", "serde", "serde_json", - "thiserror 2.0.17", + "tempo-precompiles", + "tempo-primitives", + "thiserror 2.0.18", + "tokio", "tracing", "uuid 1.19.0", ] [[package]] name = "foundry-evm-abi" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -5029,40 +5648,51 @@ dependencies = [ [[package]] name = "foundry-evm-core" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", - "alloy-evm", - "alloy-genesis", + "alloy-evm 0.33.3", + "alloy-genesis 2.0.4", "alloy-hardforks", "alloy-json-abi", "alloy-network", "alloy-op-evm", - "alloy-op-hardforks", "alloy-primitives", "alloy-provider", + "alloy-rlp", "alloy-rpc-types", + "alloy-serde 2.0.4", "alloy-sol-types", + "anvil", "auto_impl", "eyre", "foundry-cheatcodes-spec", "foundry-common", "foundry-config", "foundry-evm-abi", + "foundry-evm-hardforks", "foundry-evm-networks", "foundry-fork-db", "foundry-test-utils", "futures", "itertools 0.14.0", + "op-alloy-consensus 0.24.0", + "op-alloy-network", + "op-alloy-rpc-types", "op-revm", "parking_lot", "revm", "revm-inspectors", "serde", "serde_json", - "thiserror 2.0.17", + "tempo-alloy", + "tempo-contracts", + "tempo-evm", + "tempo-precompiles", + "tempo-revm", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -5070,7 +5700,7 @@ dependencies = [ [[package]] name = "foundry-evm-coverage" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-primitives", "eyre", @@ -5079,14 +5709,14 @@ dependencies = [ "foundry-evm-core", "rayon", "revm", - "semver 1.0.27", + "semver 1.0.28", "solar-compiler", "tracing", ] [[package]] name = "foundry-evm-fuzz" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -5105,25 +5735,48 @@ dependencies = [ "revm", "serde", "solar-compiler", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] +[[package]] +name = "foundry-evm-hardforks" +version = "1.7.1" +dependencies = [ + "alloy-chains", + "alloy-hardforks", + "alloy-op-hardforks", + "alloy-rpc-types", + "foundry-compilers", + "op-revm", + "revm", + "serde", + "tempo-chainspec", +] + [[package]] name = "foundry-evm-networks" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-chains", - "alloy-evm", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", + "alloy-op-hardforks", "alloy-primitives", "clap", + "foundry-evm-hardforks", "revm", "serde", + "serde_json", ] +[[package]] +name = "foundry-evm-sancov" +version = "1.7.1" + [[package]] name = "foundry-evm-traces" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -5141,13 +5794,15 @@ dependencies = [ "itertools 0.14.0", "memchr", "rayon", - "reqwest", + "reqwest 0.13.3", "revm", "revm-inspectors", "serde", "serde_json", "solar-compiler", "tempfile", + "tempo-contracts", + "tempo-precompiles", "tokio", "tracing", "yansi", @@ -5155,13 +5810,11 @@ dependencies = [ [[package]] name = "foundry-fork-db" -version = "0.21.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df2fd495cf7337b247d960f90355329cc625fe27fe7da9fe5e598c42df21526" +checksum = "f2ce9e91abb900e4ab5346d06b97c3784ae6ed4fc44b9fa22d3dc712b7e21be9" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-hardforks", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -5171,53 +5824,59 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "url", + "zstd 0.13.3", ] [[package]] name = "foundry-linking" -version = "1.5.1" +version = "1.7.1" dependencies = [ "alloy-primitives", "foundry-compilers", "rayon", - "semver 1.0.27", - "thiserror 2.0.17", + "semver 1.0.28", + "thiserror 2.0.18", ] [[package]] name = "foundry-macros" -version = "1.5.1" +version = "1.7.1" dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "foundry-primitives" -version = "1.5.1" +version = "1.7.1" dependencies = [ - "alloy-consensus", - "alloy-evm", + "alloy-consensus 2.0.4", + "alloy-evm 0.33.3", "alloy-network", + "alloy-op-evm", "alloy-primitives", + "alloy-provider", "alloy-rlp", "alloy-rpc-types", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "alloy-signer", "derive_more", - "op-alloy-consensus", + "op-alloy-consensus 0.24.0", "op-alloy-rpc-types", "op-revm", "revm", "serde", "serde_json", + "tempo-alloy", "tempo-primitives", + "tempo-revm", ] [[package]] @@ -5230,14 +5889,15 @@ dependencies = [ "lalrpop", "lalrpop-util", "phf 0.11.3", - "thiserror 2.0.17", + "thiserror 2.0.18", "unicode-xid", ] [[package]] name = "foundry-test-utils" -version = "1.5.1" +version = "1.7.1" dependencies = [ + "alloy-chains", "alloy-primitives", "alloy-provider", "eyre", @@ -5250,7 +5910,7 @@ dependencies = [ "parking_lot", "rand 0.9.2", "regex", - "reqwest", + "reqwest 0.13.3", "serde_json", "snapbox", "svm-rs", @@ -5263,13 +5923,15 @@ dependencies = [ [[package]] name = "foundry-wallets" -version = "1.5.1" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f2cc1ff7ea002addf41bd9c5785cd34f6a7b9658998c50035cc860ffebc3a9" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", "alloy-network", "alloy-primitives", - "alloy-rpc-types", + "alloy-rlp", "alloy-signer", "alloy-signer-aws", "alloy-signer-gcp", @@ -5283,16 +5945,17 @@ dependencies = [ "axum", "clap", "derive_builder", + "dirs", "eth-keystore", "eyre", - "foundry-common", - "foundry-config", - "reqwest", "rpassword", + "rusqlite", "serde", "serde_json", - "thiserror 2.0.17", + "tempo-primitives", + "thiserror 2.0.18", "tokio", + "toml 0.9.10+spec-1.1.0", "tower", "tower-http", "tracing", @@ -5343,16 +6006,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - [[package]] name = "futures" version = "0.3.31" @@ -5401,7 +6054,7 @@ dependencies = [ "futures-buffered", "futures-core", "futures-lite", - "pin-project 1.1.10", + "pin-project", "slab", "smallvec", ] @@ -5450,7 +6103,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5491,9 +6144,9 @@ checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" [[package]] name = "gcloud-sdk" -version = "0.27.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8458d2ad7741b6a16981b84e66b7e4d8026423096da721894769c6980d06ecc" +checksum = "6b5b58d8683fa308be9bc58caece4972315a0b2547f9da16962511f0915d5b53" dependencies = [ "async-trait", "bytes", @@ -5502,17 +6155,17 @@ dependencies = [ "hyper", "jsonwebtoken", "once_cell", - "prost 0.13.5", - "prost-types 0.13.5", - "reqwest", + "prost 0.14.1", + "prost-types 0.14.1", + "reqwest 0.13.3", "secret-vault-value", "serde", "serde_json", "tokio", "tonic", + "tonic-prost", "tower", "tower-layer", - "tower-util", "tracing", "url", ] @@ -5565,11 +6218,36 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "getset" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "gimli" version = "0.32.3" @@ -5595,16 +6273,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "gmp-mpfr-sys" -version = "1.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f8970a75c006bb2f8ae79c6768a116dd215fa8346a87aed99bf9d82ca43394" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - [[package]] name = "group" version = "0.13.0" @@ -5628,7 +6296,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.12.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -5648,9 +6316,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.3.2" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" +checksum = "d43ccdfe15a81ab0a8af639e90254227c9a46afd9c5f5b6ec7efaa345c4b0f00" dependencies = [ "derive_builder", "log", @@ -5659,7 +6327,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5681,7 +6349,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -5698,6 +6365,21 @@ dependencies = [ "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "heck" version = "0.5.0" @@ -5766,13 +6448,12 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.35.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4" +checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8" dependencies = [ "log", "markup5ever", - "match_token", ] [[package]] @@ -5848,6 +6529,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.8.1" @@ -5902,22 +6592,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.19" @@ -5936,7 +6610,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2", "system-configuration", "tokio", "tower-service", @@ -6057,6 +6731,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -6127,7 +6807,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6155,13 +6835,13 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "arbitrary", "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -6204,12 +6884,6 @@ dependencies = [ "str_stack", ] -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - [[package]] name = "inline-array" version = "0.1.14" @@ -6259,7 +6933,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6323,7 +6997,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6395,7 +7069,7 @@ checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6407,13 +7081,43 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.0", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "simd_cesu8", + "syn 2.0.117", +] + [[package]] name = "jni-sys" version = "0.3.0" @@ -6421,22 +7125,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] -name = "jobserver" -version = "0.1.34" +name = "jni-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" dependencies = [ - "getrandom 0.3.4", - "libc", + "jni-sys-macros", ] [[package]] -name = "js-sys" -version = "0.3.83" +name = "jni-sys-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ - "once_cell", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", "wasm-bindgen", ] @@ -6460,22 +7185,25 @@ dependencies = [ "http 1.4.0", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" dependencies = [ + "aws-lc-rs", "base64 0.22.1", + "getrandom 0.2.16", "js-sys", "pem", - "ring", "serde", "serde_json", + "signature", "simple_asn1", + "zeroize", ] [[package]] @@ -6489,24 +7217,35 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2", + "sha2 0.10.9", "signature", ] +[[package]] +name = "kasuari" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.18", +] + [[package]] name = "keccak" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "1766b89733097006f3a1388a02849865d6bc98c89273cb622e29fdd209922183" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -6547,7 +7286,7 @@ dependencies = [ "regex", "regex-syntax", "sha3", - "string_cache", + "string_cache 0.8.9", "term", "unicode-xid", "walkdir", @@ -6569,6 +7308,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "levenshtein" version = "1.0.5" @@ -6577,9 +7322,19 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] [[package]] name = "libm" @@ -6607,6 +7362,17 @@ dependencies = [ "libc", ] +[[package]] +name = "libsqlite3-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "947e6816f7825b2b45027c2c32e7085da9934defa535de4a6a46b10a4d5257fa" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "libusb1-sys" version = "0.7.0" @@ -6629,16 +7395,19 @@ dependencies = [ ] [[package]] -name = "linux-raw-sys" -version = "0.4.15" +name = "line-clipping" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "5f4de44e98ddbf09375cbf4d17714d18f39195f4f4894e8524501726fd9a8a4a" +dependencies = [ + "bitflags 2.10.0", +] [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -6685,20 +7454,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.5", -] - -[[package]] -name = "lru" -version = "0.13.0" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -6708,10 +7468,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] -name = "mac" -version = "0.1.1" +name = "lz4_flex" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90071f8077f8e40adfc4b7fe9cd495ce316263f19e75c2211eeff3fdf475a3d9" + +[[package]] +name = "mach2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] [[package]] name = "macro-string" @@ -6721,37 +7490,20 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "markup5ever" -version = "0.35.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3" +checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de" dependencies = [ "log", "tendril", "web_atoms", ] -[[package]] -name = "match_token" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "matchers" version = "0.2.0" @@ -6768,39 +7520,131 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] -name = "mdbook" -version = "0.4.52" +name = "mdbook-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fc1c4da7fd9e2e412f3891428f9468fab890ed159723ed0892bb85a049ac1c1" +dependencies = [ + "anyhow", + "regex", + "serde", + "serde_json", + "toml 1.1.2+spec-1.1.0", + "tracing", +] + +[[package]] +name = "mdbook-driver" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c284d2855916af7c5919cf9ad897cfc77d3c2db6f55429c7cfb769182030ec" +checksum = "2068566fc3c100cfd19f4a13e4e0eb4fdcd2250cfd0aa633ec25102b1c98d53e" dependencies = [ - "ammonia", "anyhow", - "chrono", - "clap", - "clap_complete", + "indexmap 2.14.0", + "mdbook-core", + "mdbook-html", + "mdbook-markdown", + "mdbook-preprocessor", + "mdbook-renderer", + "mdbook-summary", + "regex", + "serde", + "serde_json", + "shlex", + "tempfile", + "toml 1.1.2+spec-1.1.0", + "topological-sort", + "tracing", +] + +[[package]] +name = "mdbook-html" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ed2140251689f928615f0a5615413eb072eb28e003d179257aa4f034c95513" +dependencies = [ + "anyhow", + "ego-tree", "elasticlunr-rs", - "env_logger", + "font-awesome-as-a-crate", "handlebars", "hex", - "log", - "memchr", - "opener", + "html5ever", + "indexmap 2.14.0", + "mdbook-core", + "mdbook-markdown", + "mdbook-renderer", "pulldown-cmark", "regex", "serde", "serde_json", - "sha2", - "shlex", - "tempfile", - "toml 0.5.11", - "topological-sort", + "sha2 0.11.0", + "tracing", +] + +[[package]] +name = "mdbook-markdown" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb3ca9eadf02ce206118a0b9c264718723d669b110c01a720fa9a0786f30642" +dependencies = [ + "pulldown-cmark", + "regex", + "tracing", +] + +[[package]] +name = "mdbook-preprocessor" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eff7b4afaafd664a649a03b8891ad8199aef359a35b911ad6c31acab38ed209" +dependencies = [ + "anyhow", + "mdbook-core", + "serde", + "serde_json", +] + +[[package]] +name = "mdbook-renderer" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e607259410d53aa5cdaf5b6c1c6b3fd61f2e0f0523ebf457d34cd4f0b71e2a88" +dependencies = [ + "anyhow", + "mdbook-core", + "serde", + "serde_json", +] + +[[package]] +name = "mdbook-summary" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae8a734e5e35b0bc145b46d01fd27e266ba647dcdb9b8c907cb6a29eca9122b" +dependencies = [ + "anyhow", + "mdbook-core", + "memchr", + "pulldown-cmark", + "serde", + "tracing", ] [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] [[package]] name = "memoffset" @@ -6841,6 +7685,17 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "metrics-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161ab904c2c62e7bda0f7562bf22f96440ca35ff79e66c800cbac298f2f4f5ec" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "miette" version = "7.6.0" @@ -6860,7 +7715,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6939,14 +7794,14 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "modular-bitfield" -version = "0.11.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" +checksum = "2956e537fc68236d2aa048f55704f231cc93f1c4de42fe1ecb5bd7938061fc4a" dependencies = [ "modular-bitfield-impl", "static_assertions", @@ -6954,30 +7809,41 @@ dependencies = [ [[package]] name = "modular-bitfield-impl" -version = "0.11.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" +checksum = "59b43b4fd69e3437618106f7754f34021b831a514f9e1a98ae863cabcd8d8dad" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +name = "mpp" +version = "0.10.0" +source = "git+https://github.com/tempoxyz/mpp-rs?rev=554d20112eb014bd223d54de7f152ca59b2aa4fd#554d20112eb014bd223d54de7f152ca59b2aa4fd" dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework 2.11.1", - "security-framework-sys", - "tempfile", + "alloy", + "async-stream", + "base64 0.22.1", + "futures-core", + "futures-util", + "hex", + "hmac", + "http 1.4.0", + "rand 0.9.2", + "reqwest 0.12.26", + "serde", + "serde_json", + "serde_json_canonicalizer", + "sha2 0.10.9", + "tempo-alloy", + "tempo-primitives", + "thiserror 2.0.18", + "time", + "tokio", + "tokio-tungstenite 0.26.2", + "uuid 1.19.0", ] [[package]] @@ -7102,13 +7968,22 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -7147,9 +8022,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-format" @@ -7246,7 +8121,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7260,9 +8135,9 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4b5ecbd0beec843101bffe848217f770e8b8da81d8355b7d6e226f2199b3dc" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" dependencies = [ "alloy-rlp", "cfg-if", @@ -7281,6 +8156,15 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "objc2-encode" version = "4.1.0" @@ -7297,6 +8181,16 @@ dependencies = [ "objc2", ] +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "object" version = "0.37.3" @@ -7336,11 +8230,10 @@ dependencies = [ [[package]] name = "op-alloy" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b8fee21003dd4f076563de9b9d26f8c97840157ef78593cd7f262c5ca99848" +version = "0.24.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ - "op-alloy-consensus", + "op-alloy-consensus 0.24.0", "op-alloy-network", "op-alloy-provider", "op-alloy-rpc-types", @@ -7353,17 +8246,35 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "736381a95471d23e267263cfcee9e1d96d30b9754a94a2819148f83379de8a86" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 1.8.3", + "derive_more", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "op-alloy-consensus" +version = "0.24.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-network", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "bytes", "derive_more", + "reth-codecs 0.3.0", + "reth-zstd-compressors 0.3.1", "serde", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7374,25 +8285,21 @@ checksum = "a79f352fc3893dcd670172e615afef993a41798a1d3fc0db88a3e60ef2e70ecc" [[package]] name = "op-alloy-network" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4034183dca6bff6632e7c24c92e75ff5f0eabb58144edb4d8241814851334d47" +version = "0.24.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", - "alloy-primitives", "alloy-provider", - "alloy-rpc-types-eth", - "alloy-signer", - "op-alloy-consensus", + "alloy-rpc-types-eth 2.0.4", + "op-alloy-consensus 0.24.0", "op-alloy-rpc-types", ] [[package]] name = "op-alloy-provider" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6753d90efbaa8ea8bcb89c1737408ca85fa60d7adb875049d3f382c063666f86" +version = "0.24.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ "alloy-network", "alloy-primitives", @@ -7405,56 +8312,61 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd87c6b9e5b6eee8d6b76f41b04368dca0e9f38d83338e5b00e730c282098a4" +version = "0.24.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-network-primitives", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-network", + "alloy-network-primitives 2.0.4", "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "derive_more", - "op-alloy-consensus", + "op-alloy-consensus 0.24.0", + "reth-rpc-traits", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "op-alloy-rpc-types-engine" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727699310a18cdeed32da3928c709e2704043b6584ed416397d5da65694efc" +version = "0.24.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-engine", - "alloy-serde", + "alloy-serde 2.0.4", "derive_more", - "ethereum_ssz 0.9.1", + "ethereum_ssz", "ethereum_ssz_derive", - "op-alloy-consensus", + "op-alloy-consensus 0.24.0", "serde", - "sha2", + "sha2 0.10.9", "snap", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "op-revm" -version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1475a779c73999fc803778524042319691b31f3d6699d2b560c4ed8be1db802a" +version = "19.0.0" +source = "git+https://github.com/ethereum-optimism/optimism?rev=42f5117c2e7de0614cd3b96f274d0a3078f9701c#42f5117c2e7de0614cd3b96f274d0a3078f9701c" dependencies = [ "auto_impl", "revm", "serde", ] +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "opener" version = "0.8.3" @@ -7466,50 +8378,12 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -7538,7 +8412,17 @@ dependencies = [ "elliptic-curve", "primeorder", "serdect", - "sha2", + "sha2 0.10.9", +] + +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", ] [[package]] @@ -7573,7 +8457,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7636,29 +8520,6 @@ dependencies = [ "hmac", ] -[[package]] -name = "pear" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.111", -] - [[package]] name = "pem" version = "3.0.6" @@ -7714,7 +8575,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7724,7 +8585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" dependencies = [ "pest", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -7734,7 +8595,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", - "indexmap 2.12.1", + "indexmap 2.14.0", ] [[package]] @@ -7778,6 +8639,16 @@ dependencies = [ "phf_shared 0.11.3", ] +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", +] + [[package]] name = "phf_generator" version = "0.11.3" @@ -7808,7 +8679,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7821,7 +8692,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7842,33 +8713,13 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef0f924a5ee7ea9cbcea77529dba45f8a9ba9f622419fe3386ca581a3ae9d5a" -dependencies = [ - "pin-project-internal 0.4.30", -] - [[package]] name = "pin-project" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ - "pin-project-internal 1.1.10", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "pin-project-internal", ] [[package]] @@ -7879,7 +8730,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7910,6 +8761,17 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.12.0" @@ -7981,6 +8843,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettydiff" version = "0.9.0" @@ -7997,7 +8869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8049,7 +8921,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8061,19 +8933,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", - "version_check", - "yansi", -] - [[package]] name = "process-wrap" version = "8.2.1" @@ -8081,11 +8940,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3ef4f2f0422f23a82ec9f628ea2acd12871c81a9362b02c43c1aa86acfc3ba1" dependencies = [ "futures", - "indexmap 2.12.1", + "indexmap 2.14.0", "nix 0.30.1", "tokio", "tracing", - "windows", + "windows 0.61.3", ] [[package]] @@ -8109,13 +8968,13 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" +checksum = "fb6dc647500e84a25a85b100e76c85b8ace114c209432dc174f20aac11d4ed6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8128,16 +8987,6 @@ dependencies = [ "prost-derive 0.12.6", ] -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive 0.13.5", -] - [[package]] name = "prost" version = "0.14.1" @@ -8158,20 +9007,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.111", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8181,10 +9017,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8196,15 +9032,6 @@ dependencies = [ "prost 0.12.6", ] -[[package]] -name = "prost-types" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" -dependencies = [ - "prost 0.13.5", -] - [[package]] name = "prost-types" version = "0.14.1" @@ -8216,9 +9043,9 @@ dependencies = [ [[package]] name = "protobuf" -version = "3.3.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65f4a8ec18723a734e5dc09c173e0abf9690432da5340285d536edcb4dac190" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" dependencies = [ "once_cell", "protobuf-support", @@ -8227,18 +9054,18 @@ dependencies = [ [[package]] name = "protobuf-support" -version = "3.3.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6872f4d4f4b98303239a2b5838f5bbbb77b01ffc892d627957f37a22d7cfe69c" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" dependencies = [ "thiserror 1.0.69", ] [[package]] name = "pulldown-cmark" -version = "0.10.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ "bitflags 2.10.0", "memchr", @@ -8248,9 +9075,24 @@ dependencies = [ [[package]] name = "pulldown-cmark-escape" -version = "0.10.1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" + +[[package]] +name = "quanta" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] [[package]] name = "quick-error" @@ -8265,11 +9107,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ee9342d671fae8d66b3ae9fd7a9714dfd089c04d2a8b1ec0436ef77aee15e5f" dependencies = [ "chrono", - "indexmap 2.12.1", + "indexmap 2.14.0", "newtype-uuid", "quick-xml 0.38.4", "strip-ansi-escapes", - "thiserror 2.0.17", + "thiserror 2.0.18", "uuid 1.19.0", ] @@ -8304,8 +9146,8 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", - "thiserror 2.0.17", + "socket2", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -8317,6 +9159,7 @@ version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -8326,7 +9169,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -8341,9 +9184,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -8361,6 +9204,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -8488,25 +9337,76 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.29.0" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" +dependencies = [ + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-widgets", +] + +[[package]] +name = "ratatui-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" +checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ "bitflags 2.10.0", - "cassowary", "compact_str", - "crossterm 0.28.1", + "hashbrown 0.16.1", "indoc", - "instability", - "itertools 0.13.0", - "lru 0.12.5", - "paste", - "strum 0.26.3", + "itertools 0.14.0", + "kasuari", + "lru", + "strum", + "thiserror 2.0.18", "unicode-segmentation", "unicode-truncate", "unicode-width 0.2.0", ] +[[package]] +name = "ratatui-crossterm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" +dependencies = [ + "cfg-if", + "crossterm", + "instability", + "ratatui-core", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.16.1", + "indoc", + "instability", + "itertools 0.14.0", + "line-clipping", + "ratatui-core", + "strum", + "time", + "unicode-segmentation", + "unicode-width 0.2.0", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "rayon" version = "1.11.0" @@ -8559,7 +9459,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8579,14 +9479,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -8654,13 +9554,11 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", "mime_guess", - "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -8672,7 +9570,6 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -8681,482 +9578,977 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", "webpki-roots 1.0.4", ] +[[package]] +name = "reqwest" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.5.0", + "web-sys", +] + [[package]] name = "reth-chainspec" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-evm", - "alloy-genesis", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", + "alloy-genesis 2.0.4", "alloy-primitives", "alloy-trie", "auto_impl", "derive_more", "reth-ethereum-forks", "reth-network-peers", - "reth-primitives-traits", + "reth-primitives-traits 0.3.0", "serde_json", ] [[package]] name = "reth-codecs" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "0.3.0" +source = "git+https://github.com/paradigmxyz/reth-core?rev=6b12498#6b12498871bc1b1d42c6dcf28968c271660de8c0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-genesis", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-genesis 2.0.4", "alloy-primitives", "alloy-trie", "bytes", "modular-bitfield", - "op-alloy-consensus", - "reth-codecs-derive", - "reth-zstd-compressors", + "parity-scale-codec", + "reth-codecs-derive 0.3.0", + "reth-zstd-compressors 0.3.0", "serde", ] [[package]] -name = "reth-codecs-derive" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +name = "reth-codecs" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-genesis 1.8.3", + "alloy-primitives", + "alloy-trie", + "bytes", + "modular-bitfield", + "op-alloy-consensus 0.23.1", + "reth-codecs-derive 1.11.2", + "reth-zstd-compressors 1.11.2", + "serde", +] + +[[package]] +name = "reth-codecs-derive" +version = "0.3.0" +source = "git+https://github.com/paradigmxyz/reth-core?rev=6b12498#6b12498871bc1b1d42c6dcf28968c271660de8c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "reth-codecs-derive" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "reth-consensus" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-primitives", + "auto_impl", + "reth-execution-types", + "reth-primitives-traits 0.3.0", + "thiserror 2.0.18", +] + +[[package]] +name = "reth-consensus-common" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives", + "reth-chainspec", + "reth-consensus", + "reth-primitives-traits 0.3.0", +] + +[[package]] +name = "reth-db" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "alloy-primitives", + "derive_more", + "eyre", + "metrics", + "page_size", + "reth-db-api 1.11.2", + "reth-fs-util", + "reth-libmdbx", + "reth-metrics", + "reth-nippy-jar", + "reth-static-file-types 1.11.2", + "reth-storage-errors 1.11.2", + "reth-tracing", + "rustc-hash", + "strum", + "sysinfo", + "thiserror 2.0.18", + "tracing", ] [[package]] name = "reth-db-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ - "alloy-consensus", - "alloy-genesis", + "alloy-consensus 1.8.3", + "alloy-genesis 1.8.3", "alloy-primitives", + "arrayvec", "bytes", "derive_more", "metrics", "modular-bitfield", "parity-scale-codec", - "reth-codecs", - "reth-db-models", - "reth-ethereum-primitives", - "reth-primitives-traits", - "reth-prune-types", - "reth-stages-types", - "reth-storage-errors", - "reth-trie-common", + "reth-codecs 1.11.2", + "reth-db-models 1.11.2", + "reth-ethereum-primitives 1.11.2", + "reth-primitives-traits 1.11.2", + "reth-prune-types 1.11.2", + "reth-stages-types 1.11.2", + "reth-storage-errors 1.11.2", + "reth-trie-common 1.11.2", + "roaring", + "serde", +] + +[[package]] +name = "reth-db-api" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-primitives", + "arrayvec", + "bytes", + "derive_more", + "metrics", + "modular-bitfield", + "reth-codecs 0.3.0", + "reth-db-models 2.1.0", + "reth-ethereum-primitives 2.1.0", + "reth-primitives-traits 0.3.0", + "reth-prune-types 2.1.0", + "reth-stages-types 2.1.0", + "reth-storage-errors 2.1.0", + "reth-trie-common 2.1.0", "roaring", "serde", ] [[package]] name = "reth-db-models" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ - "alloy-eips", + "alloy-eips 1.8.3", "alloy-primitives", "bytes", "modular-bitfield", - "reth-codecs", - "reth-primitives-traits", + "reth-codecs 1.11.2", + "reth-primitives-traits 1.11.2", "serde", ] +[[package]] +name = "reth-db-models" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-eips 2.0.4", + "alloy-primitives", + "bytes", + "modular-bitfield", + "reth-codecs 0.3.0", + "reth-primitives-traits 0.3.0", + "serde", +] + +[[package]] +name = "reth-ethereum-consensus" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives", + "reth-chainspec", + "reth-consensus", + "reth-consensus-common", + "reth-execution-types", + "reth-primitives-traits 0.3.0", + "tracing", +] + [[package]] name = "reth-ethereum-forks" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ "alloy-eip2124", "alloy-hardforks", "alloy-primitives", "auto_impl", "once_cell", + "rustc-hash", ] [[package]] name = "reth-ethereum-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "modular-bitfield", - "reth-codecs", - "reth-primitives-traits", - "reth-zstd-compressors", + "reth-codecs 1.11.2", + "reth-primitives-traits 1.11.2", + "reth-zstd-compressors 1.11.2", "serde", "serde_with", ] +[[package]] +name = "reth-ethereum-primitives" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives", + "alloy-rpc-types-eth 2.0.4", + "reth-codecs 0.3.0", + "reth-primitives-traits 0.3.0", + "serde", +] + [[package]] name = "reth-evm" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-evm", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", "alloy-primitives", "auto_impl", "derive_more", "futures-util", + "rayon", "reth-execution-errors", "reth-execution-types", - "reth-primitives-traits", + "reth-primitives-traits 0.3.0", "reth-storage-api", - "reth-storage-errors", - "reth-trie-common", + "reth-storage-errors 2.1.0", + "reth-trie-common 2.1.0", + "revm", +] + +[[package]] +name = "reth-evm-ethereum" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", + "alloy-primitives", + "alloy-rpc-types-engine", + "reth-chainspec", + "reth-ethereum-forks", + "reth-ethereum-primitives 2.1.0", + "reth-evm", + "reth-execution-types", + "reth-primitives-traits 0.3.0", + "reth-storage-errors 2.1.0", "revm", ] [[package]] name = "reth-execution-errors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ - "alloy-evm", + "alloy-evm 0.33.3", "alloy-primitives", "alloy-rlp", "nybbles", - "reth-storage-errors", - "thiserror 2.0.17", + "reth-storage-errors 2.1.0", + "thiserror 2.0.18", ] [[package]] name = "reth-execution-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-evm", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", "alloy-primitives", + "alloy-rlp", "derive_more", - "reth-ethereum-primitives", - "reth-primitives-traits", - "reth-trie-common", + "reth-ethereum-primitives 2.1.0", + "reth-primitives-traits 0.3.0", + "reth-trie-common 2.1.0", "revm", + "serde", + "serde_with", +] + +[[package]] +name = "reth-fs-util" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "reth-libmdbx" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "bitflags 2.10.0", + "byteorder", + "dashmap", + "derive_more", + "parking_lot", + "reth-mdbx-sys", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "reth-mdbx-sys" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "bindgen", + "cc", +] + +[[package]] +name = "reth-metrics" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "metrics", + "metrics-derive", ] [[package]] name = "reth-network-peers" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ "alloy-primitives", "alloy-rlp", + "secp256k1 0.30.0", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", "url", ] +[[package]] +name = "reth-nippy-jar" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "anyhow", + "bincode", + "derive_more", + "lz4_flex", + "memmap2", + "reth-fs-util", + "serde", + "thiserror 2.0.18", + "tracing", + "zstd 0.13.3", +] + [[package]] name = "reth-primitives-traits" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "0.3.0" +source = "git+https://github.com/paradigmxyz/reth-core?rev=6b12498#6b12498871bc1b1d42c6dcf28968c271660de8c0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-genesis", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-genesis 2.0.4", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", + "alloy-trie", + "byteorder", + "bytes", + "dashmap", + "derive_more", + "modular-bitfield", + "once_cell", + "quanta", + "reth-codecs 0.3.0", + "revm-bytecode 10.0.0", + "revm-primitives 23.0.0", + "revm-state 11.0.1", + "secp256k1 0.30.0", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "reth-primitives-traits" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-genesis 1.8.3", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth 1.8.3", "alloy-trie", "auto_impl", "byteorder", "bytes", + "dashmap", "derive_more", "modular-bitfield", "once_cell", - "op-alloy-consensus", - "reth-codecs", - "revm-bytecode", - "revm-primitives", - "revm-state", + "op-alloy-consensus 0.23.1", + "reth-codecs 1.11.2", + "revm-bytecode 8.0.0", + "revm-primitives 22.1.0", + "revm-state 9.0.0", "secp256k1 0.30.0", "serde", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "reth-prune-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ "alloy-primitives", "derive_more", "modular-bitfield", - "reth-codecs", + "reth-codecs 1.11.2", "serde", - "strum 0.27.2", - "thiserror 2.0.17", + "strum", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "reth-prune-types" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-primitives", + "derive_more", + "modular-bitfield", + "reth-codecs 0.3.0", + "serde", + "strum", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "reth-revm" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "reth-primitives-traits 0.3.0", + "reth-storage-api", + "reth-storage-errors 2.1.0", + "revm", ] [[package]] name = "reth-rpc-convert" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ - "alloy-consensus", - "alloy-evm", + "alloy-consensus 2.0.4", + "alloy-evm 0.33.3", "alloy-json-rpc", "alloy-network", "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-signer", + "alloy-rpc-types-eth 2.0.4", "auto_impl", "dyn-clone", "jsonrpsee-types", - "reth-ethereum-primitives", "reth-evm", - "reth-primitives-traits", - "thiserror 2.0.17", + "reth-primitives-traits 0.3.0", + "reth-rpc-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "reth-rpc-traits" +version = "0.3.0" +source = "git+https://github.com/paradigmxyz/reth-core?rev=6b12498#6b12498871bc1b1d42c6dcf28968c271660de8c0" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-network", + "alloy-primitives", + "alloy-rpc-types-eth 2.0.4", + "alloy-signer", + "reth-primitives-traits 0.3.0", + "thiserror 2.0.18", ] [[package]] name = "reth-stages-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ "alloy-primitives", "bytes", "modular-bitfield", - "reth-codecs", - "reth-trie-common", + "reth-codecs 1.11.2", + "reth-trie-common 1.11.2", + "serde", +] + +[[package]] +name = "reth-stages-types" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-primitives", + "bytes", + "modular-bitfield", + "reth-codecs 0.3.0", + "reth-trie-common 2.1.0", "serde", ] [[package]] name = "reth-static-file-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ "alloy-primitives", "derive_more", + "fixed-map", + "reth-stages-types 1.11.2", "serde", - "strum 0.27.2", + "strum", +] + +[[package]] +name = "reth-static-file-types" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-primitives", + "derive_more", + "fixed-map", + "reth-stages-types 2.1.0", + "serde", + "strum", + "tracing", ] [[package]] name = "reth-storage-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rpc-types-engine", "auto_impl", "reth-chainspec", - "reth-db-models", - "reth-ethereum-primitives", + "reth-db-models 2.1.0", + "reth-ethereum-primitives 2.1.0", "reth-execution-types", - "reth-primitives-traits", - "reth-prune-types", - "reth-stages-types", - "reth-storage-errors", - "reth-trie-common", - "revm-database", + "reth-primitives-traits 0.3.0", + "reth-prune-types 2.1.0", + "reth-stages-types 2.1.0", + "reth-storage-errors 2.1.0", + "reth-trie-common 2.1.0", + "revm-database 13.0.1", + "serde_json", ] [[package]] name = "reth-storage-errors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "alloy-eips 1.8.3", + "alloy-primitives", + "alloy-rlp", + "derive_more", + "reth-primitives-traits 1.11.2", + "reth-prune-types 1.11.2", + "reth-static-file-types 1.11.2", + "revm-database-interface 9.0.0", + "revm-state 9.0.0", + "thiserror 2.0.18", +] + +[[package]] +name = "reth-storage-errors" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "alloy-primitives", "alloy-rlp", "derive_more", - "reth-primitives-traits", - "reth-prune-types", - "reth-static-file-types", - "revm-database-interface", - "thiserror 2.0.17", + "reth-codecs 0.3.0", + "reth-primitives-traits 0.3.0", + "reth-prune-types 2.1.0", + "reth-static-file-types 2.1.0", + "revm-database-interface 11.0.1", + "revm-state 11.0.1", + "thiserror 2.0.18", +] + +[[package]] +name = "reth-tracing" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" +dependencies = [ + "clap", + "eyre", + "rolling-file", + "tracing", + "tracing-appender", + "tracing-journald", + "tracing-logfmt", + "tracing-samply", + "tracing-subscriber 0.3.22", ] [[package]] name = "reth-trie-common" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ - "alloy-consensus", + "alloy-consensus 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 1.8.3", "alloy-trie", "arrayvec", "bytes", "derive_more", "itertools 0.14.0", "nybbles", - "reth-codecs", - "reth-primitives-traits", - "revm-database", + "reth-codecs 1.11.2", + "reth-primitives-traits 1.11.2", + "revm-database 10.0.0", "serde", ] +[[package]] +name = "reth-trie-common" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=7839f3d#7839f3d876b32842b059ca8171242b807ba1fc80" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "alloy-trie", + "arrayvec", + "bytes", + "derive_more", + "itertools 0.14.0", + "nybbles", + "reth-codecs 0.3.0", + "reth-primitives-traits 0.3.0", + "revm-database 13.0.1", + "serde", + "serde_with", +] + [[package]] name = "reth-zstd-compressors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=64909d3#64909d33e6b7ab60774e37f5508fb5ad17f41897" +version = "0.3.0" +source = "git+https://github.com/paradigmxyz/reth-core?rev=6b12498#6b12498871bc1b1d42c6dcf28968c271660de8c0" +dependencies = [ + "zstd 0.13.3", +] + +[[package]] +name = "reth-zstd-compressors" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c12fafa33d2f420a9d39249a3e0357b1928d09429f30758b85280409092873b2" +dependencies = [ + "zstd 0.13.3", +] + +[[package]] +name = "reth-zstd-compressors" +version = "1.11.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.11.2#793a3d5fb3e3413e9ecc9b024a5e26672e61e7c3" dependencies = [ "zstd 0.13.3", ] [[package]] name = "revm" -version = "33.1.0" +version = "38.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c85ed0028f043f87b3c88d4a4cb6f0a76440085523b6a8afe5ff003cf418054" +checksum = "91202d39dbe8e8d10e9e8f2b76c30da68ecd1d25be69ba6d853ad0d03a3a398a" dependencies = [ - "revm-bytecode", + "revm-bytecode 10.0.0", "revm-context", "revm-context-interface", - "revm-database", - "revm-database-interface", + "revm-database 13.0.1", + "revm-database-interface 11.0.1", "revm-handler", "revm-inspector", "revm-interpreter", "revm-precompile", - "revm-primitives", - "revm-state", + "revm-primitives 23.0.0", + "revm-state 11.0.1", ] [[package]] name = "revm-bytecode" -version = "7.1.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c6b5e6e8dd1e28a4a60e5f46615d4ef0809111c9e63208e55b5c7058200fb0" +checksum = "74d1e5c1eaa44d39d537f668bc5c3409dc01e5c8be954da6c83370bbdf006457" dependencies = [ "bitvec", "phf 0.13.1", - "revm-primitives", + "revm-primitives 22.1.0", + "serde", +] + +[[package]] +name = "revm-bytecode" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbb3a3d735efa94c91f2ef6bf20a35f99a77bc78f3e25bd758336901bdf9661" +dependencies = [ + "bitvec", + "phf 0.13.1", + "revm-primitives 23.0.0", "serde", ] [[package]] name = "revm-context" -version = "12.1.0" +version = "16.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f038f0c9c723393ac897a5df9140b21cfa98f5753a2cb7d0f28fa430c4118abf" +checksum = "c5f68d928d8b228e0faeb1c6ed75c4fde7d124f1ddf9119b67e7a0ad4041237d" dependencies = [ "bitvec", "cfg-if", "derive-where", - "revm-bytecode", + "revm-bytecode 10.0.0", "revm-context-interface", - "revm-database-interface", - "revm-primitives", - "revm-state", + "revm-database-interface 11.0.1", + "revm-primitives 23.0.0", + "revm-state 11.0.1", "serde", ] [[package]] name = "revm-context-interface" -version = "13.1.0" +version = "17.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431c9a14e4ef1be41ae503708fd02d974f80ef1f2b6b23b5e402e8d854d1b225" +checksum = "1f3758e6167c4ba7a59a689c519a047edaefcd4c37d74f279b93ed87bc8aece4" dependencies = [ "alloy-eip2930", "alloy-eip7702", "auto_impl", "either", - "revm-database-interface", - "revm-primitives", - "revm-state", + "revm-database-interface 11.0.1", + "revm-primitives 23.0.0", + "revm-state 11.0.1", + "serde", +] + +[[package]] +name = "revm-database" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529528d0b05fe646be86223032c3e77aa8b05caa2a35447d538c55965956a511" +dependencies = [ + "alloy-eips 1.8.3", + "revm-bytecode 8.0.0", + "revm-database-interface 9.0.0", + "revm-primitives 22.1.0", + "revm-state 9.0.0", "serde", ] [[package]] name = "revm-database" -version = "9.0.6" +version = "13.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980d8d6bba78c5dd35b83abbb6585b0b902eb25ea4448ed7bfba6283b0337191" +checksum = "c281a1f11d3bcb8c0bba1199ed6bcb001d1aeb3d4fb366819e14f88723989a4e" dependencies = [ - "alloy-eips", - "revm-bytecode", - "revm-database-interface", - "revm-primitives", - "revm-state", + "alloy-eips 1.8.3", + "revm-bytecode 10.0.0", + "revm-database-interface 11.0.1", + "revm-primitives 23.0.0", + "revm-state 11.0.1", "serde", ] [[package]] name = "revm-database-interface" -version = "8.0.5" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cce03e3780287b07abe58faf4a7f5d8be7e81321f93ccf3343c8f7755602bae" +checksum = "b7bf93ac5b91347c057610c0d96e923db8c62807e03f036762d03e981feddc1d" dependencies = [ "auto_impl", "either", - "revm-primitives", - "revm-state", + "revm-primitives 22.1.0", + "revm-state 9.0.0", "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "revm-database-interface" +version = "11.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89efb9832a4e3742bb4ded5f7fe5bf905e8860e69427d4dfec153484fc6d304" +dependencies = [ + "auto_impl", + "either", + "revm-primitives 23.0.0", + "revm-state 11.0.1", + "serde", + "thiserror 2.0.18", ] [[package]] name = "revm-handler" -version = "14.1.0" +version = "18.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44f8f6dbeec3fecf9fe55f78ef0a758bdd92ea46cd4f1ca6e2a946b32c367f3" +checksum = "783e903d6922b7f5f9a940d1bb229530502d2924b1aed9d5ca5a94ebf065d460" dependencies = [ "auto_impl", "derive-where", - "revm-bytecode", + "revm-bytecode 10.0.0", "revm-context", "revm-context-interface", - "revm-database-interface", + "revm-database-interface 11.0.1", "revm-interpreter", "revm-precompile", - "revm-primitives", - "revm-state", + "revm-primitives 23.0.0", + "revm-state 11.0.1", "serde", ] [[package]] name = "revm-inspector" -version = "14.1.0" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5617e49216ce1ca6c8826bcead0386bc84f49359ef67cde6d189961735659f93" +checksum = "8216ad58422090d0daa9eb430e0a081f7ad07e7fd30681dee71f8420c99624e0" dependencies = [ "auto_impl", "either", "revm-context", - "revm-database-interface", + "revm-database-interface 11.0.1", "revm-handler", "revm-interpreter", - "revm-primitives", - "revm-state", + "revm-primitives 23.0.0", + "revm-state 11.0.1", "serde", "serde_json", ] [[package]] name = "revm-inspectors" -version = "0.33.2" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01def7351cd9af844150b8e88980bcd11304f33ce23c3d7c25f2a8dab87c1345" +checksum = "731b682530a732ef9c189ef831589128e2ce34d4a306c956322ae2dffe009715" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-trace", "alloy-sol-types", "anstyle", @@ -9166,27 +10558,27 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "revm-interpreter" -version = "31.1.0" +version = "35.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ec36405f7477b9dccdc6caa3be19adf5662a7a0dffa6270cdb13a090c077e5" +checksum = "1ece9f41b69658c15d748288a4dbdfc06a63f3ce93d983af440de3f1631dce6a" dependencies = [ - "revm-bytecode", + "revm-bytecode 10.0.0", "revm-context-interface", - "revm-primitives", - "revm-state", + "revm-primitives 23.0.0", + "revm-state 11.0.1", "serde", ] [[package]] name = "revm-precompile" -version = "31.0.0" +version = "34.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a62958af953cc4043e93b5be9b8497df84cc3bd612b865c49a7a7dfa26a84e2" +checksum = "a346a8cc6c8c39bd65306641c692191299c0a7b63d38810e39e8fe9b92378660" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -9200,18 +10592,30 @@ dependencies = [ "cfg-if", "k256", "p256", - "revm-primitives", + "revm-context-interface", + "revm-primitives 23.0.0", "ripemd", - "rug", "secp256k1 0.31.1", - "sha2", + "sha2 0.10.9", +] + +[[package]] +name = "revm-primitives" +version = "22.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfb5ce6cf18b118932bcdb7da05cd9c250f2cb9f64131396b55f3fe3537c35" +dependencies = [ + "alloy-primitives", + "num_enum", + "once_cell", + "serde", ] [[package]] name = "revm-primitives" -version = "21.0.2" +version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e161db429d465c09ba9cbff0df49e31049fe6b549e28eb0b7bd642fcbd4412" +checksum = "0c99bda77d9661521ba0b4bc04558c6692074f01e65dd420fa3b893033d9b8a2" dependencies = [ "alloy-primitives", "num_enum", @@ -9221,13 +10625,27 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.1.1" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8be953b7e374dbdea0773cf360debed8df394ea8d82a8b240a6b5da37592fc" +checksum = "311720d4f0f239b041375e7ddafdbd20032a33b7bae718562ea188e188ed9fd3" dependencies = [ + "alloy-eip7928", "bitflags 2.10.0", - "revm-bytecode", - "revm-primitives", + "revm-bytecode 8.0.0", + "revm-primitives 22.1.0", + "serde", +] + +[[package]] +name = "revm-state" +version = "11.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c32490ed687dba31c3c882beb8c20408bdd30ef96690d8f145b0ee9a87040bfe" +dependencies = [ + "alloy-eip7928", + "bitflags 2.10.0", + "revm-bytecode 10.0.0", + "revm-primitives 23.0.0", "serde", ] @@ -9240,7 +10658,7 @@ dependencies = [ "nix 0.30.1", "regex", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9272,7 +10690,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -9297,14 +10715,23 @@ dependencies = [ [[package]] name = "roaring" -version = "0.10.12" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e8d2cfa184d94d0726d650a9f4a1be7f9b76ac9fdb954219878dc00c1c1e7b" +checksum = "1dedc5658c6ecb3bdb5ef5f3295bb9253f42dcf3fd1402c03f6b1f7659c3c4a9" dependencies = [ "bytemuck", "byteorder", ] +[[package]] +name = "rolling-file" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8395b4f860856b740f20a296ea2cd4d823e81a2658cf05ef61be22916026a906" +dependencies = [ + "chrono", +] + [[package]] name = "rpassword" version = "7.4.0" @@ -9326,18 +10753,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rug" -version = "1.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad2e973fe3c3214251a840a621812a4f40468da814b1a3d6947d433c2af11f" -dependencies = [ - "az", - "gmp-mpfr-sys", - "libc", - "libm", -] - [[package]] name = "ruint" version = "1.17.0" @@ -9383,6 +10798,20 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "rusqlite" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22715a5d6deef63c637207afbe68d0c72c3f8d0022d7cf9714c442d6157606b" +dependencies = [ + "bitflags 2.10.0", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -9428,7 +10857,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.27", + "semver 1.0.28", ] [[package]] @@ -9445,28 +10874,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] @@ -9494,7 +10910,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -9507,6 +10923,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni 0.22.4", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.8" @@ -9516,7 +10959,7 @@ dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -9641,7 +11084,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9665,7 +11108,7 @@ dependencies = [ "hmac", "pbkdf2 0.11.0", "salsa20", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -9726,30 +11169,15 @@ dependencies = [ [[package]] name = "secret-vault-value" -version = "0.3.10" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662c7f8e99d46c9d3a87561d771a970c29efaccbab4bbdc6ab65d099d2358077" +checksum = "471de2a3d4b361569b862e04491696237381641ae5808f8e69ea08de991cd306" dependencies = [ - "prost 0.14.1", - "prost-types 0.14.1", "serde", "serde_json", "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.5.1" @@ -9793,9 +11221,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", "serde_core", @@ -9849,7 +11277,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9860,7 +11288,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9874,43 +11302,45 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.14.0", "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] -name = "serde_path_to_error" -version = "0.1.20" +name = "serde_json_canonicalizer" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +checksum = "fe52319a927259afbfa5180c5157cd8167edfd3e8c254f9558c7fef44c5649f2" dependencies = [ - "itoa", + "ryu-js", "serde", - "serde_core", + "serde_json", ] [[package]] -name = "serde_spanned" -version = "0.6.9" +name = "serde_path_to_error" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ + "itoa", "serde", + "serde_core", ] [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -9937,7 +11367,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.1.0", "serde_core", @@ -9955,7 +11385,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9975,10 +11405,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.9" @@ -9986,10 +11429,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", +] + [[package]] name = "sha3" version = "0.10.8" @@ -10002,9 +11456,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "9f3f15d4e239ebe08413eed880e0f9b5af4b40ee0472543320efa91d488e96a7" dependencies = [ "cc", "cfg-if", @@ -10086,6 +11540,22 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version 0.4.1", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similar" version = "2.7.0" @@ -10114,7 +11584,7 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] @@ -10213,16 +11683,6 @@ dependencies = [ "anstream", ] -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "socket2" version = "0.6.1" @@ -10236,23 +11696,23 @@ dependencies = [ [[package]] name = "solar-ast" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "alloy-primitives", "bumpalo", "either", "num-rational", - "semver 1.0.27", + "semver 1.0.28", "solar-data-structures", "solar-interface", "solar-macros", - "strum 0.27.2", + "strum", ] [[package]] name = "solar-compiler" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "alloy-primitives", "solar-ast", @@ -10267,20 +11727,20 @@ dependencies = [ [[package]] name = "solar-config" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "colorchoice", - "strum 0.27.2", + "strum", ] [[package]] name = "solar-data-structures" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "bumpalo", "index_vec", - "indexmap 2.12.1", + "indexmap 2.14.0", "parking_lot", "rayon", "rustc-hash", @@ -10290,7 +11750,7 @@ dependencies = [ [[package]] name = "solar-interface" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "annotate-snippets 0.12.5", "anstream", @@ -10298,19 +11758,19 @@ dependencies = [ "derive_more", "dunce", "inturn", - "itertools 0.14.0", + "itertools 0.12.1", "itoa", "normalize-path", "once_map", "rayon", "scoped-tls", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "solar-config", "solar-data-structures", "solar-macros", - "thiserror 2.0.17", + "thiserror 1.0.69", "tracing", "unicode-width 0.2.0", ] @@ -10318,22 +11778,22 @@ dependencies = [ [[package]] name = "solar-macros" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "solar-parse" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "alloy-primitives", "bitflags 2.10.0", "bumpalo", - "itertools 0.14.0", + "itertools 0.12.1", "memchr", "num-bigint", "num-rational", @@ -10349,7 +11809,7 @@ dependencies = [ [[package]] name = "solar-sema" version = "0.1.8" -source = "git+https://github.com/paradigmxyz/solar.git?rev=1f28069#1f2806951b5c6a166edd975ebd797a3ebd5ff9f1" +source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -10367,7 +11827,7 @@ dependencies = [ "solar-interface", "solar-macros", "solar-parse", - "strum 0.27.2", + "strum", "thread_local", "tracing", ] @@ -10393,9 +11853,9 @@ dependencies = [ [[package]] name = "soldeer-core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295509f269318c6e3f11ea3bd09b29c974d00403bdf5291577c0bc6adaa9c2fd" +checksum = "465e595b179b442eec8f6cd8afde9e3d429c7de9bb779a228496921e3f195a81" dependencies = [ "bon", "chrono", @@ -10408,13 +11868,13 @@ dependencies = [ "path-slash", "rayon", "regex", - "reqwest", + "reqwest 0.12.26", "sanitize-filename", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", - "sha2", - "thiserror 2.0.17", + "sha2 0.10.9", + "thiserror 2.0.18", "tokio", "toml_edit 0.23.10+spec-1.0.0", "uuid 1.19.0", @@ -10486,17 +11946,28 @@ dependencies = [ "parking_lot", "phf_shared 0.11.3", "precomputed-hash", - "serde", +] + +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.13.1", + "precomputed-hash", ] [[package]] name = "string_cache_codegen" -version = "0.5.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", ] @@ -10517,34 +11988,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros 0.26.4", -] - -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros 0.27.2", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" +name = "strum" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.111", + "strum_macros", ] [[package]] @@ -10556,7 +12005,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10565,6 +12014,12 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "sval" version = "2.16.0" @@ -10651,13 +12106,13 @@ checksum = "909e8ff825120cd2b34ceb236ab72e2a7f74b1d3a86c247936c8ff7a80c5d408" dependencies = [ "const-hex", "dirs", - "reqwest", - "semver 1.0.27", + "reqwest 0.12.26", + "semver 1.0.28", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "tempfile", - "thiserror 2.0.17", + "thiserror 1.0.69", "url", "zip", ] @@ -10669,11 +12124,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1ebe77b200f965e8dbec3ef1d8337e974179ca1ecaa9fc28f67288d6b438159" dependencies = [ "const-hex", - "semver 1.0.27", + "semver 1.0.28", "serde_json", "svm-rs", ] +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + [[package]] name = "syn" version = "1.0.109" @@ -10687,9 +12148,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -10698,14 +12159,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b1d2e2059056b66fec4a6bb2b79511d5e8d76196ef49c38996f4b48db7662f" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10725,7 +12186,21 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", +] + +[[package]] +name = "sysinfo" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.62.2", ] [[package]] @@ -10773,50 +12248,211 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.2", - "windows-sys 0.61.2", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "tempo-alloy" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-contract", + "alloy-eips 2.0.4", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "alloy-signer-local", + "alloy-sol-types", + "alloy-transport", + "async-trait", + "dashmap", + "derive_more", + "futures", + "serde", + "tempo-chainspec", + "tempo-contracts", + "tempo-primitives", + "tracing", +] + +[[package]] +name = "tempo-chainspec" +version = "1.5.3" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy-eips 2.0.4", + "alloy-evm 0.33.3", + "alloy-genesis 2.0.4", + "alloy-hardforks", + "alloy-primitives", + "once_cell", + "paste", + "reth-chainspec", + "reth-network-peers", + "serde", + "serde_json", + "tempo-primitives", +] + +[[package]] +name = "tempo-consensus" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-evm 0.33.3", + "alloy-primitives", + "reth-chainspec", + "reth-consensus", + "reth-consensus-common", + "reth-ethereum-consensus", + "reth-primitives-traits 0.3.0", + "tempo-chainspec", + "tempo-primitives", + "thiserror 2.0.18", +] + +[[package]] +name = "tempo-contracts" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy-contract", + "alloy-primitives", + "alloy-sol-types", + "serde", +] + +[[package]] +name = "tempo-evm" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-evm 0.33.3", + "alloy-primitives", + "alloy-rlp", + "commonware-codec", + "commonware-cryptography", + "derive_more", + "reth-chainspec", + "reth-consensus", + "reth-evm", + "reth-evm-ethereum", + "reth-primitives-traits 0.3.0", + "reth-revm", + "tempo-chainspec", + "tempo-consensus", + "tempo-contracts", + "tempo-primitives", + "tempo-revm", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "tempo-precompiles" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy", + "alloy-evm 0.33.3", + "commonware-codec", + "commonware-cryptography", + "derive_more", + "revm", + "scoped-tls", + "tempo-chainspec", + "tempo-contracts", + "tempo-precompiles-macros", + "tempo-primitives", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "tempo-precompiles-macros" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "tempo-primitives" -version = "0.7.5" -source = "git+https://github.com/tempoxyz/tempo?tag=v0.7.5#d1c2d656fb657e3c6f46a8bc3889bdb595d45576" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-network", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "aws-lc-rs", "base64 0.22.1", "derive_more", + "ed25519-consensus", "modular-bitfield", + "once_cell", "p256", - "reth-codecs", - "reth-db-api", - "reth-ethereum-primitives", - "reth-primitives-traits", + "reth-codecs 0.3.0", + "reth-db-api 2.1.0", + "reth-ethereum-primitives 2.1.0", + "reth-primitives-traits 0.3.0", "reth-rpc-convert", + "revm", + "serde", + "serde_json", + "sha2 0.10.9", + "tempo-contracts", +] + +[[package]] +name = "tempo-revm" +version = "1.6.0" +source = "git+https://github.com/tempoxyz/tempo?rev=1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69#1e5a82dff207e2cbd6cecdcfb8ff3cd2e39baa69" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-evm 0.33.3", + "alloy-primitives", + "alloy-sol-types", + "auto_impl", + "derive_more", + "reth-evm", + "reth-storage-api", + "revm", "serde", - "sha2", + "tempo-chainspec", + "tempo-contracts", + "tempo-precompiles", + "tempo-primitives", + "thiserror 2.0.18", + "tracing", ] [[package]] name = "tendril" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" dependencies = [ - "futf", - "mac", + "new_debug_unreachable", "utf-8", ] @@ -10826,7 +12462,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -10835,7 +12471,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 1.1.2", + "rustix", "windows-sys 0.60.2", ] @@ -10848,7 +12484,7 @@ dependencies = [ "fnv", "nom", "phf 0.11.3", - "phf_codegen", + "phf_codegen 0.11.3", ] [[package]] @@ -10885,11 +12521,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -10900,18 +12536,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10954,9 +12590,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -10965,36 +12601,27 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinystr" version = "0.8.2" @@ -11023,9 +12650,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -11033,7 +12660,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2", "tokio-macros", "windows-sys 0.61.2", ] @@ -11046,17 +12673,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", + "syn 2.0.117", ] [[package]] @@ -11089,12 +12706,8 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls", - "rustls-pki-types", "tokio", - "tokio-rustls", "tungstenite 0.26.2", - "webpki-roots 0.26.11", ] [[package]] @@ -11105,8 +12718,12 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", + "rustls", + "rustls-pki-types", "tokio", + "tokio-rustls", "tungstenite 0.28.0", + "webpki-roots 0.26.11", ] [[package]] @@ -11122,49 +12739,34 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_edit 0.22.27", -] - [[package]] name = "toml" version = "0.9.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.14.0", "serde_core", - "serde_spanned 1.0.4", + "serde_spanned", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.14", ] [[package]] -name = "toml_datetime" -version = "0.6.11" +name = "toml" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ - "serde", + "indexmap 2.14.0", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.3", ] [[package]] @@ -11177,17 +12779,12 @@ dependencies = [ ] [[package]] -name = "toml_edit" -version = "0.22.27" +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ - "indexmap 2.12.1", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_write", - "winnow", + "serde_core", ] [[package]] @@ -11196,13 +12793,13 @@ version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.14.0", "serde_core", - "serde_spanned 1.0.4", + "serde_spanned", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.14", ] [[package]] @@ -11211,39 +12808,47 @@ version = "0.24.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c740b185920170a6d9191122cafef7010bd6270a3824594bff6784c04d7f09e" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.14.0", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.14", ] [[package]] -name = "toml_parser" -version = "1.0.6+spec-1.1.0" +name = "toml_edit" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "winnow", + "indexmap 2.14.0", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", ] [[package]] -name = "toml_write" -version = "0.1.2" +name = "toml_parser" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", +] [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" -version = "0.13.1" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", @@ -11257,10 +12862,9 @@ dependencies = [ "hyper-timeout", "hyper-util", "percent-encoding", - "pin-project 1.1.10", - "prost 0.13.5", - "rustls-native-certs", - "socket2 0.5.10", + "pin-project", + "socket2", + "sync_wrapper", "tokio", "tokio-rustls", "tokio-stream", @@ -11268,6 +12872,18 @@ dependencies = [ "tower-layer", "tower-service", "tracing", + "webpki-roots 1.0.4", +] + +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost 0.14.1", + "tonic", ] [[package]] @@ -11284,7 +12900,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "indexmap 2.12.1", + "indexmap 2.14.0", "pin-project-lite", "slab", "sync_wrapper", @@ -11336,18 +12952,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" -[[package]] -name = "tower-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1093c19826d33807c72511e68f73b4a0469a3f22c2bd5f7d5212178b4b89674" -dependencies = [ - "futures-core", - "futures-util", - "pin-project 0.4.30", - "tower-service", -] - [[package]] name = "tracing" version = "0.1.44" @@ -11361,44 +12965,106 @@ dependencies = [ ] [[package]] -name = "tracing-attributes" -version = "0.1.31" +name = "tracing-appender" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" +dependencies = [ + "crossbeam-channel", + "symlink", + "thiserror 2.0.18", + "time", + "tracing-subscriber 0.3.22", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber 0.3.22", +] + +[[package]] +name = "tracing-journald" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3a81ed245bfb62592b1e2bc153e77656d94ee6a0497683a65a12ccaf2438d0" +dependencies = [ + "libc", + "tracing-core", + "tracing-subscriber 0.3.22", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", + "log", + "once_cell", + "tracing-core", ] [[package]] -name = "tracing-core" -version = "0.1.36" +name = "tracing-logfmt" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +checksum = "6b1f47d22deb79c3f59fcf2a1f00f60cbdc05462bf17d1cd356c1fefa3f444bd" dependencies = [ - "once_cell", - "valuable", + "time", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.22", ] [[package]] -name = "tracing-error" -version = "0.2.1" +name = "tracing-samply" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +checksum = "c175f7ecc002b6ef04776a39f440503e4e788790ddbdbfac8259b7a069526334" dependencies = [ - "tracing", + "cfg-if", + "itoa", + "libc", + "mach2", + "memmap2", + "smallvec", + "tracing-core", "tracing-subscriber 0.3.22", ] [[package]] -name = "tracing-log" +name = "tracing-serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ - "log", - "once_cell", + "serde", "tracing-core", ] @@ -11421,12 +13087,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -11464,15 +13133,15 @@ dependencies = [ [[package]] name = "trezor-client" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10636211ab89c96ed2824adc5ec0d081e1080aeacc24c37abb318dcb31dcc779" +checksum = "87873db279766278a7e56b01139943e00a45afc079fc8fa6651e949f2234c3f6" dependencies = [ "byteorder", "hex", "protobuf", "rusb", - "thiserror 1.0.69", + "thiserror 2.0.18", "tracing", ] @@ -11494,10 +13163,8 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "rustls", - "rustls-pki-types", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] @@ -11513,16 +13180,18 @@ dependencies = [ "httparse", "log", "rand 0.9.2", + "rustls", + "rustls-pki-types", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] [[package]] name = "turnkey_api_key_stamper" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b72664037582371dfa96bfaa2e272446ea2551e269455e9fe3166445c76736" +checksum = "34f72e05a07cb04163efff0c766521ebacbb268a851db83d419b7c56df90d046" dependencies = [ "base64 0.22.1", "hex", @@ -11531,23 +13200,23 @@ dependencies = [ "rand_core 0.6.4", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] name = "turnkey_client" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbf8cea094b6536ecc5cfad42cd45d2f9abf523cc7dacf7de23f132412d0ec3" +checksum = "f216ea270ec4a37daa491679b716962cda7819cac982b49088979b2edf6067df" dependencies = [ "mime", "prost 0.12.6", "prost-types 0.12.6", - "reqwest", + "reqwest 0.12.26", "serde", "serde_json", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "turnkey_api_key_stamper", ] @@ -11560,9 +13229,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ucd-trie" @@ -11670,13 +13339,13 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" -version = "1.1.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "unicode-segmentation", - "unicode-width 0.1.14", + "unicode-width 0.2.0", ] [[package]] @@ -11703,6 +13372,22 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common 0.1.7", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -11829,14 +13514,41 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "8.3.2" +version = "10.0.0-beta.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" +checksum = "2d7cb4a83971db3f6ae36f0aa41eaf5985d2e2b469581fa755c132f9c2a1ec89" dependencies = [ "anyhow", - "cfg-if", + "bon", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "10.0.0-beta.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bba14c9676943b2899cea2ed7ea194b89b3d13564a3c93a61882a978b123a41c" +dependencies = [ + "anyhow", + "bon", "rustversion", "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "10.0.0-beta.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb684e6d170ef15a9b3c20561779a50ba8c806f8acdaff47c0a2c5c4c6cadd43" +dependencies = [ + "anyhow", + "bon", + "getset", + "rustversion", ] [[package]] @@ -11900,14 +13612,23 @@ version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.46.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -11918,22 +13639,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11941,26 +13659,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -11974,6 +13714,31 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver 1.0.28", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -12000,7 +13765,7 @@ dependencies = [ "miette", "normalize-path", "notify", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "watchexec-events", @@ -12026,7 +13791,7 @@ checksum = "377729679262964c27e6a28f360a84b7aedb172b59841301c1c77922305dfd83" dependencies = [ "miette", "nix 0.30.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -12045,9 +13810,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", @@ -12065,13 +13830,13 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.1.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414" +checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" dependencies = [ - "phf 0.11.3", - "phf_codegen", - "string_cache", + "phf 0.13.1", + "phf_codegen 0.13.1", + "string_cache 0.9.0", "string_cache_codegen", ] @@ -12082,7 +13847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" dependencies = [ "core-foundation 0.10.1", - "jni", + "jni 0.21.1", "log", "ndk-context", "objc2", @@ -12091,6 +13856,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.26.11" @@ -12116,7 +13890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ "env_home", - "rustix 1.1.2", + "rustix", "winsafe", ] @@ -12148,7 +13922,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -12163,11 +13937,23 @@ version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-collections", + "windows-collections 0.2.0", "windows-core 0.61.2", - "windows-future", + "windows-future 0.2.1", "windows-link 0.1.3", - "windows-numerics", + "windows-numerics 0.2.0", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections 0.3.2", + "windows-core 0.62.2", + "windows-future 0.3.2", + "windows-numerics 0.3.1", ] [[package]] @@ -12179,6 +13965,15 @@ dependencies = [ "windows-core 0.61.2", ] +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + [[package]] name = "windows-core" version = "0.61.2" @@ -12213,7 +14008,18 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core 0.61.2", "windows-link 0.1.3", - "windows-threading", + "windows-threading 0.1.0", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", + "windows-threading 0.2.1", ] [[package]] @@ -12224,7 +14030,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -12235,7 +14041,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -12260,6 +14066,16 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", +] + [[package]] name = "windows-registry" version = "0.6.1" @@ -12409,6 +14225,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -12556,6 +14381,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + [[package]] name = "winsafe" version = "0.0.19" @@ -12568,6 +14402,94 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.10.0", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver 1.0.28", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "write16" version = "1.0.0" @@ -12593,7 +14515,7 @@ dependencies = [ "pharos", "rustc_version 0.4.1", "send_wrapper", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -12608,6 +14530,18 @@ dependencies = [ "tap", ] +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "xmlparser" version = "0.13.6" @@ -12654,7 +14588,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -12675,7 +14609,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -12695,7 +14629,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -12716,7 +14650,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -12750,7 +14684,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -12762,7 +14696,7 @@ dependencies = [ "arbitrary", "crc32fast", "flate2", - "indexmap 2.12.1", + "indexmap 2.14.0", "memchr", "zopfli", ] @@ -12774,7 +14708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fa5b9958fd0b5b685af54f2c3fa21fca05fe295ebaf3e77b6d24d96c4174037" dependencies = [ "log", - "thiserror 2.0.17", + "thiserror 2.0.18", "zip", ] @@ -12784,6 +14718,12 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235" +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zopfli" version = "0.8.3" diff --git a/Cargo.toml b/Cargo.toml index 5f2bc033bf885..cecab8087061e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -591,6 +591,7 @@ rexpect = { git = "https://github.com/rust-cli/rexpect", rev = "2ed0b1898d7edaf6 ## reth-core reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth-core", rev = "6b12498" } +reth-rpc-traits = { git = "https://github.com/paradigmxyz/reth-core", rev = "6b12498" } reth-codecs = { git = "https://github.com/paradigmxyz/reth-core", rev = "6b12498" } reth-codecs-derive = { git = "https://github.com/paradigmxyz/reth-core", rev = "6b12498" } reth-zstd-compressors = { git = "https://github.com/paradigmxyz/reth-core", rev = "6b12498" } diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index c21be7c4ba155..7eb5d7be6b1e3 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1,7 +1,7 @@ //! Cheatcode EVM inspector. use crate::{ - CheatsConfig, CheatsCtxt, DynCheatcode, Error, Result, + Cheatcode, CheatsConfig, CheatsCtxt, Error, Result, Vm::{self, AccountAccess}, evm::{ DealRecord, GasRecord, RecordAccess, journaled_account, @@ -20,28 +20,28 @@ use crate::{ }, utils::IgnoredTraces, }; -use alloy_consensus::BlobTransactionSidecar; -use alloy_evm::eth::EthEvmContext; -use alloy_network::TransactionBuilder4844; +use alloy_consensus::BlobTransactionSidecarVariant; +use alloy_network::{Ethereum, Network, TransactionBuilder}; use alloy_primitives::{ Address, B256, Bytes, Log, TxKind, U256, hex, map::{AddressHashMap, HashMap, HashSet}, }; -use alloy_rpc_types::{ - AccessList, - request::{TransactionInput, TransactionRequest}, -}; +use alloy_rpc_types::AccessList; use alloy_sol_types::{SolCall, SolInterface, SolValue}; use foundry_common::{ - SELECTOR_LEN, TransactionMaybeSigned, + FoundryTransactionBuilder, SELECTOR_LEN, TransactionMaybeSigned, mapping_slots::{MappingSlots, step as mapping_step}, }; use foundry_evm_core::{ - Breakpoints, ContextExt, InspectorExt, + Breakpoints, EvmEnv, FoundryTransaction, InspectorExt, abi::Vm::stopExpectSafeMemoryCall, backend::{DatabaseError, DatabaseExt, RevertDiagnostic}, constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, MAGIC_ASSUME}, - evm::{FoundryEvm, new_evm_with_existing_context}, + env::FoundryContextExt, + evm::{ + BlockEnvFor, EthEvmNetwork, FoundryContextFor, FoundryEvmFactory, FoundryEvmNetwork, + NestedEvmClosure, SpecFor, TransactionRequestFor, TxEnvFor, with_cloned_context, + }, }; use foundry_evm_traces::{ CallTraceArena, TracingInspector, TracingInspectorConfig, identifier::SignaturesIdentifier, @@ -51,22 +51,23 @@ use itertools::Itertools; use proptest::test_runner::{RngAlgorithm, TestRng, TestRunner}; use rand::Rng; use revm::{ - Inspector, Journal, + Inspector, bytecode::opcode as op, - context::{BlockEnv, JournalTr, LocalContext, TransactionType, result::EVMError}, + context::{Cfg, ContextTr, Host, JournalTr, Transaction, TransactionType, result::EVMError}, context_interface::{CreateScheme, transaction::SignedAuthorization}, handler::FrameResult, + inspector::JournalExt, interpreter::{ - CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, FrameInput, Gas, Host, + CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, FrameInput, Gas, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, interpreter_types::{Jumps, LoopControl, MemoryTr}, }, - primitives::hardfork::SpecId, }; use serde_json::Value; use std::{ cmp::max, collections::{BTreeMap, VecDeque}, + fmt::Debug, fs::File, io::BufReader, ops::Range, @@ -79,90 +80,86 @@ mod utils; pub mod analysis; pub use analysis::CheatcodeAnalysis; -pub type Ecx<'a, 'b, 'c> = &'a mut EthEvmContext<&'b mut (dyn DatabaseExt + 'c)>; - -/// Helper trait for obtaining complete [revm::Inspector] instance from mutable reference to -/// [Cheatcodes]. -/// -/// This is needed for cases when inspector itself needs mutable access to [Cheatcodes] state and -/// allows us to correctly execute arbitrary EVM frames from inside cheatcode implementations. -pub trait CheatcodesExecutor { - /// Core trait method accepting mutable reference to [Cheatcodes] and returning - /// [revm::Inspector]. - fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box; - - /// Obtains [FoundryEvm] instance and executes the given CREATE frame. - fn exec_create( +/// Helper trait for running nested EVM operations from inside cheatcode implementations. +pub trait CheatcodesExecutor { + /// Runs a closure with a nested EVM built from the current context. + /// The inspector is assembled internally — never exposed to the caller. + fn with_nested_evm( &mut self, - inputs: CreateInputs, - ccx: &mut CheatsCtxt, - ) -> Result> { - with_evm(self, ccx, |evm| { - evm.journaled_state.depth += 1; - - let frame = FrameInput::Create(Box::new(inputs)); - - let outcome = match evm.run_execution(frame)? { - FrameResult::Call(_) => unreachable!(), - FrameResult::Create(create) => create, - }; + cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + f: NestedEvmClosure<'_, SpecFor, BlockEnvFor, TxEnvFor>, + ) -> Result<(), EVMError>; - evm.journaled_state.depth -= 1; - - Ok(outcome) - }) - } + /// Replays a historical transaction on the database. Inspector is assembled internally. + fn transact_on_db( + &mut self, + cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + fork_id: Option, + transaction: B256, + ) -> eyre::Result<()>; + + /// Executes a `TransactionRequest` on the database. Inspector is assembled internally. + fn transact_from_tx_on_db( + &mut self, + cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + tx: TxEnvFor, + ) -> eyre::Result<()>; + + /// Runs a closure with a fresh nested EVM built from a raw database and environment. + /// Unlike `with_nested_evm`, this does NOT clone from `ecx` and does NOT write back. + /// The caller is responsible for state merging. Used by `executeTransactionCall`. + /// Returns the final EVM environment after the closure runs (consumed without cloning). + #[allow(clippy::type_complexity)] + fn with_fresh_nested_evm( + &mut self, + cheats: &mut Cheatcodes, + db: &mut as ContextTr>::Db, + evm_env: EvmEnv, BlockEnvFor>, + f: NestedEvmClosure<'_, SpecFor, BlockEnvFor, TxEnvFor>, + ) -> Result, BlockEnvFor>, EVMError>; - fn console_log(&mut self, ccx: &mut CheatsCtxt, msg: &str) { - self.get_inspector(ccx.state).console_log(msg); - } + /// Simulates `console.log` invocation. + fn console_log(&mut self, msg: &str); /// Returns a mutable reference to the tracing inspector if it is available. fn tracing_inspector(&mut self) -> Option<&mut TracingInspector> { None } -} -/// Constructs [FoundryEvm] and runs a given closure with it. -fn with_evm( - executor: &mut E, - ccx: &mut CheatsCtxt, - f: F, -) -> Result> -where - E: CheatcodesExecutor + ?Sized, - F: for<'a, 'b> FnOnce( - &mut FoundryEvm<'a, &'b mut dyn InspectorExt>, - ) -> Result>, -{ - let mut inspector = executor.get_inspector(ccx.state); - let error = std::mem::replace(&mut ccx.ecx.error, Ok(())); - - let ctx = EthEvmContext { - block: ccx.ecx.block.clone(), - cfg: ccx.ecx.cfg.clone(), - tx: ccx.ecx.tx.clone(), - journaled_state: Journal { - inner: ccx.ecx.journaled_state.inner.clone(), - database: &mut *ccx.ecx.journaled_state.database as &mut dyn DatabaseExt, - }, - local: LocalContext::default(), - chain: (), - error, - }; - - let mut evm = new_evm_with_existing_context(ctx, &mut *inspector); + /// Marks that the next EVM frame is an "inner context" so that isolation mode does not + /// trigger a nested `transact_inner`. `original_origin` is stored for the existing + /// inner-context adjustment logic that restores `tx.origin`. + fn set_in_inner_context(&mut self, _enabled: bool, _original_origin: Option

) {} +} - let res = f(&mut evm)?; +/// Builds a sub-EVM from the current context and executes the given CREATE frame. +pub(crate) fn exec_create( + executor: &mut dyn CheatcodesExecutor, + inputs: CreateInputs, + ccx: &mut CheatsCtxt<'_, '_, FEN>, +) -> std::result::Result> { + let mut inputs = Some(inputs); + let mut outcome = None; + executor.with_nested_evm(ccx.state, ccx.ecx, &mut |evm| { + let inputs = inputs.take().unwrap(); + evm.journal_inner_mut().depth += 1; + + let frame = FrameInput::Create(Box::new(inputs)); + + let result = match evm.run_execution(frame)? { + FrameResult::Call(_) => unreachable!(), + FrameResult::Create(create) => create, + }; - let ctx = evm.into_context(); - ccx.ecx.journaled_state.inner = ctx.journaled_state.inner; - ccx.ecx.block = ctx.block; - ccx.ecx.tx = ctx.tx; - ccx.ecx.cfg = ctx.cfg; - ccx.ecx.error = ctx.error; + evm.journal_inner_mut().depth -= 1; - Ok(res) + outcome = Some(result); + Ok(()) + })?; + Ok(outcome.unwrap()) } /// Basic implementation of [CheatcodesExecutor] that simply returns the [Cheatcodes] instance as an @@ -170,10 +167,59 @@ where #[derive(Debug, Default, Clone, Copy)] struct TransparentCheatcodesExecutor; -impl CheatcodesExecutor for TransparentCheatcodesExecutor { - fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box { - Box::new(cheats) +impl CheatcodesExecutor for TransparentCheatcodesExecutor { + fn with_nested_evm( + &mut self, + cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + f: NestedEvmClosure<'_, SpecFor, BlockEnvFor, TxEnvFor>, + ) -> Result<(), EVMError> { + with_cloned_context(ecx, |db, evm_env, journal_inner| { + let mut evm = FEN::EvmFactory::default().create_foundry_nested_evm(db, evm_env, cheats); + *evm.journal_inner_mut() = journal_inner; + f(&mut *evm)?; + let sub_inner = evm.journal_inner_mut().clone(); + let sub_evm_env = evm.to_evm_env(); + Ok((sub_evm_env, sub_inner)) + }) } + + fn with_fresh_nested_evm( + &mut self, + cheats: &mut Cheatcodes, + db: &mut as ContextTr>::Db, + evm_env: EvmEnv, BlockEnvFor>, + f: NestedEvmClosure<'_, SpecFor, BlockEnvFor, TxEnvFor>, + ) -> Result, BlockEnvFor>, EVMError> { + let mut evm = FEN::EvmFactory::default().create_foundry_nested_evm(db, evm_env, cheats); + f(&mut *evm)?; + Ok(evm.to_evm_env()) + } + + fn transact_on_db( + &mut self, + cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + fork_id: Option, + transaction: B256, + ) -> eyre::Result<()> { + let evm_env = ecx.evm_clone(); + let (db, inner) = ecx.db_journal_inner_mut(); + db.transact(fork_id, transaction, evm_env, inner, cheats) + } + + fn transact_from_tx_on_db( + &mut self, + cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + tx: TxEnvFor, + ) -> eyre::Result<()> { + let evm_env = ecx.evm_clone(); + let (db, inner) = ecx.db_journal_inner_mut(); + db.transact_from_tx(tx, evm_env, inner, cheats) + } + + fn console_log(&mut self, _msg: &str) {} } macro_rules! try_or_return { @@ -208,11 +254,11 @@ impl TestContext { /// Helps collecting transactions from different forks. #[derive(Clone, Debug)] -pub struct BroadcastableTransaction { +pub struct BroadcastableTransaction { /// The optional RPC URL. pub rpc: Option, /// The transaction to broadcast. - pub transaction: TransactionMaybeSigned, + pub transaction: TransactionMaybeSigned, } #[derive(Clone, Debug, Copy)] @@ -253,12 +299,12 @@ pub struct GasMetering { impl GasMetering { /// Start the gas recording. - pub fn start(&mut self) { + pub const fn start(&mut self) { self.recording = true; } /// Stop the gas recording. - pub fn stop(&mut self) { + pub const fn stop(&mut self) { self.recording = false; } @@ -314,12 +360,17 @@ impl ArbitraryStorage { /// Saves arbitrary storage value for a given address: /// - store value in changed values cache. /// - update account's storage with given value. - pub fn save(&mut self, ecx: Ecx, address: Address, slot: U256, data: U256) { + pub fn save( + &mut self, + ecx: &mut CTX, + address: Address, + slot: U256, + data: U256, + ) { self.values.get_mut(&address).expect("missing arbitrary address entry").insert(slot, data); - let (db, journal, _) = ecx.as_db_env_and_journal(); - if journal.load_account(db, address).is_ok() { - journal - .sstore(db, address, slot, data, false) + if ecx.journal_mut().load_account(address).is_ok() { + ecx.journal_mut() + .sstore(address, slot, data) .expect("could not set arbitrary storage value"); } } @@ -329,7 +380,13 @@ impl ArbitraryStorage { /// existing value. /// - if no value was yet generated for given slot, then save new value in cache and update both /// source and target storages. - pub fn copy(&mut self, ecx: Ecx, target: Address, slot: U256, new_value: U256) -> U256 { + pub fn copy( + &mut self, + ecx: &mut CTX, + target: Address, + slot: U256, + new_value: U256, + ) -> U256 { let source = self.copies.get(&target).expect("missing arbitrary copy target entry"); let storage_cache = self.values.get_mut(source).expect("missing arbitrary source storage"); let value = match storage_cache.get(&slot) { @@ -337,26 +394,24 @@ impl ArbitraryStorage { None => { storage_cache.insert(slot, new_value); // Update source storage with new value. - let (db, journal, _) = ecx.as_db_env_and_journal(); - if journal.load_account(db, *source).is_ok() { - journal - .sstore(db, *source, slot, new_value, false) + if ecx.journal_mut().load_account(*source).is_ok() { + ecx.journal_mut() + .sstore(*source, slot, new_value) .expect("could not copy arbitrary storage value"); } new_value } }; // Update target storage with new value. - let (db, journal, _) = ecx.as_db_env_and_journal(); - if journal.load_account(db, target).is_ok() { - journal.sstore(db, target, slot, value, false).expect("could not set storage"); + if ecx.journal_mut().load_account(target).is_ok() { + ecx.journal_mut().sstore(target, slot, value).expect("could not set storage"); } value } } /// List of transactions that can be broadcasted. -pub type BroadcastableTransactions = VecDeque; +pub type BroadcastableTransactions = VecDeque>; /// An EVM inspector that handles calls to various cheatcodes, each with their own behavior. /// @@ -376,7 +431,7 @@ pub type BroadcastableTransactions = VecDeque; /// cheatcode address: by default, the caller, test contract and newly deployed contracts are /// allowed to execute cheatcodes #[derive(Clone, Debug)] -pub struct Cheatcodes { +pub struct Cheatcodes { /// Solar compiler instance, to grant syntactic and semantic analysis capabilities pub analysis: Option, @@ -384,7 +439,7 @@ pub struct Cheatcodes { /// /// Used in the cheatcode handler to overwrite the block environment separately from the /// execution block environment. - pub block: Option, + pub block: Option>, /// Currently active EIP-7702 delegations that will be consumed when building the next /// transaction. Set by `vm.attachDelegation()` and consumed via `.take()` during @@ -392,7 +447,7 @@ pub struct Cheatcodes { pub active_delegations: Vec, /// The active EIP-4844 blob that will be attached to the next call. - pub active_blob_sidecar: Option, + pub active_blob_sidecar: Option, /// The gas price. /// @@ -459,7 +514,7 @@ pub struct Cheatcodes { pub broadcast: Option, /// Scripting based transactions - pub broadcastable_transactions: BroadcastableTransactions, + pub broadcastable_transactions: BroadcastableTransactions, /// Current EIP-2930 access lists. pub access_list: Option, @@ -524,7 +579,7 @@ pub struct Cheatcodes { /// Used to determine whether the broadcasted call has dynamic gas limit. pub dynamic_gas_limit: bool, // Custom execution evm version. - pub execution_evm_version: Option, + pub execution_evm_version: Option>, } // This is not derived because calling this in `fn new` with `..Default::default()` creates a second @@ -536,7 +591,7 @@ impl Default for Cheatcodes { } } -impl Cheatcodes { +impl Cheatcodes { /// Creates a new `Cheatcodes` with the given settings. pub fn new(config: Arc) -> Self { Self { @@ -651,9 +706,9 @@ impl Cheatcodes { /// Decodes the input data and applies the cheatcode. fn apply_cheatcode( &mut self, - ecx: Ecx, + ecx: &mut FoundryContextFor<'_, FEN>, call: &CallInputs, - executor: &mut dyn CheatcodesExecutor, + executor: &mut dyn CheatcodesExecutor, ) -> Result { // decode the cheatcode call let decoded = Vm::VmCalls::abi_decode(&call.input.bytes(ecx)).map_err(|e| { @@ -672,7 +727,7 @@ impl Cheatcodes { // ensure the caller is allowed to execute cheatcodes, // but only if the backend is in forking mode - ecx.journaled_state.database.ensure_cheatcode_access_forking_mode(&caller)?; + ecx.db_mut().ensure_cheatcode_access_forking_mode(&caller)?; apply_dispatch( &decoded, @@ -686,11 +741,14 @@ impl Cheatcodes { /// /// There may be cheatcodes in the constructor of the new contract, in order to allow them /// automatically we need to determine the new address. - fn allow_cheatcodes_on_create(&self, ecx: Ecx, caller: Address, created_address: Address) { - if ecx.journaled_state.depth <= 1 - || ecx.journaled_state.database.has_cheatcode_access(&caller) - { - ecx.journaled_state.database.allow_cheatcode_access(created_address); + fn allow_cheatcodes_on_create( + &self, + ecx: &mut FoundryContextFor, + caller: Address, + created_address: Address, + ) { + if ecx.journal().depth() <= 1 || ecx.db().has_cheatcode_access(&caller) { + ecx.db_mut().allow_cheatcode_access(created_address); } } @@ -699,12 +757,12 @@ impl Cheatcodes { /// If the transaction type is [TransactionType::Legacy] we need to upgrade it to /// [TransactionType::Eip2930] in order to use access lists. Other transaction types support /// access lists themselves. - fn apply_accesslist(&mut self, ecx: Ecx) { + fn apply_accesslist(&mut self, ecx: &mut FoundryContextFor) { if let Some(access_list) = &self.access_list { - ecx.tx.access_list = access_list.clone(); + ecx.tx_mut().set_access_list(access_list.clone()); - if ecx.tx.tx_type == TransactionType::Legacy as u8 { - ecx.tx.tx_type = TransactionType::Eip2930 as u8; + if ecx.tx().tx_type() == TransactionType::Legacy as u8 { + ecx.tx_mut().set_tx_type(TransactionType::Eip2930 as u8); } } } @@ -713,7 +771,7 @@ impl Cheatcodes { /// /// Cleanup any previously applied cheatcodes that altered the state in such a way that revm's /// revert would run into issues. - pub fn on_revert(&mut self, ecx: Ecx) { + pub fn on_revert(&mut self, ecx: &mut FoundryContextFor) { trace!(deals=?self.eth_deals.len(), "rolling back deals"); // Delay revert clean up until expected revert is handled, if set. @@ -722,7 +780,7 @@ impl Cheatcodes { } // we only want to apply cleanup top level - if ecx.journaled_state.depth() > 0 { + if ecx.journal().depth() > 0 { return; } @@ -730,7 +788,7 @@ impl Cheatcodes { // This will prevent overflow issues in revm's [`JournaledState::journal_revert`] routine // which rolls back any transfers. while let Some(record) = self.eth_deals.pop() { - if let Some(acc) = ecx.journaled_state.state.get_mut(&record.address) { + if let Some(acc) = ecx.journal_mut().evm_state_mut().get_mut(&record.address) { acc.info.balance = record.old_balance; } } @@ -738,23 +796,23 @@ impl Cheatcodes { pub fn call_with_executor( &mut self, - ecx: Ecx, + ecx: &mut FoundryContextFor<'_, FEN>, call: &mut CallInputs, - executor: &mut dyn CheatcodesExecutor, + executor: &mut dyn CheatcodesExecutor, ) -> Option { // Apply custom execution evm version. if let Some(spec_id) = self.execution_evm_version { - ecx.cfg.spec = spec_id; + ecx.cfg_mut().set_spec_and_mainnet_gas_params(spec_id); } let gas = Gas::new(call.gas_limit); - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); // At the root call to test function or script `run()`/`setUp()` functions, we are // decreasing sender nonce to ensure that it matches on-chain nonce once we start // broadcasting. if curr_depth == 0 { - let sender = ecx.tx.caller; + let sender = ecx.tx().caller(); let account = match super::evm::journaled_account(ecx, sender) { Ok(account) => account, Err(err) => { @@ -805,6 +863,13 @@ impl Cheatcodes { return None; } + // `expectRevert`: track max call depth. This is also done in `initialize_interp`, but + // precompile calls don't create an interpreter frame so we must also track it here. + // The callee executes at `curr_depth + 1`. + if let Some(expected) = &mut self.expected_revert { + expected.max_depth = max(curr_depth + 1, expected.max_depth); + } + // Handle expected calls // Grab the different calldatas expected. @@ -830,6 +895,46 @@ impl Cheatcodes { } } + // Apply our prank + if let Some(prank) = &self.get_prank(curr_depth) { + // Apply delegate call, `call.caller`` will not equal `prank.prank_caller` + if prank.delegate_call + && curr_depth == prank.depth + && call.scheme == CallScheme::DelegateCall + { + call.target_address = prank.new_caller; + call.caller = prank.new_caller; + if let Some(new_origin) = prank.new_origin { + ecx.tx_mut().set_caller(new_origin); + } + } + + if curr_depth >= prank.depth && call.caller == prank.prank_caller { + // At the target depth we set `msg.sender` + let prank_applied = if curr_depth == prank.depth { + // Ensure new caller is loaded and touched + let _ = journaled_account(ecx, prank.new_caller); + call.caller = prank.new_caller; + true + } else { + false + }; + + // At the target depth, or deeper, we set `tx.origin` + let prank_applied = if let Some(new_origin) = prank.new_origin { + ecx.tx_mut().set_caller(new_origin); + true + } else { + prank_applied + }; + + // If prank applied for first time, then update + if prank_applied && let Some(applied_prank) = prank.first_time_applied() { + self.pranks.insert(curr_depth, applied_prank); + } + } + } + // Handle mocked calls if let Some(mocks) = self.mocked_calls.get_mut(&call.bytecode_address) { let ctx = MockCallDataContext { @@ -846,13 +951,43 @@ impl Cheatcodes { && mock.value.is_none_or(|value| Some(value) == call.transfer_value()) }) .map(|(_, v)| v), - } && let Some(return_data) = if return_data_queue.len() == 1 { + } && let Some(return_data) = return_data_queue.front().map(|x| x.to_owned()) + { + if let Some(value) = call.transfer_value() { + let checkpoint = ecx.journal_mut().checkpoint(); + match ecx.journal_mut().transfer_loaded( + call.transfer_from(), + call.transfer_to(), + value, + ) { + None => { + if return_data.ret_type.is_ok() { + ecx.journal_mut().checkpoint_commit(); + } else { + ecx.journal_mut().checkpoint_revert(checkpoint); + } + } + Some(err) => { + ecx.journal_mut().checkpoint_revert(checkpoint); + return Some(CallOutcome { + result: InterpreterResult { + result: err.into(), + output: Bytes::new(), + gas, + }, + memory_offset: call.return_memory_offset.clone(), + was_precompile_called: false, + precompile_call_logs: vec![], + }); + } + } + } + // If the mocked calls stack has a single element in it, don't empty it - return_data_queue.front().map(|x| x.to_owned()) - } else { - // Else, we pop the front element - return_data_queue.pop_front() - } { + if return_data_queue.len() > 1 { + return_data_queue.pop_front(); + } + return Some(CallOutcome { result: InterpreterResult { result: return_data.ret_type, @@ -866,44 +1001,6 @@ impl Cheatcodes { } } - // Apply our prank - if let Some(prank) = &self.get_prank(curr_depth) { - // Apply delegate call, `call.caller`` will not equal `prank.prank_caller` - if prank.delegate_call - && curr_depth == prank.depth - && let CallScheme::DelegateCall = call.scheme - { - call.target_address = prank.new_caller; - call.caller = prank.new_caller; - if let Some(new_origin) = prank.new_origin { - ecx.tx.caller = new_origin; - } - } - - if curr_depth >= prank.depth && call.caller == prank.prank_caller { - let mut prank_applied = false; - - // At the target depth we set `msg.sender` - if curr_depth == prank.depth { - // Ensure new caller is loaded and touched - let _ = journaled_account(ecx, prank.new_caller); - call.caller = prank.new_caller; - prank_applied = true; - } - - // At the target depth, or deeper, we set `tx.origin` - if let Some(new_origin) = prank.new_origin { - ecx.tx.caller = new_origin; - prank_applied = true; - } - - // If prank applied for first time, then update - if prank_applied && let Some(applied_prank) = prank.first_time_applied() { - self.pranks.insert(curr_depth, applied_prank); - } - } - } - // Apply EIP-2930 access list self.apply_accesslist(ecx); @@ -922,7 +1019,7 @@ impl Cheatcodes { // At the target depth we set `msg.sender` & tx.origin. // We are simulating the caller as being an EOA, so *both* must be set to the // broadcast.origin. - ecx.tx.caller = broadcast.new_origin; + ecx.tx_mut().set_caller(broadcast.new_origin); call.caller = broadcast.new_origin; // Add a `legacy` transaction to the VecDeque. We use a legacy transaction here @@ -930,8 +1027,7 @@ impl Cheatcodes { // into 1559, in the cli package, relatively easily once we // know the target chain supports EIP-1559. if !call.is_static { - let (db, journal, _) = ecx.as_db_env_and_journal(); - if let Err(err) = journal.load_account(db, broadcast.new_origin) { + if let Err(err) = ecx.journal_mut().load_account(broadcast.new_origin) { return Some(CallOutcome { result: InterpreterResult { result: InstructionResult::Revert, @@ -944,21 +1040,22 @@ impl Cheatcodes { }); } - let input = TransactionInput::new(call.input.bytes(ecx)); - + let input = call.input.bytes(ecx); + let chain_id = ecx.cfg().chain_id(); + let rpc = ecx.db().active_fork_url(); let account = - ecx.journaled_state.inner.state().get_mut(&broadcast.new_origin).unwrap(); - - let mut tx_req = TransactionRequest { - from: Some(broadcast.new_origin), - to: Some(TxKind::from(Some(call.target_address))), - value: call.transfer_value(), - input, - nonce: Some(account.info.nonce), - chain_id: Some(ecx.cfg.chain_id), - gas: if is_fixed_gas_limit { Some(call.gas_limit) } else { None }, - ..Default::default() - }; + ecx.journal_mut().evm_state_mut().get_mut(&broadcast.new_origin).unwrap(); + + let mut tx_req = TransactionRequestFor::::default() + .with_from(broadcast.new_origin) + .with_to(call.target_address) + .with_value(call.transfer_value().unwrap_or_default()) + .with_input(input) + .with_nonce(account.info.nonce) + .with_chain_id(chain_id); + if is_fixed_gas_limit { + tx_req.set_gas_limit(call.gas_limit) + } let active_delegations = std::mem::take(&mut self.active_delegations); // Set active blob sidecar, if any. @@ -992,12 +1089,14 @@ impl Cheatcodes { account.info.nonce += 1; } } - tx_req.authorization_list = Some(active_delegations); + tx_req.set_authorization_list(active_delegations); + } + if let Some(fee_token) = self.config.fee_token { + tx_req.set_fee_token(fee_token); } - self.broadcastable_transactions.push_back(BroadcastableTransaction { - rpc: ecx.journaled_state.database.active_fork_url(), - transaction: tx_req.into(), + rpc, + transaction: TransactionMaybeSigned::new(tx_req), }); debug!(target: "cheatcodes", tx=?self.broadcastable_transactions.back().unwrap(), "broadcastable call"); @@ -1027,20 +1126,12 @@ impl Cheatcodes { if let Some(recorded_account_diffs_stack) = &mut self.recorded_account_diffs_stack { // Determine if account is "initialized," ie, it has a non-zero balance, a non-zero // nonce, a non-zero KECCAK_EMPTY codehash, or non-empty code - let initialized; - let old_balance; - let old_nonce; - - let (db, journal, _) = ecx.as_db_env_and_journal(); - if let Ok(acc) = journal.load_account(db, call.target_address) { - initialized = acc.info.exists(); - old_balance = acc.info.balance; - old_nonce = acc.info.nonce; - } else { - initialized = false; - old_balance = U256::ZERO; - old_nonce = 0; - } + let (initialized, old_balance, old_nonce) = + if let Ok(acc) = ecx.journal_mut().load_account(call.target_address) { + (acc.data.info.exists(), acc.data.info.balance, acc.data.info.nonce) + } else { + (false, U256::ZERO, 0) + }; let kind = match call.scheme { CallScheme::Call => crate::Vm::AccountAccessKind::Call, @@ -1056,8 +1147,8 @@ impl Cheatcodes { // as "warm" if the call from which they were accessed is reverted recorded_account_diffs_stack.push(vec![AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.journaled_state.db().active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.cfg.chain_id), + forkId: ecx.db().active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg().chain_id()), }, accessor: call.caller, account: call.bytecode_address, @@ -1072,45 +1163,10 @@ impl Cheatcodes { reverted: false, deployedCode: Bytes::new(), storageAccesses: vec![], // updated on step - depth: ecx - .journaled_state - .depth() - .try_into() - .expect("journaled state depth exceeds u64"), + depth: ecx.journal().depth().try_into().expect("journaled state depth exceeds u64"), }]); } - #[cfg(feature = "credible")] - if let Some(assertion) = self.assertion.take() { - let tx_attributes = crate::credible::TxAttributes { - value: call.call_value(), - data: call.input.bytes(ecx), - caller: call.caller, - kind: TxKind::Call(call.target_address), - gas_limit: call.gas_limit, - }; - - return match crate::credible::execute_assertion( - &assertion, - tx_attributes, - ecx, - executor, - self, - ) { - Ok(_) => None, - Err(err) => Some(CallOutcome { - result: InterpreterResult { - result: InstructionResult::Revert, - output: err.abi_encode().into(), - gas, - }, - memory_offset: call.return_memory_offset.clone(), - was_precompile_called: false, - precompile_call_logs: vec![], - }), - }; - } - None } @@ -1184,15 +1240,19 @@ impl Cheatcodes { } } -impl Inspector> for Cheatcodes { - fn initialize_interp(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { +impl Inspector> for Cheatcodes { + fn initialize_interp( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut FoundryContextFor<'_, FEN>, + ) { // When the first interpreter is initialized we've circumvented the balance and gas checks, // so we apply our actual block data with the correct fees and all. if let Some(block) = self.block.take() { - ecx.block = block; + ecx.set_block(block); } if let Some(gas_price) = self.gas_price.take() { - ecx.tx.gas_price = gas_price; + ecx.tx_mut().set_gas_price(gas_price); } // Record gas for current frame. @@ -1202,11 +1262,11 @@ impl Inspector> for Cheatcodes { // `expectRevert`: track the max call depth during `expectRevert` if let Some(expected) = &mut self.expected_revert { - expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); + expected.max_depth = max(ecx.journal().depth(), expected.max_depth); } } - fn step(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { + fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut FoundryContextFor<'_, FEN>) { self.pc = interpreter.bytecode.pc(); if self.broadcast.is_some() { @@ -1237,7 +1297,7 @@ impl Inspector> for Cheatcodes { if !self.allowed_mem_writes.is_empty() { self.check_mem_opcodes( interpreter, - ecx.journaled_state.depth().try_into().expect("journaled state depth exceeds u64"), + ecx.journal().depth().try_into().expect("journaled state depth exceeds u64"), ); } @@ -1252,7 +1312,7 @@ impl Inspector> for Cheatcodes { } } - fn step_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { + fn step_end(&mut self, interpreter: &mut Interpreter, ecx: &mut FoundryContextFor<'_, FEN>) { if self.gas_metering.paused { self.meter_gas_end(interpreter); } @@ -1267,7 +1327,7 @@ impl Inspector> for Cheatcodes { } } - fn log(&mut self, _ecx: Ecx, log: Log) { + fn log(&mut self, _ecx: &mut FoundryContextFor<'_, FEN>, log: Log) { if !self.expected_emits.is_empty() && let Some(err) = expect::handle_expect_emit(self, &log, None) { @@ -1281,7 +1341,12 @@ impl Inspector> for Cheatcodes { record_logs(&mut self.recorded_logs, &log); } - fn log_full(&mut self, interpreter: &mut Interpreter, _ecx: Ecx, log: Log) { + fn log_full( + &mut self, + interpreter: &mut Interpreter, + _ecx: &mut FoundryContextFor<'_, FEN>, + log: Log, + ) { if !self.expected_emits.is_empty() { expect::handle_expect_emit(self, &log, Some(interpreter)); } @@ -1290,11 +1355,20 @@ impl Inspector> for Cheatcodes { record_logs(&mut self.recorded_logs, &log); } - fn call(&mut self, ecx: Ecx, call: &mut CallInputs) -> Option { - Self::call_with_executor(self, ecx, call, &mut TransparentCheatcodesExecutor) + fn call( + &mut self, + ecx: &mut FoundryContextFor<'_, FEN>, + inputs: &mut CallInputs, + ) -> Option { + Self::call_with_executor(self, ecx, inputs, &mut TransparentCheatcodesExecutor) } - fn call_end(&mut self, ecx: Ecx, call: &CallInputs, outcome: &mut CallOutcome) { + fn call_end( + &mut self, + ecx: &mut FoundryContextFor<'_, FEN>, + call: &CallInputs, + outcome: &mut CallOutcome, + ) { let cheatcode_call = call.target_address == CHEATCODE_ADDRESS || call.target_address == HARDHAT_CONSOLE_ADDRESS; @@ -1303,11 +1377,11 @@ impl Inspector> for Cheatcodes { // This should be placed before the revert handling, because we might exit early there if !cheatcode_call { // Clean up pranks - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); if let Some(prank) = &self.get_prank(curr_depth) && curr_depth == prank.depth { - ecx.tx.caller = prank.prank_origin; + ecx.tx_mut().set_caller(prank.prank_origin); // Clean single-call prank once we have returned to the original depth if prank.single_call { @@ -1319,7 +1393,7 @@ impl Inspector> for Cheatcodes { if let Some(broadcast) = &self.broadcast && curr_depth == broadcast.depth { - ecx.tx.caller = broadcast.original_origin; + ecx.tx_mut().set_caller(broadcast.original_origin); // Clean single-call broadcast once we have returned to the original depth if broadcast.single_call { @@ -1336,10 +1410,10 @@ impl Inspector> for Cheatcodes { assume_no_revert.reverted_by = Some(call.target_address); } - let curr_depth = ecx.journaled_state.depth(); // allow multiple cheatcode calls at the same depth + let curr_depth = ecx.journal().depth(); if curr_depth <= assume_no_revert.depth && !cheatcode_call { - // discard run if we're at the same depth as cheatcode, call reverted, and no + // Discard run if we're at the same depth as cheatcode, call reverted, and no // specific reason was supplied if outcome.result.is_revert() { let assume_no_revert = std::mem::take(&mut self.assume_no_revert).unwrap(); @@ -1362,10 +1436,9 @@ impl Inspector> for Cheatcodes { outcome.result.output = error.abi_encode().into(); } }; - } else { - // Call didn't revert, reset `assume_no_revert` state. - self.assume_no_revert = None; } + // Call didn't revert, reset `assume_no_revert` state. + self.assume_no_revert = None; } } @@ -1384,7 +1457,7 @@ impl Inspector> for Cheatcodes { } } - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); if curr_depth <= expected_revert.depth { let needs_processing = match expected_revert.kind { ExpectedRevertKind::Default => !cheatcode_call, @@ -1443,7 +1516,7 @@ impl Inspector> for Cheatcodes { let gas = outcome.result.gas; self.gas_metering.last_call_gas = Some(crate::Vm::Gas { gasLimit: gas.limit(), - gasTotalUsed: gas.spent(), + gasTotalUsed: gas.total_gas_spent(), gasMemoryUsed: 0, gasRefunded: gas.refunded(), gasRemaining: gas.remaining(), @@ -1453,19 +1526,18 @@ impl Inspector> for Cheatcodes { // previous call depth's recorded accesses, if any if let Some(recorded_account_diffs_stack) = &mut self.recorded_account_diffs_stack { // The root call cannot be recorded. - if ecx.journaled_state.depth() > 0 + if ecx.journal().depth() > 0 && let Some(mut last_recorded_depth) = recorded_account_diffs_stack.pop() { // Update the reverted status of all deeper calls if this call reverted, in // accordance with EVM behavior if outcome.result.is_revert() { - last_recorded_depth.iter_mut().for_each(|element| { + for element in &mut *last_recorded_depth { element.reverted = true; - element - .storageAccesses - .iter_mut() - .for_each(|storage_access| storage_access.reverted = true); - }) + for storage_access in &mut element.storageAccesses { + storage_access.reverted = true; + } + } } if let Some(call_access) = last_recorded_depth.first_mut() { @@ -1473,14 +1545,13 @@ impl Inspector> for Cheatcodes { // changes. Depending on the depth the cheat was // called at, there may not be any pending // calls to update if execution has percolated up to a higher depth. - let (db, journal, _) = ecx.as_db_env_and_journal(); - let curr_depth = journal.depth; + let curr_depth = ecx.journal().depth(); if call_access.depth == curr_depth as u64 - && let Ok(acc) = journal.load_account(db, call.target_address) + && let Ok(acc) = ecx.journal_mut().load_account(call.target_address) { debug_assert!(access_is_call(call_access.kind)); - call_access.newBalance = acc.info.balance; - call_access.newNonce = acc.info.nonce; + call_access.newBalance = acc.data.info.balance; + call_access.newNonce = acc.data.info.nonce; } // Merge the last depth's AccountAccesses into the AccountAccesses at the // current depth, or push them back onto the pending @@ -1495,6 +1566,21 @@ impl Inspector> for Cheatcodes { } } + // this will ensure we don't have false positives when trying to diagnose reverts in fork + // mode + let diag = self.fork_revert_diagnostic.take(); + + // If the call already reverted, preserve that primary failure and skip post-call + // expect* validation so it cannot overwrite the original revert. + if outcome.result.is_revert() { + // if there's a revert and a previous call was diagnosed as fork related revert then we + // can return a better error here + if let Some(err) = diag { + outcome.result.output = Error::encode(err.to_error_msg(&self.labels)); + } + return; + } + // At the end of the call, // we need to check if we've found all the emits. // We know we've found all the expected emits in the right order @@ -1510,7 +1596,7 @@ impl Inspector> for Cheatcodes { .expected_emits .iter() .any(|(expected, _)| { - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); expected.depth == curr_depth }) && // Ignore staticcalls @@ -1535,7 +1621,7 @@ impl Inspector> for Cheatcodes { }, }; - if count != expected.count { Some((expected, count)) } else { None } + (count != expected.count).then_some((expected, count)) }) .collect::>(); @@ -1572,36 +1658,22 @@ impl Inspector> for Cheatcodes { self.expected_emits.clear() } - // this will ensure we don't have false positives when trying to diagnose reverts in fork - // mode - let diag = self.fork_revert_diagnostic.take(); - - // if there's a revert and a previous call was diagnosed as fork related revert then we can - // return a better error here - if outcome.result.is_revert() - && let Some(err) = diag - { - outcome.result.output = Error::encode(err.to_error_msg(&self.labels)); - return; - } - // try to diagnose reverts in multi-fork mode where a call is made to an address that does // not exist - if let TxKind::Call(test_contract) = ecx.tx.kind { + if let TxKind::Call(test_contract) = ecx.tx().kind() { // if a call to a different contract than the original test contract returned with // `Stop` we check if the contract actually exists on the active fork - if ecx.journaled_state.db().is_forked_mode() + if ecx.db().is_forked_mode() && outcome.result.result == InstructionResult::Stop && call.target_address != test_contract { - let journaled_state = ecx.journaled_state.clone(); self.fork_revert_diagnostic = - ecx.journaled_state.db().diagnose_revert(call.target_address, &journaled_state); + ecx.db().diagnose_revert(call.target_address, ecx.journal().evm_state()); } } // If the depth is 0, then this is the root call terminating - if ecx.journaled_state.depth() == 0 { + if ecx.journal().depth() == 0 { // If we already have a revert, we shouldn't run the below logic as it can obfuscate an // earlier error that happened first with unrelated information about // another error when using cheatcodes. @@ -1698,10 +1770,14 @@ impl Inspector> for Cheatcodes { } } - fn create(&mut self, ecx: Ecx, mut input: &mut CreateInputs) -> Option { + fn create( + &mut self, + ecx: &mut FoundryContextFor<'_, FEN>, + mut input: &mut CreateInputs, + ) -> Option { // Apply custom execution evm version. if let Some(spec_id) = self.execution_evm_version { - ecx.cfg.spec = spec_id; + ecx.cfg_mut().set_spec_and_mainnet_gas_params(spec_id); } let gas = Gas::new(input.gas_limit()); @@ -1720,28 +1796,30 @@ impl Inspector> for Cheatcodes { }); } - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); // Apply our prank if let Some(prank) = &self.get_prank(curr_depth) && curr_depth >= prank.depth && input.caller() == prank.prank_caller { - let mut prank_applied = false; - // At the target depth we set `msg.sender` - if curr_depth == prank.depth { + let prank_applied = if curr_depth == prank.depth { // Ensure new caller is loaded and touched let _ = journaled_account(ecx, prank.new_caller); input.set_caller(prank.new_caller); - prank_applied = true; - } + true + } else { + false + }; // At the target depth, or deeper, we set `tx.origin` - if let Some(new_origin) = prank.new_origin { - ecx.tx.caller = new_origin; - prank_applied = true; - } + let prank_applied = if let Some(new_origin) = prank.new_origin { + ecx.tx_mut().set_caller(new_origin); + true + } else { + prank_applied + }; // If prank applied for first time, then update if prank_applied && let Some(applied_prank) = prank.first_time_applied() { @@ -1757,8 +1835,7 @@ impl Inspector> for Cheatcodes { && curr_depth >= broadcast.depth && input.caller() == broadcast.original_caller { - let (db, journal, _) = ecx.as_db_env_and_journal(); - if let Err(err) = journal.load_account(db, broadcast.new_origin) { + if let Err(err) = ecx.journal_mut().load_account(broadcast.new_origin) { return Some(CreateOutcome { result: InterpreterResult { result: InstructionResult::Revert, @@ -1769,7 +1846,7 @@ impl Inspector> for Cheatcodes { }); } - ecx.tx.caller = broadcast.new_origin; + ecx.tx_mut().set_caller(broadcast.new_origin); if curr_depth == broadcast.depth || broadcast.deploy_from_code { // Reset deploy from code flag for upcoming calls; @@ -1777,18 +1854,20 @@ impl Inspector> for Cheatcodes { input.set_caller(broadcast.new_origin); - let account = &ecx.journaled_state.inner.state()[&broadcast.new_origin]; + let rpc = ecx.db().active_fork_url(); + let account = &ecx.journal().evm_state()[&broadcast.new_origin]; + let mut tx_req = TransactionRequestFor::::default() + .with_from(broadcast.new_origin) + .with_kind(TxKind::Create) + .with_value(input.value()) + .with_input(input.init_code()) + .with_nonce(account.info.nonce); + if let Some(fee_token) = self.config.fee_token { + tx_req.set_fee_token(fee_token); + } self.broadcastable_transactions.push_back(BroadcastableTransaction { - rpc: ecx.journaled_state.database.active_fork_url(), - transaction: TransactionRequest { - from: Some(broadcast.new_origin), - to: None, - value: Some(input.value()), - input: TransactionInput::new(input.init_code()), - nonce: Some(account.info.nonce), - ..Default::default() - } - .into(), + rpc, + transaction: TransactionMaybeSigned::new(tx_req), }); input.log_debug(self, &input.scheme().unwrap_or(CreateScheme::Create)); @@ -1802,8 +1881,8 @@ impl Inspector> for Cheatcodes { if let Some(recorded_account_diffs_stack) = &mut self.recorded_account_diffs_stack { recorded_account_diffs_stack.push(vec![AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.journaled_state.db().active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.cfg.chain_id), + forkId: ecx.db().active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg().chain_id()), }, accessor: input.caller(), account: address, @@ -1821,47 +1900,24 @@ impl Inspector> for Cheatcodes { depth: curr_depth as u64, }]); } - #[cfg(feature = "credible")] - if let Some(assertion) = self.assertion.take() { - let tx_attributes = crate::credible::TxAttributes { - value: input.value(), - data: input.init_code(), - caller: input.caller(), - kind: TxKind::Create, - gas_limit: input.gas_limit(), - }; - - return match crate::credible::execute_assertion( - &assertion, - tx_attributes, - ecx, - &mut TransparentCheatcodesExecutor, - self, - ) { - Ok(_) => None, - Err(err) => Some(CreateOutcome { - result: InterpreterResult { - result: InstructionResult::Revert, - output: err.abi_encode().into(), - gas, - }, - address: None, - }), - }; - } None } - fn create_end(&mut self, ecx: Ecx, call: &CreateInputs, outcome: &mut CreateOutcome) { + fn create_end( + &mut self, + ecx: &mut FoundryContextFor<'_, FEN>, + call: &CreateInputs, + outcome: &mut CreateOutcome, + ) { let call = Some(call); - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); // Clean up pranks if let Some(prank) = &self.get_prank(curr_depth) && curr_depth == prank.depth { - ecx.tx.caller = prank.prank_origin; + ecx.tx_mut().set_caller(prank.prank_origin); // Clean single-call prank once we have returned to the original depth if prank.single_call { @@ -1873,7 +1929,7 @@ impl Inspector> for Cheatcodes { if let Some(broadcast) = &self.broadcast && curr_depth == broadcast.depth { - ecx.tx.caller = broadcast.original_origin; + ecx.tx_mut().set_caller(broadcast.original_origin); // Clean single-call broadcast once we have returned to the original depth if broadcast.single_call { @@ -1882,10 +1938,23 @@ impl Inspector> for Cheatcodes { } // Handle expected reverts - if let Some(expected_revert) = &self.expected_revert + if let Some(expected_revert) = &mut self.expected_revert && curr_depth <= expected_revert.depth && matches!(expected_revert.kind, ExpectedRevertKind::Default) { + // Mirror the logic in `call_end`: when an expected reverter address is set + // and we don't yet have one (or we're matching multiple reverts), record the + // would-be deployed address as the reverter. revm guarantees `outcome.address` + // is `Some(_)` whenever the constructor actually ran (including the revert + // case); it is only `None` for pre-frame rejection (depth/balance/nonce), + // for which a reverter address is meaningless. + if outcome.result.is_revert() + && expected_revert.reverter.is_some() + && (expected_revert.reverted_by.is_none() || expected_revert.count > 1) + && let Some(addr) = outcome.address + { + expected_revert.reverted_by = Some(addr); + } let mut expected_revert = std::mem::take(&mut self.expected_revert).unwrap(); return match revert_handlers::handle_expect_revert( false, @@ -1923,13 +1992,12 @@ impl Inspector> for Cheatcodes { // Update the reverted status of all deeper calls if this call reverted, in // accordance with EVM behavior if outcome.result.is_revert() { - last_depth.iter_mut().for_each(|element| { + for element in &mut *last_depth { element.reverted = true; - element - .storageAccesses - .iter_mut() - .for_each(|storage_access| storage_access.reverted = true); - }) + for storage_access in &mut element.storageAccesses { + storage_access.reverted = true; + } + } } if let Some(create_access) = last_depth.first_mut() { @@ -1937,20 +2005,24 @@ impl Inspector> for Cheatcodes { // changes. Depending on what depth the cheat was called at, there // may not be any pending calls to update if execution has // percolated up to a higher depth. - let depth = ecx.journaled_state.depth(); + let depth = ecx.journal().depth(); if create_access.depth == depth as u64 { debug_assert_eq!( create_access.kind as u8, crate::Vm::AccountAccessKind::Create as u8 ); - let (db, journal, _) = ecx.as_db_env_and_journal(); if let Some(address) = outcome.address - && let Ok(created_acc) = journal.load_account(db, address) + && let Ok(created_acc) = ecx.journal_mut().load_account(address) { - create_access.newBalance = created_acc.info.balance; - create_access.newNonce = created_acc.info.nonce; - create_access.deployedCode = - created_acc.info.code.clone().unwrap_or_default().original_bytes(); + create_access.newBalance = created_acc.data.info.balance; + create_access.newNonce = created_acc.data.info.nonce; + create_access.deployedCode = created_acc + .data + .info + .code + .clone() + .unwrap_or_default() + .original_bytes(); } } // Merge the last depth's AccountAccesses into the AccountAccesses at the @@ -1967,16 +2039,15 @@ impl Inspector> for Cheatcodes { } // Match the create against expected_creates - let (db, journal, _) = ecx.as_db_env_and_journal(); if !self.expected_creates.is_empty() && let (Some(address), Some(call)) = (outcome.address, call) - && let Ok(created_acc) = journal.load_account(db, address) + && let Ok(created_acc) = ecx.journal_mut().load_account(address) { - let bytecode = created_acc.info.code.clone().unwrap_or_default().original_bytes(); + let bytecode = created_acc.data.info.code.clone().unwrap_or_default().original_bytes(); if let Some((index, _)) = self.expected_creates.iter().find_position(|expected_create| { - expected_create.deployer == call.caller - && expected_create.create_scheme.eq(call.scheme.into()) + expected_create.deployer == call.caller() + && expected_create.create_scheme.eq(call.scheme().into()) && expected_create.bytecode == bytecode }) { @@ -1986,10 +2057,9 @@ impl Inspector> for Cheatcodes { } } -impl InspectorExt for Cheatcodes { - fn should_use_create2_factory(&mut self, ecx: Ecx, inputs: &CreateInputs) -> bool { - if let CreateScheme::Create2 { .. } = inputs.scheme { - let depth = ecx.journaled_state.depth(); +impl InspectorExt for Cheatcodes { + fn should_use_create2_factory(&mut self, depth: usize, inputs: &CreateInputs) -> bool { + if let CreateScheme::Create2 { .. } = inputs.scheme() { let target_depth = if let Some(prank) = &self.get_prank(depth) { prank.depth } else if let Some(broadcast) = &self.broadcast { @@ -2010,7 +2080,7 @@ impl InspectorExt for Cheatcodes { } } -impl Cheatcodes { +impl Cheatcodes { #[cold] fn meter_gas(&mut self, interpreter: &mut Interpreter) { if let Some(paused_gas) = self.gas_metering.paused_frames.last() { @@ -2027,22 +2097,28 @@ impl Cheatcodes { } #[cold] - fn meter_gas_record(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { + fn meter_gas_record( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut FoundryContextFor<'_, FEN>, + ) { if interpreter.bytecode.action.as_ref().and_then(|i| i.instruction_result()).is_none() { self.gas_metering.gas_records.iter_mut().for_each(|record| { - let curr_depth = ecx.journaled_state.depth(); + let curr_depth = ecx.journal().depth(); if curr_depth == record.depth { // Skip the first opcode of the first call frame as it includes the gas cost of // creating the snapshot. if self.gas_metering.last_gas_used != 0 { - let gas_diff = - interpreter.gas.spent().saturating_sub(self.gas_metering.last_gas_used); + let gas_diff = interpreter + .gas + .total_gas_spent() + .saturating_sub(self.gas_metering.last_gas_used); record.gas_used = record.gas_used.saturating_add(gas_diff); } // Update `last_gas_used` to the current spent gas for the next iteration to // compare against. - self.gas_metering.last_gas_used = interpreter.gas.spent(); + self.gas_metering.last_gas_used = interpreter.gas.total_gas_spent(); } }); } @@ -2075,7 +2151,7 @@ impl Cheatcodes { // Reset gas if spent is less than refunded. // This can happen if gas was paused / resumed or reset. // https://github.com/foundry-rs/foundry/issues/4370 - if interpreter.gas.spent() + if interpreter.gas.total_gas_spent() < u64::try_from(interpreter.gas.refunded()).unwrap_or_default() { interpreter.gas = Gas::new(interpreter.gas.limit()); @@ -2091,7 +2167,11 @@ impl Cheatcodes { /// cache) from mapped source address to the target address. /// - generates arbitrary value and saves it in target address storage. #[cold] - fn arbitrary_storage_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { + fn arbitrary_storage_end( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut FoundryContextFor<'_, FEN>, + ) { let (key, target_address) = if interpreter.bytecode.opcode() == op::SLOAD { (try_or_return!(interpreter.stack.peek(0)), interpreter.input.target_address) } else { @@ -2143,7 +2223,11 @@ impl Cheatcodes { } #[cold] - fn record_state_diffs(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { + fn record_state_diffs( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut FoundryContextFor<'_, FEN>, + ) { let Some(account_accesses) = &mut self.recorded_account_diffs_stack else { return }; match interpreter.bytecode.opcode() { op::SELFDESTRUCT => { @@ -2153,11 +2237,15 @@ impl Cheatcodes { // get previous balance, nonce and initialized status of the target account let target = try_or_return!(interpreter.stack.peek(0)); let target = Address::from_word(B256::from(target)); - let (db, journal, _) = ecx.as_db_env_and_journal(); - let (initialized, old_balance, old_nonce) = journal - .load_account(db, target) + let (initialized, old_balance, old_nonce) = ecx + .journal_mut() + .load_account(target) .map(|account| { - (account.info.exists(), account.info.balance, account.info.nonce) + ( + account.data.info.exists(), + account.data.info.balance, + account.data.info.nonce, + ) }) .unwrap_or_default(); @@ -2170,8 +2258,8 @@ impl Cheatcodes { // register access for the target account last.push(crate::Vm::AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.journaled_state.database.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.cfg.chain_id), + forkId: ecx.db().active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg().chain_id()), }, accessor: interpreter.input.target_address, account: target, @@ -2187,7 +2275,7 @@ impl Cheatcodes { deployedCode: Bytes::new(), storageAccesses: vec![], depth: ecx - .journaled_state + .journal() .depth() .try_into() .expect("journaled state depth exceeds u64"), @@ -2202,14 +2290,14 @@ impl Cheatcodes { // Try to include present value for informational purposes, otherwise assume // it's not set (zero value) - let mut present_value = U256::ZERO; // Try to load the account and the slot's present value - let (db, journal, _) = ecx.as_db_env_and_journal(); - if journal.load_account(db, address).is_ok() + let present_value = if ecx.journal_mut().load_account(address).is_ok() && let Some(previous) = ecx.sload(address, key) { - present_value = previous.data; - } + previous.data + } else { + U256::ZERO + }; let access = crate::Vm::StorageAccess { account: interpreter.input.target_address, slot: key.into(), @@ -2218,11 +2306,8 @@ impl Cheatcodes { newValue: present_value.into(), reverted: false, }; - let curr_depth = ecx - .journaled_state - .depth() - .try_into() - .expect("journaled state depth exceeds u64"); + let curr_depth = + ecx.journal().depth().try_into().expect("journaled state depth exceeds u64"); append_storage_access(last, access, curr_depth); } op::SSTORE => { @@ -2233,13 +2318,13 @@ impl Cheatcodes { let address = interpreter.input.target_address; // Try to load the account and the slot's previous value, otherwise, assume it's // not set (zero value) - let mut previous_value = U256::ZERO; - let (db, journal, _) = ecx.as_db_env_and_journal(); - if journal.load_account(db, address).is_ok() + let previous_value = if ecx.journal_mut().load_account(address).is_ok() && let Some(previous) = ecx.sload(address, key) { - previous_value = previous.data; - } + previous.data + } else { + U256::ZERO + }; let access = crate::Vm::StorageAccess { account: address, @@ -2249,11 +2334,8 @@ impl Cheatcodes { newValue: value.into(), reverted: false, }; - let curr_depth = ecx - .journaled_state - .depth() - .try_into() - .expect("journaled state depth exceeds u64"); + let curr_depth = + ecx.journal().depth().try_into().expect("journaled state depth exceeds u64"); append_storage_access(last, access, curr_depth); } @@ -2268,28 +2350,18 @@ impl Cheatcodes { }; let address = Address::from_word(B256::from(try_or_return!(interpreter.stack.peek(0)))); - let initialized; - let balance; - let nonce; - let (db, journal, _) = ecx.as_db_env_and_journal(); - if let Ok(acc) = journal.load_account(db, address) { - initialized = acc.info.exists(); - balance = acc.info.balance; - nonce = acc.info.nonce; - } else { - initialized = false; - balance = U256::ZERO; - nonce = 0; - } - let curr_depth = ecx - .journaled_state - .depth() - .try_into() - .expect("journaled state depth exceeds u64"); + let (initialized, balance, nonce) = + if let Ok(acc) = ecx.journal_mut().load_account(address) { + (acc.data.info.exists(), acc.data.info.balance, acc.data.info.nonce) + } else { + (false, U256::ZERO, 0) + }; + let curr_depth = + ecx.journal().depth().try_into().expect("journaled state depth exceeds u64"); let account_access = crate::Vm::AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.journaled_state.database.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.cfg.chain_id), + forkId: ecx.db().active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg().chain_id()), }, accessor: interpreter.input.target_address, account: address, @@ -2521,7 +2593,7 @@ fn disallowed_mem_write( "memory write at offset 0x{:02X} of size 0x{:02X} not allowed; safe range: {}", dest_offset, size, - ranges.iter().map(|r| format!("(0x{:02X}, 0x{:02X}]", r.start, r.end)).join(" U ") + ranges.iter().map(|r| format!("[0x{:02X}, 0x{:02X})", r.start, r.end)).join(" U ") ); interpreter.bytecode.set_action(InterpreterAction::new_return( @@ -2532,7 +2604,7 @@ fn disallowed_mem_write( } /// Returns true if the kind of account access is a call. -fn access_is_call(kind: crate::Vm::AccountAccessKind) -> bool { +const fn access_is_call(kind: crate::Vm::AccountAccessKind) -> bool { matches!( kind, crate::Vm::AccountAccessKind::Call @@ -2601,29 +2673,61 @@ fn append_storage_access( } } +/// Returns the [`spec::Cheatcode`] definition for a given [`spec::CheatcodeDef`] implementor. +const fn cheatcode_of(_: &T) -> &'static spec::Cheatcode<'static> { + T::CHEATCODE +} + +fn cheatcode_name(cheat: &spec::Cheatcode<'static>) -> &'static str { + cheat.func.signature.split('(').next().unwrap() +} + +const fn cheatcode_id(cheat: &spec::Cheatcode<'static>) -> &'static str { + cheat.func.id +} + +const fn cheatcode_signature(cheat: &spec::Cheatcode<'static>) -> &'static str { + cheat.func.signature +} + /// Dispatches the cheatcode call to the appropriate function. -fn apply_dispatch( +fn apply_dispatch( calls: &Vm::VmCalls, - ccx: &mut CheatsCtxt, - executor: &mut dyn CheatcodesExecutor, + ccx: &mut CheatsCtxt<'_, '_, FEN>, + executor: &mut dyn CheatcodesExecutor, ) -> Result { - let cheat = calls_as_dyn_cheatcode(calls); + // Extract metadata for logging/deprecation via CheatcodeDef. + macro_rules! get_cheatcode { + ($($variant:ident),*) => { + match calls { + $(Vm::VmCalls::$variant(cheat) => cheatcode_of(cheat),)* + } + }; + } + let cheat = vm_calls!(get_cheatcode); - let _guard = debug_span!(target: "cheatcodes", "apply", id = %cheat.id()).entered(); - trace!(target: "cheatcodes", ?cheat, "applying"); + let _guard = debug_span!(target: "cheatcodes", "apply", id = %cheatcode_id(cheat)).entered(); + trace!(target: "cheatcodes", cheat = %cheatcode_signature(cheat), "applying"); - if let spec::Status::Deprecated(replacement) = *cheat.status() { - ccx.state.deprecated.insert(cheat.signature(), replacement); + if let spec::Status::Deprecated(replacement) = cheat.status { + ccx.state.deprecated.insert(cheatcode_signature(cheat), replacement); } - // Apply the cheatcode. - let mut result = cheat.dyn_apply(ccx, executor); + // Monomorphized dispatch: calls apply_full directly, no trait objects. + macro_rules! dispatch { + ($($variant:ident),*) => { + match calls { + $(Vm::VmCalls::$variant(cheat) => Cheatcode::apply_full(cheat, ccx, executor),)* + } + }; + } + let mut result = vm_calls!(dispatch); // Format the error message to include the cheatcode name. if let Err(e) = &mut result && e.is_str() { - let name = cheat.name(); + let name = cheatcode_name(cheat); // Skip showing the cheatcode name for: // - assertions: too verbose, and can already be inferred from the error message // - `rpcUrl`: forge-std relies on it in `getChainWithUpdatedRpcUrl` @@ -2643,19 +2747,8 @@ fn apply_dispatch( result } -fn calls_as_dyn_cheatcode(calls: &Vm::VmCalls) -> &dyn DynCheatcode { - macro_rules! as_dyn { - ($($variant:ident),*) => { - match calls { - $(Vm::VmCalls::$variant(cheat) => cheat,)* - } - }; - } - vm_calls!(as_dyn) -} - /// Helper function to check if frame execution will exit. -fn will_exit(action: &InterpreterAction) -> bool { +const fn will_exit(action: &InterpreterAction) -> bool { match action { InterpreterAction::Return(result) => { result.result.is_ok_or_revert() || result.result.is_error() diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index cc3c07862af0b..d06c8850bb9d3 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -74,9 +74,13 @@ pub mod credible; #[cfg(not(feature = "credible"))] mod credible_stub { use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; + use foundry_evm_core::evm::FoundryEvmNetwork; impl Cheatcode for assertionCall { - fn apply_stateful(&self, _ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful( + &self, + _ccx: &mut CheatsCtxt<'_, '_, FEN>, + ) -> Result { bail!( "vm.assertion() requires Phylax-built forge with the `credible` feature enabled. \ Install from: https://github.com/phylaxsystems/phoundry" diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index cb061f856b608..5c5fe29c3154c 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -1,31 +1,35 @@ //! Foundry's main executor backend abstraction and implementation. use crate::{ - AsEnvMut, Env, EnvMut, InspectorExt, + FoundryBlock, FoundryInspectorExt, FoundryTransaction, FromAnyRpcTransaction, constants::{CALLER, CHEATCODE_ADDRESS, DEFAULT_CREATE2_DEPLOYER, TEST_CONTRACT_ADDRESS}, - evm::new_evm_with_inspector, + evm::{ + BlockEnvFor, EthEvmNetwork, EvmEnvFor, FoundryContextFor, FoundryEvmFactory, + FoundryEvmNetwork, HaltReasonFor, PrecompilesFor, SpecFor, TxEnvFor, + }, fork::{CreateFork, ForkId, MultiFork}, state_snapshot::StateSnapshots, - utils::{configure_tx_env, configure_tx_req_env, get_blob_base_fee_update_fraction_by_spec_id}, + utils::get_blob_base_fee_update_fraction, }; -use alloy_consensus::Typed2718; -use alloy_evm::Evm; +use alloy_consensus::{BlockHeader, Typed2718}; +use alloy_evm::{Evm, EvmEnv, EvmFactory}; use alloy_genesis::GenesisAccount; -use alloy_network::{AnyRpcBlock, AnyTxEnvelope, TransactionResponse}; +use alloy_network::{ + AnyNetwork, AnyRpcBlock, AnyRpcTransaction, BlockResponse, Network, TransactionResponse, +}; use alloy_primitives::{Address, B256, TxKind, U256, keccak256, uint}; -use alloy_rpc_types::{BlockNumberOrTag, Transaction, TransactionRequest}; +use alloy_rpc_types::BlockNumberOrTag; use eyre::Context; use foundry_common::{SYSTEM_TRANSACTION_TYPE, is_known_system_sender}; -pub use foundry_fork_db::{BlockchainDb, SharedBackend, cache::BlockchainDbMeta}; +pub use foundry_fork_db::{BlockchainDb, ForkBlockEnv, SharedBackend, cache::BlockchainDbMeta}; +use itertools::Itertools; use revm::{ Database, DatabaseCommit, JournalEntry, bytecode::Bytecode, - context::JournalInner, - context_interface::{block::BlobExcessGasAndPrice, result::ResultAndState}, - database::{CacheDB, DatabaseRef}, - inspector::NoOpInspector, - precompile::{PrecompileSpecId, Precompiles}, - primitives::{HashMap as Map, KECCAK_EMPTY, Log, hardfork::SpecId}, + context::{Block, BlockEnv, CfgEnv, ContextTr, JournalInner, Transaction}, + context_interface::{journaled_state::account::JournaledAccountTr, result::ResultAndState}, + database::{CacheDB, DatabaseRef, EmptyDB}, + primitives::{AddressMap, HashMap as Map, KECCAK_EMPTY, Log}, state::{Account, AccountInfo, EvmState, EvmStorageSlot}, }; use std::{ @@ -50,7 +54,7 @@ mod snapshot; pub use snapshot::{BackendStateSnapshot, RevertStateSnapshotAction, StateSnapshot}; // A `revm::Database` that is used in forking mode -type ForkDB = CacheDB; +type ForkDB = CacheDB>; /// Represents a numeric `ForkId` valid only for the existence of the `Backend`. /// @@ -77,13 +81,19 @@ pub type JournaledState = JournalInner; /// An extension trait that allows us to easily extend the `revm::Inspector` capabilities #[auto_impl::auto_impl(&mut)] -pub trait DatabaseExt: Database + DatabaseCommit + Debug + Send { +pub trait DatabaseExt: + Database + DatabaseCommit + Debug +{ /// Creates a new state snapshot at the current point of execution. /// /// A state snapshot is associated with a new unique id that's created for the snapshot. /// State snapshots can be reverted: [DatabaseExt::revert_state], however, depending on the /// [RevertStateSnapshotAction], it will keep the snapshot alive or delete it. - fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &mut EnvMut<'_>) -> U256; + fn snapshot_state( + &mut self, + journaled_state: &JournaledState, + evm_env: &EvmEnv, + ) -> U256; /// Reverts the snapshot if it exists /// @@ -93,15 +103,16 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug /// **N.B.** While this reverts the state of the evm to the snapshot, it keeps new logs made /// since the snapshots was created. This way we can show logs that were emitted between /// snapshot and its revert. - /// This will also revert any changes in the `Env` and replace it with the captured `Env` of - /// `Self::snapshot_state`. + /// This will also revert any changes in the `EvmEnv` and `TxEnv` and replace them with the + /// captured values from `Self::snapshot_state`. /// /// Depending on [RevertStateSnapshotAction] it will keep the snapshot alive or delete it. fn revert_state( &mut self, id: U256, journaled_state: &JournaledState, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnv, + caller: Address, action: RevertStateSnapshotAction, ) -> Option; @@ -120,11 +131,12 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug fn create_select_fork( &mut self, fork: CreateFork, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnv, + tx_env: &mut F::Tx, journaled_state: &mut JournaledState, ) -> eyre::Result { let id = self.create_fork(fork)?; - self.select_fork(id, env, journaled_state)?; + self.select_fork(id, evm_env, tx_env, journaled_state)?; Ok(id) } @@ -134,12 +146,13 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug fn create_select_fork_at_transaction( &mut self, fork: CreateFork, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnv, + tx_env: &mut F::Tx, journaled_state: &mut JournaledState, transaction: B256, ) -> eyre::Result { let id = self.create_fork_at_transaction(fork, transaction)?; - self.select_fork(id, env, journaled_state)?; + self.select_fork(id, evm_env, tx_env, journaled_state)?; Ok(id) } @@ -155,7 +168,7 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug /// Selects the fork's state /// - /// This will also modify the current `Env`. + /// This will also modify the current `EvmEnv` and `TxEnv`. /// /// **Note**: this does not change the local state, but swaps the remote state /// @@ -165,7 +178,8 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug fn select_fork( &mut self, id: LocalForkId, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnv, + tx_env: &mut F::Tx, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -180,7 +194,7 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug &mut self, id: Option, block_number: u64, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnv, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -196,7 +210,7 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug &mut self, id: Option, transaction: B256, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnv, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -205,18 +219,18 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug &mut self, id: Option, transaction: B256, - env: Env, + evm_env: EvmEnv, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn for<'db> FoundryInspectorExt>, ) -> eyre::Result<()>; /// Executes a given TransactionRequest, commits the new state to the DB fn transact_from_tx( &mut self, - transaction: &TransactionRequest, - env: Env, + tx_env: F::Tx, + evm_env: EvmEnv, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn for<'db> FoundryInspectorExt>, ) -> eyre::Result<()>; /// Returns the `ForkId` that's currently used in the database, if fork mode is on @@ -271,11 +285,7 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug /// the contract is deployed there. /// /// Returns a more useful error message if that's the case - fn diagnose_revert( - &self, - callee: Address, - journaled_state: &JournaledState, - ) -> Option; + fn diagnose_revert(&self, callee: Address, evm_state: &EvmState) -> Option; /// Loads the account allocs from the given `allocs` map into the passed [JournaledState]. /// @@ -377,8 +387,6 @@ pub trait DatabaseExt: Database + DatabaseCommit + Debug fn set_blockhash(&mut self, block_number: U256, block_hash: B256); } -struct _ObjectSafe(dyn DatabaseExt); - /// Provides the underlying `revm::Database` implementation. /// /// A `Backend` can be initialised in two forms: @@ -411,7 +419,7 @@ struct _ObjectSafe(dyn DatabaseExt); /// Multiple "forks" can be created `Backend::create_fork()`, however only 1 can be used by the /// `db`. However, their state can be hot-swapped by swapping the read half of `db` from one fork to /// another. -/// When swapping forks (`Backend::select_fork()`) we also update the current `Env` of the `EVM` +/// When swapping forks (`Backend::select_fork()`) we also update the current `EvmEnv` of the `EVM` /// accordingly, so that all `block.*` config values match /// /// When another for is selected [`DatabaseExt::select_fork()`] the entire storage, including @@ -431,11 +439,10 @@ struct _ObjectSafe(dyn DatabaseExt); /// **Note:** State snapshots work across fork-swaps, e.g. if fork `A` is currently active, then a /// snapshot is created before fork `B` is selected, then fork `A` will be the active fork again /// after reverting the snapshot. -#[derive(Clone, Debug)] #[must_use] -pub struct Backend { +pub struct Backend { /// The access point for managing forks - forks: MultiFork, + forks: MultiFork, BlockEnvFor>, // The default in memory db mem_db: FoundryEvmInMemoryDB, /// The journaled_state to use to initialize new forks with @@ -460,16 +467,40 @@ pub struct Backend { /// If this is set, then the Backend is currently in forking mode active_fork_ids: Option<(LocalForkId, ForkLookupIndex)>, /// holds additional Backend data - inner: BackendInner, + inner: BackendInner, } -impl Backend { +impl Clone for Backend { + fn clone(&self) -> Self { + Self { + forks: self.forks.clone(), + mem_db: self.mem_db.clone(), + fork_init_journaled_state: self.fork_init_journaled_state.clone(), + active_fork_ids: self.active_fork_ids, + inner: self.inner.clone(), + } + } +} + +impl Debug for Backend { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Backend") + .field("forks", &self.forks) + .field("mem_db", &self.mem_db) + .field("fork_init_journaled_state", &self.fork_init_journaled_state) + .field("active_fork_ids", &self.active_fork_ids) + .field("inner", &self.inner) + .finish() + } +} + +impl Backend { /// Creates a new Backend with a spawned multi fork thread. /// /// If `fork` is `Some` this will use a `fork` database, otherwise with an in-memory /// database. pub fn spawn(fork: Option) -> eyre::Result { - Self::new(MultiFork::spawn(), fork) + Self::new(MultiFork::, BlockEnvFor>::spawn(), fork) } /// Creates a new instance of `Backend` @@ -478,7 +509,10 @@ impl Backend { /// database. /// /// Prefer using [`spawn`](Self::spawn) instead. - pub fn new(forks: MultiFork, fork: Option) -> eyre::Result { + pub fn new( + forks: MultiFork, BlockEnvFor>, + fork: Option, + ) -> eyre::Result { trace!(target: "backend", forking_mode=?fork.is_some(), "creating executor backend"); // Note: this will take of registering the `fork` let inner = BackendInner { @@ -515,7 +549,7 @@ impl Backend { /// as active pub(crate) fn new_with_fork( id: &ForkId, - fork: Fork, + fork: Fork>, journaled_state: JournaledState, ) -> eyre::Result { let mut backend = Self::spawn(None)?; @@ -568,16 +602,23 @@ impl Backend { storage: Map, ) -> Result<(), DatabaseError> { if let Some(db) = self.active_fork_db_mut() { - db.replace_account_storage(address, storage) + db.replace_account_storage(address, storage.into_iter().collect()) } else { - self.mem_db.replace_account_storage(address, storage) + self.mem_db.replace_account_storage(address, storage.into_iter().collect()) } } /// Returns all snapshots created in this backend - pub fn state_snapshots( + #[allow(clippy::type_complexity)] + pub const fn state_snapshots( &self, - ) -> &StateSnapshots> { + ) -> &StateSnapshots< + BackendStateSnapshot< + BackendDatabaseSnapshot>, + SpecFor, + BlockEnvFor, + >, + > { &self.inner.state_snapshots } @@ -589,8 +630,8 @@ impl Backend { /// This will also grant cheatcode access to the test account pub fn set_test_contract(&mut self, acc: Address) -> &mut Self { trace!(?acc, "setting test account"); - self.add_persistent_account(acc); - self.allow_cheatcode_access(acc); + self.inner.persistent_accounts.insert(acc); + self.inner.cheatcode_access_accounts.insert(acc); self } @@ -598,19 +639,18 @@ impl Backend { pub fn set_caller(&mut self, acc: Address) -> &mut Self { trace!(?acc, "setting caller account"); self.inner.caller = Some(acc); - self.allow_cheatcode_access(acc); + self.inner.cheatcode_access_accounts.insert(acc); self } /// Sets the current spec id - pub fn set_spec_id(&mut self, spec_id: SpecId) -> &mut Self { - trace!(?spec_id, "setting spec ID"); - self.inner.spec_id = spec_id; + pub fn set_spec_id(&mut self, spec_id: impl Into>) -> &mut Self { + self.inner.spec_id = spec_id.into(); self } /// Returns the set caller address - pub fn caller_address(&self) -> Option
{ + pub const fn caller_address(&self) -> Option
{ self.inner.caller } @@ -619,12 +659,12 @@ impl Backend { /// If an error occurs in a restored state snapshot, the test is considered failed. /// /// This returns whether there was a reverted state snapshot that recorded an error. - pub fn has_state_snapshot_failure(&self) -> bool { + pub const fn has_state_snapshot_failure(&self) -> bool { self.inner.has_state_snapshot_failure } /// Sets the state snapshot failure flag. - pub fn set_state_snapshot_failure(&mut self, has_state_snapshot_failure: bool) { + pub const fn set_state_snapshot_failure(&mut self, has_state_snapshot_failure: bool) { self.inner.has_state_snapshot_failure = has_state_snapshot_failure } @@ -632,7 +672,7 @@ impl Backend { pub(crate) fn update_fork_db( &self, active_journaled_state: &mut JournaledState, - target_fork: &mut Fork, + target_fork: &mut Fork>, ) { self.update_fork_db_contracts( self.inner.persistent_accounts.iter().copied(), @@ -646,7 +686,7 @@ impl Backend { &self, accounts: impl IntoIterator, active_journaled_state: &mut JournaledState, - target_fork: &mut Fork, + target_fork: &mut Fork>, ) { if let Some(db) = self.active_fork_db() { merge_account_data(accounts, db, active_journaled_state, target_fork) @@ -656,7 +696,7 @@ impl Backend { } /// Returns the memory db used if not in forking mode - pub fn mem_db(&self) -> &FoundryEvmInMemoryDB { + pub const fn mem_db(&self) -> &FoundryEvmInMemoryDB { &self.mem_db } @@ -671,22 +711,22 @@ impl Backend { } /// Returns the currently active `Fork`, if any - pub fn active_fork(&self) -> Option<&Fork> { + pub fn active_fork(&self) -> Option<&Fork>> { self.active_fork_ids.map(|(_, idx)| self.inner.get_fork(idx)) } /// Returns the currently active `Fork`, if any - pub fn active_fork_mut(&mut self) -> Option<&mut Fork> { + pub fn active_fork_mut(&mut self) -> Option<&mut Fork>> { self.active_fork_ids.map(|(_, idx)| self.inner.get_fork_mut(idx)) } /// Returns the currently active `ForkDB`, if any - pub fn active_fork_db(&self) -> Option<&ForkDB> { + pub fn active_fork_db(&self) -> Option<&ForkDB>> { self.active_fork().map(|f| &f.db) } /// Returns the currently active `ForkDB`, if any - pub fn active_fork_db_mut(&mut self) -> Option<&mut ForkDB> { + pub fn active_fork_db_mut(&mut self) -> Option<&mut ForkDB>> { self.active_fork_mut().map(|f| &mut f.db) } @@ -707,7 +747,9 @@ impl Backend { } /// Creates a snapshot of the currently active database - pub(crate) fn create_db_snapshot(&self) -> BackendDatabaseSnapshot { + pub(crate) fn create_db_snapshot( + &self, + ) -> BackendDatabaseSnapshot> { if let Some((id, idx)) = self.active_fork_ids { let fork = self.inner.get_fork(idx).clone(); let fork_id = self.inner.ensure_fork_id(id).cloned().expect("Exists; qed"); @@ -743,18 +785,21 @@ impl Backend { /// Initializes settings we need to keep track of. /// /// We need to track these mainly to prevent issues when switching between different evms - pub(crate) fn initialize(&mut self, env: &Env) { - self.set_caller(env.tx.caller); - self.set_spec_id(env.evm_env.cfg_env.spec); + pub(crate) fn initialize( + &mut self, + spec_id: impl Into>, + caller: Address, + tx_kind: TxKind, + ) { + self.set_caller(caller); + self.set_spec_id(spec_id); - let test_contract = match env.tx.kind { + let test_contract = match tx_kind { TxKind::Call(to) => to, TxKind::Create => { - let nonce = self - .basic_ref(env.tx.caller) - .map(|b| b.unwrap_or_default().nonce) - .unwrap_or_default(); - env.tx.caller.create(nonce) + let nonce = + self.basic_ref(caller).map(|b| b.unwrap_or_default().nonce).unwrap_or_default(); + caller.create(nonce) } }; self.set_test_contract(test_contract); @@ -765,24 +810,29 @@ impl Backend { /// Note: in case there are any cheatcodes executed that modify the environment, this will /// update the given `env` with the new values. #[instrument(name = "inspect", level = "debug", skip_all)] - pub fn inspect( + pub fn inspect FoundryInspectorExt>>( &mut self, - env: &mut Env, + evm_env: &mut EvmEnvFor, + tx_env: &mut TxEnvFor, inspector: I, - ) -> eyre::Result { - self.initialize(env); - let mut evm = crate::evm::new_evm_with_inspector(self, env.to_owned(), inspector); - - let res = evm.transact(env.tx.clone()).wrap_err("EVM error")?; + ) -> eyre::Result>> { + self.initialize(evm_env.cfg_env.spec, tx_env.caller(), tx_env.kind()); + let mut evm = FEN::EvmFactory::default().create_foundry_evm_with_inspector( + self, + evm_env.to_owned(), + inspector, + ); + let res = evm.transact(tx_env.clone()).wrap_err("EVM error")?; - *env = evm.as_env_mut().to_owned(); + *tx_env = evm.tx().clone(); + *evm_env = evm.finish().1; Ok(res) } /// Returns true if the address is a precompile pub fn is_existing_precompile(&self, addr: &Address) -> bool { - self.inner.precompiles().contains(addr) + self.inner.precompiles().addresses().contains(addr) } /// Sets the initial journaled state to use when initializing forks @@ -806,7 +856,10 @@ impl Backend { .fork_init_journaled_state .state .iter() - .filter(|(addr, _)| !self.is_existing_precompile(addr) && !self.is_persistent(addr)) + .filter(|(addr, _)| { + !self.is_existing_precompile(addr) + && !self.inner.persistent_accounts.contains(*addr) + }) .map(|(addr, _)| addr) .copied() .collect::>(); @@ -844,20 +897,20 @@ impl Backend { transaction: B256, ) -> eyre::Result<(u64, AnyRpcBlock)> { let fork = self.inner.get_fork_by_id(id)?; - let tx = fork.db.db.get_transaction(transaction)?; + let tx = fork.backend().get_transaction(transaction)?; // get the block number we need to fork - if let Some(tx_block) = tx.block_number { - let block = fork.db.db.get_full_block(tx_block)?; + if let Some(tx_block) = tx.block_number() { + let block = fork.backend().get_full_block(tx_block)?; // we need to subtract 1 here because we want the state before the transaction // was mined let fork_block = tx_block - 1; Ok((fork_block, block)) } else { - let block = fork.db.db.get_full_block(BlockNumberOrTag::Latest)?; + let block = fork.backend().get_full_block(BlockNumberOrTag::Latest)?; - let number = block.header.number; + let number = block.header().number(); Ok((number, block)) } @@ -869,57 +922,74 @@ impl Backend { pub fn replay_until( &mut self, id: LocalForkId, - mut env: Env, + evm_env: EvmEnvFor, tx_hash: B256, journaled_state: &mut JournaledState, - ) -> eyre::Result>> { + ) -> eyre::Result> { trace!(?id, ?tx_hash, "replay until transaction"); let persistent_accounts = self.inner.persistent_accounts.clone(); - let fork_id = self.ensure_fork_id(id)?.clone(); let fork = self.inner.get_fork_by_id_mut(id)?; let full_block = - fork.db.db.get_full_block(env.evm_env.block_env.number.saturating_to::())?; + fork.backend().get_full_block(evm_env.block_env.number().saturating_to::())?; - for tx in full_block.inner.transactions.txns() { - // System transactions such as on L2s don't contain any pricing info so we skip them - // otherwise this would cause reverts - if is_known_system_sender(tx.inner().inner.signer()) - || tx.ty() == SYSTEM_TRANSACTION_TYPE - { - trace!(tx=?tx.tx_hash(), "skipping system transaction"); - continue; - } + // Collect non-system transactions up to and including the target. + let txs = full_block + .transactions() + .txns() + .filter(|tx| !is_known_system_sender(tx.from()) && tx.ty() != SYSTEM_TRANSACTION_TYPE); + let mut txs_to_replay = Vec::new(); + let mut target_tx = None; + for tx in txs { if tx.tx_hash() == tx_hash { - // found the target transaction - return Ok(Some(tx.inner.clone())); + target_tx = Some(tx.clone()); + break; } - trace!(tx=?tx.tx_hash(), "committing transaction"); - - commit_transaction( - &tx.inner, - &mut env.as_env_mut(), - journaled_state, - fork, - &fork_id, - &persistent_accounts, - &mut NoOpInspector, - )?; + txs_to_replay.push(tx.clone()); } - Ok(None) + // Replay all preceding transactions using a single EVM + cloned ForkDB. + if !txs_to_replay.is_empty() { + let now = Instant::now(); + + // Clone the fork's CacheDB once. The underlying SharedBackend is Arc-backed, + // so only the local cache layer is actually duplicated. + let replay_db = fork.db.clone(); + let mut evm = FEN::EvmFactory::default().create_evm(replay_db, evm_env); + + for tx in &txs_to_replay { + let tx_env = TxEnvFor::::from_any_rpc_transaction(tx)?; + trace!(tx=?tx.tx_hash(), "committing transaction"); + evm.transact_commit(tx_env).wrap_err("backend: failed committing transaction")?; + } + + // Extract the DB back and replace the fork's database with the replayed state. + fork.db = evm.into_db(); + + // Refresh journaled states from the updated database, preserving persistent + // accounts (cheatcode address, CREATE2 deployer, test contract, etc.). + fork.refresh_journaled_states(journaled_state, &persistent_accounts)?; + + trace!(elapsed=?now.elapsed(), count=txs_to_replay.len(), "replayed transactions"); + } + + Ok(target_tx) } } -impl DatabaseExt for Backend { - fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &mut EnvMut<'_>) -> U256 { +impl DatabaseExt for Backend { + fn snapshot_state( + &mut self, + journaled_state: &JournaledState, + evm_env: &EvmEnvFor, + ) -> U256 { trace!("create snapshot"); let id = self.inner.state_snapshots.insert(BackendStateSnapshot::new( self.create_db_snapshot(), journaled_state.clone(), - env.to_owned(), + evm_env.clone(), )); trace!(target: "backend", "Created new snapshot {}", id); id @@ -929,7 +999,8 @@ impl DatabaseExt for Backend { &mut self, id: U256, current_state: &JournaledState, - current: &mut EnvMut<'_>, + evm_env: &mut EvmEnvFor, + caller: Address, action: RevertStateSnapshotAction, ) -> Option { trace!(?id, "revert snapshot"); @@ -952,7 +1023,7 @@ impl DatabaseExt for Backend { // merge additional logs snapshot.merge(current_state); - let BackendStateSnapshot { db, mut journaled_state, env } = snapshot; + let BackendStateSnapshot { db, mut journaled_state, snap_evm_env } = snapshot; match db { BackendDatabaseSnapshot::InMemory(mem_db) => { self.mem_db = mem_db; @@ -961,7 +1032,6 @@ impl DatabaseExt for Backend { // there might be the case where the snapshot was created during `setUp` with // another caller, so we need to ensure the caller account is present in the // journaled state and database - let caller = current.tx.caller; journaled_state.state.entry(caller).or_insert_with(|| { let caller_account = current_state .state @@ -980,7 +1050,7 @@ impl DatabaseExt for Backend { } } - update_current_env_with_fork_env(&mut current.as_env_mut(), env); + *evm_env = snap_evm_env; trace!(target: "backend", "Reverted snapshot {}", id); Some(journaled_state) @@ -1016,9 +1086,9 @@ impl DatabaseExt for Backend { trace!(?transaction, "create fork at transaction"); let id = self.create_fork(fork)?; let fork_id = self.ensure_fork_id(id).cloned()?; - let mut env = self + let mut evm_env = self .forks - .get_env(fork_id)? + .get_evm_env(fork_id)? .ok_or_else(|| eyre::eyre!("Requested fork `{}` does not exist", id))?; // we still need to roll to the transaction, but we only need an empty dummy state since we @@ -1026,7 +1096,7 @@ impl DatabaseExt for Backend { self.roll_fork_to_transaction( Some(id), transaction, - &mut env.as_env_mut(), + &mut evm_env, &mut self.inner.new_journaled_state(), )?; @@ -1038,7 +1108,8 @@ impl DatabaseExt for Backend { fn select_fork( &mut self, id: LocalForkId, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnvFor, + tx_env: &mut TxEnvFor, active_journaled_state: &mut JournaledState, ) -> eyre::Result<()> { trace!(?id, "select fork"); @@ -1052,16 +1123,16 @@ impl DatabaseExt for Backend { if let Some(active_fork_id) = self.active_fork_id() { self.forks.update_block( self.ensure_fork_id(active_fork_id).cloned()?, - env.block.number, - env.block.timestamp, + evm_env.block_env.number(), + evm_env.block_env.timestamp(), )?; } let fork_id = self.ensure_fork_id(id).cloned()?; let idx = self.inner.ensure_fork_index(&fork_id)?; - let fork_env = self + let fork_evm_env = self .forks - .get_env(fork_id)? + .get_evm_env(fork_id)? .ok_or_else(|| eyre::eyre!("Requested fork `{}` does not exist", id))?; // If we're currently in forking mode we need to update the journaled_state to this point, @@ -1069,8 +1140,8 @@ impl DatabaseExt for Backend { if let Some(active) = self.active_fork_mut() { active.journaled_state = active_journaled_state.clone(); - let caller = env.tx.caller; - let caller_account = active.journaled_state.state.get(&env.tx.caller).cloned(); + let caller = tx_env.caller(); + let caller_account = active.journaled_state.state.get(&caller).cloned(); let target_fork = self.inner.get_fork_mut(idx); // depth 0 will be the default value when the fork was created @@ -1135,11 +1206,11 @@ impl DatabaseExt for Backend { // another edge case where a fork is created and selected during setup with not // necessarily the same caller as for the test, however we must always // ensure that fork's state contains the current sender - let caller = env.tx.caller; + let caller = tx_env.caller(); fork.journaled_state.state.entry(caller).or_insert_with(|| { let caller_account = active_journaled_state .state - .get(&env.tx.caller) + .get(&caller) .map(|acc| acc.info.clone()) .unwrap_or_default(); @@ -1158,7 +1229,8 @@ impl DatabaseExt for Backend { self.active_fork_ids = Some((id, idx)); // Update current environment with environment of newly selected fork. - update_current_env_with_fork_env(env, fork_env); + tx_env.set_chain_id(Some(fork_evm_env.cfg_env.chain_id)); + *evm_env = fork_evm_env; Ok(()) } @@ -1169,7 +1241,7 @@ impl DatabaseExt for Backend { &mut self, id: Option, block_number: u64, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnvFor, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { trace!(?id, ?block_number, "roll fork"); @@ -1184,7 +1256,7 @@ impl DatabaseExt for Backend { if active_id == id { // need to update the block's env settings right away, which is otherwise set when // forks are selected `select_fork` - update_current_env_with_fork_env(env, fork_env); + *evm_env = fork_env; // we also need to update the journaled_state right away, this has essentially the // same effect as selecting (`select_fork`) by discarding @@ -1233,7 +1305,7 @@ impl DatabaseExt for Backend { &mut self, id: Option, transaction: B256, - env: &mut EnvMut<'_>, + evm_env: &mut EvmEnvFor, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { trace!(?id, ?transaction, "roll fork to transaction"); @@ -1245,20 +1317,19 @@ impl DatabaseExt for Backend { // roll the fork to the transaction's parent block or latest if it's pending, because we // need to fork off the parent block's state for tx level forking and then replay the txs // before the tx in that block to get the state at the tx - self.roll_fork(Some(id), fork_block, env, journaled_state)?; + self.roll_fork(Some(id), fork_block, evm_env, journaled_state)?; // we need to update the env to the block - update_env_block(env, &block); + update_env_block(evm_env, block.header()); // after we forked at the fork block we need to properly update the block env to the block // env of the tx's block - let _ = - self.forks.update_block_env(self.inner.ensure_fork_id(id).cloned()?, env.block.clone()); - - let env = env.to_owned(); + let _ = self + .forks + .update_block_env(self.inner.ensure_fork_id(id).cloned()?, evm_env.block_env.clone()); // replay all transactions that came before - self.replay_until(id, env, transaction, journaled_state)?; + self.replay_until(id, evm_env.clone(), transaction, journaled_state)?; Ok(()) } @@ -1267,9 +1338,11 @@ impl DatabaseExt for Backend { &mut self, maybe_id: Option, transaction: B256, - mut env: Env, + mut evm_env: EvmEnvFor, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn for<'db> FoundryInspectorExt< + ::FoundryContext<'db>, + >, ) -> eyre::Result<()> { trace!(?maybe_id, ?transaction, "execute transaction"); let persistent_accounts = self.inner.persistent_accounts.clone(); @@ -1278,8 +1351,9 @@ impl DatabaseExt for Backend { let tx = { let fork = self.inner.get_fork_by_id_mut(id)?; - fork.db.db.get_transaction(transaction)? + fork.backend().get_transaction(transaction)? }; + let tx_env = TxEnvFor::::from_any_rpc_transaction(&tx)?; // This is a bit ambiguous because the user wants to transact an arbitrary transaction in // the current context, but we're assuming the user wants to transact the transaction as it @@ -1289,12 +1363,12 @@ impl DatabaseExt for Backend { // So we modify the env to match the transaction's block. let (_fork_block, block) = self.get_block_number_and_block_for_transaction(id, transaction)?; - update_env_block(&mut env.as_env_mut(), &block); + update_env_block(&mut evm_env, block.header()); let fork = self.inner.get_fork_by_id_mut(id)?; - commit_transaction( - &tx.inner, - &mut env.as_env_mut(), + commit_transaction::( + evm_env, + tx_env, journaled_state, fork, &fork_id, @@ -1305,22 +1379,24 @@ impl DatabaseExt for Backend { fn transact_from_tx( &mut self, - tx: &TransactionRequest, - mut env: Env, + tx_env: TxEnvFor, + evm_env: EvmEnvFor, journaled_state: &mut JournaledState, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn for<'db> FoundryInspectorExt< + ::FoundryContext<'db>, + >, ) -> eyre::Result<()> { - trace!(?tx, "execute signed transaction"); + trace!("execute signed transaction"); self.commit(journaled_state.state.clone()); let res = { - configure_tx_req_env(&mut env.as_env_mut(), tx, None)?; - let mut db = self.clone(); - let mut evm = new_evm_with_inspector(&mut db, env.to_owned(), inspector); - evm.journaled_state.depth = journaled_state.depth + 1; - evm.transact(env.tx)? + let depth = journaled_state.depth + 1; + let mut evm = + FEN::EvmFactory::default().create_foundry_nested_evm(&mut db, evm_env, inspector); + evm.journal_inner_mut().depth = depth; + evm.transact_raw(tx_env)? }; self.commit(res.state); @@ -1352,11 +1428,7 @@ impl DatabaseExt for Backend { self.inner.ensure_fork_id(id) } - fn diagnose_revert( - &self, - callee: Address, - journaled_state: &JournaledState, - ) -> Option { + fn diagnose_revert(&self, callee: Address, evm_state: &EvmState) -> Option { let active_id = self.active_fork_id()?; let active_fork = self.active_fork()?; @@ -1366,7 +1438,7 @@ impl DatabaseExt for Backend { return None; } - if !active_fork.is_contract(callee) && !is_contract_in_state(journaled_state, callee) { + if !active_fork.is_contract(callee) && !is_contract_in_state(evm_state, callee) { // no contract for `callee` available on current fork, check if available on other forks let mut available_on = Vec::new(); for (id, fork) in self.inner.forks_iter().filter(|(id, _)| *id != active_id) { @@ -1498,7 +1570,7 @@ impl DatabaseExt for Backend { } } -impl DatabaseRef for Backend { +impl DatabaseRef for Backend { type Error = DatabaseError; fn basic_ref(&self, address: Address) -> Result, Self::Error> { @@ -1534,8 +1606,8 @@ impl DatabaseRef for Backend { } } -impl DatabaseCommit for Backend { - fn commit(&mut self, changes: Map) { +impl DatabaseCommit for Backend { + fn commit(&mut self, changes: AddressMap) { if let Some(db) = self.active_fork_db_mut() { db.commit(changes) } else { @@ -1544,7 +1616,7 @@ impl DatabaseCommit for Backend { } } -impl Database for Backend { +impl Database for Backend { type Error = DatabaseError; fn basic(&mut self, address: Address) -> Result, Self::Error> { if let Some(db) = self.active_fork_db_mut() { @@ -1581,21 +1653,26 @@ impl Database for Backend { /// Variants of a [revm::Database] #[derive(Clone, Debug)] -pub enum BackendDatabaseSnapshot { +pub enum BackendDatabaseSnapshot { /// Simple in-memory [revm::Database] InMemory(FoundryEvmInMemoryDB), /// Contains the entire forking mode database - Forked(LocalForkId, ForkId, ForkLookupIndex, Box), + Forked(LocalForkId, ForkId, ForkLookupIndex, Box>), } /// Represents a fork #[derive(Clone, Debug)] -pub struct Fork { - db: ForkDB, +pub struct Fork { + db: ForkDB, journaled_state: JournaledState, } -impl Fork { +impl Fork { + /// Returns a reference to the underlying [`SharedBackend`]. + pub const fn backend(&self) -> &SharedBackend { + &self.db.db + } + /// Returns true if the account is a contract pub fn is_contract(&self, acc: Address) -> bool { if let Ok(Some(acc)) = self.db.basic_ref(acc) @@ -1603,13 +1680,24 @@ impl Fork { { return true; } - is_contract_in_state(&self.journaled_state, acc) + is_contract_in_state(&self.journaled_state.state, acc) + } + + /// Refreshes the given journaled state and the fork's own journaled state from the + /// database, preserving persistent accounts. + fn refresh_journaled_states( + &mut self, + journaled_state: &mut JournaledState, + persistent_accounts: &HashSet
, + ) -> Result<(), BackendError> { + update_state(&mut journaled_state.state, &mut self.db, Some(persistent_accounts))?; + update_state(&mut self.journaled_state.state, &mut self.db, Some(persistent_accounts))?; + Ok(()) } } /// Container type for various Backend related data -#[derive(Clone, Debug)] -pub struct BackendInner { +pub struct BackendInner { /// Stores the `ForkId` of the fork the `Backend` launched with from the start. /// /// In other words if [`Backend::spawn()`] was called with a `CreateFork` command, to launch @@ -1632,9 +1720,16 @@ pub struct BackendInner { pub created_forks: HashMap, /// Holds all created fork databases // Note: data is stored in an `Option` so we can remove it without reshuffling - pub forks: Vec>, + pub forks: Vec>>>, /// Contains state snapshots made at a certain point - pub state_snapshots: StateSnapshots>, + #[allow(clippy::type_complexity)] + pub state_snapshots: StateSnapshots< + BackendStateSnapshot< + BackendDatabaseSnapshot>, + SpecFor, + BlockEnvFor, + >, + >, /// Tracks whether there was a failure in a snapshot that was reverted /// /// The Test contract contains a bool variable that is set to true when an `assert` function @@ -1654,12 +1749,48 @@ pub struct BackendInner { /// instead the use only one that's persistent across fork swaps. pub persistent_accounts: HashSet
, /// The configured spec id - pub spec_id: SpecId, + pub spec_id: SpecFor, /// All accounts that are allowed to execute cheatcodes pub cheatcode_access_accounts: HashSet
, } -impl BackendInner { +impl Clone for BackendInner { + fn clone(&self) -> Self { + Self { + launched_with_fork: self.launched_with_fork.clone(), + issued_local_fork_ids: self.issued_local_fork_ids.clone(), + created_forks: self.created_forks.clone(), + forks: self.forks.clone(), + state_snapshots: self.state_snapshots.clone(), + has_state_snapshot_failure: self.has_state_snapshot_failure, + caller: self.caller, + next_fork_id: self.next_fork_id, + persistent_accounts: self.persistent_accounts.clone(), + spec_id: self.spec_id, + cheatcode_access_accounts: self.cheatcode_access_accounts.clone(), + } + } +} + +impl Debug for BackendInner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("BackendInner") + .field("launched_with_fork", &self.launched_with_fork) + .field("issued_local_fork_ids", &self.issued_local_fork_ids) + .field("created_forks", &self.created_forks) + .field("forks", &self.forks) + .field("state_snapshots", &self.state_snapshots) + .field("has_state_snapshot_failure", &self.has_state_snapshot_failure) + .field("caller", &self.caller) + .field("next_fork_id", &self.next_fork_id) + .field("persistent_accounts", &self.persistent_accounts) + .field("spec_id", &self.spec_id) + .field("cheatcode_access_accounts", &self.cheatcode_access_accounts) + .finish() + } +} + +impl BackendInner { pub fn ensure_fork_id(&self, id: LocalForkId) -> eyre::Result<&ForkId> { self.issued_local_fork_ids .get(&id) @@ -1679,51 +1810,58 @@ impl BackendInner { /// Returns the underlying fork mapped to the index #[track_caller] - fn get_fork(&self, idx: ForkLookupIndex) -> &Fork { + fn get_fork(&self, idx: ForkLookupIndex) -> &Fork> { debug_assert!(idx < self.forks.len(), "fork lookup index must exist"); self.forks[idx].as_ref().unwrap() } /// Returns the underlying fork mapped to the index #[track_caller] - fn get_fork_mut(&mut self, idx: ForkLookupIndex) -> &mut Fork { + fn get_fork_mut(&mut self, idx: ForkLookupIndex) -> &mut Fork> { debug_assert!(idx < self.forks.len(), "fork lookup index must exist"); self.forks[idx].as_mut().unwrap() } /// Returns the underlying fork corresponding to the id #[track_caller] - fn get_fork_by_id_mut(&mut self, id: LocalForkId) -> eyre::Result<&mut Fork> { + fn get_fork_by_id_mut( + &mut self, + id: LocalForkId, + ) -> eyre::Result<&mut Fork>> { let idx = self.ensure_fork_index_by_local_id(id)?; Ok(self.get_fork_mut(idx)) } /// Returns the underlying fork corresponding to the id #[track_caller] - fn get_fork_by_id(&self, id: LocalForkId) -> eyre::Result<&Fork> { + fn get_fork_by_id(&self, id: LocalForkId) -> eyre::Result<&Fork>> { let idx = self.ensure_fork_index_by_local_id(id)?; Ok(self.get_fork(idx)) } /// Removes the fork - fn take_fork(&mut self, idx: ForkLookupIndex) -> Fork { + fn take_fork(&mut self, idx: ForkLookupIndex) -> Fork> { debug_assert!(idx < self.forks.len(), "fork lookup index must exist"); self.forks[idx].take().unwrap() } - fn set_fork(&mut self, idx: ForkLookupIndex, fork: Fork) { + fn set_fork(&mut self, idx: ForkLookupIndex, fork: Fork>) { self.forks[idx] = Some(fork) } /// Returns an iterator over Forks - pub fn forks_iter(&self) -> impl Iterator + '_ { + pub fn forks_iter( + &self, + ) -> impl Iterator>)> + '_ { self.issued_local_fork_ids .iter() .map(|(id, fork_id)| (*id, self.get_fork(self.created_forks[fork_id]))) } /// Returns a mutable iterator over all Forks - pub fn forks_iter_mut(&mut self) -> impl Iterator + '_ { + pub fn forks_iter_mut( + &mut self, + ) -> impl Iterator>> + '_ { self.forks.iter_mut().filter_map(|f| f.as_mut()) } @@ -1733,7 +1871,7 @@ impl BackendInner { id: LocalForkId, fork_id: ForkId, idx: ForkLookupIndex, - fork: Fork, + fork: Fork>, ) { self.created_forks.insert(fork_id.clone(), idx); self.issued_local_fork_ids.insert(id, fork_id); @@ -1745,7 +1883,7 @@ impl BackendInner { &mut self, id: LocalForkId, fork_id: ForkId, - db: ForkDB, + db: ForkDB>, journaled_state: JournaledState, ) -> ForkLookupIndex { let idx = self.forks.len(); @@ -1761,7 +1899,7 @@ impl BackendInner { &mut self, id: LocalForkId, new_fork_id: ForkId, - backend: SharedBackend, + backend: SharedBackend>, ) -> eyre::Result { let fork_id = self.ensure_fork_id(id)?; let idx = self.ensure_fork_index(fork_id)?; @@ -1786,7 +1924,7 @@ impl BackendInner { pub fn insert_new_fork( &mut self, fork_id: ForkId, - db: ForkDB, + db: ForkDB>, journaled_state: JournaledState, ) -> (LocalForkId, ForkLookupIndex) { let idx = self.forks.len(); @@ -1814,15 +1952,19 @@ impl BackendInner { self.issued_local_fork_ids.is_empty() } - pub fn precompiles(&self) -> &'static Precompiles { - Precompiles::new(PrecompileSpecId::from_spec_id(self.spec_id)) + pub fn precompiles(&self) -> PrecompilesFor { + let evm = FEN::EvmFactory::default().create_evm( + EmptyDB::default(), + EvmEnv::new(CfgEnv::new_with_spec(self.spec_id), Default::default()), + ); + evm.precompiles().clone() } /// Returns a new, empty, `JournaledState` with set precompiles pub fn new_journaled_state(&self) -> JournaledState { let mut journal = { let mut journal_inner = JournalInner::new(); - journal_inner.set_spec_id(self.spec_id); + journal_inner.set_spec_id(self.spec_id.into()); journal_inner }; journal @@ -1832,7 +1974,7 @@ impl BackendInner { } } -impl Default for BackendInner { +impl Default for BackendInner { fn default() -> Self { Self { launched_with_fork: None, @@ -1844,7 +1986,7 @@ impl Default for BackendInner { caller: None, next_fork_id: Default::default(), persistent_accounts: Default::default(), - spec_id: SpecId::default(), + spec_id: SpecFor::::default(), // grant the cheatcode,default test and caller address access to execute cheatcodes // itself cheatcode_access_accounts: HashSet::from([ @@ -1856,22 +1998,15 @@ impl Default for BackendInner { } } -/// This updates the currently used env with the fork's environment -pub(crate) fn update_current_env_with_fork_env(current: &mut EnvMut<'_>, fork: Env) { - *current.block = fork.evm_env.block_env; - *current.cfg = fork.evm_env.cfg_env; - current.tx.chain_id = fork.tx.chain_id; -} - /// Clones the data of the given `accounts` from the `active` database into the `fork_db` /// This includes the data held in storage (`CacheDB`) and kept in the `JournaledState`. -pub(crate) fn merge_account_data( +pub(crate) fn merge_account_data( accounts: impl IntoIterator, active: &CacheDB, active_journaled_state: &mut JournaledState, - target_fork: &mut Fork, + target_fork: &mut Fork, ) { - for addr in accounts.into_iter() { + for addr in accounts { merge_db_account_data(addr, active, &mut target_fork.db); merge_journaled_state_data(addr, active_journaled_state, &mut target_fork.journaled_state); } @@ -1898,10 +2033,10 @@ fn merge_journaled_state_data( } /// Clones the account data from the `active` db into the `ForkDB` -fn merge_db_account_data( +fn merge_db_account_data( addr: Address, active: &CacheDB, - fork_db: &mut ForkDB, + fork_db: &mut ForkDB, ) { trace!(?addr, "merging database data"); @@ -1933,56 +2068,56 @@ fn merge_db_account_data( } /// Returns true of the address is a contract -fn is_contract_in_state(journaled_state: &JournaledState, acc: Address) -> bool { - journaled_state - .state - .get(&acc) - .map(|acc| acc.info.code_hash != KECCAK_EMPTY) - .unwrap_or_default() +fn is_contract_in_state(evm_state: &EvmState, acc: Address) -> bool { + evm_state.get(&acc).map(|acc| acc.info.code_hash != KECCAK_EMPTY).unwrap_or_default() } -/// Updates the env's block with the block's data -fn update_env_block(env: &mut EnvMut<'_>, block: &AnyRpcBlock) { - env.block.timestamp = U256::from(block.header.timestamp); - env.block.beneficiary = block.header.beneficiary; - env.block.difficulty = block.header.difficulty; - env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); - env.block.basefee = block.header.base_fee_per_gas.unwrap_or_default(); - env.block.gas_limit = block.header.gas_limit; - env.block.number = U256::from(block.header.number); - - if let Some(excess_blob_gas) = block.header.excess_blob_gas { - env.block.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new( +/// Updates the evm env's block with the block's data +fn update_env_block( + evm_env: &mut EvmEnv, + header: &impl BlockHeader, +) { + let block_env = &mut evm_env.block_env; + block_env.set_timestamp(U256::from(header.timestamp())); + block_env.set_beneficiary(header.beneficiary()); + block_env.set_difficulty(header.difficulty()); + block_env.set_prevrandao(header.mix_hash()); + block_env.set_basefee(header.base_fee_per_gas().unwrap_or_default()); + block_env.set_gas_limit(header.gas_limit()); + block_env.set_number(U256::from(header.number())); + + if let Some(excess_blob_gas) = header.excess_blob_gas() { + evm_env.block_env.set_blob_excess_gas_and_price( excess_blob_gas, - get_blob_base_fee_update_fraction_by_spec_id(env.cfg.spec), - )); + get_blob_base_fee_update_fraction(evm_env.cfg_env.chain_id, header.timestamp()), + ); } } /// Executes the given transaction and commits state changes to the database _and_ the journaled /// state, with an inspector. -fn commit_transaction( - tx: &Transaction, - env: &mut EnvMut<'_>, +fn commit_transaction( + evm_env: EvmEnvFor, + tx_env: TxEnvFor, journaled_state: &mut JournaledState, - fork: &mut Fork, + fork: &mut Fork>, fork_id: &ForkId, persistent_accounts: &HashSet
, - inspector: &mut dyn InspectorExt, + inspector: &mut dyn for<'db> FoundryInspectorExt< + ::FoundryContext<'db>, + >, ) -> eyre::Result<()> { - configure_tx_env(env, tx); - let now = Instant::now(); let res = { let fork = fork.clone(); let journaled_state = journaled_state.clone(); let depth = journaled_state.depth; - let mut db = Backend::new_with_fork(fork_id, fork, journaled_state)?; + let mut db: Backend = Backend::new_with_fork(fork_id, fork, journaled_state)?; - let mut evm = crate::evm::new_evm_with_inspector(&mut db as _, env.to_owned(), inspector); - // Adjust inner EVM depth to ensure that inspectors receive accurate data. - evm.journaled_state.depth = depth + 1; - evm.transact(env.tx.clone()).wrap_err("backend: failed committing transaction")? + let mut evm = + FEN::EvmFactory::default().create_foundry_nested_evm(&mut db, evm_env, inspector); + evm.journal_inner_mut().depth = depth + 1; + evm.transact_raw(tx_env).wrap_err("backend: failed committing transaction")? }; trace!(elapsed = ?now.elapsed(), "transacted transaction"); @@ -2011,30 +2146,30 @@ pub fn update_state( /// Applies the changeset of a transaction to the active journaled state and also commits it in the /// forked db -fn apply_state_changeset( - state: Map, +fn apply_state_changeset( + state: EvmState, journaled_state: &mut JournaledState, - fork: &mut Fork, + fork: &mut Fork, persistent_accounts: &HashSet
, ) -> Result<(), BackendError> { // commit the state and update the loaded accounts fork.db.commit(state); - - update_state(&mut journaled_state.state, &mut fork.db, Some(persistent_accounts))?; - update_state(&mut fork.journaled_state.state, &mut fork.db, Some(persistent_accounts))?; - - Ok(()) + fork.refresh_journaled_states(journaled_state, persistent_accounts) } #[cfg(test)] mod tests { - use crate::{backend::Backend, fork::CreateFork, opts::EvmOpts}; + use crate::{backend::Backend, evm::EthEvmNetwork, opts::EvmOpts}; use alloy_primitives::{U256, address}; use alloy_provider::Provider; use foundry_common::provider::get_http_provider; use foundry_config::{Config, NamedChain}; use foundry_fork_db::cache::{BlockchainDb, BlockchainDbMeta}; - use revm::database::DatabaseRef; + use revm::{ + context::{BlockEnv, TxEnv}, + database::DatabaseRef, + primitives::hardfork::SpecId, + }; #[tokio::test(flavor = "multi_thread")] async fn can_read_write_cache() { @@ -2043,20 +2178,16 @@ mod tests { let block_num = provider.get_block_number().await.unwrap(); - let config = Config::figment(); - let mut evm_opts = config.extract::().unwrap(); + let mut evm_opts = Config::figment().extract::().unwrap(); + evm_opts.fork_url = Some(endpoint.to_string()); evm_opts.fork_block_number = Some(block_num); - let (env, _block) = evm_opts.fork_evm_env(endpoint).await.unwrap(); + let (evm_env, _, fork_block) = evm_opts.env::().await.unwrap(); - let fork = CreateFork { - enable_caching: true, - url: endpoint.to_string(), - env: env.clone(), - evm_opts, - }; + let fork = + evm_opts.get_fork(&Config::default(), evm_env.cfg_env.chain_id, fork_block).unwrap(); - let backend = Backend::spawn(Some(fork)).unwrap(); + let backend = Backend::::spawn(Some(fork)).unwrap(); // some rng contract from etherscan let address = address!("0x63091244180ae240c87d1f528f5f269134cb07b3"); @@ -2070,7 +2201,7 @@ mod tests { let meta = BlockchainDbMeta { chain: None, - block_env: env.evm_env.block_env, + block_env: evm_env.block_env, hosts: Default::default(), }; diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 51570c239db8f..84874f444dd4d 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -100,6 +100,13 @@ impl CallTraceDecoderBuilder { self } + /// Sets the chain ID for chain-specific precompile decoding. + #[inline] + pub fn with_chain_id(mut self, chain_id: Option) -> Self { + self.decoder.chain_id = chain_id; + self + } + /// Build the decoder. #[inline] pub fn build(self) -> CallTraceDecoder { @@ -150,6 +157,9 @@ pub struct CallTraceDecoder { /// Disable showing of labels. pub disable_labels: bool, + + /// Chain ID used for chain-specific precompile decoding. + pub chain_id: Option, } impl CallTraceDecoder { @@ -207,6 +217,7 @@ impl CallTraceDecoder { debug_identifier: None, disable_labels: false, + chain_id: None, } } @@ -381,7 +392,7 @@ impl CallTraceDecoder { return DecodedCallTrace { label, ..Default::default() }; } - if let Some(trace) = precompiles::decode(trace, 1) { + if let Some(trace) = precompiles::decode(trace, self.chain_id) { return trace; } @@ -774,7 +785,7 @@ impl CallTraceDecoder { // Ignore known addresses. if n.trace.address == DEFAULT_CREATE2_DEPLOYER || n.is_precompile() - || precompiles::is_known_precompile(n.trace.address, 1) + || precompiles::is_known_precompile(n.trace.address, self.chain_id) { return false; } From 44ba6a740f97e118a42b8df2a6c2cdbaf7171f0e Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 17:37:43 +0200 Subject: [PATCH 72/83] port credible cheatcode to generic evm context --- crates/cheatcodes/src/credible.rs | 195 ++++++++++++----------------- crates/cheatcodes/src/inspector.rs | 60 +++++++++ crates/evm/core/src/backend/mod.rs | 2 +- 3 files changed, 142 insertions(+), 115 deletions(-) diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index c172cb971c88c..493bc08648088 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -1,4 +1,4 @@ -use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*, inspector::Ecx}; +use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Bytes, FixedBytes, TxKind}; use assertion_executor::{ ExecutorConfig, @@ -9,12 +9,16 @@ use assertion_executor::{ }, store::{AssertionState, AssertionStore}, }; -use foundry_evm_core::{ContextExt, decode::RevertDecoder}; -use foundry_evm_traces::{TraceMode, TracingInspector, TracingInspectorConfig}; +use foundry_evm_core::{ + decode::RevertDecoder, + env::FoundryContextExt, + evm::{FoundryContextFor, FoundryEvmNetwork}, +}; use foundry_fork_db::DatabaseError; - -use foundry_evm_core::backend::DatabaseExt; -use revm::context_interface::{ContextTr, JournalTr}; +use revm::{ + Database, + context::{Block, BlockEnv, ContextTr, JournalTr, Transaction}, +}; use std::{ cmp::max, collections::HashSet, @@ -23,38 +27,30 @@ use std::{ use revm::primitives::eip7825::TX_GAS_LIMIT_CAP; -/// Wrapper around DatabaseExt to make it thread-safe and 'static. -/// Uses a leaked reference internally to satisfy 'static bounds required by -/// the inspector API. This is safe because the wrapper is only used within -/// a single function scope and the original database outlives this usage. -#[derive(Clone)] -struct ThreadSafeDb { - // Im fine with leaking this because it only lives for the duration - // of assex execution - db: Arc>, +/// Wrapper around DatabaseExt so assertion-executor can clone and share the active database. +struct ThreadSafeDb<'db, DB: Database + Send> { + db: Arc>, } -impl std::fmt::Debug for ThreadSafeDb { +impl + Send> Clone for ThreadSafeDb<'_, DB> { + fn clone(&self) -> Self { + Self { db: self.db.clone() } + } +} + +impl + Send> std::fmt::Debug for ThreadSafeDb<'_, DB> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "ThreadSafeDb") } } -impl ThreadSafeDb { - /// Creates a new thread-safe database wrapper by leaking the reference. - /// # Safety - /// The caller must ensure the original database outlives all uses of this wrapper. - pub fn new(db: &mut dyn DatabaseExt) -> Self { - // SAFETY: We transmute the lifetime to 'static. This is safe because: - // 1. ThreadSafeDb is only used within execute_assertion's scope - // 2. The original ecx.db_mut() outlives this entire function - // 3. We don't store ThreadSafeDb beyond this function's execution - let static_ref: &'static mut dyn DatabaseExt = unsafe { std::mem::transmute(db) }; - Self { db: Arc::new(Mutex::new(static_ref)) } +impl<'db, DB: Database + Send> ThreadSafeDb<'db, DB> { + pub fn new(db: &'db mut DB) -> Self { + Self { db: Arc::new(Mutex::new(db)) } } } -impl DatabaseRef for ThreadSafeDb { +impl + Send> DatabaseRef for ThreadSafeDb<'_, DB> { type Error = DatabaseError; fn basic_ref( @@ -82,7 +78,7 @@ impl DatabaseRef for ThreadSafeDb { } impl Cheatcode for assertionCall { - fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_stateful(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result { let Self { adopter, createData: create_data, fnSelector: fn_selector } = self; ensure!( @@ -93,7 +89,7 @@ impl Cheatcode for assertionCall { adopter: *adopter, create_data: create_data.to_vec(), fn_selector: *fn_selector, - depth: ccx.ecx.journaled_state.depth(), + depth: ccx.ecx.journal().depth(), }; ccx.state.assertion = Some(assertion); @@ -137,44 +133,64 @@ fn check_assertion_gas_limit(gas_used: u64) -> Option { fn build_tx_env( tx_attributes: TxAttributes, - base_tx_env: &TxEnv, + base_tx_env: &impl Transaction, chain_id: u64, nonce: u64, ) -> TxEnv { let tx_gas_limit = tx_attributes.gas_limit.min(TX_GAS_LIMIT_CAP); - let mut tx_env = base_tx_env.clone(); + let mut tx_env = TxEnv::default(); + tx_env.tx_type = base_tx_env.tx_type(); tx_env.caller = tx_attributes.caller; tx_env.gas_limit = tx_gas_limit; + tx_env.gas_price = base_tx_env.gas_price(); tx_env.chain_id = Some(chain_id); tx_env.value = tx_attributes.value; tx_env.data = tx_attributes.data; tx_env.kind = tx_attributes.kind; tx_env.nonce = nonce; + tx_env.gas_priority_fee = base_tx_env.max_priority_fee_per_gas(); + tx_env.blob_hashes = base_tx_env.blob_versioned_hashes().to_vec(); + tx_env.max_fee_per_blob_gas = base_tx_env.max_fee_per_blob_gas(); tx_env } +fn build_block_env(block: &impl Block) -> BlockEnv { + let mut block_env = BlockEnv::default(); + block_env.number = block.number(); + block_env.beneficiary = block.beneficiary(); + block_env.timestamp = block.timestamp(); + block_env.gas_limit = block.gas_limit(); + block_env.basefee = block.basefee(); + block_env.difficulty = block.difficulty(); + block_env.prevrandao = block.prevrandao(); + block_env.blob_excess_gas_and_price = block.blob_excess_gas_and_price(); + block_env +} + /// Used to handle assertion execution in inspector in calls after the cheatcode was called. -pub fn execute_assertion( +pub fn execute_assertion( assertion: &Assertion, tx_attributes: TxAttributes, - ecx: Ecx, - executor: &mut dyn CheatcodesExecutor, - cheats: &mut Cheatcodes, + ecx: &mut FoundryContextFor<'_, FEN>, + executor: &mut dyn CheatcodesExecutor, + cheats: &mut Cheatcodes, ) -> Result<(), crate::Error> { - let spec_id = ecx.cfg.spec; - let block = ecx.block.clone(); - let state = ecx.journaled_state.state.clone(); - let chain_id = ecx.cfg.chain_id; - let base_tx_env = ecx.tx.clone(); - let verbosity = cheats.config.evm_opts.verbosity; - - let nonce = { - let (db, journal, _) = ecx.as_db_env_and_journal(); - journal.load_account(db, tx_attributes.caller).map(|acc| acc.info.nonce).unwrap_or(0) - }; + let spec_id = ecx.cfg().spec.into(); + let block = build_block_env(ecx.block()); + let chain_id = ecx.cfg().chain_id; + let nonce = ecx + .journal_mut() + .load_account(tx_attributes.caller) + .map(|acc| acc.data.info.nonce) + .unwrap_or(0); // Prepare assertion store - let config = ExecutorConfig { spec_id, chain_id, assertion_gas_limit: TX_GAS_LIMIT_CAP }; + let config = ExecutorConfig { + spec_id, + chain_id, + assertion_gas_limit: TX_GAS_LIMIT_CAP, + assertion_evaluation_enabled: true, + }; let store = AssertionStore::new_ephemeral(); @@ -198,12 +214,13 @@ pub fn execute_assertion( store.insert(assertion.adopter, assertion_state).expect("Failed to store assertions"); - let tx_env = build_tx_env(tx_attributes, &base_tx_env, chain_id, nonce); + let tx_env = build_tx_env(tx_attributes, ecx.tx(), chain_id, nonce); let mut assertion_executor = config.build(store); - // Setup assertion database with 'static lifetime (via transmute in ThreadSafeDb::new) - let db = ThreadSafeDb::new(*ecx.db_mut()); + let (raw_db, journal_inner) = ecx.db_journal_inner_mut(); + let state = journal_inner.state.clone(); + let db = ThreadSafeDb::new(raw_db); // Commit current journal state so that it is available for assertions and triggering tx let mut fork_db = ForkDb::new(db.clone()); @@ -215,53 +232,10 @@ pub fn execute_assertion( // TODO: Remove this once we have a proper way to handle this. let mut ext_db = revm::database::WrapDatabaseRef(fork_db.clone()); - // Minimum verbosity for tracing (matches Foundry's -vvv) - const TRACING_VERBOSITY: u8 = 3; - - // Execute assertion validation with optional tracing based on verbosity - let (tx_validation, tracing_inspectors): (TxValidationResult, Option>) = - if verbosity >= TRACING_VERBOSITY { - // Create tracing inspector configured based on verbosity - let tracing_config = TraceMode::Call - .with_verbosity(verbosity) - .into_config() - .unwrap_or_else(TracingInspectorConfig::default_parity); - let tracing_inspector = TracingInspector::new(tracing_config); - - let result_with_inspectors = assertion_executor - .validate_transaction_with_inspector( - block, - &tx_env, - &mut fork_db, - &mut ext_db, - tracing_inspector, - ) - .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; - - (result_with_inspectors.result, Some(result_with_inspectors.inspectors)) - } else { - // No tracing - use the standard path - let result = assertion_executor - .validate_transaction_ext_db(block, &tx_env, &mut fork_db, &mut ext_db) - .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; - (result, None) - }; - - if let Some(inspectors) = tracing_inspectors { - let mut inspectors = inspectors.into_iter(); - if let Some(trigger_inspector) = inspectors.next() { - let trigger_traces = std::iter::once(trigger_inspector.into_traces()) - .filter(|arena| !arena.nodes().is_empty()); - cheats.push_assertion_trigger_traces(trigger_traces); - } - - let traces = inspectors - .map(|tracing_inspector| tracing_inspector.into_traces()) - .filter(|arena| !arena.nodes().is_empty()); - cheats.push_assertion_traces(traces); - } + let tx_validation: TxValidationResult = assertion_executor + .validate_transaction_ext_db(block, &tx_env, &mut fork_db, &mut ext_db) + .map_err(|e| format!("Assertion Executor Error: {e:#?}"))?; - let mut inspector = executor.get_inspector(cheats); // if transaction execution reverted, log the revert reason if !tx_validation.result_and_state.result.is_success() { bail!(format!( @@ -273,18 +247,16 @@ pub fn execute_assertion( // else get information about the assertion execution let total_assertion_gas = tx_validation.total_assertions_gas(); let total_assertions_ran = tx_validation.total_assertion_funcs_ran(); - let tx_gas_used = tx_validation.result_and_state.result.gas_used(); + let tx_gas_used = tx_validation.result_and_state.result.tx_gas_used(); if total_assertions_ran != 1 { // If assertions were not executed, we need to update expect revert depth to // allow for matching on this revert condition, as we will not execute against // test evm in this case. - ecx.journaled_state.inner.checkpoint(); + journal_inner.checkpoint(); - // Drop inspector first to release the borrow on cheats - std::mem::drop(inspector); if let Some(expected) = &mut cheats.expected_revert { - expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); + expected.max_depth = max(journal_inner.depth, expected.max_depth); } bail!("Expected 1 assertion to be executed, but {total_assertions_ran} were executed."); } @@ -301,29 +273,25 @@ pub fn execute_assertion( .expect("Expected 1 assertion to be executed, but got 0"); if !assertion_fn_result.console_logs.is_empty() { - inspector.console_log("Assertion function logs: "); + executor.console_log("Assertion function logs: "); for log in &assertion_fn_result.console_logs { - inspector.console_log(log); + executor.console_log(log); } } - inspector.console_log(&format!( + executor.console_log(&format!( "Transaction gas cost: {tx_gas_used}\n Assertion gas cost: {total_assertion_gas}" )); - // Drop the inspector to avoid borrow checker issues - std::mem::drop(inspector); - if !tx_validation.is_valid() { // If invalidated, we don't execute against test evm, so we must update expected depth // for expect revert cheatcode. - ecx.journaled_state.inner.checkpoint(); + journal_inner.checkpoint(); if let Some(expected) = &mut cheats.expected_revert { - expected.max_depth = max(ecx.journaled_state.depth(), expected.max_depth); + expected.max_depth = max(journal_inner.depth, expected.max_depth); } - let mut inspector = executor.get_inspector(cheats); let (msg, result) = match &assertion_fn_result.result { AssertionFunctionExecutionResult::AssertionContractDeployFailure(r) => { ("Assertion contract deploy failed", r) @@ -332,13 +300,12 @@ pub fn execute_assertion( ("Assertion function reverted", r) } }; - inspector.console_log(&format!("{msg}: {}", decode_invalidated_assertion(result))); + executor.console_log(&format!("{msg}: {}", decode_invalidated_assertion(result))); return Err(crate::Error::from(result.output().unwrap_or_default().clone())); } if let Some(log_msg) = check_assertion_gas_limit(total_assertion_gas) { - let mut inspector = executor.get_inspector(cheats); - inspector.console_log(&log_msg); + executor.console_log(&log_msg); bail!("Assertion exceeded gas limit"); } diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 7eb5d7be6b1e3..78acecf8be6fa 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1167,6 +1167,37 @@ impl Cheatcodes { }]); } + #[cfg(feature = "credible")] + if let Some(assertion) = self.assertion.take() { + let tx_attributes = crate::credible::TxAttributes { + value: call.call_value(), + data: call.input.bytes(ecx), + caller: call.caller, + kind: TxKind::Call(call.target_address), + gas_limit: call.gas_limit, + }; + + return match crate::credible::execute_assertion( + &assertion, + tx_attributes, + ecx, + executor, + self, + ) { + Ok(()) => None, + Err(err) => Some(CallOutcome { + result: InterpreterResult { + result: InstructionResult::Revert, + output: err.abi_encode().into(), + gas, + }, + memory_offset: call.return_memory_offset.clone(), + was_precompile_called: false, + precompile_call_logs: vec![], + }), + }; + } + None } @@ -1901,6 +1932,35 @@ impl Inspector> for Cheatcode }]); } + #[cfg(feature = "credible")] + if let Some(assertion) = self.assertion.take() { + let tx_attributes = crate::credible::TxAttributes { + value: input.value(), + data: input.init_code(), + caller: input.caller(), + kind: TxKind::Create, + gas_limit: input.gas_limit(), + }; + + return match crate::credible::execute_assertion( + &assertion, + tx_attributes, + ecx, + &mut TransparentCheatcodesExecutor, + self, + ) { + Ok(()) => None, + Err(err) => Some(CreateOutcome { + result: InterpreterResult { + result: InstructionResult::Revert, + output: err.abi_encode().into(), + gas, + }, + address: None, + }), + }; + } + None } diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 5c5fe29c3154c..b1708ebb85abd 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -82,7 +82,7 @@ pub type JournaledState = JournalInner; /// An extension trait that allows us to easily extend the `revm::Inspector` capabilities #[auto_impl::auto_impl(&mut)] pub trait DatabaseExt: - Database + DatabaseCommit + Debug + Database + DatabaseCommit + Debug + Send { /// Creates a new state snapshot at the current point of execution. /// From 4d58f09d8e1eb3f3c83a30c3aa80e303d4b344af Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 21:37:55 +0200 Subject: [PATCH 73/83] fix: phoundry clippy errors and ExecutionResult fixtures - Port ExecutionResult test fixtures to revm 38 (gas: ResultGas, add logs) - Drop unused tempo-contracts/tempo-precompiles deps from foundry-evm-traces - Mark trivial setters as const fn (with_verbosity, with_label_disabled, with_chain_id, without_label, is_assertion_trigger, is_assertion) - Simplify if/else with bool::then in credible.rs and decoder - Replace Default + field assignment with struct literal in build_tx_env, build_block_env (alloy/revm Block trait has no blanket Into) --- Cargo.lock | 2 - crates/cheatcodes/src/credible.rs | 89 ++++++++++++++++------------ crates/evm/traces/Cargo.toml | 3 - crates/evm/traces/src/decoder/mod.rs | 28 ++++----- crates/evm/traces/src/lib.rs | 4 +- 5 files changed, 65 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e99055403f4a..b2c717d2fba9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5801,8 +5801,6 @@ dependencies = [ "serde_json", "solar-compiler", "tempfile", - "tempo-contracts", - "tempo-precompiles", "tokio", "tracing", "yansi", diff --git a/crates/cheatcodes/src/credible.rs b/crates/cheatcodes/src/credible.rs index 493bc08648088..ae108a2eeb634 100644 --- a/crates/cheatcodes/src/credible.rs +++ b/crates/cheatcodes/src/credible.rs @@ -120,15 +120,13 @@ const ASSERTION_GAS_LIMIT: u64 = 300_000; /// Checks if the assertion gas usage is within the allowed limit. /// Returns a detailed log message if the limit is exceeded, None otherwise. fn check_assertion_gas_limit(gas_used: u64) -> Option { - if gas_used > ASSERTION_GAS_LIMIT { + (gas_used > ASSERTION_GAS_LIMIT).then(|| { let over_by = gas_used - ASSERTION_GAS_LIMIT; let over_percent = (over_by as f64 / ASSERTION_GAS_LIMIT as f64) * 100.0; - Some(format!( + format!( "Assertion used {gas_used} gas, exceeding limit of {ASSERTION_GAS_LIMIT} by {over_by} ({over_percent:.1}% over)" - )) - } else { - None - } + ) + }) } fn build_tx_env( @@ -138,33 +136,35 @@ fn build_tx_env( nonce: u64, ) -> TxEnv { let tx_gas_limit = tx_attributes.gas_limit.min(TX_GAS_LIMIT_CAP); - let mut tx_env = TxEnv::default(); - tx_env.tx_type = base_tx_env.tx_type(); - tx_env.caller = tx_attributes.caller; - tx_env.gas_limit = tx_gas_limit; - tx_env.gas_price = base_tx_env.gas_price(); - tx_env.chain_id = Some(chain_id); - tx_env.value = tx_attributes.value; - tx_env.data = tx_attributes.data; - tx_env.kind = tx_attributes.kind; - tx_env.nonce = nonce; - tx_env.gas_priority_fee = base_tx_env.max_priority_fee_per_gas(); - tx_env.blob_hashes = base_tx_env.blob_versioned_hashes().to_vec(); - tx_env.max_fee_per_blob_gas = base_tx_env.max_fee_per_blob_gas(); - tx_env + TxEnv { + tx_type: base_tx_env.tx_type(), + caller: tx_attributes.caller, + gas_limit: tx_gas_limit, + gas_price: base_tx_env.gas_price(), + chain_id: Some(chain_id), + value: tx_attributes.value, + data: tx_attributes.data, + kind: tx_attributes.kind, + nonce, + gas_priority_fee: base_tx_env.max_priority_fee_per_gas(), + blob_hashes: base_tx_env.blob_versioned_hashes().to_vec(), + max_fee_per_blob_gas: base_tx_env.max_fee_per_blob_gas(), + ..Default::default() + } } fn build_block_env(block: &impl Block) -> BlockEnv { - let mut block_env = BlockEnv::default(); - block_env.number = block.number(); - block_env.beneficiary = block.beneficiary(); - block_env.timestamp = block.timestamp(); - block_env.gas_limit = block.gas_limit(); - block_env.basefee = block.basefee(); - block_env.difficulty = block.difficulty(); - block_env.prevrandao = block.prevrandao(); - block_env.blob_excess_gas_and_price = block.blob_excess_gas_and_price(); - block_env + BlockEnv { + number: block.number(), + beneficiary: block.beneficiary(), + timestamp: block.timestamp(), + gas_limit: block.gas_limit(), + basefee: block.basefee(), + difficulty: block.difficulty(), + prevrandao: block.prevrandao(), + blob_excess_gas_and_price: block.blob_excess_gas_and_price(), + ..Default::default() + } } /// Used to handle assertion execution in inspector in calls after the cheatcode was called. @@ -337,13 +337,12 @@ mod tests { use super::*; use alloy_sol_types::{Revert, SolError}; use assertion_executor::primitives::HaltReason; - use revm::context_interface::result::{Output, SuccessReason}; + use revm::context_interface::result::{Output, ResultGas, SuccessReason}; #[test] fn test_decode_revert_error_success() { let result = ExecutionResult::Success { - gas_used: 0, - gas_refunded: 0, + gas: ResultGas::new_with_state_gas(0, 0, 0, 0), logs: vec![], output: Output::Call(Bytes::new()), reason: SuccessReason::Return, @@ -356,7 +355,11 @@ mod tests { fn test_decode_revert_error_revert() { let revert_reason = "Something is a bit fky wuky"; let revert_output = Revert::new((revert_reason.to_string(),)).abi_encode(); - let result = ExecutionResult::Revert { output: revert_output.into(), gas_used: 0 }; + let result = ExecutionResult::Revert { + output: revert_output.into(), + gas: ResultGas::new_with_state_gas(0, 0, 0, 0), + logs: vec![], + }; let decoded = decode_invalidated_assertion(&result); assert_eq!(decoded, revert_reason); } @@ -365,7 +368,11 @@ mod tests { fn test_decode_revert_panic() { // Panic(uint256) with code 0x01 (assertion failed) let panic_output = alloy_sol_types::Panic::from(0x01).abi_encode(); - let result = ExecutionResult::Revert { output: panic_output.into(), gas_used: 0 }; + let result = ExecutionResult::Revert { + output: panic_output.into(), + gas: ResultGas::new_with_state_gas(0, 0, 0, 0), + logs: vec![], + }; let decoded = decode_invalidated_assertion(&result); assert!(decoded.contains("Panic") || decoded.contains("panic")); } @@ -374,7 +381,11 @@ mod tests { fn test_decode_revert_raw_bytes() { // Raw bytes that don't match any known format let raw_bytes = vec![0xde, 0xad, 0xbe, 0xef]; - let result = ExecutionResult::Revert { output: raw_bytes.into(), gas_used: 0 }; + let result = ExecutionResult::Revert { + output: raw_bytes.into(), + gas: ResultGas::new_with_state_gas(0, 0, 0, 0), + logs: vec![], + }; let decoded = decode_invalidated_assertion(&result); // Should contain hex representation assert!(decoded.contains("deadbeef") || decoded.contains("custom error")); @@ -383,7 +394,11 @@ mod tests { #[test] fn test_decode_revert_error_halt() { let halt_reason = HaltReason::CallTooDeep; - let result = ExecutionResult::Halt { reason: halt_reason, gas_used: 0 }; + let result = ExecutionResult::Halt { + reason: halt_reason, + gas: ResultGas::new_with_state_gas(0, 0, 0, 0), + logs: vec![], + }; let decoded = decode_invalidated_assertion(&result); assert_eq!(decoded, "Halt reason: CallTooDeep"); } diff --git a/crates/evm/traces/Cargo.toml b/crates/evm/traces/Cargo.toml index 90d2db724cebc..0d31cfca6a7ae 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -32,9 +32,6 @@ alloy-primitives = { workspace = true, features = [ alloy-sol-types.workspace = true revm-inspectors.workspace = true -tempo-contracts.workspace = true -tempo-precompiles.workspace = true - async-trait.workspace = true eyre.workspace = true futures.workspace = true diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 84874f444dd4d..04f9f684b9c90 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -74,7 +74,7 @@ impl CallTraceDecoderBuilder { /// Sets the verbosity level of the decoder. #[inline] - pub fn with_verbosity(mut self, level: u8) -> Self { + pub const fn with_verbosity(mut self, level: u8) -> Self { self.decoder.verbosity = level; self } @@ -88,7 +88,7 @@ impl CallTraceDecoderBuilder { /// Sets the signature identifier for events and functions. #[inline] - pub fn with_label_disabled(mut self, disable_alias: bool) -> Self { + pub const fn with_label_disabled(mut self, disable_alias: bool) -> Self { self.decoder.disable_labels = disable_alias; self } @@ -102,7 +102,7 @@ impl CallTraceDecoderBuilder { /// Sets the chain ID for chain-specific precompile decoding. #[inline] - pub fn with_chain_id(mut self, chain_id: Option) -> Self { + pub const fn with_chain_id(mut self, chain_id: Option) -> Self { self.decoder.chain_id = chain_id; self } @@ -306,7 +306,7 @@ impl CallTraceDecoder { self.revert_decoder.push_error(error); } - pub fn without_label(&mut self, disable: bool) { + pub const fn without_label(&mut self, disable: bool) { self.disable_labels = disable; } @@ -426,7 +426,9 @@ impl CallTraceDecoder { && !contract_selectors.contains(&selector) && (!cdata.is_empty() || !self.receive_contracts.contains(&trace.address)) { - let return_data = if !trace.success { + let return_data = if trace.success { + None + } else { let revert_msg = self.revert_decoder.decode(&trace.output, trace.status); if trace.output.is_empty() || revert_msg.contains("EvmError: Revert") { @@ -437,8 +439,6 @@ impl CallTraceDecoder { } else { Some(revert_msg) } - } else { - None }; return if let Some(func) = functions.first() { @@ -521,20 +521,14 @@ impl CallTraceDecoder { "broadcast" | "startBroadcast" => { // Redact private key if defined // broadcast(uint256) / startBroadcast(uint256) - if !func.inputs.is_empty() && func.inputs[0].ty == "uint256" { - Some(vec!["".to_string()]) - } else { - None - } + (!func.inputs.is_empty() && func.inputs[0].ty == "uint256") + .then(|| vec!["".to_string()]) } "getNonce" => { // Redact private key if defined // getNonce(Wallet) - if !func.inputs.is_empty() && func.inputs[0].ty == "tuple" { - Some(vec!["".to_string()]) - } else { - None - } + (!func.inputs.is_empty() && func.inputs[0].ty == "tuple") + .then(|| vec!["".to_string()]) } "sign" | "signP256" => { let mut decoded = func.abi_decode_input(&data[SELECTOR_LEN..]).ok()?; diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 3685e44e50bd5..a392836fb2206 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -279,7 +279,7 @@ impl TraceKind { /// /// [`AssertionTrigger`]: TraceKind::AssertionTrigger #[must_use] - pub fn is_assertion_trigger(self) -> bool { + pub const fn is_assertion_trigger(self) -> bool { matches!(self, Self::AssertionTrigger) } @@ -287,7 +287,7 @@ impl TraceKind { /// /// [`Assertion`]: TraceKind::Assertion #[must_use] - pub fn is_assertion(self) -> bool { + pub const fn is_assertion(self) -> bool { matches!(self, Self::Assertion) } } From 72d5c81e6f1215a7be5b5e6577149e9a2bee9d43 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 21:45:27 +0200 Subject: [PATCH 74/83] ci: install sccache in deny job so RUSTC_WRAPPER resolves --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7a12110a6c76..3437887f04c15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -211,6 +211,7 @@ jobs: env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: git config --global url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf "https://github.com/" + - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - uses: taiki-e/install-action@763e3324d4fd026c9bd284c504378585777a87d5 # v2 with: tool: cargo-deny From 1ee9e513b9e8c29eb628116afa577305fd85bdcf Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 21:56:36 +0200 Subject: [PATCH 75/83] ci: extend deny.toml to cover phoundry 1.7 / revm 38 dep graph - Ignore new advisories: RUSTSEC-2026-0012 (keccak ARMv8 asm), -0098/-0099 (rustls-webpki name constraints), -0103 (thin-vec UAF), -0104 (rustls-webpki CRL panic). All awaiting upstream updates. - Allow CC-BY-4.0 for font-awesome-as-a-crate (transitive doc icon set). - Allow git sources for ethereum-optimism/optimism (OP fork: op-revm, alloy-op-*, op-alloy-*), tempoxyz/mpp-rs, paradigmxyz/reth-core. --- deny.toml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/deny.toml b/deny.toml index 3e477868150bd..9c451486007c9 100644 --- a/deny.toml +++ b/deny.toml @@ -33,6 +33,16 @@ ignore = [ "RUSTSEC-2026-0049", # https://rustsec.org/advisories/RUSTSEC-2026-0009 time DoS via stack exhaustion — awaiting upstream update "RUSTSEC-2026-0009", + # https://rustsec.org/advisories/RUSTSEC-2026-0012 keccak ARMv8 asm — off-by-default `asm` feature, not enabled + "RUSTSEC-2026-0012", + # https://rustsec.org/advisories/RUSTSEC-2026-0098 rustls-webpki URI name constraint — awaiting upstream update + "RUSTSEC-2026-0098", + # https://rustsec.org/advisories/RUSTSEC-2026-0099 rustls-webpki wildcard name constraint — awaiting upstream update + "RUSTSEC-2026-0099", + # https://rustsec.org/advisories/RUSTSEC-2026-0103 thin-vec IntoIter UAF — awaiting upstream update + "RUSTSEC-2026-0103", + # https://rustsec.org/advisories/RUSTSEC-2026-0104 rustls-webpki CRL panic — awaiting upstream update + "RUSTSEC-2026-0104", ] # This section is considered when running `cargo deny check bans`. @@ -96,6 +106,8 @@ exceptions = [ { allow = ["CC0-1.0"], name = "notify" }, { allow = ["CC0-1.0"], name = "dunce" }, { allow = ["CC0-1.0"], name = "aurora-engine-modexp" }, + # font-awesome icons embedded as a crate; CC-BY-4.0 applies to the icon set. + { allow = ["CC-BY-4.0"], name = "font-awesome-as-a-crate" }, ] # Crates from credible-sdk and evm-glue don't have license fields @@ -138,8 +150,14 @@ allow-git = [ "https://github.com/rust-cli/rexpect", # Tempo "https://github.com/tempoxyz/tempo", + # Tempo transitive: mpp-rs + "https://github.com/tempoxyz/mpp-rs", # Transitive dependency of Tempo "https://github.com/paradigmxyz/reth", + # reth-core split crates pinned for 1.7.1-compatible API + "https://github.com/paradigmxyz/reth-core", + # OP fork: op-revm / alloy-op-evm / alloy-op-hardforks / op-alloy-* aligned with phoundry 1.7.1 + "https://github.com/ethereum-optimism/optimism", # Assertion executor and its dependencies "https://github.com/phylaxsystems/credible-sdk", "https://git@github.com/Philogy/evm-glue", From 4e7a3a792e17aefa8ef474a32ec412482a76d855 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 22:05:42 +0200 Subject: [PATCH 76/83] ci: prune stale advisory ignores no longer matching any crate --- deny.toml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/deny.toml b/deny.toml index 9c451486007c9..7c6327f77457a 100644 --- a/deny.toml +++ b/deny.toml @@ -7,8 +7,6 @@ yanked = "warn" ignore = [ # https://rustsec.org/advisories/RUSTSEC-2024-0436 paste! is unmaintained "RUSTSEC-2024-0436", - # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. - "RUSTSEC-2024-0437", # https://rustsec.org/advisories/RUSTSEC-2025-0141 bincode is unmaintained, need to transition all deps to wincode first "RUSTSEC-2025-0141", # https://rustsec.org/advisories/RUSTSEC-2023-0018 remove_dir_all vulnerability @@ -19,20 +17,8 @@ ignore = [ # https://rustsec.org/advisories/RUSTSEC-2018-0017 tempdir deprecated # Transitive dep: sled -> assertion-executor. Not fixable until sled updates. "RUSTSEC-2018-0017", - # aws-lc-sys vulnerabilities — transitive dep via rustls. Upgrade blocked by alloy pinning aws-lc-rs. - "RUSTSEC-2026-0044", - "RUSTSEC-2026-0045", - "RUSTSEC-2026-0046", - "RUSTSEC-2026-0047", - "RUSTSEC-2026-0048", - # https://rustsec.org/advisories/RUSTSEC-2026-0007 bytes integer overflow — awaiting upstream update - "RUSTSEC-2026-0007", - # https://rustsec.org/advisories/RUSTSEC-2026-0097 rand unsoundness with custom logger — awaiting upstream update - "RUSTSEC-2026-0097", # https://rustsec.org/advisories/RUSTSEC-2026-0049 rustls-webpki CRL bypass — awaiting upstream update "RUSTSEC-2026-0049", - # https://rustsec.org/advisories/RUSTSEC-2026-0009 time DoS via stack exhaustion — awaiting upstream update - "RUSTSEC-2026-0009", # https://rustsec.org/advisories/RUSTSEC-2026-0012 keccak ARMv8 asm — off-by-default `asm` feature, not enabled "RUSTSEC-2026-0012", # https://rustsec.org/advisories/RUSTSEC-2026-0098 rustls-webpki URI name constraint — awaiting upstream update From 8ba3db121fc0b383e9f31b9369566a5c6de3908f Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 22:13:37 +0200 Subject: [PATCH 77/83] fix: regen Vm.sol iface, restore rand advisory ignore, skip aarch64 svm test - Regenerate testdata/utils/Vm.sol after cheatcodes spec drift (foundry-cheatcodes-spec::iface_up_to_date test was failing) - Restore RUSTSEC-2026-0097 (rand unsoundness): still present at both rand 0.8.5 and 0.9.2 in lockfile; my prior prune was based on stale local DB - Drop unused evm-glue entries from licenses.private and allow-git; the crate is no longer in the dep graph - Skip test_svm_releases_linux_aarch64 with #[ignore]: svm-builds has not yet published linux-aarch64 binaries for LATEST_SOLC (0.8.34) --- crates/forge/tests/cli/svm.rs | 10 ++- deny.toml | 6 +- testdata/utils/Vm.sol | 129 ++++++++++++++++++---------------- 3 files changed, 80 insertions(+), 65 deletions(-) diff --git a/crates/forge/tests/cli/svm.rs b/crates/forge/tests/cli/svm.rs index b80805cbecfc4..b65bb9ac4ab7e 100644 --- a/crates/forge/tests/cli/svm.rs +++ b/crates/forge/tests/cli/svm.rs @@ -33,14 +33,22 @@ async fn ensure_latest_release(platform: Platform) { } // ensures all platform have the latest solc release version +// +// `test_svm_releases_linux_aarch64` is skipped until svm-builds publishes +// linux-aarch64 binaries for `LATEST_SOLC`; the other platforms ship sooner. ensure_svm_releases!( test_svm_releases_linux_amd64 => LinuxAmd64, - test_svm_releases_linux_aarch64 => LinuxAarch64, test_svm_releases_macos_amd64 => MacOsAmd64, test_svm_releases_macos_aarch64 => MacOsAarch64, test_svm_releases_windows_amd64 => WindowsAmd64 ); +#[tokio::test(flavor = "multi_thread")] +#[ignore = "awaiting svm-builds publishing linux-aarch64 for LATEST_SOLC"] +async fn test_svm_releases_linux_aarch64() { + ensure_latest_release(Platform::LinuxAarch64).await +} + // Ensures we can always test with the latest solc build forgetest_init!(can_test_with_latest_solc, |prj, cmd| { prj.initialize_default_contracts(); diff --git a/deny.toml b/deny.toml index 7c6327f77457a..d33e9002050ca 100644 --- a/deny.toml +++ b/deny.toml @@ -19,6 +19,8 @@ ignore = [ "RUSTSEC-2018-0017", # https://rustsec.org/advisories/RUSTSEC-2026-0049 rustls-webpki CRL bypass — awaiting upstream update "RUSTSEC-2026-0049", + # https://rustsec.org/advisories/RUSTSEC-2026-0097 rand unsoundness with custom logger — awaiting upstream update + "RUSTSEC-2026-0097", # https://rustsec.org/advisories/RUSTSEC-2026-0012 keccak ARMv8 asm — off-by-default `asm` feature, not enabled "RUSTSEC-2026-0012", # https://rustsec.org/advisories/RUSTSEC-2026-0098 rustls-webpki URI name constraint — awaiting upstream update @@ -96,14 +98,13 @@ exceptions = [ { allow = ["CC-BY-4.0"], name = "font-awesome-as-a-crate" }, ] -# Crates from credible-sdk and evm-glue don't have license fields +# Crates from credible-sdk don't have license fields # These are internal/trusted dependencies - ignore unlicensed crates from these sources [licenses.private] ignore = true registries = [] ignore-sources = [ "https://github.com/phylaxsystems/credible-sdk", - "https://git@github.com/Philogy/evm-glue", ] # copyleft = "deny" @@ -146,5 +147,4 @@ allow-git = [ "https://github.com/ethereum-optimism/optimism", # Assertion executor and its dependencies "https://github.com/phylaxsystems/credible-sdk", - "https://git@github.com/Philogy/evm-glue", ] diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index 6e855f9f95377..94cf994dfb834 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -36,122 +36,122 @@ interface Vm { function addr(uint256 privateKey) external pure returns (address keyAddr); function allowCheatcodes(address account) external; function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; - function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata err) external pure; function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata err) external pure; function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) external pure; - function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) external pure; - function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error) external pure; + function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata err) external pure; function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; - function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) external pure; + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata err) external pure; function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) external pure; + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata err) external pure; function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertEq(bool left, bool right) external pure; - function assertEq(bool left, bool right, string calldata error) external pure; + function assertEq(bool left, bool right, string calldata err) external pure; function assertEq(string calldata left, string calldata right) external pure; - function assertEq(string calldata left, string calldata right, string calldata error) external pure; + function assertEq(string calldata left, string calldata right, string calldata err) external pure; function assertEq(bytes calldata left, bytes calldata right) external pure; - function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertEq(bytes calldata left, bytes calldata right, string calldata err) external pure; function assertEq(bool[] calldata left, bool[] calldata right) external pure; - function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; - function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; function assertEq(int256[] calldata left, int256[] calldata right) external pure; - function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; function assertEq(uint256 left, uint256 right) external pure; function assertEq(address[] calldata left, address[] calldata right) external pure; - function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertEq(address[] calldata left, address[] calldata right, string calldata err) external pure; function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; - function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; function assertEq(string[] calldata left, string[] calldata right) external pure; - function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertEq(string[] calldata left, string[] calldata right, string calldata err) external pure; function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; - function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; - function assertEq(uint256 left, uint256 right, string calldata error) external pure; + function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; + function assertEq(uint256 left, uint256 right, string calldata err) external pure; function assertEq(int256 left, int256 right) external pure; - function assertEq(int256 left, int256 right, string calldata error) external pure; + function assertEq(int256 left, int256 right, string calldata err) external pure; function assertEq(address left, address right) external pure; - function assertEq(address left, address right, string calldata error) external pure; + function assertEq(address left, address right, string calldata err) external pure; function assertEq(bytes32 left, bytes32 right) external pure; - function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertEq(bytes32 left, bytes32 right, string calldata err) external pure; function assertFalse(bool condition) external pure; - function assertFalse(bool condition, string calldata error) external pure; + function assertFalse(bool condition, string calldata err) external pure; function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertGe(uint256 left, uint256 right) external pure; - function assertGe(uint256 left, uint256 right, string calldata error) external pure; + function assertGe(uint256 left, uint256 right, string calldata err) external pure; function assertGe(int256 left, int256 right) external pure; - function assertGe(int256 left, int256 right, string calldata error) external pure; + function assertGe(int256 left, int256 right, string calldata err) external pure; function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertGt(uint256 left, uint256 right) external pure; - function assertGt(uint256 left, uint256 right, string calldata error) external pure; + function assertGt(uint256 left, uint256 right, string calldata err) external pure; function assertGt(int256 left, int256 right) external pure; - function assertGt(int256 left, int256 right, string calldata error) external pure; + function assertGt(int256 left, int256 right, string calldata err) external pure; function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertLe(uint256 left, uint256 right) external pure; - function assertLe(uint256 left, uint256 right, string calldata error) external pure; + function assertLe(uint256 left, uint256 right, string calldata err) external pure; function assertLe(int256 left, int256 right) external pure; - function assertLe(int256 left, int256 right, string calldata error) external pure; + function assertLe(int256 left, int256 right, string calldata err) external pure; function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertLt(uint256 left, uint256 right) external pure; - function assertLt(uint256 left, uint256 right, string calldata error) external pure; + function assertLt(uint256 left, uint256 right, string calldata err) external pure; function assertLt(int256 left, int256 right) external pure; - function assertLt(int256 left, int256 right, string calldata error) external pure; + function assertLt(int256 left, int256 right, string calldata err) external pure; function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata err) external pure; function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata err) external pure; function assertNotEq(bool left, bool right) external pure; - function assertNotEq(bool left, bool right, string calldata error) external pure; + function assertNotEq(bool left, bool right, string calldata err) external pure; function assertNotEq(string calldata left, string calldata right) external pure; - function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; + function assertNotEq(string calldata left, string calldata right, string calldata err) external pure; function assertNotEq(bytes calldata left, bytes calldata right) external pure; - function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + function assertNotEq(bytes calldata left, bytes calldata right, string calldata err) external pure; function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; - function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata err) external pure; function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; - function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata err) external pure; function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; - function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata err) external pure; function assertNotEq(uint256 left, uint256 right) external pure; function assertNotEq(address[] calldata left, address[] calldata right) external pure; - function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + function assertNotEq(address[] calldata left, address[] calldata right, string calldata err) external pure; function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; - function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata err) external pure; function assertNotEq(string[] calldata left, string[] calldata right) external pure; - function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + function assertNotEq(string[] calldata left, string[] calldata right, string calldata err) external pure; function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; - function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; - function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; + function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata err) external pure; + function assertNotEq(uint256 left, uint256 right, string calldata err) external pure; function assertNotEq(int256 left, int256 right) external pure; - function assertNotEq(int256 left, int256 right, string calldata error) external pure; + function assertNotEq(int256 left, int256 right, string calldata err) external pure; function assertNotEq(address left, address right) external pure; - function assertNotEq(address left, address right, string calldata error) external pure; + function assertNotEq(address left, address right, string calldata err) external pure; function assertNotEq(bytes32 left, bytes32 right) external pure; - function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; + function assertNotEq(bytes32 left, bytes32 right, string calldata err) external pure; function assertTrue(bool condition) external pure; - function assertTrue(bool condition, string calldata error) external pure; - function assertionEx(bytes calldata tx, address assertionAdopter, bytes calldata assertionContract, string calldata assertionContractLabel) external; + function assertTrue(bool condition, string calldata err) external pure; + function assertion(address adopter, bytes calldata createData, bytes4 fnSelector) external; function assume(bool condition) external pure; function assumeNoRevert() external pure; function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure; @@ -183,6 +183,7 @@ interface Vm { function copyFile(string calldata from, string calldata to) external returns (uint64 copied); function copyStorage(address from, address to) external; function createDir(string calldata path, bool recursive) external; + function createEd25519Key(bytes32 salt) external pure returns (bytes32 publicKey, bytes32 privateKey); function createFork(string calldata urlOrAlias) external returns (uint256 forkId); function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); @@ -192,6 +193,7 @@ interface Vm { function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); function createWallet(uint256 privateKey) external returns (Wallet memory wallet); function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); + function currentFilePath() external view returns (string memory path); function deal(address account, uint256 newBalance) external; function deleteSnapshot(uint256 snapshotId) external returns (bool success); function deleteSnapshots() external; @@ -248,6 +250,7 @@ interface Vm { function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); function etch(address target, bytes calldata newRuntimeBytecode) external; function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) external view returns (EthGetLogs[] memory logs); + function executeTransaction(bytes calldata rawTx) external returns (bytes memory); function exists(string calldata path) external view returns (bool result); function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) external; @@ -320,6 +323,7 @@ interface Vm { function getNonce(Wallet calldata wallet) external view returns (uint64 nonce); function getRawBlockHeader(uint256 blockNumber) external view returns (bytes memory rlpHeader); function getRecordedLogs() external view returns (Log[] memory logs); + function getRecordedLogsJson() external view returns (string memory logsJson); function getStateDiff() external view returns (string memory diff); function getStateDiffJson() external view returns (string memory diff); function getStorageAccesses() external view returns (StorageAccess[] memory storageAccesses); @@ -414,6 +418,7 @@ interface Vm { function promptSecret(string calldata promptText) external returns (string memory input); function promptSecretUint(string calldata promptText) external returns (uint256); function promptUint(string calldata promptText) external returns (uint256); + function publicKeyEd25519(bytes32 privateKey) external pure returns (bytes32 publicKey); function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); function randomAddress() external view returns (address); function randomBool() external view returns (bool); @@ -493,16 +498,17 @@ interface Vm { function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signAndAttachDelegation(address implementation, uint256 privateKey, uint64 nonce) external returns (SignedDelegation memory signedDelegation); function signAndAttachDelegation(address implementation, uint256 privateKey, bool crossChain) external returns (SignedDelegation memory signedDelegation); - function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); + function signCompact(Wallet calldata wallet, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signDelegation(address implementation, uint256 privateKey, uint64 nonce) external returns (SignedDelegation memory signedDelegation); function signDelegation(address implementation, uint256 privateKey, bool crossChain) external returns (SignedDelegation memory signedDelegation); + function signEd25519(bytes calldata namespace, bytes calldata message, bytes32 privateKey) external pure returns (bytes memory signature); function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); function signWithNonceUnsafe(uint256 privateKey, bytes32 digest, uint256 nonce) external pure returns (uint8 v, bytes32 r, bytes32 s); - function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + function sign(Wallet calldata wallet, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); @@ -559,6 +565,7 @@ interface Vm { function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); function txGasPrice(uint256 newGasPrice) external; function unixTime() external view returns (uint256 milliseconds); + function verifyEd25519(bytes calldata signature, bytes calldata namespace, bytes calldata message, bytes32 publicKey) external pure returns (bool valid); function warmSlot(address target, bytes32 slot) external; function warp(uint256 newTimestamp) external; function writeFile(string calldata path, string calldata data) external; From 86fba3225da582836a1e4aaec1dced14a8c7222e Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Mon, 25 May 2026 22:19:15 +0200 Subject: [PATCH 78/83] deps: bump svm-rs 0.5.22 -> 0.5.25 so linux-aarch64 solc 0.8.34 is known svm-rs 0.5.25 picks up the published linux-aarch64 binary entry for solc 0.8.34, which the older 0.5.22 release index was missing. Restores the unmodified upstream svm test set (no #[ignore] hack needed). --- Cargo.lock | 41 +++++++++++++++++------------------ crates/forge/tests/cli/svm.rs | 10 +-------- 2 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2c717d2fba9d..76b03ecc7ec47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3395,7 +3395,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4277,7 +4277,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -4619,7 +4619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4792,7 +4792,7 @@ checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6179,8 +6179,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link 0.1.3", + "windows-result 0.3.4", ] [[package]] @@ -6995,7 +6995,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7981,7 +7981,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -9184,7 +9184,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -9543,7 +9543,6 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", - "futures-channel", "futures-core", "futures-util", "h2", @@ -9561,7 +9560,6 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -9589,6 +9587,7 @@ checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", + "futures-channel", "futures-core", "futures-util", "h2", @@ -10880,7 +10879,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -10939,7 +10938,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -11768,7 +11767,7 @@ dependencies = [ "solar-config", "solar-data-structures", "solar-macros", - "thiserror 1.0.69", + "thiserror 2.0.18", "tracing", "unicode-width 0.2.0", ] @@ -12098,19 +12097,19 @@ dependencies = [ [[package]] name = "svm-rs" -version = "0.5.22" +version = "0.5.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909e8ff825120cd2b34ceb236ab72e2a7f74b1d3a86c247936c8ff7a80c5d408" +checksum = "4572dd9845e37ca0293acb5fe591a7f61b51f1b7b62d3dc6fb8e99e2664f3755" dependencies = [ "const-hex", "dirs", - "reqwest 0.12.26", + "reqwest 0.13.3", "semver 1.0.28", "serde", "serde_json", "sha2 0.10.9", "tempfile", - "thiserror 1.0.69", + "thiserror 2.0.18", "url", "zip", ] @@ -12254,7 +12253,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -12460,7 +12459,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -13920,7 +13919,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/crates/forge/tests/cli/svm.rs b/crates/forge/tests/cli/svm.rs index b65bb9ac4ab7e..b80805cbecfc4 100644 --- a/crates/forge/tests/cli/svm.rs +++ b/crates/forge/tests/cli/svm.rs @@ -33,22 +33,14 @@ async fn ensure_latest_release(platform: Platform) { } // ensures all platform have the latest solc release version -// -// `test_svm_releases_linux_aarch64` is skipped until svm-builds publishes -// linux-aarch64 binaries for `LATEST_SOLC`; the other platforms ship sooner. ensure_svm_releases!( test_svm_releases_linux_amd64 => LinuxAmd64, + test_svm_releases_linux_aarch64 => LinuxAarch64, test_svm_releases_macos_amd64 => MacOsAmd64, test_svm_releases_macos_aarch64 => MacOsAarch64, test_svm_releases_windows_amd64 => WindowsAmd64 ); -#[tokio::test(flavor = "multi_thread")] -#[ignore = "awaiting svm-builds publishing linux-aarch64 for LATEST_SOLC"] -async fn test_svm_releases_linux_aarch64() { - ensure_latest_release(Platform::LinuxAarch64).await -} - // Ensures we can always test with the latest solc build forgetest_init!(can_test_with_latest_solc, |prj, cmd| { prj.initialize_default_contracts(); From 02265030683bfbd720a0862081b35ca10def7324 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Tue, 26 May 2026 10:31:15 +0200 Subject: [PATCH 79/83] fix: first tests batch fix --- crates/forge/tests/cli/cmd.rs | 3 +++ crates/test-utils/src/prj.rs | 19 +++++++++++++++---- crates/test-utils/src/util.rs | 32 +++++++++++++++++++++++++++++++- testdata/foundry.lock | 8 ++++++++ 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 testdata/foundry.lock diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 6e0acebc67225..d9f6e6be77fef 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -298,6 +298,9 @@ forgetest!( // checks that init works forgetest!(can_init_repo_with_config, |prj, cmd| { let foundry_toml = prj.root().join(Config::FILE_NAME); + // `TestProject::new` pre-writes a foundry.toml to match the project's PathStyle; remove it + // so this test exercises `forge init`'s empty-directory path. + let _ = fs::remove_file(&foundry_toml); assert!(!foundry_toml.exists()); cmd.args(["init", "--force"]) diff --git a/crates/test-utils/src/prj.rs b/crates/test-utils/src/prj.rs index 96fa065317bec..462c5625f8975 100644 --- a/crates/test-utils/src/prj.rs +++ b/crates/test-utils/src/prj.rs @@ -22,7 +22,9 @@ use std::{ }, }; -use crate::util::{SOLC_VERSION, copy_dir_filtered, pretty_err}; +use crate::util::{ + SOLC_VERSION, copy_dir_filtered, pretty_err, test_config_default, test_config_for_style, +}; static CURRENT_DIR_LOCK: LazyLock> = LazyLock::new(|| Mutex::new(())); @@ -177,8 +179,17 @@ impl TestProject { /// to a logical grouping of tests. pub fn new(name: &str, style: PathStyle) -> Self { let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); - let project = pretty_err(name, TempProject::with_style(&format!("{name}-{id}"), style)); - Self::with_project(project) + let project = + pretty_err(name, TempProject::with_style(&format!("{name}-{id}"), style.clone())); + let this = Self::with_project(project); + // Write a foundry.toml so `forge` sees the same paths the TempProject scaffolds. + // Without this, Phylax's `assertions/*` defaults (Config::default()) take effect and + // `forge build|clean|...` look in directories the test never touches. + let config_path = this.config(); + if !config_path.exists() { + this.write_config(test_config_for_style(style)); + } + this } pub fn with_project(project: TempProject) -> Self { @@ -245,7 +256,7 @@ impl TestProject { .exists() .then_some(()) .and_then(|()| Config::load_with_root(self.root()).ok()) - .unwrap_or_default(); + .unwrap_or_else(test_config_default); config.remappings.clear(); f(&mut config); self.write_config(config); diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 48489e43e34d9..815aa23e86af4 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -37,6 +37,36 @@ pub const SOLC_VERSION: &str = "0.8.35"; /// Necessary to avoid downloading multiple versions. pub const OTHER_SOLC_VERSION: &str = "0.8.26"; +/// Returns a [`Config`] suitable for tests: starts from [`Config::default()`] but overrides the +/// Phylax `assertions/*` path defaults with upstream `src/`, `test/`, `script/`, ... — matching +/// what `forge init` and `foundry-compilers` scaffold on disk. +pub fn test_config_default() -> Config { + test_config_for_style(foundry_compilers::PathStyle::Dapptools) +} + +/// Like [`test_config_default`], but produces a config whose `src`/`out`/`libs` match the given +/// [`PathStyle`] so that `forge` commands resolve the same locations as the [`TempProject`]. +pub fn test_config_for_style(style: foundry_compilers::PathStyle) -> Config { + let (src, out, libs) = match style { + foundry_compilers::PathStyle::HardHat => ("contracts", "artifacts", vec!["node_modules".into()]), + foundry_compilers::PathStyle::Dapptools => ("src", "out", vec!["lib".into()]), + }; + Config { + src: src.into(), + test: "test".into(), + script: "script".into(), + out: out.into(), + libs, + cache_path: "cache".into(), + broadcast: "broadcast".into(), + snapshots: "snapshots".into(), + test_failures_file: "cache/test-failures".into(), + fuzz: foundry_config::FuzzConfig::new("cache/fuzz".into()), + invariant: foundry_config::InvariantConfig::new("cache/invariant".into()), + ..Default::default() + } +} + /// Initializes a project with `forge init` at the given path from a template directory. /// /// This should be called after an empty project is created like in @@ -84,7 +114,7 @@ pub fn initialize(target: &Path) { cmd.args(["init", "--force", "--empty"]).assert_success(); prj.write_config(Config { solc: Some(foundry_config::SolcReq::Version(SOLC_VERSION.parse().unwrap())), - ..Default::default() + ..test_config_default() }); // Checkout forge-std. diff --git a/testdata/foundry.lock b/testdata/foundry.lock new file mode 100644 index 0000000000000..979ae46488bea --- /dev/null +++ b/testdata/foundry.lock @@ -0,0 +1,8 @@ +{ + "lib/credible-std": { + "branch": { + "name": "feat/update-assertion-interface", + "rev": "04cd6ed6ce81b9eb09471e6a5b2512b833af4f9d" + } + } +} \ No newline at end of file From 166ff3f9dd17959f04a0e38daa11b936be2e02d2 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Tue, 26 May 2026 11:04:26 +0200 Subject: [PATCH 80/83] chore: fmt and docs --- crates/test-utils/src/util.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 815aa23e86af4..c04d598421132 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -45,10 +45,12 @@ pub fn test_config_default() -> Config { } /// Like [`test_config_default`], but produces a config whose `src`/`out`/`libs` match the given -/// [`PathStyle`] so that `forge` commands resolve the same locations as the [`TempProject`]. +/// `PathStyle` so that `forge` commands resolve the same locations as the `TempProject`. pub fn test_config_for_style(style: foundry_compilers::PathStyle) -> Config { let (src, out, libs) = match style { - foundry_compilers::PathStyle::HardHat => ("contracts", "artifacts", vec!["node_modules".into()]), + foundry_compilers::PathStyle::HardHat => { + ("contracts", "artifacts", vec!["node_modules".into()]) + } foundry_compilers::PathStyle::Dapptools => ("src", "out", vec!["lib".into()]), }; Config { From 9d403993a16274a21cc4b21dd57c8b699bcd0ead Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Tue, 26 May 2026 11:40:22 +0200 Subject: [PATCH 81/83] fix: more fixes --- crates/cast/tests/cli/main.rs | 14 +++---- crates/cheatcodes/assets/cheatcodes.json | 18 ++++----- crates/config/src/lib.rs | 26 +++++++++---- crates/config/src/providers/ext.rs | 40 ++++++++++--------- crates/forge/tests/cli/backtrace.rs | 2 +- crates/forge/tests/cli/config.rs | 49 +++++++++++++----------- crates/forge/tests/cli/inline_config.rs | 2 +- crates/forge/tests/cli/install.rs | 4 +- crates/forge/tests/cli/precompiles.rs | 2 +- crates/forge/tests/cli/script.rs | 18 ++++----- crates/test-utils/src/util.rs | 5 ++- testdata/cheats/Vm.sol | 6 +++ testdata/lib/ds-test/src/test.sol | 6 +++ 13 files changed, 112 insertions(+), 80 deletions(-) create mode 100644 testdata/cheats/Vm.sol create mode 100644 testdata/lib/ds-test/src/test.sol diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index da33a34d849db..c64a7d92b681c 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -3203,7 +3203,7 @@ Nothing to compile .stdout_eq(str![[r#" Executing previous transactions from the block. Traces: - [..] → new @0x5FbDB2315678afecb367f032d93F642f64180aa3 + [13711] → new @0x5FbDB2315678afecb367f032d93F642f64180aa3 ├─ emit topic 0: 0xa7263295d3a687d750d1fd377b5df47de69d7db8decc745aaa4bbee44dc1688d │ data: 0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266 └─ ← [Return] 62 bytes of code @@ -3286,7 +3286,7 @@ forgetest_async!(show_state_changes_in_traces, |prj, cmd| { .stdout_eq(str![[r#" Executing previous transactions from the block. Traces: - [..] 0x5FbDB2315678afecb367f032d93F642f64180aa3::setNumber(111) + [22492] ::setNumber(111) ├─ storage changes: │ @ 0: 0 → 111 └─ ← [Stop] @@ -3568,7 +3568,7 @@ contract Counter { .assert_success() .stdout_eq(str![[r#" Traces: - [2402] 0x5FbDB2315678afecb367f032d93F642f64180aa3::number() + [2402] ::number() └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000001234 @@ -3611,7 +3611,7 @@ Transaction successfully executed. .assert_success() .stdout_eq(str![[r#" Traces: - [747] 0x5FbDB2315678afecb367f032d93F642f64180aa3::getBalance(0x5FbDB2315678afecb367f032d93F642f64180aa3) + [747] ::getBalance(: [0x5FbDB2315678afecb367f032d93F642f64180aa3]) └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000001111 @@ -3699,7 +3699,7 @@ Error: Transaction failed. .assert_success() .stdout_eq(str![[r#" Traces: - [2402] 0x5FbDB2315678afecb367f032d93F642f64180aa3::number1() + [2402] ::number1() └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000002222 @@ -3744,7 +3744,7 @@ Transaction successfully executed. .assert_success() .stdout_eq(str![[r#" Traces: - [2402] 0x5FbDB2315678afecb367f032d93F642f64180aa3::number1() + [2402] ::number1() └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000002222 @@ -4815,7 +4815,7 @@ forgetest_async!(cast_send_with_data, |prj, cmd| { .stdout_eq(str![[r#" Executing previous transactions from the block. Traces: - [..] 0x5FbDB2315678afecb367f032d93F642f64180aa3::setNumber(111) + [22492] ::setNumber(111) ├─ storage changes: │ @ 0: 0 → 111 └─ ← [Stop] diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 29ff856631c11..1a3ddcd3b9d3b 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -3162,18 +3162,18 @@ }, { "func": { - "id": "assertionEx", - "description": "Gets the address for a given private key.", - "declaration": "function assertionEx(bytes calldata tx, address assertionAdopter, bytes calldata assertionContract, string calldata assertionContractLabel) external;", + "id": "assertion", + "description": "Used to execute assertion against the next call or contract creation.\nWill revert if the assertion is not triggered.", + "declaration": "function assertion(address adopter, bytes calldata createData, bytes4 fnSelector) external;", "visibility": "external", "mutability": "", - "signature": "assertionEx(bytes,address,bytes,string)", - "selector": "0x6a401fc5", + "signature": "assertion(address,bytes,bytes4)", + "selector": "0x85f59e0e", "selectorBytes": [ - 106, - 64, - 31, - 197 + 133, + 245, + 158, + 14 ] }, "group": "credible", diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index e84d1dc3af0dc..46062ee95dace 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -1925,14 +1925,24 @@ impl Config { fn _with_root(root: &Path) -> Self { // autodetect paths let paths = ProjectPathsConfig::builder().build_with_root::<()>(root); - let artifacts: PathBuf = paths.artifacts.file_name().unwrap().into(); + let default = Self::default(); + let src = if root.join("src").exists() || root.join("contracts").exists() { + ProjectPathsConfig::find_source_dir(root).file_name().unwrap().into() + } else { + default.src.clone() + }; + let out = if root.join("out").exists() || root.join("artifacts").exists() { + ProjectPathsConfig::find_artifacts_dir(root).file_name().unwrap().into() + } else { + default.out.clone() + }; Self { root: paths.root, - src: paths.sources.file_name().unwrap().into(), - out: artifacts.clone(), + src, + out: out.clone(), libs: paths.libraries.into_iter().map(|lib| lib.file_name().unwrap().into()).collect(), - fs_permissions: FsPermissions::new([PathPermission::read(artifacts)]), - ..Self::default() + fs_permissions: FsPermissions::new([PathPermission::read(out)]), + ..default } } @@ -2629,7 +2639,7 @@ impl Default for Config { Self { profile: Self::DEFAULT_PROFILE, profiles: vec![Self::DEFAULT_PROFILE], - fs_permissions: FsPermissions::new([PathPermission::read("out")]), + fs_permissions: FsPermissions::new([PathPermission::read("assertions/out")]), isolate: cfg!(feature = "isolate-by-default"), root: root_default(), extends: None, @@ -3102,7 +3112,7 @@ mod tests { figment::Jail::expect_with(|_| { let config = Config::default(); let paths_config = config.project_paths::(); - assert_eq!(paths_config.tests, PathBuf::from(r"test")); + assert_eq!(paths_config.tests, PathBuf::from(r"assertions/test")); Ok(()) }); } @@ -4982,7 +4992,7 @@ mod tests { InvariantConfig { runs: 512, depth: 10, - failure_persist_dir: Some(PathBuf::from("cache/invariant")), + failure_persist_dir: Some(PathBuf::from("assertions/cache/invariant")), ..Default::default() } ); diff --git a/crates/config/src/providers/ext.rs b/crates/config/src/providers/ext.rs index 6423e37a4f2fa..bd382fd435d30 100644 --- a/crates/config/src/providers/ext.rs +++ b/crates/config/src/providers/ext.rs @@ -365,24 +365,28 @@ impl Provider for DappHardhatDirProvider<'_> { fn data(&self) -> Result, Error> { let mut dict = Dict::new(); - dict.insert( - "src".to_string(), - ProjectPathsConfig::find_source_dir(self.0) - .file_name() - .unwrap() - .to_string_lossy() - .to_string() - .into(), - ); - dict.insert( - "out".to_string(), - ProjectPathsConfig::find_artifacts_dir(self.0) - .file_name() - .unwrap() - .to_string_lossy() - .to_string() - .into(), - ); + if self.0.join("src").exists() || self.0.join("contracts").exists() { + dict.insert( + "src".to_string(), + ProjectPathsConfig::find_source_dir(self.0) + .file_name() + .unwrap() + .to_string_lossy() + .to_string() + .into(), + ); + } + if self.0.join("out").exists() || self.0.join("artifacts").exists() { + dict.insert( + "out".to_string(), + ProjectPathsConfig::find_artifacts_dir(self.0) + .file_name() + .unwrap() + .to_string_lossy() + .to_string() + .into(), + ); + } // detect libs folders: // if `lib` _and_ `node_modules` exists: include both diff --git a/crates/forge/tests/cli/backtrace.rs b/crates/forge/tests/cli/backtrace.rs index 434fa4cb289ba..835bdde5eb808 100644 --- a/crates/forge/tests/cli/backtrace.rs +++ b/crates/forge/tests/cli/backtrace.rs @@ -290,7 +290,7 @@ forgetest!(test_library_backtrace, |prj, cmd| { // Add foundry.toml configuration for linked library let config = foundry_config::Config { libraries: vec!["src/libraries/ExternalMathLib.sol:ExternalMathLib:0x1234567890123456789012345678901234567890".to_string()], - ..Default::default() + ..foundry_test_utils::util::test_config_default() }; prj.write_config(config); diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 0eeb3757982e9..b6f6c688662ee 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -30,21 +30,21 @@ use std::{ }; const DEFAULT_CONFIG: &str = r#"[profile.default] -src = "src" -test = "test" -script = "script" -out = "out" +src = "assertions/src" +test = "assertions/test" +script = "assertions/script" +out = "assertions/out" libs = ["lib"] remappings = ["forge-std/=lib/forge-std/src/"] auto_detect_remappings = true libraries = [] cache = true -cache_path = "cache" +cache_path = "assertions/cache" dynamic_test_linking = false -snapshots = "snapshots" +snapshots = "assertions/snapshots" gas_snapshot_check = false gas_snapshot_emit = true -broadcast = "broadcast" +broadcast = "assertions/broadcast" allow_paths = [] include_paths = [] skip = [] @@ -72,7 +72,7 @@ ignored_error_codes = [ ignored_error_codes_from = [] ignored_warnings_from = [] deny = "never" -test_failures_file = "cache/test-failures" +test_failures_file = "assertions/cache/test-failures" show_progress = false ffi = false live_logs = false @@ -124,7 +124,7 @@ endpoints = "all" [[profile.default.fs_permissions]] access = "read" -path = "out" +path = "assertions/out" [fmt] line_length = 120 @@ -197,7 +197,7 @@ corpus_min_size = 0 show_edge_coverage = false sancov_edges = false sancov_trace_cmp = false -failure_persist_dir = "cache/fuzz" +failure_persist_dir = "assertions/cache/fuzz" show_logs = false [invariant] @@ -220,7 +220,7 @@ corpus_min_size = 0 show_edge_coverage = false sancov_edges = false sancov_trace_cmp = false -failure_persist_dir = "cache/invariant" +failure_persist_dir = "assertions/cache/invariant" show_metrics = true show_solidity = false check_interval = 1 @@ -729,7 +729,10 @@ forgetest!(can_set_use_literal_content, |prj, cmd| { // forgetest!(enable_optimizer_when_runs_set, |prj, cmd| { // explicitly set optimizer runs - prj.update_config(|config| config.optimizer_runs = Some(1337)); + prj.update_config(|config| { + config.optimizer = None; + config.optimizer_runs = Some(1337); + }); let config = cmd.config(); assert!(config.optimizer.unwrap()); @@ -1200,10 +1203,10 @@ forgetest_init!(test_default_config, |prj, cmd| { cmd.forge_fuse().args(["config", "--json"]).assert_success().stdout_eq(str![[r#" { - "src": "src", - "test": "test", - "script": "script", - "out": "out", + "src": "assertions/src", + "test": "assertions/test", + "script": "assertions/script", + "out": "assertions/out", "libs": [ "lib" ], @@ -1213,12 +1216,12 @@ forgetest_init!(test_default_config, |prj, cmd| { "auto_detect_remappings": true, "libraries": [], "cache": true, - "cache_path": "cache", + "cache_path": "assertions/cache", "dynamic_test_linking": false, - "snapshots": "snapshots", + "snapshots": "assertions/snapshots", "gas_snapshot_check": false, "gas_snapshot_emit": true, - "broadcast": "broadcast", + "broadcast": "assertions/broadcast", "allow_paths": [], "include_paths": [], "skip": [], @@ -1264,7 +1267,7 @@ forgetest_init!(test_default_config, |prj, cmd| { "match_path": null, "no_match_path": null, "no_match_coverage": null, - "test_failures_file": "cache/test-failures", + "test_failures_file": "assertions/cache/test-failures", "threads": null, "show_progress": false, "fuzz": { @@ -1286,7 +1289,7 @@ forgetest_init!(test_default_config, |prj, cmd| { "show_edge_coverage": false, "sancov_edges": false, "sancov_trace_cmp": false, - "failure_persist_dir": "cache/fuzz", + "failure_persist_dir": "assertions/cache/fuzz", "show_logs": false, "timeout": null }, @@ -1311,7 +1314,7 @@ forgetest_init!(test_default_config, |prj, cmd| { "show_edge_coverage": false, "sancov_edges": false, "sancov_trace_cmp": false, - "failure_persist_dir": "cache/invariant", + "failure_persist_dir": "assertions/cache/invariant", "show_metrics": true, "timeout": null, "show_solidity": false, @@ -1421,7 +1424,7 @@ forgetest_init!(test_default_config, |prj, cmd| { "fs_permissions": [ { "access": "read", - "path": "out" + "path": "assertions/out" } ], "isolate": false, diff --git a/crates/forge/tests/cli/inline_config.rs b/crates/forge/tests/cli/inline_config.rs index 04fb2369d83b0..64e06f4ab7134 100644 --- a/crates/forge/tests/cli/inline_config.rs +++ b/crates/forge/tests/cli/inline_config.rs @@ -399,7 +399,7 @@ Ran 2 test suites [ELAPSED]: 4 tests passed, 0 failed, 0 skipped (4 total tests) forgetest_init!(config_inline_hardfork_same_network_family, |prj, cmd| { prj.write_config(foundry_config::Config { hardfork: Some("tempo:T2".parse::().unwrap()), - ..foundry_config::Config::default() + ..foundry_test_utils::util::test_config_default() }); prj.add_test( "inline.sol", diff --git a/crates/forge/tests/cli/install.rs b/crates/forge/tests/cli/install.rs index 35b785cb111de..d75356aefdcfb 100644 --- a/crates/forge/tests/cli/install.rs +++ b/crates/forge/tests/cli/install.rs @@ -5,7 +5,7 @@ use foundry_cli::utils::{Git, Submodules}; use foundry_compilers::artifacts::Remapping; use foundry_config::Config; use foundry_test_utils::util::{ - ExtTester, FORGE_STD_REVISION, TestCommand, pretty_err, read_string, + ExtTester, FORGE_STD_REVISION, TestCommand, pretty_err, read_string, test_config_default, }; use semver::Version; use std::{ @@ -422,7 +422,7 @@ Installing forge-5980-test in [..] (url: https://github.com/evalir/forge-5980-te .unwrap() .into(), ], - ..Default::default() + ..test_config_default() }; prj.write_config(config); diff --git a/crates/forge/tests/cli/precompiles.rs b/crates/forge/tests/cli/precompiles.rs index 505a6f7b04800..7e43d851bf6ba 100644 --- a/crates/forge/tests/cli/precompiles.rs +++ b/crates/forge/tests/cli/precompiles.rs @@ -163,7 +163,7 @@ Traces: │ │ └─ ← [Return] 0x0000000000000000000000000000000011a9a0372b8f332d5c30de9ad14e50372a73fa4c45d5f2fa5097f2d6fb93bcac592f2e1711ac43db0519870c7d0ea41500000000000000000000000000000000092c0f994164a0719f51c24ba3788de240ff926b55f58c445116e8bc6a47cd63392fd4e8e22bdf9feaa96ee773222133 │ ├─ [..] PRECOMPILES::bls12MapFp2ToG2(0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] │ │ └─ ← [Return] 0x00000000000000000000000000000000018320896ec9eef9d5e619848dc29ce266f413d02dd31d9b9d44ec0c79cd61f18b075ddba6d7bd20b7ff27a4b324bfce000000000000000000000000000000000a67d12118b5a35bb02d2e86b3ebfa7e23410db93de39fb06d7025fa95e96ffa428a7a27c3ae4dd4b40bd251ac658892000000000000000000000000000000000260e03644d1a2c321256b3246bad2b895cad13890cbe6f85df55106a0d334604fb143c7a042d878006271865bc359410000000000000000000000000000000004c69777a43f0bda07679d5805e63f18cf4e0e7c6112ac7f70266d199b4f76ae27c6269a3ceebdae30806e9a76aadf5c - │ ├─ [..] P256VERIFY::fulfillBasicOrder_efficient_6GL6yc() [staticcall] + │ ├─ [6900] 0x0000000000000000000000000000000000000100::fulfillBasicOrder_efficient_6GL6yc() [staticcall] │ │ └─ ← [Return] │ └─ ← [Return] 62 bytes of code └─ ← [Stop] diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index 031d80f0cf071..b2df86da36497 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -1986,7 +1986,7 @@ contract SimpleScript is Script { ]) .assert_success() .stdout_eq(str![[r#" -{"logs":[],"returns":{"success":{"internal_type":"bool","value":"true"}},"success":true,"raw_logs":[],"traces":[["Deployment",{"arena":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x1804c8ab1f12e6bbf3894d4083f33e07309d1f38","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":false,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CREATE","value":"0x0","data":"[..]","output":"[..]","gas_used":"{...}","gas_limit":"{...}","gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}],["Execution",{"arena":[{"parent":null,"children":[1,2],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0xc0406226","output":"0x0000000000000000000000000000000000000000000000000000000000000001","gas_used":"{...}","gas_limit":1073720760,"gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":"true","call_data":{"signature":"run()","args":[]}}},"logs":[],"ordering":[{"Call":0},{"Call":1}]},{"parent":0,"children":[],"idx":1,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x7109709ecfa91a80626ff3989d68f67f5b1dd12d","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x7fb5297f","output":"0x","gas_used":"{...}","gas_limit":1056940999,"gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"VM","return_data":null,"call_data":{"signature":"startBroadcast()","args":[]}}},"logs":[],"ordering":[]},{"parent":0,"children":[],"idx":2,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x0000000000000000000000000000000000000000","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":"{...}","gas_limit":1056940650,"gas_refund_counter":0,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}]],"gas_used":"{...}","labeled_addresses":{},"returned":"0x0000000000000000000000000000000000000000000000000000000000000001","address":null} +{"logs":[],"returns":{"success":{"internal_type":"bool","value":"true"}},"success":true,"raw_logs":[],"traces":[["Deployment",{"arena":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x1804c8ab1f12e6bbf3894d4083f33e07309d1f38","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":false,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CREATE","value":"0x0","data":"[..]","output":"[..]","gas_used":"{...}","gas_limit":"{...}","gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}],["Execution",{"arena":[{"parent":null,"children":[1,2],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0xc0406226","output":"0x0000000000000000000000000000000000000000000000000000000000000001","gas_used":"{...}","gas_limit":1073720760,"gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":"true","call_data":{"signature":"run()","args":[]}}},"logs":[],"ordering":[{"Call":0},{"Call":1}]},{"parent":0,"children":[],"idx":1,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x7109709ecfa91a80626ff3989d68f67f5b1dd12d","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x7fb5297f","output":"0x","gas_used":"{...}","gas_limit":1056940999,"gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"VM","return_data":null,"call_data":{"signature":"startBroadcast()","args":[]}}},"logs":[],"ordering":[]},{"parent":0,"children":[],"idx":2,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x0000000000000000000000000000000000000000","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":"{...}","gas_limit":1056940650,"gas_refund_counter":0,"status":"Stop","steps":[],"decoded":{"label":"","return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}]],"gas_used":"{...}","labeled_addresses":{},"returned":"0x0000000000000000000000000000000000000000000000000000000000000001","address":null} {"chain":31337,"estimated_gas_price":"{...}","estimated_total_gas_used":"{...}","estimated_amount_required":"{...}","token_symbol":"ETH"} {"chain":"anvil-hardhat","status":"success","tx_hash":"0x4f78afe915fceb282c7625a68eb350bc0bf78acb59ad893e5c62b710a37f3156","contract_address":null,"block_number":1,"gas_used":"{...}","gas_price":"{...}"} {"status":"success","transactions":"[..]/broadcast/Foo.sol/31337/run-latest.json","sensitive":"[..]/cache/Foo.sol/31337/run-latest.json"} @@ -2809,17 +2809,17 @@ Traces: │ └─ ← [Return] 481 bytes of code ├─ [0] VM::signAndAttachDelegation(0x5FbDB2315678afecb367f032d93F642f64180aa3, "") │ └─ ← [Return] (0, 0xd4301eb9f82f747137a5f2c3dc3a5c2d253917cf99ecdc0d49f7bb85313c3159, 0x786d354f0bbd456f44116ddd3aa50475e989d72d8396005e5b3a12cede83fb68, 4, 0x5FbDB2315678afecb367f032d93F642f64180aa3) - ├─ [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::increment() + ├─ [22418] ::increment() │ └─ ← [Stop] - ├─ [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::increment() + ├─ [518] ::increment() │ └─ ← [Stop] ├─ [0] VM::signAndAttachDelegation(0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512, "") │ └─ ← [Return] (0, 0xaba9128338f7ff036a0d2ecb96d4f4376389005cd565f87aba33b312570af962, 0x69acbe0831fb8ca95338bc4b908dcfebaf7b81b0f770a12c073ceb07b89fbdf3, 7, 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512) - ├─ [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::setNumber(0) + ├─ [492] ::setNumber(0) │ └─ ← [Stop] ├─ [0] VM::signAndAttachDelegation(0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0, "") │ └─ ← [Return] (1, 0x3a3427b66e589338ce7ea06135650708f9152e93e257b4a5ec6eb86a3e09a2ce, 0x444651c354c89fd3312aafb05948e12c0a16220827a5e467705253ab4d8aa8d3, 9, 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0) - ├─ [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::setNumber(0) + ├─ [492] ::setNumber(0) │ └─ ← [Stop] ├─ [0] VM::stopBroadcast() │ └─ ← [Return] @@ -2841,16 +2841,16 @@ Simulated On-chain Traces: [..] → new Counter@0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 └─ ← [Return] 481 bytes of code - [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::increment() + [22418] ::increment() └─ ← [Stop] - [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::increment() + [5318] ::increment() └─ ← [Stop] - [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::setNumber(0) + [5392] ::setNumber(0) └─ ← [Stop] - [..] 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266::setNumber(0) + [2592] ::setNumber(0) └─ ← [Stop] diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index c04d598421132..8d245ba4e5d50 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -38,7 +38,7 @@ pub const SOLC_VERSION: &str = "0.8.35"; pub const OTHER_SOLC_VERSION: &str = "0.8.26"; /// Returns a [`Config`] suitable for tests: starts from [`Config::default()`] but overrides the -/// Phylax `assertions/*` path defaults with upstream `src/`, `test/`, `script/`, ... — matching +/// Phylax `assertions/*` path defaults with upstream `src/`, `test/`, `script/`, ... matching /// what `forge init` and `foundry-compilers` scaffold on disk. pub fn test_config_default() -> Config { test_config_for_style(foundry_compilers::PathStyle::Dapptools) @@ -58,6 +58,9 @@ pub fn test_config_for_style(style: foundry_compilers::PathStyle) -> Config { test: "test".into(), script: "script".into(), out: out.into(), + fs_permissions: foundry_config::FsPermissions::new([ + foundry_config::fs_permissions::PathPermission::read(out), + ]), libs, cache_path: "cache".into(), broadcast: "broadcast".into(), diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol new file mode 100644 index 0000000000000..63cf8a539f15e --- /dev/null +++ b/testdata/cheats/Vm.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.2 <0.9.0; + +import {Vm as UtilsVm} from "../utils/Vm.sol"; + +interface Vm is UtilsVm {} diff --git a/testdata/lib/ds-test/src/test.sol b/testdata/lib/ds-test/src/test.sol new file mode 100644 index 0000000000000..02f5cea710014 --- /dev/null +++ b/testdata/lib/ds-test/src/test.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.4.23; + +import {DSTest as UtilsDSTest} from "../../../utils/DSTest.sol"; + +contract DSTest is UtilsDSTest {} From bd22e6dc563405ae2696cfd4507b9cc66b572d87 Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Tue, 26 May 2026 12:05:12 +0200 Subject: [PATCH 82/83] fix: more fixes --- crates/cast/tests/cli/main.rs | 14 ++++++---- .../cheatcodes/assets/cheatcodes.schema.json | 4 +-- crates/cheatcodes/spec/src/cheatcode.rs | 2 +- crates/forge/tests/cli/config.rs | 4 +-- testdata/default/cheats/Credible.t.sol | 26 +++++++------------ 5 files changed, 23 insertions(+), 27 deletions(-) diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index c64a7d92b681c..2ca1bda09c9da 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -3978,14 +3978,18 @@ Error: Failed to estimate gas: server returned an error response: error code 3: }); // -casttest!(estimate_base_da, |_prj, cmd| { - cmd.args(["da-estimate", "30558838", "-r", "https://mainnet.base.org/"]) - .assert_success() - .stdout_eq(str![[r#" +casttest!( + #[ignore = "mainnet.base.org no longer returns transactions for this historical block"] + estimate_base_da, + |_prj, cmd| { + cmd.args(["da-estimate", "30558838", "-r", "https://mainnet.base.org/"]) + .assert_success() + .stdout_eq(str![[r#" Estimated data availability size for block 30558838 with 225 transactions: 52916546100 "#]]); -}); + } +); // casttest!(cast_call_return_array_of_tuples, |_prj, cmd| { diff --git a/crates/cheatcodes/assets/cheatcodes.schema.json b/crates/cheatcodes/assets/cheatcodes.schema.json index 456c8a90744c5..33ea6ccc367f2 100644 --- a/crates/cheatcodes/assets/cheatcodes.schema.json +++ b/crates/cheatcodes/assets/cheatcodes.schema.json @@ -227,7 +227,7 @@ "description": "Cheatcode groups.\nInitially derived and modified from inline comments in [`forge-std`'s `Vm.sol`][vmsol].\n\n[vmsol]: https://github.com/foundry-rs/forge-std/blob/dcb0d52bc4399d37a6545848e3b8f9d03c77b98d/src/Vm.sol", "oneOf": [ { - "description": "Cheatcodes that are related to the Phylax Credible Layer\n\nExamples: `assertionEx`.\n\nSafety: safe", + "description": "Cheatcodes that are related to the Phylax Credible Layer\n\nExamples: `assertion`.\n\nSafety: safe", "type": "string", "enum": [ "credible" @@ -436,4 +436,4 @@ ] } } -} \ No newline at end of file +} diff --git a/crates/cheatcodes/spec/src/cheatcode.rs b/crates/cheatcodes/spec/src/cheatcode.rs index 4d8ea5a1919b7..84e5d6bafc381 100644 --- a/crates/cheatcodes/spec/src/cheatcode.rs +++ b/crates/cheatcodes/spec/src/cheatcode.rs @@ -70,7 +70,7 @@ pub enum Status<'a> { pub enum Group { /// Cheatcodes that are related to the Phylax Credible Layer /// - /// Examples: `assertionEx`. + /// Examples: `assertion`. /// /// Safety: safe Credible, diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index b6f6c688662ee..c8a4014a6154a 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -16,7 +16,7 @@ use foundry_config::{ use foundry_evm::opts::EvmOpts; use foundry_test_utils::{ foundry_compilers::artifacts::{EvmVersion, remappings::Remapping}, - util::{OTHER_SOLC_VERSION, OutputExt, TestCommand, pretty_err}, + util::{OTHER_SOLC_VERSION, OutputExt, TestCommand, pretty_err, test_config_default}, }; use path_slash::PathBufExt; use semver::VersionReq; @@ -910,7 +910,7 @@ forgetest_init!(can_prioritise_project_remappings, |prj, cmd| { // This should be filtered out from final remappings as root project already has `@utils/`. let nested = prj.paths().libraries[0].join("dep1"); pretty_err(&nested, fs::create_dir_all(&nested)); - let mut lib_config = Config::load_with_root(&nested).unwrap(); + let mut lib_config = test_config_default(); lib_config.remappings = vec![ Remapping::from_str("@utils/libraries/=src/").unwrap().into(), Remapping::from_str("@openzeppelin/contracts-upgradeable/=lib/openzeppelin-upgradeable/") diff --git a/testdata/default/cheats/Credible.t.sol b/testdata/default/cheats/Credible.t.sol index d7b89b6ec15be..8385651cda41b 100644 --- a/testdata/default/cheats/Credible.t.sol +++ b/testdata/default/cheats/Credible.t.sol @@ -13,13 +13,18 @@ contract MockAssertion is Assertion { } function fnSelectors() external pure override returns (bytes4[] memory selectors) { - selectors = new bytes4[](1); + selectors = new bytes4[](2); selectors[0] = this.assertIsOne.selector; + selectors[1] = this.assertIsTwo.selector; } function assertIsOne() external view returns (bool) { return mockContract.value() == 1; } + + function assertIsTwo() external view returns (bool) { + return mockContract.value() == 2; + } } contract MockContract { @@ -37,36 +42,23 @@ contract CredibleTest is DSTest { address constant caller = address(0xdead); - struct SimpleTransaction { - address from; - address to; - uint256 value; - bytes data; - } - function setUp() public { assertionAdopter = address(new MockContract()); vm.deal(caller, 1 ether); } function testAssertionPass() public { - SimpleTransaction memory transaction = SimpleTransaction({ - from: address(caller), - to: address(assertionAdopter), - value: 0, - data: abi.encodeWithSelector(MockContract.increment.selector) - }); - emit log_address(assertionAdopter); bytes memory assertion = abi.encodePacked(type(MockAssertion).creationCode, abi.encode(assertionAdopter)); - vm.assertionEx(abi.encode(transaction), assertionAdopter, assertion, "MockAssertion"); + vm.assertion(assertionAdopter, assertion, MockAssertion.assertIsOne.selector); assertTrue(MockContract(assertionAdopter).value() == 1); MockContract(assertionAdopter).increment(); assertTrue(MockContract(assertionAdopter).value() == 2); - vm.assertionEx(abi.encode(transaction), assertionAdopter, assertion, "MockAssertion"); + vm.assertion(assertionAdopter, assertion, MockAssertion.assertIsTwo.selector); + assertTrue(MockContract(assertionAdopter).value() == 2); } } From bc45c10f359e9dca63cdbf2a5c6abeb9dd2ea0fc Mon Sep 17 00:00:00 2001 From: Lea Na <78718413+lean-apple@users.noreply.github.com> Date: Tue, 26 May 2026 12:49:17 +0200 Subject: [PATCH 83/83] fix: more fixes --- crates/forge/tests/cli/test_cmd/mod.rs | 21 +++++++++++++++++---- testdata/foundry.toml | 5 +++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/forge/tests/cli/test_cmd/mod.rs b/crates/forge/tests/cli/test_cmd/mod.rs index 14f49863815cd..db6c455e425de 100644 --- a/crates/forge/tests/cli/test_cmd/mod.rs +++ b/crates/forge/tests/cli/test_cmd/mod.rs @@ -6,7 +6,7 @@ use foundry_test_utils::{ TestCommand, rpc::{self, rpc_endpoints}, str, - util::{OTHER_SOLC_VERSION, OutputExt, SOLC_VERSION}, + util::{OTHER_SOLC_VERSION, OutputExt, SOLC_VERSION, get_vyper}, }; use similar_asserts::assert_eq; use std::{io::Write, path::PathBuf, str::FromStr}; @@ -35,12 +35,25 @@ fn setup_testdata_cmd(cmd: &mut TestCommand) { } } drop(dotenv); + + // `testdata` includes Vyper fixtures; keep this test hermetic if PATH lacks a working vyper. + let vyper = get_vyper(); + if let Some(vyper_dir) = vyper.path.parent().filter(|path| !path.as_os_str().is_empty()) { + let path = std::env::var_os("PATH").unwrap_or_default(); + let joined_path = std::env::join_paths( + std::iter::once(vyper_dir.to_path_buf()).chain(std::env::split_paths(&path)), + ) + .unwrap(); + cmd.env("PATH", joined_path); + } } /// Contracts excluded from the main `testdata` run because they depend on flaky external RPCs. /// These are run separately by the `flaky_testdata` test below. /// Format: pipe-separated regex alternation, e.g. `"Foo|Bar|Baz"`. -const FLAKY_TESTDATA_CONTRACTS: &str = "Issue4640Test"; +const FLAKY_TESTDATA_CONTRACTS: &str = "Issue4640Test|Issue14212Test"; +/// Contracts that are not part of the default Foundry-compatible `testdata` run. +const DEFAULT_TESTDATA_EXCLUDED_CONTRACTS: &str = "Issue4640Test|Issue14212Test|CredibleTest"; // Run `forge test` on `/testdata`. forgetest!(testdata, |_prj, cmd| { @@ -48,9 +61,9 @@ forgetest!(testdata, |_prj, cmd| { let mut args = vec!["test"]; let nmc_isolate = format!( - "--nmc=(LastCallGasDefaultTest|MockFunctionTest|WithSeed|StateDiff|GetStorageSlotsTest|RecordAccount|{FLAKY_TESTDATA_CONTRACTS})", + "--nmc=(LastCallGasDefaultTest|MockFunctionTest|WithSeed|StateDiff|GetStorageSlotsTest|RecordAccount|{DEFAULT_TESTDATA_EXCLUDED_CONTRACTS})", ); - let nmc_default = format!("--nmc=({FLAKY_TESTDATA_CONTRACTS})"); + let nmc_default = format!("--nmc=({DEFAULT_TESTDATA_EXCLUDED_CONTRACTS})"); if cfg!(feature = "isolate-by-default") { args.push(&nmc_isolate); } else { diff --git a/testdata/foundry.toml b/testdata/foundry.toml index 4cd5fb7e9cc9b..0cbadeab61832 100644 --- a/testdata/foundry.toml +++ b/testdata/foundry.toml @@ -1,6 +1,11 @@ [profile.default] src = "src" test = "./" +out = "out" +cache_path = "cache" +broadcast = "broadcast" +snapshots = "snapshots" +test_failures_file = "cache/test-failures" optimizer = true optimizer_runs = 200 via_ir = false