diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 88698e13cc08..1f005d4436b1 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -1913,7 +1913,6 @@ impl EthApi { pub async fn anvil_metadata(&self) -> Result { node_info!("anvil_metadata"); let fork_config = self.backend.get_fork(); - let snapshots = self.backend.list_snapshots(); Ok(Metadata { client_version: CLIENT_VERSION.to_string(), @@ -1926,7 +1925,7 @@ impl EthApi { fork_block_number: cfg.block_number(), fork_block_hash: cfg.block_hash(), }), - snapshots, + snapshots: self.backend.list_state_snapshots(), }) } @@ -2059,7 +2058,7 @@ impl EthApi { /// Handler for RPC call: `evm_snapshot` pub async fn evm_snapshot(&self) -> Result { node_info!("evm_snapshot"); - Ok(self.backend.create_snapshot().await) + Ok(self.backend.create_state_snapshot().await) } /// Revert the state of the blockchain to a previous snapshot. @@ -2068,7 +2067,7 @@ impl EthApi { /// Handler for RPC call: `evm_revert` pub async fn evm_revert(&self, id: U256) -> Result { node_info!("evm_revert"); - self.backend.revert_snapshot(id).await + self.backend.revert_state_snapshot(id).await } /// Jump forward in time by the given amount of time, in seconds. diff --git a/crates/anvil/src/eth/backend/db.rs b/crates/anvil/src/eth/backend/db.rs index a02f9d0e31e1..0aa0f8d13cb7 100644 --- a/crates/anvil/src/eth/backend/db.rs +++ b/crates/anvil/src/eth/backend/db.rs @@ -11,7 +11,8 @@ use anvil_core::eth::{ use foundry_common::errors::FsPathError; use foundry_evm::{ backend::{ - BlockchainDb, DatabaseError, DatabaseResult, MemDb, RevertSnapshotAction, StateSnapshot, + BlockchainDb, DatabaseError, DatabaseResult, MemDb, RevertStateSnapshotAction, + StateSnapshot, }, revm::{ db::{CacheDB, DatabaseRef, DbAccount}, @@ -35,19 +36,19 @@ pub trait MaybeFullDatabase: DatabaseRef { None } - /// Clear the state and move it into a new `StateSnapshot` - fn clear_into_snapshot(&mut self) -> StateSnapshot; + /// Clear the state and move it into a new `StateSnapshot`. + fn clear_into_state_snapshot(&mut self) -> StateSnapshot; - /// Read the state snapshot + /// Read the state snapshot. /// - /// This clones all the states and returns a new `StateSnapshot` - fn read_as_snapshot(&self) -> StateSnapshot; + /// This clones all the states and returns a new `StateSnapshot`. + fn read_as_state_snapshot(&self) -> StateSnapshot; /// Clears the entire database fn clear(&mut self); - /// Reverses `clear_into_snapshot` by initializing the db's state with the snapshot - fn init_from_snapshot(&mut self, snapshot: StateSnapshot); + /// Reverses `clear_into_snapshot` by initializing the db's state with the state snapshot. + fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot); } impl<'a, T: 'a + MaybeFullDatabase + ?Sized> MaybeFullDatabase for &'a T @@ -62,17 +63,17 @@ where T::maybe_as_full_db(self) } - fn clear_into_snapshot(&mut self) -> StateSnapshot { + fn clear_into_state_snapshot(&mut self) -> StateSnapshot { unreachable!("never called for DatabaseRef") } - fn read_as_snapshot(&self) -> StateSnapshot { + fn read_as_state_snapshot(&self) -> StateSnapshot { unreachable!("never called for DatabaseRef") } fn clear(&mut self) {} - fn init_from_snapshot(&mut self, _snapshot: StateSnapshot) {} + fn init_from_state_snapshot(&mut self, _state_snapshot: StateSnapshot) {} } /// Helper trait to reset the DB if it's forked @@ -176,13 +177,13 @@ pub trait Db: Ok(true) } - /// Creates a new snapshot - fn snapshot(&mut self) -> U256; + /// Creates a new state snapshot. + fn snapshot_state(&mut self) -> U256; - /// Reverts a snapshot + /// Reverts a state snapshot. /// - /// Returns `true` if the snapshot was reverted - fn revert(&mut self, snapshot: U256, action: RevertSnapshotAction) -> bool; + /// Returns `true` if the state snapshot was reverted. + fn revert_state(&mut self, state_snapshot: U256, action: RevertStateSnapshotAction) -> bool; /// Returns the state root if possible to compute fn maybe_state_root(&self) -> Option { @@ -228,11 +229,11 @@ impl + Send + Sync + Clone + fmt::Debug> D Ok(None) } - fn snapshot(&mut self) -> U256 { + fn snapshot_state(&mut self) -> U256 { U256::ZERO } - fn revert(&mut self, _snapshot: U256, _action: RevertSnapshotAction) -> bool { + fn revert_state(&mut self, _state_snapshot: U256, _action: RevertStateSnapshotAction) -> bool { false } @@ -250,7 +251,7 @@ impl> MaybeFullDatabase for CacheDB { Some(&self.accounts) } - fn clear_into_snapshot(&mut self) -> StateSnapshot { + fn clear_into_state_snapshot(&mut self) -> StateSnapshot { let db_accounts = std::mem::take(&mut self.accounts); let mut accounts = HashMap::new(); let mut account_storage = HashMap::new(); @@ -265,7 +266,7 @@ impl> MaybeFullDatabase for CacheDB { StateSnapshot { accounts, storage: account_storage, block_hashes } } - fn read_as_snapshot(&self) -> StateSnapshot { + fn read_as_state_snapshot(&self) -> StateSnapshot { let db_accounts = self.accounts.clone(); let mut accounts = HashMap::new(); let mut account_storage = HashMap::new(); @@ -282,11 +283,11 @@ impl> MaybeFullDatabase for CacheDB { } fn clear(&mut self) { - self.clear_into_snapshot(); + self.clear_into_state_snapshot(); } - fn init_from_snapshot(&mut self, snapshot: StateSnapshot) { - let StateSnapshot { accounts, mut storage, block_hashes } = snapshot; + fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot) { + let StateSnapshot { accounts, mut storage, block_hashes } = state_snapshot; for (addr, mut acc) in accounts { if let Some(code) = acc.code.take() { @@ -330,7 +331,7 @@ impl StateDb { pub fn serialize_state(&mut self) -> StateSnapshot { // Using read_as_snapshot makes sures we don't clear the historical state from the current // instance. - self.read_as_snapshot() + self.read_as_state_snapshot() } } @@ -362,20 +363,20 @@ impl MaybeFullDatabase for StateDb { self.0.maybe_as_full_db() } - fn clear_into_snapshot(&mut self) -> StateSnapshot { - self.0.clear_into_snapshot() + fn clear_into_state_snapshot(&mut self) -> StateSnapshot { + self.0.clear_into_state_snapshot() } - fn read_as_snapshot(&self) -> StateSnapshot { - self.0.read_as_snapshot() + fn read_as_state_snapshot(&self) -> StateSnapshot { + self.0.read_as_state_snapshot() } fn clear(&mut self) { self.0.clear() } - fn init_from_snapshot(&mut self, snapshot: StateSnapshot) { - self.0.init_from_snapshot(snapshot) + fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot) { + self.0.init_from_state_snapshot(state_snapshot) } } diff --git a/crates/anvil/src/eth/backend/mem/fork_db.rs b/crates/anvil/src/eth/backend/mem/fork_db.rs index a5f6cf455a22..a4528a8f034a 100644 --- a/crates/anvil/src/eth/backend/mem/fork_db.rs +++ b/crates/anvil/src/eth/backend/mem/fork_db.rs @@ -8,8 +8,10 @@ use crate::{ use alloy_primitives::{Address, B256, U256, U64}; use alloy_rpc_types::BlockId; use foundry_evm::{ - backend::{BlockchainDb, DatabaseError, DatabaseResult, RevertSnapshotAction, StateSnapshot}, - fork::database::ForkDbSnapshot, + backend::{ + BlockchainDb, DatabaseError, DatabaseResult, RevertStateSnapshotAction, StateSnapshot, + }, + fork::database::ForkDbStateSnapshot, revm::{primitives::BlockEnv, Database}, }; use revm::DatabaseRef; @@ -72,16 +74,16 @@ impl Db for ForkedDatabase { })) } - fn snapshot(&mut self) -> U256 { - self.insert_snapshot() + fn snapshot_state(&mut self) -> U256 { + self.insert_state_snapshot() } - fn revert(&mut self, id: U256, action: RevertSnapshotAction) -> bool { - self.revert_snapshot(id, action) + fn revert_state(&mut self, id: U256, action: RevertStateSnapshotAction) -> bool { + self.revert_state_snapshot(id, action) } fn current_state(&self) -> StateDb { - StateDb::new(self.create_snapshot()) + StateDb::new(self.create_state_snapshot()) } } @@ -90,7 +92,7 @@ impl MaybeFullDatabase for ForkedDatabase { self } - fn clear_into_snapshot(&mut self) -> StateSnapshot { + fn clear_into_state_snapshot(&mut self) -> StateSnapshot { let db = self.inner().db(); let accounts = std::mem::take(&mut *db.accounts.write()); let storage = std::mem::take(&mut *db.storage.write()); @@ -98,7 +100,7 @@ impl MaybeFullDatabase for ForkedDatabase { StateSnapshot { accounts, storage, block_hashes } } - fn read_as_snapshot(&self) -> StateSnapshot { + fn read_as_state_snapshot(&self) -> StateSnapshot { let db = self.inner().db(); let accounts = db.accounts.read().clone(); let storage = db.storage.read().clone(); @@ -108,38 +110,38 @@ impl MaybeFullDatabase for ForkedDatabase { fn clear(&mut self) { self.flush_cache(); - self.clear_into_snapshot(); + self.clear_into_state_snapshot(); } - fn init_from_snapshot(&mut self, snapshot: StateSnapshot) { + fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot) { let db = self.inner().db(); - let StateSnapshot { accounts, storage, block_hashes } = snapshot; + let StateSnapshot { accounts, storage, block_hashes } = state_snapshot; *db.accounts.write() = accounts; *db.storage.write() = storage; *db.block_hashes.write() = block_hashes; } } -impl MaybeFullDatabase for ForkDbSnapshot { +impl MaybeFullDatabase for ForkDbStateSnapshot { fn as_dyn(&self) -> &dyn DatabaseRef { self } - fn clear_into_snapshot(&mut self) -> StateSnapshot { - std::mem::take(&mut self.snapshot) + fn clear_into_state_snapshot(&mut self) -> StateSnapshot { + std::mem::take(&mut self.state_snapshot) } - fn read_as_snapshot(&self) -> StateSnapshot { - self.snapshot.clone() + fn read_as_state_snapshot(&self) -> StateSnapshot { + self.state_snapshot.clone() } fn clear(&mut self) { - std::mem::take(&mut self.snapshot); + std::mem::take(&mut self.state_snapshot); self.local.clear() } - fn init_from_snapshot(&mut self, snapshot: StateSnapshot) { - self.snapshot = snapshot; + fn init_from_state_snapshot(&mut self, state_snapshot: StateSnapshot) { + self.state_snapshot = state_snapshot; } } diff --git a/crates/anvil/src/eth/backend/mem/in_memory_db.rs b/crates/anvil/src/eth/backend/mem/in_memory_db.rs index f984b93bbbcf..01243c90f47b 100644 --- a/crates/anvil/src/eth/backend/mem/in_memory_db.rs +++ b/crates/anvil/src/eth/backend/mem/in_memory_db.rs @@ -17,7 +17,7 @@ use foundry_evm::{ // reexport for convenience pub use foundry_evm::{backend::MemDb, revm::db::DatabaseRef}; -use foundry_evm::{backend::RevertSnapshotAction, revm::primitives::BlockEnv}; +use foundry_evm::{backend::RevertStateSnapshotAction, revm::primitives::BlockEnv}; impl Db for MemDb { fn insert_account(&mut self, address: Address, account: AccountInfo) { @@ -74,22 +74,22 @@ impl Db for MemDb { } /// Creates a new snapshot - fn snapshot(&mut self) -> U256 { - let id = self.snapshots.insert(self.inner.clone()); - trace!(target: "backend::memdb", "Created new snapshot {}", id); + fn snapshot_state(&mut self) -> U256 { + let id = self.state_snapshots.insert(self.inner.clone()); + trace!(target: "backend::memdb", "Created new state snapshot {}", id); id } - fn revert(&mut self, id: U256, action: RevertSnapshotAction) -> bool { - if let Some(snapshot) = self.snapshots.remove(id) { + fn revert_state(&mut self, id: U256, action: RevertStateSnapshotAction) -> bool { + if let Some(state_snapshot) = self.state_snapshots.remove(id) { if action.is_keep() { - self.snapshots.insert_at(snapshot.clone(), id); + self.state_snapshots.insert_at(state_snapshot.clone(), id); } - self.inner = snapshot; - trace!(target: "backend::memdb", "Reverted snapshot {}", id); + self.inner = state_snapshot; + trace!(target: "backend::memdb", "Reverted state snapshot {}", id); true } else { - warn!(target: "backend::memdb", "No snapshot to revert for {}", id); + warn!(target: "backend::memdb", "No state snapshot to revert for {}", id); false } } @@ -112,20 +112,20 @@ impl MaybeFullDatabase for MemDb { Some(&self.inner.accounts) } - fn clear_into_snapshot(&mut self) -> StateSnapshot { - self.inner.clear_into_snapshot() + fn clear_into_state_snapshot(&mut self) -> StateSnapshot { + self.inner.clear_into_state_snapshot() } - fn read_as_snapshot(&self) -> StateSnapshot { - self.inner.read_as_snapshot() + fn read_as_state_snapshot(&self) -> StateSnapshot { + self.inner.read_as_state_snapshot() } fn clear(&mut self) { self.inner.clear(); } - fn init_from_snapshot(&mut self, snapshot: StateSnapshot) { - self.inner.init_from_snapshot(snapshot) + fn init_from_state_snapshot(&mut self, snapshot: StateSnapshot) { + self.inner.init_from_state_snapshot(snapshot) } } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 89cd0bd4b33c..cd23fa6d3a94 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -68,7 +68,7 @@ use anvil_rpc::error::RpcError; use alloy_chains::NamedChain; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; use foundry_evm::{ - backend::{DatabaseError, DatabaseResult, RevertSnapshotAction}, + backend::{DatabaseError, DatabaseResult, RevertStateSnapshotAction}, constants::DEFAULT_CREATE2_DEPLOYER_RUNTIME_CODE, decode::RevertDecoder, inspectors::AccessListInspector, @@ -153,26 +153,26 @@ pub struct Backend { /// need to read from it, while it's currently written to, don't block. E.g. a new block is /// currently mined and a new [`Self::set_storage_at()`] request is being executed. db: Arc>>, - /// stores all block related data in memory + /// stores all block related data in memory. blockchain: Blockchain, - /// Historic states of previous blocks + /// Historic states of previous blocks. states: Arc>, - /// env data of the chain + /// Env data of the chain env: Arc>, - /// this is set if this is currently forked off another client + /// This is set if this is currently forked off another client. fork: Arc>>, - /// provides time related info, like timestamp + /// Provides time related info, like timestamp. time: TimeManager, - /// Contains state of custom overrides + /// Contains state of custom overrides. cheats: CheatsManager, - /// contains fee data + /// Contains fee data. fees: FeeManager, - /// initialised genesis + /// Initialised genesis. genesis: GenesisConfig, - /// listeners for new blocks that get notified when a new block was imported + /// Listeners for new blocks that get notified when a new block was imported. new_block_listeners: Arc>>>, - /// keeps track of active snapshots at a specific block - active_snapshots: Arc>>, + /// Keeps track of active state snapshots at a specific block. + active_state_snapshots: Arc>>, enable_steps_tracing: bool, print_logs: bool, alphanet: bool, @@ -256,7 +256,7 @@ impl Backend { new_block_listeners: Default::default(), fees, genesis, - active_snapshots: Arc::new(Mutex::new(Default::default())), + active_state_snapshots: Arc::new(Mutex::new(Default::default())), enable_steps_tracing, print_logs, alphanet, @@ -695,21 +695,21 @@ impl Backend { self.blockchain.storage.read().total_difficulty } - /// Creates a new `evm_snapshot` at the current height + /// Creates a new `evm_snapshot` at the current height. /// - /// Returns the id of the snapshot created - pub async fn create_snapshot(&self) -> U256 { + /// Returns the id of the snapshot created. + pub async fn create_state_snapshot(&self) -> U256 { let num = self.best_number(); let hash = self.best_hash(); - let id = self.db.write().await.snapshot(); + let id = self.db.write().await.snapshot_state(); trace!(target: "backend", "creating snapshot {} at {}", id, num); - self.active_snapshots.lock().insert(id, (num, hash)); + self.active_state_snapshots.lock().insert(id, (num, hash)); id } - /// Reverts the state to the snapshot identified by the given `id`. - pub async fn revert_snapshot(&self, id: U256) -> Result { - let block = { self.active_snapshots.lock().remove(&id) }; + /// Reverts the state to the state snapshot identified by the given `id`. + pub async fn revert_state_snapshot(&self, id: U256) -> Result { + let block = { self.active_state_snapshots.lock().remove(&id) }; if let Some((num, hash)) = block { let best_block_hash = { // revert the storage that's newer than the snapshot @@ -752,11 +752,11 @@ impl Backend { ..Default::default() }; } - Ok(self.db.write().await.revert(id, RevertSnapshotAction::RevertRemove)) + Ok(self.db.write().await.revert_state(id, RevertStateSnapshotAction::RevertRemove)) } - pub fn list_snapshots(&self) -> BTreeMap { - self.active_snapshots.lock().clone().into_iter().collect() + pub fn list_state_snapshots(&self) -> BTreeMap { + self.active_state_snapshots.lock().clone().into_iter().collect() } /// Get the current state. diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index 4cb588221ae8..928fb66e4e03 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -147,8 +147,8 @@ impl InMemoryBlockStates { { // only write to disk if supported if !self.is_memory_only() { - let snapshot = state.0.clear_into_snapshot(); - self.disk_cache.write(hash, snapshot); + let state_snapshot = state.0.clear_into_state_snapshot(); + self.disk_cache.write(hash, state_snapshot); self.on_disk_states.insert(hash, state); self.oldest_on_disk.push_back(hash); } @@ -170,7 +170,7 @@ impl InMemoryBlockStates { self.states.get(hash).or_else(|| { if let Some(state) = self.on_disk_states.get_mut(hash) { if let Some(cached) = self.disk_cache.read(*hash) { - state.init_from_snapshot(cached); + state.init_from_state_snapshot(cached); return Some(state); } } @@ -204,8 +204,8 @@ impl InMemoryBlockStates { // Get on-disk state snapshots self.on_disk_states.iter().for_each(|(hash, _)| { - if let Some(snapshot) = self.disk_cache.read(*hash) { - states.push((*hash, snapshot)); + if let Some(state_snapshot) = self.disk_cache.read(*hash) { + states.push((*hash, state_snapshot)); } }); @@ -214,9 +214,9 @@ impl InMemoryBlockStates { /// Load states from serialized data pub fn load_states(&mut self, states: SerializableHistoricalStates) { - for (hash, snapshot) in states { + for (hash, state_snapshot) in states { let mut state_db = StateDb::new(MemDb::default()); - state_db.init_from_snapshot(snapshot); + state_db.init_from_state_snapshot(state_snapshot); self.insert(hash, state_db); } } diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index 0e8001853a95..31e37c98b781 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -591,9 +591,9 @@ async fn test_fork_revert_next_block_timestamp() { api.mine_one().await; let latest_block = api.block_by_number(BlockNumberOrTag::Latest).await.unwrap().unwrap(); - let snapshot_id = api.evm_snapshot().await.unwrap(); + let state_snapshot = api.evm_snapshot().await.unwrap(); api.mine_one().await; - api.evm_revert(snapshot_id).await.unwrap(); + api.evm_revert(state_snapshot).await.unwrap(); let block = api.block_by_number(BlockNumberOrTag::Latest).await.unwrap().unwrap(); assert_eq!(block, latest_block); @@ -613,9 +613,9 @@ async fn test_fork_revert_call_latest_block_timestamp() { api.mine_one().await; let latest_block = api.block_by_number(BlockNumberOrTag::Latest).await.unwrap().unwrap(); - let snapshot_id = api.evm_snapshot().await.unwrap(); + let state_snapshot = api.evm_snapshot().await.unwrap(); api.mine_one().await; - api.evm_revert(snapshot_id).await.unwrap(); + api.evm_revert(state_snapshot).await.unwrap(); let multicall_contract = Multicall::new(address!("eefba1e63905ef1d7acba5a8513c70307c1ce441"), &provider); diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index 3f96513c5c8e..f93fa92a19f9 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -302,10 +302,10 @@ async fn test_fork_reset_setup() { } #[tokio::test(flavor = "multi_thread")] -async fn test_fork_snapshotting() { +async fn test_fork_state_snapshotting() { let (api, handle) = spawn(fork_config()).await; let provider = handle.http_provider(); - let snapshot = api.evm_snapshot().await.unwrap(); + let state_snapshot = api.evm_snapshot().await.unwrap(); let accounts: Vec<_> = handle.dev_wallets().collect(); let from = accounts[0].address(); @@ -329,7 +329,7 @@ async fn test_fork_snapshotting() { let to_balance = provider.get_balance(to).await.unwrap(); assert_eq!(balance_before.saturating_add(amount), to_balance); - assert!(api.evm_revert(snapshot).await.unwrap()); + assert!(api.evm_revert(state_snapshot).await.unwrap()); let nonce = provider.get_transaction_count(from).await.unwrap(); assert_eq!(nonce, initial_nonce); @@ -341,11 +341,11 @@ async fn test_fork_snapshotting() { } #[tokio::test(flavor = "multi_thread")] -async fn test_fork_snapshotting_repeated() { +async fn test_fork_state_snapshotting_repeated() { let (api, handle) = spawn(fork_config()).await; let provider = handle.http_provider(); - let snapshot = api.evm_snapshot().await.unwrap(); + let state_snapshot = api.evm_snapshot().await.unwrap(); let accounts: Vec<_> = handle.dev_wallets().collect(); let from = accounts[0].address(); @@ -366,9 +366,9 @@ async fn test_fork_snapshotting_repeated() { let to_balance = provider.get_balance(to).await.unwrap(); assert_eq!(balance_before.saturating_add(amount), to_balance); - let _second_snapshot = api.evm_snapshot().await.unwrap(); + let _second_state_snapshot = api.evm_snapshot().await.unwrap(); - assert!(api.evm_revert(snapshot).await.unwrap()); + assert!(api.evm_revert(state_snapshot).await.unwrap()); let nonce = provider.get_transaction_count(from).await.unwrap(); assert_eq!(nonce, initial_nonce); @@ -383,17 +383,16 @@ async fn test_fork_snapshotting_repeated() { // assert!(!api.evm_revert(second_snapshot).await.unwrap()); // nothing is reverted, snapshot gone - assert!(!api.evm_revert(snapshot).await.unwrap()); + assert!(!api.evm_revert(state_snapshot).await.unwrap()); } // #[tokio::test(flavor = "multi_thread")] -async fn test_fork_snapshotting_blocks() { +async fn test_fork_state_snapshotting_blocks() { let (api, handle) = spawn(fork_config()).await; let provider = handle.http_provider(); - // create a snapshot - let snapshot = api.evm_snapshot().await.unwrap(); + let state_snapshot = api.evm_snapshot().await.unwrap(); let accounts: Vec<_> = handle.dev_wallets().collect(); let from = accounts[0].address(); @@ -417,8 +416,7 @@ async fn test_fork_snapshotting_blocks() { let to_balance = provider.get_balance(to).await.unwrap(); assert_eq!(balance_before.saturating_add(amount), to_balance); - // revert snapshot - assert!(api.evm_revert(snapshot).await.unwrap()); + assert!(api.evm_revert(state_snapshot).await.unwrap()); assert_eq!(initial_nonce, provider.get_transaction_count(from).await.unwrap()); let block_number_after = provider.get_block_number().await.unwrap(); @@ -429,8 +427,8 @@ async fn test_fork_snapshotting_blocks() { let nonce = provider.get_transaction_count(from).await.unwrap(); assert_eq!(nonce, initial_nonce + 1); - // revert again: nothing to revert since snapshot gone - assert!(!api.evm_revert(snapshot).await.unwrap()); + // revert again: nothing to revert since state snapshot gone + assert!(!api.evm_revert(state_snapshot).await.unwrap()); let nonce = provider.get_transaction_count(from).await.unwrap(); assert_eq!(nonce, initial_nonce + 1); let block_number_after = provider.get_block_number().await.unwrap(); @@ -1244,7 +1242,7 @@ async fn test_arbitrum_fork_block_number() { assert_eq!(block_number, initial_block_number); // take snapshot at initial block number - let snapshot = api.evm_snapshot().await.unwrap(); + let snapshot_state = api.evm_snapshot().await.unwrap(); // mine new block and check block number returned by `eth_blockNumber` api.mine_one().await; @@ -1257,7 +1255,7 @@ async fn test_arbitrum_fork_block_number() { assert!(block_by_number.other.get("l1BlockNumber").is_some()); // revert to recorded snapshot and check block number - assert!(api.evm_revert(snapshot).await.unwrap()); + assert!(api.evm_revert(snapshot_state).await.unwrap()); let block_number = api.block_number().unwrap().to::(); assert_eq!(block_number, initial_block_number); diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 451ce6cb44c3..fbf33e500d53 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -3574,7 +3574,7 @@ { "func": { "id": "deleteSnapshot", - "description": "Removes the snapshot with the given ID created by `snapshot`.\nTakes the snapshot ID to delete.\nReturns `true` if the snapshot was successfully deleted.\nReturns `false` if the snapshot does not exist.", + "description": "`deleteSnapshot` is being deprecated in favor of `deleteStateSnapshot`. It will be removed in future versions.", "declaration": "function deleteSnapshot(uint256 snapshotId) external returns (bool success);", "visibility": "external", "mutability": "", @@ -3588,13 +3588,15 @@ ] }, "group": "evm", - "status": "stable", + "status": { + "deprecated": "replaced by `deleteStateSnapshot`" + }, "safety": "unsafe" }, { "func": { "id": "deleteSnapshots", - "description": "Removes _all_ snapshots previously created by `snapshot`.", + "description": "`deleteSnapshots` is being deprecated in favor of `deleteStateSnapshots`. It will be removed in future versions.", "declaration": "function deleteSnapshots() external;", "visibility": "external", "mutability": "", @@ -3608,6 +3610,48 @@ ] }, "group": "evm", + "status": { + "deprecated": "replaced by `deleteStateSnapshots`" + }, + "safety": "unsafe" + }, + { + "func": { + "id": "deleteStateSnapshot", + "description": "Removes the snapshot with the given ID created by `snapshot`.\nTakes the snapshot ID to delete.\nReturns `true` if the snapshot was successfully deleted.\nReturns `false` if the snapshot does not exist.", + "declaration": "function deleteStateSnapshot(uint256 snapshotId) external returns (bool success);", + "visibility": "external", + "mutability": "", + "signature": "deleteStateSnapshot(uint256)", + "selector": "0x08d6b37a", + "selectorBytes": [ + 8, + 214, + 179, + 122 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "deleteStateSnapshots", + "description": "Removes _all_ snapshots previously created by `snapshot`.", + "declaration": "function deleteStateSnapshots() external;", + "visibility": "external", + "mutability": "", + "signature": "deleteStateSnapshots()", + "selector": "0xe0933c74", + "selectorBytes": [ + 224, + 147, + 60, + 116 + ] + }, + "group": "evm", "status": "stable", "safety": "unsafe" }, @@ -7456,7 +7500,7 @@ { "func": { "id": "revertTo", - "description": "Revert the state of the EVM to a previous snapshot\nTakes the snapshot ID to revert to.\nReturns `true` if the snapshot was successfully reverted.\nReturns `false` if the snapshot does not exist.\n**Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`.", + "description": "`revertTo` is being deprecated in favor of `revertToState`. It will be removed in future versions.", "declaration": "function revertTo(uint256 snapshotId) external returns (bool success);", "visibility": "external", "mutability": "", @@ -7470,13 +7514,15 @@ ] }, "group": "evm", - "status": "stable", + "status": { + "deprecated": "replaced by `revertToState`" + }, "safety": "unsafe" }, { "func": { "id": "revertToAndDelete", - "description": "Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots\nTakes the snapshot ID to revert to.\nReturns `true` if the snapshot was successfully reverted and deleted.\nReturns `false` if the snapshot does not exist.", + "description": "`revertToAndDelete` is being deprecated in favor of `revertToStateAndDelete`. It will be removed in future versions.", "declaration": "function revertToAndDelete(uint256 snapshotId) external returns (bool success);", "visibility": "external", "mutability": "", @@ -7490,6 +7536,48 @@ ] }, "group": "evm", + "status": { + "deprecated": "replaced by `revertToStateAndDelete`" + }, + "safety": "unsafe" + }, + { + "func": { + "id": "revertToState", + "description": "Revert the state of the EVM to a previous snapshot\nTakes the snapshot ID to revert to.\nReturns `true` if the snapshot was successfully reverted.\nReturns `false` if the snapshot does not exist.\n**Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteStateSnapshot`.", + "declaration": "function revertToState(uint256 snapshotId) external returns (bool success);", + "visibility": "external", + "mutability": "", + "signature": "revertToState(uint256)", + "selector": "0xc2527405", + "selectorBytes": [ + 194, + 82, + 116, + 5 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "revertToStateAndDelete", + "description": "Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots\nTakes the snapshot ID to revert to.\nReturns `true` if the snapshot was successfully reverted and deleted.\nReturns `false` if the snapshot does not exist.", + "declaration": "function revertToStateAndDelete(uint256 snapshotId) external returns (bool success);", + "visibility": "external", + "mutability": "", + "signature": "revertToStateAndDelete(uint256)", + "selector": "0x3a1985dc", + "selectorBytes": [ + 58, + 25, + 133, + 220 + ] + }, + "group": "evm", "status": "stable", "safety": "unsafe" }, @@ -8456,7 +8544,7 @@ { "func": { "id": "snapshot", - "description": "Snapshot the current state of the evm.\nReturns the ID of the snapshot that was created.\nTo revert a snapshot use `revertTo`.", + "description": "`snapshot` is being deprecated in favor of `snapshotState`. It will be removed in future versions.", "declaration": "function snapshot() external returns (uint256 snapshotId);", "visibility": "external", "mutability": "", @@ -8470,6 +8558,28 @@ ] }, "group": "evm", + "status": { + "deprecated": "replaced by `snapshotState`" + }, + "safety": "unsafe" + }, + { + "func": { + "id": "snapshotState", + "description": "Snapshot the current state of the evm.\nReturns the ID of the snapshot that was created.\nTo revert a snapshot use `revertToState`.", + "declaration": "function snapshotState() external returns (uint256 snapshotId);", + "visibility": "external", + "mutability": "", + "signature": "snapshotState()", + "selector": "0x9cd23835", + "selectorBytes": [ + 156, + 210, + 56, + 53 + ] + }, + "group": "evm", "status": "stable", "safety": "unsafe" }, diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 22500ec980a6..69293d1b6d6e 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -511,11 +511,19 @@ interface Vm { // -------- State Snapshots -------- + /// `snapshot` is being deprecated in favor of `snapshotState`. It will be removed in future versions. + #[cheatcode(group = Evm, safety = Unsafe, status = Deprecated(Some("replaced by `snapshotState`")))] + function snapshot() external returns (uint256 snapshotId); + /// Snapshot the current state of the evm. /// Returns the ID of the snapshot that was created. - /// To revert a snapshot use `revertTo`. + /// To revert a snapshot use `revertToState`. #[cheatcode(group = Evm, safety = Unsafe)] - function snapshot() external returns (uint256 snapshotId); + function snapshotState() external returns (uint256 snapshotId); + + /// `revertTo` is being deprecated in favor of `revertToState`. It will be removed in future versions. + #[cheatcode(group = Evm, safety = Unsafe, status = Deprecated(Some("replaced by `revertToState`")))] + function revertTo(uint256 snapshotId) external returns (bool success); /// Revert the state of the EVM to a previous snapshot /// Takes the snapshot ID to revert to. @@ -523,9 +531,13 @@ interface Vm { /// Returns `true` if the snapshot was successfully reverted. /// Returns `false` if the snapshot does not exist. /// - /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. + /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteStateSnapshot`. #[cheatcode(group = Evm, safety = Unsafe)] - function revertTo(uint256 snapshotId) external returns (bool success); + function revertToState(uint256 snapshotId) external returns (bool success); + + /// `revertToAndDelete` is being deprecated in favor of `revertToStateAndDelete`. It will be removed in future versions. + #[cheatcode(group = Evm, safety = Unsafe, status = Deprecated(Some("replaced by `revertToStateAndDelete`")))] + function revertToAndDelete(uint256 snapshotId) external returns (bool success); /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots /// Takes the snapshot ID to revert to. @@ -533,7 +545,11 @@ interface Vm { /// Returns `true` if the snapshot was successfully reverted and deleted. /// Returns `false` if the snapshot does not exist. #[cheatcode(group = Evm, safety = Unsafe)] - function revertToAndDelete(uint256 snapshotId) external returns (bool success); + function revertToStateAndDelete(uint256 snapshotId) external returns (bool success); + + /// `deleteSnapshot` is being deprecated in favor of `deleteStateSnapshot`. It will be removed in future versions. + #[cheatcode(group = Evm, safety = Unsafe, status = Deprecated(Some("replaced by `deleteStateSnapshot`")))] + function deleteSnapshot(uint256 snapshotId) external returns (bool success); /// Removes the snapshot with the given ID created by `snapshot`. /// Takes the snapshot ID to delete. @@ -541,11 +557,15 @@ interface Vm { /// Returns `true` if the snapshot was successfully deleted. /// Returns `false` if the snapshot does not exist. #[cheatcode(group = Evm, safety = Unsafe)] - function deleteSnapshot(uint256 snapshotId) external returns (bool success); + function deleteStateSnapshot(uint256 snapshotId) external returns (bool success); + + /// `deleteSnapshots` is being deprecated in favor of `deleteStateSnapshots`. It will be removed in future versions. + #[cheatcode(group = Evm, safety = Unsafe, status = Deprecated(Some("replaced by `deleteStateSnapshots`")))] + function deleteSnapshots() external; /// Removes _all_ snapshots previously created by `snapshot`. #[cheatcode(group = Evm, safety = Unsafe)] - function deleteSnapshots() external; + function deleteStateSnapshots() external; // -------- Forking -------- // --- Creation and Selection --- diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 45b6f8c75270..7ed1ce1a4edf 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -10,7 +10,7 @@ use alloy_rlp::Decodable; use alloy_sol_types::SolValue; use foundry_common::fs::{read_json_file, write_json_file}; use foundry_evm_core::{ - backend::{DatabaseExt, RevertSnapshotAction}, + backend::{DatabaseExt, RevertStateSnapshotAction}, constants::{CALLER, CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, TEST_CONTRACT_ADDRESS}, }; use rand::Rng; @@ -506,63 +506,78 @@ impl Cheatcode for readCallersCall { } } +// Deprecated in favor of `snapshotStateCall` impl Cheatcode for snapshotCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - Ok(ccx.ecx.db.snapshot(&ccx.ecx.journaled_state, &ccx.ecx.env).abi_encode()) + inner_snapshot_state(ccx) } } +impl Cheatcode for snapshotStateCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self {} = self; + inner_snapshot_state(ccx) + } +} + +// Deprecated in favor of `revertToStateCall` impl Cheatcode for revertToCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; - let result = if let Some(journaled_state) = ccx.ecx.db.revert( - *snapshotId, - &ccx.ecx.journaled_state, - &mut ccx.ecx.env, - RevertSnapshotAction::RevertKeep, - ) { - // we reset the evm's journaled_state to the state of the snapshot previous state - ccx.ecx.journaled_state = journaled_state; - true - } else { - false - }; - Ok(result.abi_encode()) + inner_revert_to_state(ccx, *snapshotId) } } +impl Cheatcode for revertToStateCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { snapshotId } = self; + inner_revert_to_state(ccx, *snapshotId) + } +} + +// Deprecated in favor of `revertToStateAndDeleteCall` impl Cheatcode for revertToAndDeleteCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; - let result = if let Some(journaled_state) = ccx.ecx.db.revert( - *snapshotId, - &ccx.ecx.journaled_state, - &mut ccx.ecx.env, - RevertSnapshotAction::RevertRemove, - ) { - // we reset the evm's journaled_state to the state of the snapshot previous state - ccx.ecx.journaled_state = journaled_state; - true - } else { - false - }; - Ok(result.abi_encode()) + inner_revert_to_state_and_delete(ccx, *snapshotId) } } +impl Cheatcode for revertToStateAndDeleteCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { snapshotId } = self; + inner_revert_to_state_and_delete(ccx, *snapshotId) + } +} + +// Deprecated in favor of `deleteStateSnapshotCall` impl Cheatcode for deleteSnapshotCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { snapshotId } = self; - let result = ccx.ecx.db.delete_snapshot(*snapshotId); - Ok(result.abi_encode()) + inner_delete_state_snapshot(ccx, *snapshotId) + } +} + +impl Cheatcode for deleteStateSnapshotCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { snapshotId } = self; + inner_delete_state_snapshot(ccx, *snapshotId) } } + +// Deprecated in favor of `deleteStateSnapshotsCall` impl Cheatcode for deleteSnapshotsCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - ccx.ecx.db.delete_snapshots(); - Ok(Default::default()) + inner_delete_state_snapshots(ccx) + } +} + +impl Cheatcode for deleteStateSnapshotsCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self {} = self; + inner_delete_state_snapshots(ccx) } } @@ -628,6 +643,58 @@ pub(super) fn get_nonce(ccx: &mut CheatsCtxt, address: &Add Ok(account.info.nonce.abi_encode()) } +fn inner_snapshot_state(ccx: &mut CheatsCtxt) -> Result { + Ok(ccx.ecx.db.snapshot_state(&ccx.ecx.journaled_state, &ccx.ecx.env).abi_encode()) +} + +fn inner_revert_to_state(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { + let result = if let Some(journaled_state) = ccx.ecx.db.revert_state( + snapshot_id, + &ccx.ecx.journaled_state, + &mut ccx.ecx.env, + RevertStateSnapshotAction::RevertKeep, + ) { + // we reset the evm's journaled_state to the state of the snapshot previous state + ccx.ecx.journaled_state = journaled_state; + true + } else { + false + }; + Ok(result.abi_encode()) +} + +fn inner_revert_to_state_and_delete( + ccx: &mut CheatsCtxt, + snapshot_id: U256, +) -> Result { + let result = if let Some(journaled_state) = ccx.ecx.db.revert_state( + snapshot_id, + &ccx.ecx.journaled_state, + &mut ccx.ecx.env, + RevertStateSnapshotAction::RevertRemove, + ) { + // we reset the evm's journaled_state to the state of the snapshot previous state + ccx.ecx.journaled_state = journaled_state; + true + } else { + false + }; + Ok(result.abi_encode()) +} + +fn inner_delete_state_snapshot( + ccx: &mut CheatsCtxt, + snapshot_id: U256, +) -> Result { + let result = ccx.ecx.db.delete_state_snapshot(snapshot_id); + Ok(result.abi_encode()) +} + +fn inner_delete_state_snapshots(ccx: &mut CheatsCtxt) -> Result { + ccx.ecx.db.delete_state_snapshots(); + Ok(Default::default()) +} + /// Reads the current caller information and returns the current [CallerMode], `msg.sender` and /// `tx.origin`. /// diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index cba792b32d89..8156d75fbddf 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -3,7 +3,7 @@ use super::BackendError; use crate::{ backend::{ - diagnostic::RevertDiagnostic, Backend, DatabaseExt, LocalForkId, RevertSnapshotAction, + diagnostic::RevertDiagnostic, Backend, DatabaseExt, LocalForkId, RevertStateSnapshotAction, }, fork::{CreateFork, ForkId}, InspectorExt, @@ -84,11 +84,11 @@ impl<'a> CowBackend<'a> { Ok(res) } - /// Returns whether there was a snapshot failure in the backend. + /// Returns whether there was a state snapshot failure in the backend. /// /// This is bubbled up from the underlying Copy-On-Write backend when a revert occurs. - pub fn has_snapshot_failure(&self) -> bool { - self.backend.has_snapshot_failure() + pub fn has_state_snapshot_failure(&self) -> bool { + self.backend.has_state_snapshot_failure() } /// Returns a mutable instance of the Backend. @@ -115,31 +115,31 @@ impl<'a> CowBackend<'a> { } impl<'a> DatabaseExt for CowBackend<'a> { - fn snapshot(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { - self.backend_mut(env).snapshot(journaled_state, env) + fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { + self.backend_mut(env).snapshot_state(journaled_state, env) } - fn revert( + fn revert_state( &mut self, id: U256, journaled_state: &JournaledState, current: &mut Env, - action: RevertSnapshotAction, + action: RevertStateSnapshotAction, ) -> Option { - self.backend_mut(current).revert(id, journaled_state, current, action) + self.backend_mut(current).revert_state(id, journaled_state, current, action) } - fn delete_snapshot(&mut self, id: U256) -> bool { - // delete snapshot requires a previous snapshot to be initialized + fn delete_state_snapshot(&mut self, id: U256) -> bool { + // delete state snapshot requires a previous snapshot to be initialized if let Some(backend) = self.initialized_backend_mut() { - return backend.delete_snapshot(id) + return backend.delete_state_snapshot(id) } false } - fn delete_snapshots(&mut self) { + fn delete_state_snapshots(&mut self) { if let Some(backend) = self.initialized_backend_mut() { - backend.delete_snapshots() + backend.delete_state_snapshots() } } diff --git a/crates/evm/core/src/backend/in_memory_db.rs b/crates/evm/core/src/backend/in_memory_db.rs index e819c5313c2a..4e90bfec0ae0 100644 --- a/crates/evm/core/src/backend/in_memory_db.rs +++ b/crates/evm/core/src/backend/in_memory_db.rs @@ -1,6 +1,6 @@ //! In-memory database. -use crate::snapshot::Snapshots; +use crate::state_snapshot::StateSnapshots; use alloy_primitives::{Address, B256, U256}; use foundry_fork_db::DatabaseError; use revm::{ @@ -20,12 +20,12 @@ pub type FoundryEvmInMemoryDB = CacheDB; #[derive(Debug)] pub struct MemDb { pub inner: FoundryEvmInMemoryDB, - pub snapshots: Snapshots, + pub state_snapshots: StateSnapshots, } impl Default for MemDb { fn default() -> Self { - Self { inner: CacheDB::new(Default::default()), snapshots: Default::default() } + Self { inner: CacheDB::new(Default::default()), state_snapshots: Default::default() } } } diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 6fbd2086dde8..49830bc892d0 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -3,7 +3,7 @@ use crate::{ constants::{CALLER, CHEATCODE_ADDRESS, DEFAULT_CREATE2_DEPLOYER, TEST_CONTRACT_ADDRESS}, fork::{CreateFork, ForkId, MultiFork}, - snapshot::Snapshots, + state_snapshot::StateSnapshots, utils::{configure_tx_env, new_evm_with_inspector}, InspectorExt, }; @@ -42,7 +42,7 @@ mod in_memory_db; pub use in_memory_db::{EmptyDBWrapper, FoundryEvmInMemoryDB, MemDb}; mod snapshot; -pub use snapshot::{BackendSnapshot, RevertSnapshotAction, StateSnapshot}; +pub use snapshot::{BackendStateSnapshot, RevertStateSnapshotAction, StateSnapshot}; // A `revm::Database` that is used in forking mode type ForkDB = CacheDB; @@ -71,12 +71,12 @@ pub const GLOBAL_FAIL_SLOT: U256 = /// An extension trait that allows us to easily extend the `revm::Inspector` capabilities #[auto_impl::auto_impl(&mut)] pub trait DatabaseExt: Database + DatabaseCommit { - /// Creates a new snapshot at the current point of execution. + /// Creates a new state snapshot at the current point of execution. /// - /// A snapshot is associated with a new unique id that's created for the snapshot. - /// Snapshots can be reverted: [DatabaseExt::revert], however, depending on the - /// [RevertSnapshotAction], it will keep the snapshot alive or delete it. - fn snapshot(&mut self, journaled_state: &JournaledState, env: &Env) -> U256; + /// 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: &Env) -> U256; /// Reverts the snapshot if it exists /// @@ -87,25 +87,25 @@ pub trait DatabaseExt: Database + DatabaseCommit { /// 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`. + /// `Self::snapshot_state`. /// - /// Depending on [RevertSnapshotAction] it will keep the snapshot alive or delete it. - fn revert( + /// Depending on [RevertStateSnapshotAction] it will keep the snapshot alive or delete it. + fn revert_state( &mut self, id: U256, journaled_state: &JournaledState, env: &mut Env, - action: RevertSnapshotAction, + action: RevertStateSnapshotAction, ) -> Option; - /// Deletes the snapshot with the given `id` + /// Deletes the state snapshot with the given `id` /// /// Returns `true` if the snapshot was successfully deleted, `false` if no snapshot for that id /// exists. - fn delete_snapshot(&mut self, id: U256) -> bool; + fn delete_state_snapshot(&mut self, id: U256) -> bool; - /// Deletes all snapshots. - fn delete_snapshots(&mut self); + /// Deletes all state snapshots. + fn delete_state_snapshots(&mut self); /// Creates and also selects a new fork /// @@ -410,7 +410,7 @@ struct _ObjectSafe(dyn DatabaseExt); /// afterwards, as well as any snapshots taken after the reverted snapshot, (e.g.: reverting to id /// 0x1 will delete snapshots with ids 0x1, 0x2, etc.) /// -/// **Note:** Snapshots work across fork-swaps, e.g. if fork `A` is currently active, then a +/// **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)] @@ -554,8 +554,10 @@ impl Backend { } /// Returns all snapshots created in this backend - pub fn snapshots(&self) -> &Snapshots> { - &self.inner.snapshots + pub fn state_snapshots( + &self, + ) -> &StateSnapshots> { + &self.inner.state_snapshots } /// Sets the address of the `DSTest` contract that is being executed @@ -591,18 +593,18 @@ impl Backend { self.inner.caller } - /// Failures occurred in snapshots are tracked when the snapshot is reverted + /// Failures occurred in state snapshots are tracked when the state snapshot is reverted. /// - /// If an error occurs in a restored snapshot, the test is considered failed. + /// If an error occurs in a restored state snapshot, the test is considered failed. /// - /// This returns whether there was a reverted snapshot that recorded an error - pub fn has_snapshot_failure(&self) -> bool { - self.inner.has_snapshot_failure + /// This returns whether there was a reverted state snapshot that recorded an error. + pub fn has_state_snapshot_failure(&self) -> bool { + self.inner.has_state_snapshot_failure } - /// Sets the snapshot failure flag. - pub fn set_snapshot_failure(&mut self, has_snapshot_failure: bool) { - self.inner.has_snapshot_failure = has_snapshot_failure + /// Sets the state snapshot failure flag. + pub fn set_state_snapshot_failure(&mut self, has_state_snapshot_failure: bool) { + self.inner.has_state_snapshot_failure = has_state_snapshot_failure } /// When creating or switching forks, we update the AccountInfo of the contract @@ -904,9 +906,9 @@ impl Backend { } impl DatabaseExt for Backend { - fn snapshot(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { + fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { trace!("create snapshot"); - let id = self.inner.snapshots.insert(BackendSnapshot::new( + let id = self.inner.state_snapshots.insert(BackendStateSnapshot::new( self.create_db_snapshot(), journaled_state.clone(), env.clone(), @@ -915,18 +917,18 @@ impl DatabaseExt for Backend { id } - fn revert( + fn revert_state( &mut self, id: U256, current_state: &JournaledState, current: &mut Env, - action: RevertSnapshotAction, + action: RevertStateSnapshotAction, ) -> Option { trace!(?id, "revert snapshot"); - if let Some(mut snapshot) = self.inner.snapshots.remove_at(id) { + if let Some(mut snapshot) = self.inner.state_snapshots.remove_at(id) { // Re-insert snapshot to persist it if action.is_keep() { - self.inner.snapshots.insert_at(snapshot.clone(), id); + self.inner.state_snapshots.insert_at(snapshot.clone(), id); } // https://github.com/foundry-rs/foundry/issues/3055 @@ -936,14 +938,14 @@ impl DatabaseExt for Backend { if let Some(account) = current_state.state.get(&CHEATCODE_ADDRESS) { if let Some(slot) = account.storage.get(&GLOBAL_FAIL_SLOT) { if !slot.present_value.is_zero() { - self.set_snapshot_failure(true); + self.set_state_snapshot_failure(true); } } } // merge additional logs snapshot.merge(current_state); - let BackendSnapshot { db, mut journaled_state, env } = snapshot; + let BackendStateSnapshot { db, mut journaled_state, env } = snapshot; match db { BackendDatabaseSnapshot::InMemory(mem_db) => { self.mem_db = mem_db; @@ -966,7 +968,7 @@ impl DatabaseExt for Backend { } caller_account.into() }); - self.inner.revert_snapshot(id, fork_id, idx, *fork); + self.inner.revert_state_snapshot(id, fork_id, idx, *fork); self.active_fork_ids = Some((id, idx)) } } @@ -981,12 +983,12 @@ impl DatabaseExt for Backend { } } - fn delete_snapshot(&mut self, id: U256) -> bool { - self.inner.snapshots.remove_at(id).is_some() + fn delete_state_snapshot(&mut self, id: U256) -> bool { + self.inner.state_snapshots.remove_at(id).is_some() } - fn delete_snapshots(&mut self) { - self.inner.snapshots.clear() + fn delete_state_snapshots(&mut self) { + self.inner.state_snapshots.clear() } fn create_fork(&mut self, create_fork: CreateFork) -> eyre::Result { @@ -1599,8 +1601,8 @@ pub struct BackendInner { /// Holds all created fork databases // Note: data is stored in an `Option` so we can remove it without reshuffling pub forks: Vec>, - /// Contains snapshots made at a certain point - pub snapshots: Snapshots>, + /// Contains state snapshots made at a certain point + pub state_snapshots: StateSnapshots>, /// 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 @@ -1610,7 +1612,7 @@ pub struct BackendInner { /// reverted we get the _current_ `revm::JournaledState` which contains the state that we can /// check if the `_failed` variable is set, /// additionally - pub has_snapshot_failure: bool, + pub has_state_snapshot_failure: bool, /// Tracks the caller of the test function pub caller: Option
, /// Tracks numeric identifiers for forks @@ -1694,7 +1696,7 @@ impl BackendInner { } /// Reverts the entire fork database - pub fn revert_snapshot( + pub fn revert_state_snapshot( &mut self, id: LocalForkId, fork_id: ForkId, @@ -1797,8 +1799,8 @@ impl Default for BackendInner { issued_local_fork_ids: Default::default(), created_forks: Default::default(), forks: vec![], - snapshots: Default::default(), - has_snapshot_failure: false, + state_snapshots: Default::default(), + has_state_snapshot_failure: false, caller: None, next_fork_id: Default::default(), persistent_accounts: Default::default(), diff --git a/crates/evm/core/src/backend/snapshot.rs b/crates/evm/core/src/backend/snapshot.rs index f8961c7a0e67..7bfed1283fea 100644 --- a/crates/evm/core/src/backend/snapshot.rs +++ b/crates/evm/core/src/backend/snapshot.rs @@ -13,9 +13,9 @@ pub struct StateSnapshot { pub block_hashes: HashMap, } -/// Represents a snapshot taken during evm execution +/// Represents a state snapshot taken during evm execution #[derive(Clone, Debug)] -pub struct BackendSnapshot { +pub struct BackendStateSnapshot { pub db: T, /// The journaled_state state at a specific point pub journaled_state: JournaledState, @@ -23,38 +23,38 @@ pub struct BackendSnapshot { pub env: Env, } -impl BackendSnapshot { - /// Takes a new snapshot +impl BackendStateSnapshot { + /// Takes a new state snapshot. pub fn new(db: T, journaled_state: JournaledState, env: Env) -> Self { Self { db, journaled_state, env } } - /// Called when this snapshot is reverted. + /// Called when this state snapshot is reverted. /// /// Since we want to keep all additional logs that were emitted since the snapshot was taken /// we'll merge additional logs into the snapshot's `revm::JournaledState`. Additional logs are /// those logs that are missing in the snapshot's journaled_state, since the current /// journaled_state includes the same logs, we can simply replace use that See also - /// `DatabaseExt::revert` + /// `DatabaseExt::revert`. pub fn merge(&mut self, current: &JournaledState) { self.journaled_state.logs.clone_from(¤t.logs); } } -/// What to do when reverting a snapshot +/// What to do when reverting a state snapshot. /// -/// Whether to remove the snapshot or keep it +/// Whether to remove the state snapshot or keep it. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub enum RevertSnapshotAction { - /// Remove the snapshot after reverting +pub enum RevertStateSnapshotAction { + /// Remove the state snapshot after reverting. #[default] RevertRemove, - /// Keep the snapshot after reverting + /// Keep the state snapshot after reverting. RevertKeep, } -impl RevertSnapshotAction { - /// Returns `true` if the action is to keep the snapshot +impl RevertStateSnapshotAction { + /// Returns `true` if the action is to keep the state snapshot. pub fn is_keep(&self) -> bool { matches!(self, Self::RevertKeep) } diff --git a/crates/evm/core/src/fork/database.rs b/crates/evm/core/src/fork/database.rs index 873e8a8962ab..a8d2ccc1db9a 100644 --- a/crates/evm/core/src/fork/database.rs +++ b/crates/evm/core/src/fork/database.rs @@ -1,8 +1,8 @@ //! A revm database that forks off a remote client use crate::{ - backend::{RevertSnapshotAction, StateSnapshot}, - snapshot::Snapshots, + backend::{RevertStateSnapshotAction, StateSnapshot}, + state_snapshot::StateSnapshots, }; use alloy_primitives::{Address, B256, U256}; use alloy_rpc_types::BlockId; @@ -23,22 +23,22 @@ use std::sync::Arc; /// `backend` will also write (missing) data to the `db` in the background #[derive(Clone, Debug)] pub struct ForkedDatabase { - /// responsible for fetching missing data + /// Responsible for fetching missing data. /// - /// This is responsible for getting data + /// This is responsible for getting data. backend: SharedBackend, /// Cached Database layer, ensures that changes are not written to the database that /// exclusively stores the state of the remote client. /// /// This separates Read/Write operations - /// - reads from the `SharedBackend as DatabaseRef` writes to the internal cache storage + /// - reads from the `SharedBackend as DatabaseRef` writes to the internal cache storage. cache_db: CacheDB, - /// Contains all the data already fetched + /// Contains all the data already fetched. /// - /// This exclusively stores the _unchanged_ remote client state + /// This exclusively stores the _unchanged_ remote client state. db: BlockchainDb, - /// holds the snapshot state of a blockchain - snapshots: Arc>>, + /// Holds the state snapshots of a blockchain. + state_snapshots: Arc>>, } impl ForkedDatabase { @@ -48,7 +48,7 @@ impl ForkedDatabase { cache_db: CacheDB::new(backend.clone()), backend, db, - snapshots: Arc::new(Mutex::new(Default::default())), + state_snapshots: Arc::new(Mutex::new(Default::default())), } } @@ -60,8 +60,8 @@ impl ForkedDatabase { &mut self.cache_db } - pub fn snapshots(&self) -> &Arc>> { - &self.snapshots + pub fn state_snapshots(&self) -> &Arc>> { + &self.state_snapshots } /// Reset the fork to a fresh forked state, and optionally update the fork config @@ -92,35 +92,35 @@ impl ForkedDatabase { &self.db } - pub fn create_snapshot(&self) -> ForkDbSnapshot { + pub fn create_state_snapshot(&self) -> ForkDbStateSnapshot { let db = self.db.db(); - let snapshot = StateSnapshot { + let state_snapshot = StateSnapshot { accounts: db.accounts.read().clone(), storage: db.storage.read().clone(), block_hashes: db.block_hashes.read().clone(), }; - ForkDbSnapshot { local: self.cache_db.clone(), snapshot } + ForkDbStateSnapshot { local: self.cache_db.clone(), state_snapshot } } - pub fn insert_snapshot(&self) -> U256 { - let snapshot = self.create_snapshot(); - let mut snapshots = self.snapshots().lock(); - let id = snapshots.insert(snapshot); + pub fn insert_state_snapshot(&self) -> U256 { + let state_snapshot = self.create_state_snapshot(); + let mut state_snapshots = self.state_snapshots().lock(); + let id = state_snapshots.insert(state_snapshot); trace!(target: "backend::forkdb", "Created new snapshot {}", id); id } /// Removes the snapshot from the tracked snapshot and sets it as the current state - pub fn revert_snapshot(&mut self, id: U256, action: RevertSnapshotAction) -> bool { - let snapshot = { self.snapshots().lock().remove_at(id) }; - if let Some(snapshot) = snapshot { + pub fn revert_state_snapshot(&mut self, id: U256, action: RevertStateSnapshotAction) -> bool { + let state_snapshot = { self.state_snapshots().lock().remove_at(id) }; + if let Some(state_snapshot) = state_snapshot { if action.is_keep() { - self.snapshots().lock().insert_at(snapshot.clone(), id); + self.state_snapshots().lock().insert_at(state_snapshot.clone(), id); } - let ForkDbSnapshot { + let ForkDbStateSnapshot { local, - snapshot: StateSnapshot { accounts, storage, block_hashes }, - } = snapshot; + state_snapshot: StateSnapshot { accounts, storage, block_hashes }, + } = state_snapshot; let db = self.inner().db(); { let mut accounts_lock = db.accounts.write(); @@ -202,12 +202,12 @@ impl DatabaseCommit for ForkedDatabase { /// /// This mimics `revm::CacheDB` #[derive(Clone, Debug)] -pub struct ForkDbSnapshot { +pub struct ForkDbStateSnapshot { pub local: CacheDB, - pub snapshot: StateSnapshot, + pub state_snapshot: StateSnapshot, } -impl ForkDbSnapshot { +impl ForkDbStateSnapshot { fn get_storage(&self, address: Address, index: U256) -> Option { self.local.accounts.get(&address).and_then(|account| account.storage.get(&index)).copied() } @@ -216,14 +216,14 @@ impl ForkDbSnapshot { // This `DatabaseRef` implementation works similar to `CacheDB` which prioritizes modified elements, // and uses another db as fallback // We prioritize stored changed accounts/storage -impl DatabaseRef for ForkDbSnapshot { +impl DatabaseRef for ForkDbStateSnapshot { type Error = DatabaseError; fn basic_ref(&self, address: Address) -> Result, Self::Error> { match self.local.accounts.get(&address) { Some(account) => Ok(Some(account.info.clone())), None => { - let mut acc = self.snapshot.accounts.get(&address).cloned(); + let mut acc = self.state_snapshot.accounts.get(&address).cloned(); if acc.is_none() { acc = self.local.basic_ref(address)?; @@ -254,7 +254,7 @@ impl DatabaseRef for ForkDbSnapshot { } fn block_hash_ref(&self, number: u64) -> Result { - match self.snapshot.block_hashes.get(&U256::from(number)).copied() { + match self.state_snapshot.block_hashes.get(&U256::from(number)).copied() { None => self.local.block_hash_ref(number), Some(block_hash) => Ok(block_hash), } diff --git a/crates/evm/core/src/lib.rs b/crates/evm/core/src/lib.rs index 48c6478651ac..b30a36544b48 100644 --- a/crates/evm/core/src/lib.rs +++ b/crates/evm/core/src/lib.rs @@ -26,7 +26,7 @@ pub mod fork; pub mod opcodes; pub mod opts; pub mod precompiles; -pub mod snapshot; +pub mod state_snapshot; pub mod utils; /// An extension trait that allows us to add additional hooks to Inspector for later use in diff --git a/crates/evm/core/src/snapshot.rs b/crates/evm/core/src/snapshot.rs deleted file mode 100644 index 423f853eed49..000000000000 --- a/crates/evm/core/src/snapshot.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! support for snapshotting different states - -use alloy_primitives::U256; -use std::{collections::HashMap, ops::Add}; - -/// Represents all snapshots -#[derive(Clone, Debug)] -pub struct Snapshots { - id: U256, - snapshots: HashMap, -} - -impl Snapshots { - fn next_id(&mut self) -> U256 { - let id = self.id; - self.id = id.saturating_add(U256::from(1)); - id - } - - /// Returns the snapshot with the given id `id` - pub fn get(&self, id: U256) -> Option<&T> { - self.snapshots.get(&id) - } - - /// Removes the snapshot with the given `id`. - /// - /// This will also remove any snapshots taken after the snapshot with the `id`. e.g.: reverting - /// to id 1 will delete snapshots with ids 1, 2, 3, etc.) - pub fn remove(&mut self, id: U256) -> Option { - let snapshot = self.snapshots.remove(&id); - - // revert all snapshots taken after the snapshot - let mut to_revert = id.add(U256::from(1)); - while to_revert < self.id { - self.snapshots.remove(&to_revert); - to_revert += U256::from(1); - } - - snapshot - } - - /// Removes all snapshots - pub fn clear(&mut self) { - self.snapshots.clear(); - } - - /// Removes the snapshot with the given `id`. - /// - /// Does not remove snapshots after it. - pub fn remove_at(&mut self, id: U256) -> Option { - self.snapshots.remove(&id) - } - - /// Inserts the new snapshot and returns the id - pub fn insert(&mut self, snapshot: T) -> U256 { - let id = self.next_id(); - self.snapshots.insert(id, snapshot); - id - } - - /// Inserts the new snapshot at the given `id`. - /// - /// Does not auto-increment the next `id`. - pub fn insert_at(&mut self, snapshot: T, id: U256) -> U256 { - self.snapshots.insert(id, snapshot); - id - } -} - -impl Default for Snapshots { - fn default() -> Self { - Self { id: U256::ZERO, snapshots: HashMap::new() } - } -} diff --git a/crates/evm/core/src/state_snapshot.rs b/crates/evm/core/src/state_snapshot.rs new file mode 100644 index 000000000000..e273a573344d --- /dev/null +++ b/crates/evm/core/src/state_snapshot.rs @@ -0,0 +1,74 @@ +//! Support for snapshotting different states + +use alloy_primitives::U256; +use std::{collections::HashMap, ops::Add}; + +/// Represents all state snapshots +#[derive(Clone, Debug)] +pub struct StateSnapshots { + id: U256, + state_snapshots: HashMap, +} + +impl StateSnapshots { + fn next_id(&mut self) -> U256 { + let id = self.id; + self.id = id.saturating_add(U256::from(1)); + id + } + + /// Returns the state snapshot with the given id `id` + pub fn get(&self, id: U256) -> Option<&T> { + self.state_snapshots.get(&id) + } + + /// Removes the state snapshot with the given `id`. + /// + /// This will also remove any state snapshots taken after the state snapshot with the `id`. + /// e.g.: reverting to id 1 will delete snapshots with ids 1, 2, 3, etc.) + pub fn remove(&mut self, id: U256) -> Option { + let snapshot_state = self.state_snapshots.remove(&id); + + // Revert all state snapshots taken after the state snapshot with the `id` + let mut to_revert = id.add(U256::from(1)); + while to_revert < self.id { + self.state_snapshots.remove(&to_revert); + to_revert += U256::from(1); + } + + snapshot_state + } + + /// Removes all state snapshots. + pub fn clear(&mut self) { + self.state_snapshots.clear(); + } + + /// Removes the state snapshot with the given `id`. + /// + /// Does not remove state snapshots after it. + pub fn remove_at(&mut self, id: U256) -> Option { + self.state_snapshots.remove(&id) + } + + /// Inserts the new state snapshot and returns the id. + pub fn insert(&mut self, state_snapshot: T) -> U256 { + let id = self.next_id(); + self.state_snapshots.insert(id, state_snapshot); + id + } + + /// Inserts the new state snapshot at the given `id`. + /// + /// Does not auto-increment the next `id`. + pub fn insert_at(&mut self, state_snapshot: T, id: U256) -> U256 { + self.state_snapshots.insert(id, state_snapshot); + id + } +} + +impl Default for StateSnapshots { + fn default() -> Self { + Self { id: U256::ZERO, state_snapshots: HashMap::new() } + } +} diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index dc923d6e00b3..7a1a794f607e 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -395,7 +395,7 @@ impl Executor { let mut inspector = self.inspector().clone(); let mut backend = CowBackend::new_borrowed(self.backend()); let result = backend.inspect(&mut env, &mut inspector)?; - convert_executed_result(env, inspector, result, backend.has_snapshot_failure()) + convert_executed_result(env, inspector, result, backend.has_state_snapshot_failure()) } /// Execute the transaction configured in `env.tx`. @@ -405,7 +405,7 @@ impl Executor { let backend = self.backend_mut(); let result = backend.inspect(&mut env, &mut inspector)?; let mut result = - convert_executed_result(env, inspector, result, backend.has_snapshot_failure())?; + convert_executed_result(env, inspector, result, backend.has_state_snapshot_failure())?; self.commit(&mut result); Ok(result) } @@ -465,7 +465,7 @@ impl Executor { call_result: &RawCallResult, should_fail: bool, ) -> bool { - if call_result.has_snapshot_failure { + if call_result.has_state_snapshot_failure { // a failure occurred in a reverted snapshot, which is considered a failed test return should_fail; } @@ -517,7 +517,7 @@ impl Executor { } // A failure occurred in a reverted snapshot, which is considered a failed test. - if self.backend().has_snapshot_failure() { + if self.backend().has_state_snapshot_failure() { return false; } @@ -711,7 +711,7 @@ pub struct RawCallResult { /// /// This is tracked separately from revert because a snapshot failure can occur without a /// revert, since assert failures are stored in a global variable (ds-test legacy) - pub has_snapshot_failure: bool, + pub has_state_snapshot_failure: bool, /// The raw result of the call. pub result: Bytes, /// The gas used for the call @@ -747,7 +747,7 @@ impl Default for RawCallResult { Self { exit_reason: InstructionResult::Continue, reverted: false, - has_snapshot_failure: false, + has_state_snapshot_failure: false, result: Bytes::new(), gas_used: 0, gas_refunded: 0, @@ -842,7 +842,7 @@ fn convert_executed_result( env: EnvWithHandlerCfg, inspector: InspectorStack, ResultAndState { result, state: state_changeset }: ResultAndState, - has_snapshot_failure: bool, + has_state_snapshot_failure: bool, ) -> eyre::Result { let (exit_reason, gas_refunded, gas_used, out, exec_logs) = match result { ExecutionResult::Success { reason, gas_used, gas_refunded, output, logs, .. } => { @@ -884,7 +884,7 @@ fn convert_executed_result( Ok(RawCallResult { exit_reason, reverted: !matches!(exit_reason, return_ok!()), - has_snapshot_failure, + has_state_snapshot_failure, result, gas_used, gas_refunded, diff --git a/crates/forge/bin/cmd/snapshot.rs b/crates/forge/bin/cmd/snapshot.rs index 8c3d57fc3135..20c5013ec450 100644 --- a/crates/forge/bin/cmd/snapshot.rs +++ b/crates/forge/bin/cmd/snapshot.rs @@ -24,8 +24,8 @@ pub static RE_BASIC_SNAPSHOT_ENTRY: LazyLock = LazyLock::new(|| { /// CLI arguments for `forge snapshot`. #[derive(Clone, Debug, Parser)] -pub struct SnapshotArgs { - /// Output a diff against a pre-existing snapshot. +pub struct GasSnapshotArgs { + /// Output a diff against a pre-existing gas snapshot. /// /// By default, the comparison is done with .gas-snapshot. #[arg( @@ -36,9 +36,9 @@ pub struct SnapshotArgs { )] diff: Option>, - /// Compare against a pre-existing snapshot, exiting with code 1 if they do not match. + /// Compare against a pre-existing gas snapshot, exiting with code 1 if they do not match. /// - /// Outputs a diff if the snapshots do not match. + /// Outputs a diff if the gas snapshots do not match. /// /// By default, the comparison is done with .gas-snapshot. #[arg( @@ -54,7 +54,7 @@ pub struct SnapshotArgs { #[arg(long, hide(true))] format: Option, - /// Output file for the snapshot. + /// Output file for the gas snapshot. #[arg( long, default_value = ".gas-snapshot", @@ -77,11 +77,11 @@ pub struct SnapshotArgs { /// Additional configs for test results #[command(flatten)] - config: SnapshotConfig, + config: GasSnapshotConfig, } -impl SnapshotArgs { - /// Returns whether `SnapshotArgs` was configured with `--watch` +impl GasSnapshotArgs { + /// Returns whether `GasSnapshotArgs` was configured with `--watch` pub fn is_watch(&self) -> bool { self.test.is_watch() } @@ -102,18 +102,18 @@ impl SnapshotArgs { if let Some(path) = self.diff { let snap = path.as_ref().unwrap_or(&self.snap); - let snaps = read_snapshot(snap)?; + let snaps = read_gas_snapshot(snap)?; diff(tests, snaps)?; } else if let Some(path) = self.check { let snap = path.as_ref().unwrap_or(&self.snap); - let snaps = read_snapshot(snap)?; + let snaps = read_gas_snapshot(snap)?; if check(tests, snaps, self.tolerance) { std::process::exit(0) } else { std::process::exit(1) } } else { - write_to_snapshot_file(&tests, self.snap, self.format)?; + write_to_gas_snapshot_file(&tests, self.snap, self.format)?; } Ok(()) } @@ -138,7 +138,7 @@ impl FromStr for Format { /// Additional filters that can be applied on the test results #[derive(Clone, Debug, Default, Parser)] -struct SnapshotConfig { +struct GasSnapshotConfig { /// Sort results by gas used (ascending). #[arg(long)] asc: bool, @@ -156,7 +156,7 @@ struct SnapshotConfig { max: Option, } -impl SnapshotConfig { +impl GasSnapshotConfig { fn is_in_gas_range(&self, gas_used: u64) -> bool { if let Some(min) = self.min { if gas_used < min { @@ -187,20 +187,20 @@ impl SnapshotConfig { } } -/// A general entry in a snapshot file +/// A general entry in a gas snapshot file /// /// Has the form: /// `(gas:? 40181)` for normal tests /// `(runs: 256, μ: 40181, ~: 40181)` for fuzz tests /// `(runs: 256, calls: 40181, reverts: 40181)` for invariant tests #[derive(Clone, Debug, PartialEq, Eq)] -pub struct SnapshotEntry { +pub struct GasSnapshotEntry { pub contract_name: String, pub signature: String, pub gas_used: TestKindReport, } -impl FromStr for SnapshotEntry { +impl FromStr for GasSnapshotEntry { type Err = String; fn from_str(s: &str) -> Result { @@ -253,8 +253,8 @@ impl FromStr for SnapshotEntry { } } -/// Reads a list of snapshot entries from a snapshot file -fn read_snapshot(path: impl AsRef) -> Result> { +/// Reads a list of gas snapshot entries from a gas snapshot file. +fn read_gas_snapshot(path: impl AsRef) -> Result> { let path = path.as_ref(); let mut entries = Vec::new(); for line in io::BufReader::new( @@ -263,13 +263,14 @@ fn read_snapshot(path: impl AsRef) -> Result> { ) .lines() { - entries.push(SnapshotEntry::from_str(line?.as_str()).map_err(|err| eyre::eyre!("{err}"))?); + entries + .push(GasSnapshotEntry::from_str(line?.as_str()).map_err(|err| eyre::eyre!("{err}"))?); } Ok(entries) } -/// Writes a series of tests to a snapshot file after sorting them -fn write_to_snapshot_file( +/// Writes a series of tests to a gas snapshot file after sorting them. +fn write_to_gas_snapshot_file( tests: &[SuiteTestResult], path: impl AsRef, _format: Option, @@ -288,15 +289,15 @@ fn write_to_snapshot_file( Ok(fs::write(path, content)?) } -/// A Snapshot entry diff +/// A Gas snapshot entry diff. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct SnapshotDiff { +pub struct GasSnapshotDiff { pub signature: String, pub source_gas_used: TestKindReport, pub target_gas_used: TestKindReport, } -impl SnapshotDiff { +impl GasSnapshotDiff { /// Returns the gas diff /// /// `> 0` if the source used more gas @@ -311,10 +312,14 @@ impl SnapshotDiff { } } -/// Compares the set of tests with an existing snapshot +/// Compares the set of tests with an existing gas snapshot. /// /// Returns true all tests match -fn check(tests: Vec, snaps: Vec, tolerance: Option) -> bool { +fn check( + tests: Vec, + snaps: Vec, + tolerance: Option, +) -> bool { let snaps = snaps .into_iter() .map(|s| ((s.contract_name, s.signature), s.gas_used)) @@ -347,8 +352,8 @@ fn check(tests: Vec, snaps: Vec, tolerance: Opti !has_diff } -/// Compare the set of tests with an existing snapshot -fn diff(tests: Vec, snaps: Vec) -> Result<()> { +/// Compare the set of tests with an existing gas snapshot. +fn diff(tests: Vec, snaps: Vec) -> Result<()> { let snaps = snaps .into_iter() .map(|s| ((s.contract_name, s.signature), s.gas_used)) @@ -358,7 +363,7 @@ fn diff(tests: Vec, snaps: Vec) -> Result<()> { if let Some(target_gas_used) = snaps.get(&(test.contract_name().to_string(), test.signature.clone())).cloned() { - diffs.push(SnapshotDiff { + diffs.push(GasSnapshotDiff { source_gas_used: test.result.kind.report(), signature: test.signature, target_gas_used, @@ -446,12 +451,12 @@ mod tests { } #[test] - fn can_parse_basic_snapshot_entry() { + fn can_parse_basic_gas_snapshot_entry() { let s = "Test:deposit() (gas: 7222)"; - let entry = SnapshotEntry::from_str(s).unwrap(); + let entry = GasSnapshotEntry::from_str(s).unwrap(); assert_eq!( entry, - SnapshotEntry { + GasSnapshotEntry { contract_name: "Test".to_string(), signature: "deposit()".to_string(), gas_used: TestKindReport::Unit { gas: 7222 } @@ -460,12 +465,12 @@ mod tests { } #[test] - fn can_parse_fuzz_snapshot_entry() { + fn can_parse_fuzz_gas_snapshot_entry() { let s = "Test:deposit() (runs: 256, μ: 100, ~:200)"; - let entry = SnapshotEntry::from_str(s).unwrap(); + let entry = GasSnapshotEntry::from_str(s).unwrap(); assert_eq!( entry, - SnapshotEntry { + GasSnapshotEntry { contract_name: "Test".to_string(), signature: "deposit()".to_string(), gas_used: TestKindReport::Fuzz { runs: 256, median_gas: 200, mean_gas: 100 } @@ -474,12 +479,12 @@ mod tests { } #[test] - fn can_parse_invariant_snapshot_entry() { + fn can_parse_invariant_gas_snapshot_entry() { let s = "Test:deposit() (runs: 256, calls: 100, reverts: 200)"; - let entry = SnapshotEntry::from_str(s).unwrap(); + let entry = GasSnapshotEntry::from_str(s).unwrap(); assert_eq!( entry, - SnapshotEntry { + GasSnapshotEntry { contract_name: "Test".to_string(), signature: "deposit()".to_string(), gas_used: TestKindReport::Invariant { runs: 256, calls: 100, reverts: 200 } @@ -488,12 +493,12 @@ mod tests { } #[test] - fn can_parse_invariant_snapshot_entry2() { + fn can_parse_invariant_gas_snapshot_entry2() { let s = "ERC20Invariants:invariantBalanceSum() (runs: 256, calls: 3840, reverts: 2388)"; - let entry = SnapshotEntry::from_str(s).unwrap(); + let entry = GasSnapshotEntry::from_str(s).unwrap(); assert_eq!( entry, - SnapshotEntry { + GasSnapshotEntry { contract_name: "ERC20Invariants".to_string(), signature: "invariantBalanceSum()".to_string(), gas_used: TestKindReport::Invariant { runs: 256, calls: 3840, reverts: 2388 } diff --git a/crates/forge/bin/cmd/watch.rs b/crates/forge/bin/cmd/watch.rs index 10562ba1295c..19b37009fd6f 100644 --- a/crates/forge/bin/cmd/watch.rs +++ b/crates/forge/bin/cmd/watch.rs @@ -1,4 +1,4 @@ -use super::{build::BuildArgs, doc::DocArgs, snapshot::SnapshotArgs, test::TestArgs}; +use super::{build::BuildArgs, doc::DocArgs, snapshot::GasSnapshotArgs, test::TestArgs}; use clap::Parser; use eyre::Result; use foundry_cli::utils::{self, FoundryPathExt}; @@ -249,7 +249,7 @@ pub async fn watch_build(args: BuildArgs) -> Result<()> { /// Executes a [`Watchexec`] that listens for changes in the project's src dir and reruns `forge /// snapshot` -pub async fn watch_snapshot(args: SnapshotArgs) -> Result<()> { +pub async fn watch_gas_snapshot(args: GasSnapshotArgs) -> Result<()> { let config = args.watchexec_config()?; run(config).await } diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index f92d3db8085b..9a98d8aeffd0 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -88,7 +88,7 @@ fn main() -> Result<()> { } ForgeSubcommand::Snapshot(cmd) => { if cmd.is_watch() { - utils::block_on(watch::watch_snapshot(cmd)) + utils::block_on(watch::watch_gas_snapshot(cmd)) } else { utils::block_on(cmd.run()) } diff --git a/crates/forge/bin/opts.rs b/crates/forge/bin/opts.rs index fbe1f67df88a..c929d0185ba7 100644 --- a/crates/forge/bin/opts.rs +++ b/crates/forge/bin/opts.rs @@ -123,9 +123,9 @@ pub enum ForgeSubcommand { /// Manage the Foundry cache. Cache(CacheArgs), - /// Create a snapshot of each test's gas usage. + /// Create a gas snapshot of each test's gas usage. #[command(visible_alias = "s")] - Snapshot(snapshot::SnapshotArgs), + Snapshot(snapshot::GasSnapshotArgs), /// Display the current config. #[command(visible_alias = "co")] diff --git a/crates/forge/tests/it/repros.rs b/crates/forge/tests/it/repros.rs index 0d1e15052a79..d463d12dd7c7 100644 --- a/crates/forge/tests/it/repros.rs +++ b/crates/forge/tests/it/repros.rs @@ -251,7 +251,7 @@ test_repro!(6355, false, None, |res| { let test = res.test_results.remove("test_shouldFail()").unwrap(); assert_eq!(test.status, TestStatus::Failure); - let test = res.test_results.remove("test_shouldFailWithRevertTo()").unwrap(); + let test = res.test_results.remove("test_shouldFailWithRevertToState()").unwrap(); assert_eq!(test.status, TestStatus::Failure); }); diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 2b93473827eb..09099f5402a2 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -176,6 +176,8 @@ interface Vm { function deal(address account, uint256 newBalance) external; function deleteSnapshot(uint256 snapshotId) external returns (bool success); function deleteSnapshots() external; + function deleteStateSnapshot(uint256 snapshotId) external returns (bool success); + function deleteStateSnapshots() external; function deployCode(string calldata artifactPath) external returns (address deployedAddress); function deployCode(string calldata artifactPath, bytes calldata constructorArgs) external returns (address deployedAddress); function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); @@ -370,6 +372,8 @@ interface Vm { function resumeTracing() external view; function revertTo(uint256 snapshotId) external returns (bool success); function revertToAndDelete(uint256 snapshotId) external returns (bool success); + function revertToState(uint256 snapshotId) external returns (bool success); + function revertToStateAndDelete(uint256 snapshotId) external returns (bool success); function revokePersistent(address account) external; function revokePersistent(address[] calldata accounts) external; function roll(uint256 newHeight) external; @@ -419,6 +423,7 @@ interface Vm { function skip(bool skipTest, string calldata reason) external; function sleep(uint256 duration) external; function snapshot() external returns (uint256 snapshotId); + function snapshotState() external returns (uint256 snapshotId); function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); function startBroadcast() external; function startBroadcast(address signer) external; diff --git a/testdata/default/cheats/Prevrandao.t.sol b/testdata/default/cheats/Prevrandao.t.sol index 7011ce3bee9c..75f2b2cc1302 100644 --- a/testdata/default/cheats/Prevrandao.t.sol +++ b/testdata/default/cheats/Prevrandao.t.sol @@ -23,12 +23,12 @@ contract PrevrandaoTest is DSTest { function testPrevrandaoSnapshotFuzzed(uint256 newPrevrandao) public { vm.assume(newPrevrandao != block.prevrandao); uint256 oldPrevrandao = block.prevrandao; - uint256 snapshot = vm.snapshot(); + uint256 snapshotId = vm.snapshotState(); vm.prevrandao(newPrevrandao); assertEq(block.prevrandao, newPrevrandao); - assert(vm.revertTo(snapshot)); + assert(vm.revertToState(snapshotId)); assertEq(block.prevrandao, oldPrevrandao); } } diff --git a/testdata/default/cheats/Snapshots.t.sol b/testdata/default/cheats/Snapshots.t.sol deleted file mode 100644 index bb7b4e0e6008..000000000000 --- a/testdata/default/cheats/Snapshots.t.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity 0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -struct Storage { - uint256 slot0; - uint256 slot1; -} - -contract SnapshotTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - Storage store; - - function setUp() public { - store.slot0 = 10; - store.slot1 = 20; - } - - function testSnapshot() public { - uint256 snapshot = vm.snapshot(); - store.slot0 = 300; - store.slot1 = 400; - - assertEq(store.slot0, 300); - assertEq(store.slot1, 400); - - vm.revertTo(snapshot); - assertEq(store.slot0, 10, "snapshot revert for slot 0 unsuccessful"); - assertEq(store.slot1, 20, "snapshot revert for slot 1 unsuccessful"); - } - - function testSnapshotRevertDelete() public { - uint256 snapshot = vm.snapshot(); - store.slot0 = 300; - store.slot1 = 400; - - assertEq(store.slot0, 300); - assertEq(store.slot1, 400); - - vm.revertToAndDelete(snapshot); - assertEq(store.slot0, 10, "snapshot revert for slot 0 unsuccessful"); - assertEq(store.slot1, 20, "snapshot revert for slot 1 unsuccessful"); - // nothing to revert to anymore - assert(!vm.revertTo(snapshot)); - } - - function testSnapshotDelete() public { - uint256 snapshot = vm.snapshot(); - store.slot0 = 300; - store.slot1 = 400; - - vm.deleteSnapshot(snapshot); - // nothing to revert to anymore - assert(!vm.revertTo(snapshot)); - } - - function testSnapshotDeleteAll() public { - uint256 snapshot = vm.snapshot(); - store.slot0 = 300; - store.slot1 = 400; - - vm.deleteSnapshots(); - // nothing to revert to anymore - assert(!vm.revertTo(snapshot)); - } - - // - function testSnapshotsMany() public { - uint256 preState; - for (uint256 c = 0; c < 10; c++) { - for (uint256 cc = 0; cc < 10; cc++) { - preState = vm.snapshot(); - vm.revertToAndDelete(preState); - assert(!vm.revertTo(preState)); - } - } - } - - // tests that snapshots can also revert changes to `block` - function testBlockValues() public { - uint256 num = block.number; - uint256 time = block.timestamp; - uint256 prevrandao = block.prevrandao; - - uint256 snapshot = vm.snapshot(); - - vm.warp(1337); - assertEq(block.timestamp, 1337); - - vm.roll(99); - assertEq(block.number, 99); - - vm.prevrandao(uint256(123)); - assertEq(block.prevrandao, 123); - - assert(vm.revertTo(snapshot)); - - assertEq(block.number, num, "snapshot revert for block.number unsuccessful"); - assertEq(block.timestamp, time, "snapshot revert for block.timestamp unsuccessful"); - assertEq(block.prevrandao, prevrandao, "snapshot revert for block.prevrandao unsuccessful"); - } -} diff --git a/testdata/default/cheats/StateSnapshots.t.sol b/testdata/default/cheats/StateSnapshots.t.sol new file mode 100644 index 000000000000..92ee38d26e2e --- /dev/null +++ b/testdata/default/cheats/StateSnapshots.t.sol @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +struct Storage { + uint256 slot0; + uint256 slot1; +} + +contract StateSnapshotTest is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + Storage store; + + function setUp() public { + store.slot0 = 10; + store.slot1 = 20; + } + + function testStateSnapshot() public { + uint256 snapshotId = vm.snapshotState(); + store.slot0 = 300; + store.slot1 = 400; + + assertEq(store.slot0, 300); + assertEq(store.slot1, 400); + + vm.revertToState(snapshotId); + assertEq(store.slot0, 10, "snapshot revert for slot 0 unsuccessful"); + assertEq(store.slot1, 20, "snapshot revert for slot 1 unsuccessful"); + } + + function testStateSnapshotRevertDelete() public { + uint256 snapshotId = vm.snapshotState(); + store.slot0 = 300; + store.slot1 = 400; + + assertEq(store.slot0, 300); + assertEq(store.slot1, 400); + + vm.revertToStateAndDelete(snapshotId); + assertEq(store.slot0, 10, "snapshot revert for slot 0 unsuccessful"); + assertEq(store.slot1, 20, "snapshot revert for slot 1 unsuccessful"); + // nothing to revert to anymore + assert(!vm.revertToState(snapshotId)); + } + + function testStateSnapshotDelete() public { + uint256 snapshotId = vm.snapshotState(); + store.slot0 = 300; + store.slot1 = 400; + + vm.deleteStateSnapshot(snapshotId); + // nothing to revert to anymore + assert(!vm.revertToState(snapshotId)); + } + + function testStateSnapshotDeleteAll() public { + uint256 snapshotId = vm.snapshotState(); + store.slot0 = 300; + store.slot1 = 400; + + vm.deleteStateSnapshots(); + // nothing to revert to anymore + assert(!vm.revertToState(snapshotId)); + } + + // + function testStateSnapshotsMany() public { + uint256 snapshotId; + for (uint256 c = 0; c < 10; c++) { + for (uint256 cc = 0; cc < 10; cc++) { + snapshotId = vm.snapshotState(); + vm.revertToStateAndDelete(snapshotId); + assert(!vm.revertToState(snapshotId)); + } + } + } + + // tests that snapshots can also revert changes to `block` + function testBlockValues() public { + uint256 num = block.number; + uint256 time = block.timestamp; + uint256 prevrandao = block.prevrandao; + + uint256 snapshotId = vm.snapshotState(); + + vm.warp(1337); + assertEq(block.timestamp, 1337); + + vm.roll(99); + assertEq(block.number, 99); + + vm.prevrandao(uint256(123)); + assertEq(block.prevrandao, 123); + + assert(vm.revertToState(snapshotId)); + + assertEq(block.number, num, "snapshot revert for block.number unsuccessful"); + assertEq(block.timestamp, time, "snapshot revert for block.timestamp unsuccessful"); + assertEq(block.prevrandao, prevrandao, "snapshot revert for block.prevrandao unsuccessful"); + } +} + +// TODO: remove this test suite once `snapshot*` has been deprecated in favor of `snapshotState*`. +contract DeprecatedStateSnapshotTest is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + Storage store; + + function setUp() public { + store.slot0 = 10; + store.slot1 = 20; + } + + function testSnapshotState() public { + uint256 snapshotId = vm.snapshot(); + store.slot0 = 300; + store.slot1 = 400; + + assertEq(store.slot0, 300); + assertEq(store.slot1, 400); + + vm.revertTo(snapshotId); + assertEq(store.slot0, 10, "snapshot revert for slot 0 unsuccessful"); + assertEq(store.slot1, 20, "snapshot revert for slot 1 unsuccessful"); + } + + function testSnapshotStateRevertDelete() public { + uint256 snapshotId = vm.snapshot(); + store.slot0 = 300; + store.slot1 = 400; + + assertEq(store.slot0, 300); + assertEq(store.slot1, 400); + + vm.revertToAndDelete(snapshotId); + assertEq(store.slot0, 10, "snapshot revert for slot 0 unsuccessful"); + assertEq(store.slot1, 20, "snapshot revert for slot 1 unsuccessful"); + // nothing to revert to anymore + assert(!vm.revertTo(snapshotId)); + } + + function testSnapshotStateDelete() public { + uint256 snapshotId = vm.snapshot(); + store.slot0 = 300; + store.slot1 = 400; + + vm.deleteSnapshot(snapshotId); + // nothing to revert to anymore + assert(!vm.revertTo(snapshotId)); + } + + function testSnapshotStateDeleteAll() public { + uint256 snapshotId = vm.snapshot(); + store.slot0 = 300; + store.slot1 = 400; + + vm.deleteSnapshots(); + // nothing to revert to anymore + assert(!vm.revertTo(snapshotId)); + } + + // + function testSnapshotStatesMany() public { + uint256 snapshotId; + for (uint256 c = 0; c < 10; c++) { + for (uint256 cc = 0; cc < 10; cc++) { + snapshotId = vm.snapshot(); + vm.revertToAndDelete(snapshotId); + assert(!vm.revertTo(snapshotId)); + } + } + } + + // tests that snapshots can also revert changes to `block` + function testBlockValues() public { + uint256 num = block.number; + uint256 time = block.timestamp; + uint256 prevrandao = block.prevrandao; + + uint256 snapshotId = vm.snapshot(); + + vm.warp(1337); + assertEq(block.timestamp, 1337); + + vm.roll(99); + assertEq(block.number, 99); + + vm.prevrandao(uint256(123)); + assertEq(block.prevrandao, 123); + + assert(vm.revertTo(snapshotId)); + + assertEq(block.number, num, "snapshot revert for block.number unsuccessful"); + assertEq(block.timestamp, time, "snapshot revert for block.timestamp unsuccessful"); + assertEq(block.prevrandao, prevrandao, "snapshot revert for block.prevrandao unsuccessful"); + } +} diff --git a/testdata/default/cheats/loadAllocs.t.sol b/testdata/default/cheats/loadAllocs.t.sol index 358608860bd5..a4b72af6b2fe 100644 --- a/testdata/default/cheats/loadAllocs.t.sol +++ b/testdata/default/cheats/loadAllocs.t.sol @@ -16,7 +16,7 @@ contract LoadAllocsTest is DSTest { allocsPath = string.concat(vm.projectRoot(), "/fixtures/Json/test_allocs.json"); // Snapshot the state; We'll restore it in each test that loads allocs inline. - snapshotId = vm.snapshot(); + snapshotId = vm.snapshotState(); // Load the allocs file. vm.loadAllocs(allocsPath); @@ -40,7 +40,7 @@ contract LoadAllocsTest is DSTest { /// @dev Checks that the `loadAllocs` cheatcode persists account info if called inline function testLoadAllocsStatic() public { // Restore the state snapshot prior to the allocs file being loaded. - vm.revertTo(snapshotId); + vm.revertToState(snapshotId); // Load the allocs file vm.loadAllocs(allocsPath); @@ -61,7 +61,7 @@ contract LoadAllocsTest is DSTest { /// @dev Checks that the `loadAllocs` cheatcode overrides existing account information (if present) function testLoadAllocsOverride() public { // Restore the state snapshot prior to the allocs file being loaded. - vm.revertTo(snapshotId); + vm.revertToState(snapshotId); // Populate the alloc'd account's code. vm.etch(ALLOCD, hex"FF"); @@ -88,7 +88,7 @@ contract LoadAllocsTest is DSTest { /// within the allocs/genesis file for the account field (i.e., partial overrides) function testLoadAllocsPartialOverride() public { // Restore the state snapshot prior to the allocs file being loaded. - vm.revertTo(snapshotId); + vm.revertToState(snapshotId); // Populate the alloc'd account's code. vm.etch(ALLOCD_B, hex"FF"); diff --git a/testdata/default/repros/Issue2984.t.sol b/testdata/default/repros/Issue2984.t.sol index 1a181ad533c2..5f0203369e0d 100644 --- a/testdata/default/repros/Issue2984.t.sol +++ b/testdata/default/repros/Issue2984.t.sol @@ -12,11 +12,11 @@ contract Issue2984Test is DSTest { function setUp() public { fork = vm.createSelectFork("avaxTestnet", 12880747); - snapshot = vm.snapshot(); + snapshot = vm.snapshotState(); } function testForkRevertSnapshot() public { - vm.revertTo(snapshot); + vm.revertToState(snapshot); } function testForkSelectSnapshot() public { diff --git a/testdata/default/repros/Issue3055.t.sol b/testdata/default/repros/Issue3055.t.sol index cacf5282f058..72461a6c0165 100644 --- a/testdata/default/repros/Issue3055.t.sol +++ b/testdata/default/repros/Issue3055.t.sol @@ -9,15 +9,15 @@ contract Issue3055Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function test_snapshot() external { - uint256 snapId = vm.snapshot(); + uint256 snapshotId = vm.snapshotState(); assertEq(uint256(0), uint256(1)); - vm.revertTo(snapId); + vm.revertToState(snapshotId); } function test_snapshot2() public { - uint256 snapshot = vm.snapshot(); + uint256 snapshotId = vm.snapshotState(); assertTrue(false); - vm.revertTo(snapshot); + vm.revertToState(snapshotId); assertTrue(true); } @@ -29,8 +29,8 @@ contract Issue3055Test is DSTest { } function exposed_snapshot3() public { - uint256 snapshot = vm.snapshot(); + uint256 snapshotId = vm.snapshotState(); assertTrue(false); - vm.revertTo(snapshot); + vm.revertToState(snapshotId); } } diff --git a/testdata/default/repros/Issue3792.t.sol b/testdata/default/repros/Issue3792.t.sol index 723329f937a1..1adeb88af8c9 100644 --- a/testdata/default/repros/Issue3792.t.sol +++ b/testdata/default/repros/Issue3792.t.sol @@ -16,10 +16,10 @@ contract TestSetup is Config, DSTest { // We now check for keccak256("failed") on the hevm address. // This test should succeed. function testSnapshotStorageShift() public { - uint256 snapshotId = vm.snapshot(); + uint256 snapshotId = vm.snapshotState(); vm.prank(test); - vm.revertTo(snapshotId); + vm.revertToState(snapshotId); } } diff --git a/testdata/default/repros/Issue6355.t.sol b/testdata/default/repros/Issue6355.t.sol index d7830152a60a..f002b2a87c03 100644 --- a/testdata/default/repros/Issue6355.t.sol +++ b/testdata/default/repros/Issue6355.t.sol @@ -7,11 +7,11 @@ import "cheats/Vm.sol"; // https://github.com/foundry-rs/foundry/issues/6355 contract Issue6355Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); - uint256 snapshot; + uint256 snapshotId; Target targ; function setUp() public { - snapshot = vm.snapshot(); + snapshotId = vm.snapshotState(); targ = new Target(); } @@ -21,9 +21,9 @@ contract Issue6355Test is DSTest { } // always fails - function test_shouldFailWithRevertTo() public { + function test_shouldFailWithRevertToState() public { assertEq(3, targ.num()); - vm.revertTo(snapshot); + vm.revertToState(snapshotId); } // always fails