degenbot_simulation/sim/evm/
storage_memo.rs1use alloy::primitives::{Address, StorageValue, U256};
19use parking_lot::Mutex;
20use std::collections::HashMap;
21use std::sync::atomic::{AtomicU64, Ordering};
22
23#[derive(Default)]
24struct Inner {
25 map: HashMap<(Address, U256), StorageValue>,
26}
27
28#[derive(Default)]
29pub struct StorageMemo {
30 inner: Mutex<Inner>,
31 hits: AtomicU64,
32 misses: AtomicU64,
33}
34
35impl StorageMemo {
36 #[must_use]
37 pub fn new() -> Self {
38 Self::default()
39 }
40
41 pub fn get(&self, address: Address, index: U256) -> Option<StorageValue> {
44 let inner = self.inner.lock();
45 let hit = inner.map.get(&(address, index)).copied();
46 if hit.is_some() {
47 self.hits.fetch_add(1, Ordering::Relaxed);
48 } else {
49 self.misses.fetch_add(1, Ordering::Relaxed);
50 }
51 hit
52 }
53
54 pub fn put(&self, address: Address, index: U256, value: StorageValue) {
55 self.inner.lock().map.insert((address, index), value);
56 }
57
58 #[must_use]
60 pub fn stats(&self) -> (u64, u64) {
61 (
62 self.hits.load(Ordering::Relaxed),
63 self.misses.load(Ordering::Relaxed),
64 )
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn round_trip_and_stats() {
74 let memo = StorageMemo::new();
75 let addr = Address::ZERO;
76 let key = U256::from(7u64);
77 assert_eq!(memo.get(addr, key), None);
78 memo.put(addr, key, StorageValue::from(42u64));
79 assert_eq!(memo.get(addr, key), Some(StorageValue::from(42u64)));
80 let (h, m) = memo.stats();
81 assert_eq!((h, m), (1, 1));
82 }
83}