Skip to main content

revm_trace/evm/
reset.rs

1use crate::{
2    errors::EvmError,
3    traits::{ResetBlock, ResetDB},
4    types::AllDBType,
5    TraceEvm,
6};
7use alloy::eips::{BlockId, BlockNumberOrTag};
8use revm::{
9    context::BlockEnv,
10    context_interface::ContextTr,
11    database::{CacheDB, DatabaseRef},
12    ExecuteEvm,
13};
14// ========================= Database Management =========================
15
16/// Implementation for TraceEvm instances with CacheDB
17///
18/// Provides database cache management utilities specifically for EVM instances
19/// that use `CacheDB` as their database layer.
20impl<DB, INSP> ResetDB for TraceEvm<CacheDB<DB>, INSP>
21where
22    DB: DatabaseRef,
23{
24    /// Reset the database cache to clear all cached state
25    ///
26    /// This method clears all cached data from the `CacheDB` layer, including:
27    /// - Account states and balances
28    /// - Contract bytecode and storage
29    /// - Event logs
30    /// - Block hashes
31    ///
32    /// # Use Cases
33    /// - Resetting state between independent transaction simulations
34    /// - Clearing cache when switching to a different block context
35    /// - Memory management in long-running applications
36    /// - Testing scenarios requiring clean state
37    ///
38    /// # Performance Impact
39    /// After calling this method, subsequent database queries will need to
40    /// fetch data from the underlying database layer, which may be slower
41    /// until the cache is repopulated.
42    ///
43    /// # Example
44    /// ```no_run
45    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
46    /// use revm_trace::{create_evm, traits::ResetDB};
47    ///
48    /// let mut evm = create_evm("https://eth.llamarpc.com").await?;
49    ///
50    /// // Clear cache before processing a new batch of transactions
51    /// evm.reset_db();
52    /// # Ok(())
53    /// # }
54    /// ```
55    fn reset_db(&mut self) {
56        let cached_db = &mut self.0.ctx.db().cache;
57        cached_db.accounts.clear();
58        cached_db.contracts.clear();
59        cached_db.logs = Vec::new();
60        cached_db.block_hashes.clear();
61    }
62}
63
64impl ResetBlock for AllDBType {
65    type Error = EvmError;
66    fn reset_block(&mut self, block_number: u64) -> Result<(), EvmError> {
67        // Reset the block number in the EVM context
68        let db = self.get_db_mut();
69        db.set_block_number(BlockId::Number(BlockNumberOrTag::Number(block_number)));
70        Ok(())
71    }
72}
73
74// Generic set_db_block implementation for any database type implementing ResetBlock
75impl<DB, INSP> TraceEvm<CacheDB<DB>, INSP>
76where
77    DB: DatabaseRef + ResetBlock,
78    <DB as ResetBlock>::Error: Into<EvmError>,
79{
80    /// Reset the underlying database to a specific block, clear cache, and update EVM context
81    ///
82    /// Steps:
83    /// 1. Reset the underlying database's block state
84    /// 2. Clear the outer CacheDB cache
85    /// 3. Update the EVM's block context
86    pub fn set_db_block(&mut self, block_env: BlockEnv) -> Result<(), EvmError> {
87        // Step 1: Reset the underlying database's block state
88        {
89            let cache_db = &mut self.0.ctx.db().db;
90            cache_db.reset_block(block_env.number).map_err(Into::into)?;
91        }
92        // Step 2: Clear the outer CacheDB cache
93        self.reset_db();
94
95        // Step 3: Update the EVM's block context
96        self.set_block(block_env);
97
98        Ok(())
99    }
100}
101
102#[cfg(feature = "foundry-fork")]
103use foundry_fork_db::backend::SharedBackend;
104
105#[cfg(feature = "foundry-fork")]
106use crate::errors::InitError;
107
108#[cfg(feature = "foundry-fork")]
109impl ResetBlock for SharedBackend {
110    type Error = EvmError;
111    fn reset_block(&mut self, block_number: u64) -> Result<(), EvmError> {
112        // Reset the block number in the EVM context
113        self.set_pinned_block(BlockId::Number(BlockNumberOrTag::Number(block_number)))
114            .map_err(|e| EvmError::Init(InitError::DatabaseError(e.to_string())))?;
115        // Clear the cache
116        let data = self.data();
117        data.clear();
118        Ok(())
119    }
120}