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}