1use alloy_primitives::{Address, B256, U256};
2use revm::Database;
3
4use crate::{
5 slot::storage_key_map,
6 state_ops::{read_arbos_storage, write_arbos_storage},
7};
8
9fn compute_slot(base_key: B256, offset: u64) -> U256 {
10 if base_key == B256::ZERO {
11 storage_key_map(&[], offset)
12 } else {
13 storage_key_map(base_key.as_slice(), offset)
14 }
15}
16
17fn read_slot<D: Database>(state: *mut revm::database::State<D>, slot: U256) -> Result<U256, ()> {
19 unsafe {
20 let state = &mut *state;
21 Ok(read_arbos_storage(state, slot))
22 }
23}
24
25fn write_slot<D: Database>(
27 state: *mut revm::database::State<D>,
28 slot: U256,
29 value: U256,
30) -> Result<(), ()> {
31 unsafe {
32 let state = &mut *state;
33 write_arbos_storage(state, slot, value);
34 Ok(())
35 }
36}
37
38pub struct StorageBackedUint64<D> {
40 pub state: *mut revm::database::State<D>,
41 pub slot: U256,
42}
43
44impl<D: Database> StorageBackedUint64<D> {
45 pub fn new(state: *mut revm::database::State<D>, base_key: B256, offset: u64) -> Self {
46 Self {
47 state,
48 slot: compute_slot(base_key, offset),
49 }
50 }
51
52 pub fn get(&self) -> Result<u64, ()> {
53 let value = read_slot(self.state, self.slot)?;
54 Ok(value.try_into().unwrap_or(0))
55 }
56
57 pub fn set(&self, value: u64) -> Result<(), ()> {
58 write_slot(self.state, self.slot, U256::from(value))
59 }
60}
61
62impl<D> Clone for StorageBackedUint64<D> {
63 fn clone(&self) -> Self {
64 Self {
65 state: self.state,
66 slot: self.slot,
67 }
68 }
69}
70
71unsafe impl<D: Send> Send for StorageBackedUint64<D> {}
72unsafe impl<D: Sync> Sync for StorageBackedUint64<D> {}
73
74pub struct StorageBackedBigUint<D> {
76 state: *mut revm::database::State<D>,
77 slot: U256,
78}
79
80impl<D: Database> StorageBackedBigUint<D> {
81 pub fn new(state: *mut revm::database::State<D>, base_key: B256, offset: u64) -> Self {
82 Self {
83 state,
84 slot: compute_slot(base_key, offset),
85 }
86 }
87
88 pub fn get(&self) -> Result<U256, ()> {
89 read_slot(self.state, self.slot)
90 }
91
92 pub fn set(&self, value: U256) -> Result<(), ()> {
93 write_slot(self.state, self.slot, value)
94 }
95}
96
97impl<D> Clone for StorageBackedBigUint<D> {
98 fn clone(&self) -> Self {
99 Self {
100 state: self.state,
101 slot: self.slot,
102 }
103 }
104}
105
106unsafe impl<D: Send> Send for StorageBackedBigUint<D> {}
107unsafe impl<D: Sync> Sync for StorageBackedBigUint<D> {}
108
109pub struct StorageBackedAddress<D> {
111 state: *mut revm::database::State<D>,
112 slot: U256,
113}
114
115impl<D: Database> StorageBackedAddress<D> {
116 pub fn new(state: *mut revm::database::State<D>, base_key: B256, offset: u64) -> Self {
117 Self {
118 state,
119 slot: compute_slot(base_key, offset),
120 }
121 }
122
123 pub fn get(&self) -> Result<Address, ()> {
124 let value = read_slot(self.state, self.slot)?;
125 let bytes = value.to_be_bytes::<32>();
126 let addr_bytes: [u8; 20] = bytes[12..32].try_into().map_err(|_| ())?;
127 Ok(Address::from(addr_bytes))
128 }
129
130 pub fn set(&self, value: Address) -> Result<(), ()> {
131 let mut value_bytes = [0u8; 32];
132 value_bytes[12..32].copy_from_slice(value.as_slice());
133 write_slot(self.state, self.slot, U256::from_be_bytes(value_bytes))
134 }
135}
136
137impl<D> Clone for StorageBackedAddress<D> {
138 fn clone(&self) -> Self {
139 Self {
140 state: self.state,
141 slot: self.slot,
142 }
143 }
144}
145
146unsafe impl<D: Send> Send for StorageBackedAddress<D> {}
147unsafe impl<D: Sync> Sync for StorageBackedAddress<D> {}
148
149pub struct StorageBackedInt64<D> {
153 state: *mut revm::database::State<D>,
154 slot: U256,
155}
156
157impl<D: Database> StorageBackedInt64<D> {
158 pub fn new(state: *mut revm::database::State<D>, base_key: B256, offset: u64) -> Self {
159 Self {
160 state,
161 slot: compute_slot(base_key, offset),
162 }
163 }
164
165 pub fn get(&self) -> Result<i64, ()> {
166 let value = read_slot(self.state, self.slot)?;
167 let value_u64: u64 = value.try_into().unwrap_or(0);
168 Ok(value_u64 as i64)
169 }
170
171 pub fn set(&self, value: i64) -> Result<(), ()> {
172 write_slot(self.state, self.slot, U256::from(value as u64))
173 }
174}
175
176impl<D> Clone for StorageBackedInt64<D> {
177 fn clone(&self) -> Self {
178 Self {
179 state: self.state,
180 slot: self.slot,
181 }
182 }
183}
184
185unsafe impl<D: Send> Send for StorageBackedInt64<D> {}
186unsafe impl<D: Sync> Sync for StorageBackedInt64<D> {}
187
188pub struct StorageBackedBigInt<D> {
190 pub state: *mut revm::database::State<D>,
191 pub slot: U256,
192}
193
194impl<D: Database> StorageBackedBigInt<D> {
195 pub fn new(state: *mut revm::database::State<D>, base_key: B256, offset: u64) -> Self {
196 Self {
197 state,
198 slot: compute_slot(base_key, offset),
199 }
200 }
201
202 pub fn get_raw(&self) -> Result<U256, ()> {
204 read_slot(self.state, self.slot)
205 }
206
207 pub fn is_negative(&self) -> Result<bool, ()> {
209 Ok(self.get_raw()?.bit(255))
210 }
211
212 pub fn get_signed(&self) -> Result<(U256, bool), ()> {
214 let raw = self.get_raw()?;
215 if raw.bit(255) {
216 let magnitude = (!raw).wrapping_add(U256::from(1));
217 Ok((magnitude, true))
218 } else {
219 Ok((raw, false))
220 }
221 }
222
223 pub fn set(&self, value: U256) -> Result<(), ()> {
225 write_slot(self.state, self.slot, value)
226 }
227
228 pub fn set_negative(&self, magnitude: U256) -> Result<(), ()> {
230 let neg_value = (!magnitude).wrapping_add(U256::from(1));
231 self.set(neg_value)
232 }
233}
234
235impl<D> Clone for StorageBackedBigInt<D> {
236 fn clone(&self) -> Self {
237 Self {
238 state: self.state,
239 slot: self.slot,
240 }
241 }
242}
243
244unsafe impl<D: Send> Send for StorageBackedBigInt<D> {}
245unsafe impl<D: Sync> Sync for StorageBackedBigInt<D> {}
246
247fn nil_address_representation() -> U256 {
249 U256::from(1u64) << 255
250}
251
252pub struct StorageBackedAddressOrNil<D> {
256 state: *mut revm::database::State<D>,
257 slot: U256,
258}
259
260impl<D: Database> StorageBackedAddressOrNil<D> {
261 pub fn new(state: *mut revm::database::State<D>, base_key: B256, offset: u64) -> Self {
262 Self {
263 state,
264 slot: compute_slot(base_key, offset),
265 }
266 }
267
268 pub fn get(&self) -> Result<Option<Address>, ()> {
269 let value = read_slot(self.state, self.slot)?;
270 if value == nil_address_representation() {
271 return Ok(None);
272 }
273 let bytes = value.to_be_bytes::<32>();
274 let addr_bytes: [u8; 20] = bytes[12..32].try_into().map_err(|_| ())?;
275 Ok(Some(Address::from(addr_bytes)))
276 }
277
278 pub fn set(&self, value: Option<Address>) -> Result<(), ()> {
279 let value_u256 = match value {
280 None => nil_address_representation(),
281 Some(addr) => {
282 let mut bytes = [0u8; 32];
283 bytes[12..32].copy_from_slice(addr.as_slice());
284 U256::from_be_bytes(bytes)
285 }
286 };
287 write_slot(self.state, self.slot, value_u256)
288 }
289}
290
291impl<D> Clone for StorageBackedAddressOrNil<D> {
292 fn clone(&self) -> Self {
293 Self {
294 state: self.state,
295 slot: self.slot,
296 }
297 }
298}
299
300unsafe impl<D: Send> Send for StorageBackedAddressOrNil<D> {}
301unsafe impl<D: Sync> Sync for StorageBackedAddressOrNil<D> {}