diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index f23d90589d255..953ad4f8c689d 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -3464,7 +3464,13 @@ where { // Unwind the storage back to the common ancestor first - self.blockchain.storage.write().unwind_to(common_block.header.number(), hash); + let removed_blocks = + self.blockchain.storage.write().unwind_to(common_block.header.number(), hash); + + // Clean up in-memory and on-disk states for removed blocks + let removed_hashes: Vec<_> = + removed_blocks.iter().map(|b| b.header.hash_slow()).collect(); + self.states.write().remove_block_states(&removed_hashes); // Set environment back to common block let mut env = self.evm_env.write(); diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index 51f8000bd44bf..3f3f3d9014329 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -209,6 +209,20 @@ impl InMemoryBlockStates { } } + /// Removes states for the given block hashes. + /// + /// This is used during chain rollback to clean up states for blocks that are no longer part + /// of the canonical chain. + pub fn remove_block_states(&mut self, hashes: &[B256]) { + for hash in hashes { + self.states.remove(hash); + self.on_disk_states.remove(hash); + self.disk_cache.remove(*hash); + } + self.present.retain(|h| !hashes.contains(h)); + self.oldest_on_disk.retain(|h| !hashes.contains(h)); + } + /// Serialize all states to a list of serializable historical states pub fn serialized_states(&mut self) -> SerializableHistoricalStates { // Get in-memory states