tempo_precompiles/storage/
hashmap.rs1use alloy::primitives::{Address, LogData, U256};
2use revm::state::{AccountInfo, Bytecode};
3use std::collections::HashMap;
4use tempo_chainspec::hardfork::TempoHardfork;
5
6use crate::{error::TempoPrecompileError, storage::PrecompileStorageProvider};
7
8pub struct HashMapStorageProvider {
9 internals: HashMap<(Address, U256), U256>,
10 transient: HashMap<(Address, U256), U256>,
11 accounts: HashMap<Address, AccountInfo>,
12 pub events: HashMap<Address, Vec<LogData>>,
13 chain_id: u64,
14 timestamp: U256,
15 beneficiary: Address,
16 spec: TempoHardfork,
17}
18
19impl HashMapStorageProvider {
20 pub fn new(chain_id: u64) -> Self {
21 Self::new_with_spec(chain_id, TempoHardfork::default())
22 }
23
24 pub fn new_with_spec(chain_id: u64, spec: TempoHardfork) -> Self {
25 Self {
26 internals: HashMap::new(),
27 transient: HashMap::new(),
28 accounts: HashMap::new(),
29 events: HashMap::new(),
30 chain_id,
31 #[expect(clippy::disallowed_methods)]
32 timestamp: U256::from(
33 std::time::SystemTime::now()
34 .duration_since(std::time::UNIX_EPOCH)
35 .unwrap()
36 .as_secs(),
37 ),
38 beneficiary: Address::ZERO,
39 spec,
40 }
41 }
42
43 pub fn with_spec(mut self, spec: TempoHardfork) -> Self {
44 self.spec = spec;
45 self
46 }
47}
48
49impl PrecompileStorageProvider for HashMapStorageProvider {
50 fn chain_id(&self) -> u64 {
51 self.chain_id
52 }
53
54 fn timestamp(&self) -> U256 {
55 self.timestamp
56 }
57
58 fn beneficiary(&self) -> Address {
59 self.beneficiary
60 }
61
62 fn set_code(&mut self, address: Address, code: Bytecode) -> Result<(), TempoPrecompileError> {
63 let account = self.accounts.entry(address).or_default();
64 account.code_hash = code.hash_slow();
65 account.code = Some(code);
66 Ok(())
67 }
68
69 fn with_account_info(
70 &mut self,
71 address: Address,
72 f: &mut dyn FnMut(&AccountInfo),
73 ) -> Result<(), TempoPrecompileError> {
74 let account = self.accounts.entry(address).or_default();
75 f(&*account);
76 Ok(())
77 }
78
79 fn sstore(
80 &mut self,
81 address: Address,
82 key: U256,
83 value: U256,
84 ) -> Result<(), TempoPrecompileError> {
85 self.internals.insert((address, key), value);
86 Ok(())
87 }
88
89 fn tstore(
90 &mut self,
91 address: Address,
92 key: U256,
93 value: U256,
94 ) -> Result<(), TempoPrecompileError> {
95 self.transient.insert((address, key), value);
96 Ok(())
97 }
98
99 fn emit_event(&mut self, address: Address, event: LogData) -> Result<(), TempoPrecompileError> {
100 self.events.entry(address).or_default().push(event);
101 Ok(())
102 }
103
104 fn sload(&mut self, address: Address, key: U256) -> Result<U256, TempoPrecompileError> {
105 Ok(self
106 .internals
107 .get(&(address, key))
108 .copied()
109 .unwrap_or(U256::ZERO))
110 }
111
112 fn tload(&mut self, address: Address, key: U256) -> Result<U256, TempoPrecompileError> {
113 Ok(self
114 .transient
115 .get(&(address, key))
116 .copied()
117 .unwrap_or(U256::ZERO))
118 }
119
120 fn deduct_gas(&mut self, _gas: u64) -> Result<(), TempoPrecompileError> {
121 Ok(())
122 }
123
124 fn refund_gas(&mut self, _gas: i64) {
125 }
127
128 fn gas_used(&self) -> u64 {
129 0
130 }
131
132 fn gas_refunded(&self) -> i64 {
133 0
134 }
135
136 fn spec(&self) -> TempoHardfork {
137 self.spec
138 }
139}
140
141#[cfg(any(test, feature = "test-utils"))]
142impl HashMapStorageProvider {
143 pub fn get_account_info(&self, address: Address) -> Option<&AccountInfo> {
144 self.accounts.get(&address)
145 }
146
147 pub fn get_events(&self, address: Address) -> &Vec<LogData> {
148 static EMPTY: Vec<LogData> = Vec::new();
149 self.events.get(&address).unwrap_or(&EMPTY)
150 }
151
152 pub fn set_nonce(&mut self, address: Address, nonce: u64) {
153 let account = self.accounts.entry(address).or_default();
154 account.nonce = nonce;
155 }
156
157 pub fn set_timestamp(&mut self, timestamp: U256) {
158 self.timestamp = timestamp;
159 }
160
161 pub fn set_beneficiary(&mut self, beneficiary: Address) {
162 self.beneficiary = beneficiary;
163 }
164
165 pub fn set_spec(&mut self, spec: TempoHardfork) {
166 self.spec = spec;
167 }
168
169 pub fn clear_transient(&mut self) {
170 self.transient.clear();
171 }
172}