Skip to main content

revm_state/
types.rs

1use super::{Account, EvmStorageSlot};
2use core::ops::{Deref, DerefMut};
3use primitives::{Address, AddressMap, StorageKey, StorageKeyMap, StorageValue};
4
5/// EVM State is a mapping from addresses to accounts.
6pub type EvmState = AddressMap<Account>;
7
8/// An account's Storage is a mapping from 256-bit integer keys to [EvmStorageSlot]s.
9pub type EvmStorage = StorageKeyMap<EvmStorageSlot>;
10
11/// Structure used for EIP-1153 transient storage.
12///
13/// Maps each account [`Address`] to its transient storage slots, a mapping from
14/// storage [`StorageKey`]s to [`StorageValue`]s. Transient storage is discarded
15/// after every transaction.
16///
17/// See [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153).
18///
19/// This is a thin wrapper around an [`AddressMap`] of [`StorageKeyMap`]s. It
20/// implements [`Deref`]/[`DerefMut`] to the inner map so all map operations are
21/// available, and provides [`get_value`](Self::get_value),
22/// [`insert_value`](Self::insert_value) and [`remove_value`](Self::remove_value)
23/// helpers for accessing individual slots without manually traversing the two
24/// levels of maps.
25#[derive(Debug, Clone, Default, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct TransientStorage(pub AddressMap<StorageKeyMap<StorageValue>>);
28
29impl Deref for TransientStorage {
30    type Target = AddressMap<StorageKeyMap<StorageValue>>;
31
32    #[inline]
33    fn deref(&self) -> &Self::Target {
34        &self.0
35    }
36}
37
38impl DerefMut for TransientStorage {
39    #[inline]
40    fn deref_mut(&mut self) -> &mut Self::Target {
41        &mut self.0
42    }
43}
44
45impl TransientStorage {
46    /// Returns the transient storage value for the given account `address` and
47    /// storage `key`.
48    ///
49    /// Returns [`StorageValue::ZERO`](primitives::StorageValue) (the default) if
50    /// the slot was never set.
51    #[inline]
52    pub fn get_value(&self, address: Address, key: StorageKey) -> StorageValue {
53        self.0
54            .get(&address)
55            .and_then(|slots| slots.get(&key))
56            .copied()
57            .unwrap_or_default()
58    }
59
60    /// Inserts a transient storage `value` for the given account `address` and
61    /// storage `key`, creating the account's slot map if it does not exist yet.
62    ///
63    /// Returns the previous value if the slot was already set.
64    #[inline]
65    pub fn insert_value(
66        &mut self,
67        address: Address,
68        key: StorageKey,
69        value: StorageValue,
70    ) -> Option<StorageValue> {
71        self.0.entry(address).or_default().insert(key, value)
72    }
73
74    /// Removes the transient storage slot for the given account `address` and
75    /// storage `key`.
76    ///
77    /// Returns the removed value if the slot was set.
78    #[inline]
79    pub fn remove_value(&mut self, address: Address, key: StorageKey) -> Option<StorageValue> {
80        self.0.get_mut(&address)?.remove(&key)
81    }
82}