1use crate::backend::{Apply, Backend, Basic, Log};
2use crate::core::utils::{U256_ONE, U256_ZERO, U64_MAX};
3use crate::executor::stack::executor::{
4 Accessed, Authorization, StackState, StackSubstateMetadata,
5};
6use crate::prelude::*;
7use crate::{ExitError, Transfer};
8use core::mem;
9use primitive_types::{H160, H256, U256};
10
11#[derive(Clone, Debug)]
12pub struct MemoryStackAccount {
13 pub basic: Basic,
14 pub code: Option<Vec<u8>>,
15 pub reset: bool,
16}
17
18#[derive(Clone, Debug)]
19pub struct MemoryStackSubstate<'config> {
20 metadata: StackSubstateMetadata<'config>,
21 parent: Option<Box<MemoryStackSubstate<'config>>>,
22 logs: Vec<Log>,
23 accounts: BTreeMap<H160, MemoryStackAccount>,
24 storages: BTreeMap<(H160, H256), H256>,
25 tstorages: BTreeMap<(H160, H256), U256>,
26 deletes: BTreeSet<H160>,
27 creates: BTreeSet<H160>,
28}
29
30impl<'config> MemoryStackSubstate<'config> {
31 #[must_use]
32 pub const fn new(metadata: StackSubstateMetadata<'config>) -> Self {
33 Self {
34 metadata,
35 parent: None::<Box<_>>,
36 logs: Vec::new(),
37 accounts: BTreeMap::new(),
38 storages: BTreeMap::new(),
39 tstorages: BTreeMap::new(),
40 deletes: BTreeSet::new(),
41 creates: BTreeSet::new(),
42 }
43 }
44
45 #[must_use]
46 #[allow(clippy::missing_const_for_fn)]
47 pub fn logs(&self) -> &[Log] {
48 &self.logs
49 }
50
51 pub const fn logs_mut(&mut self) -> &mut Vec<Log> {
52 &mut self.logs
53 }
54
55 #[must_use]
56 pub const fn metadata(&self) -> &StackSubstateMetadata<'config> {
57 &self.metadata
58 }
59
60 pub const fn metadata_mut(&mut self) -> &mut StackSubstateMetadata<'config> {
61 &mut self.metadata
62 }
63
64 #[must_use]
70 pub fn deconstruct<B: Backend>(
71 mut self,
72 backend: &B,
73 ) -> (
74 impl IntoIterator<Item = Apply<impl IntoIterator<Item = (H256, H256)>>>,
75 impl IntoIterator<Item = Log>,
76 ) {
77 assert!(self.parent.is_none());
78
79 let mut applies = Vec::<Apply<BTreeMap<H256, H256>>>::new();
80
81 let mut addresses = BTreeSet::new();
82
83 for address in self.accounts.keys() {
84 addresses.insert(*address);
85 }
86
87 for (address, _) in self.storages.keys() {
88 addresses.insert(*address);
89 }
90
91 for address in addresses {
92 if self.deletes.contains(&address) {
93 continue;
94 }
95
96 let mut storage = BTreeMap::new();
97 for ((oa, ok), ov) in &self.storages {
98 if *oa == address {
99 storage.insert(*ok, *ov);
100 }
101 }
102
103 let apply = {
104 let account = if self.is_created(address) {
105 let account = self
106 .accounts
107 .get_mut(&address)
108 .expect("New account was just inserted");
109 account.reset = true;
112 account
113 } else {
114 self.account_mut(address, backend)
115 };
116
117 Apply::Modify {
118 address,
119 basic: account.basic.clone(),
120 code: account.code.clone(),
121 storage,
122 reset_storage: account.reset,
123 }
124 };
125
126 applies.push(apply);
127 }
128
129 for address in self.deletes {
130 applies.push(Apply::Delete { address });
131 }
132
133 (applies, self.logs)
134 }
135
136 pub fn enter(&mut self, gas_limit: u64, is_static: bool) {
137 let mut entering = Self {
138 metadata: self.metadata.spit_child(gas_limit, is_static),
139 parent: None,
140 logs: Vec::new(),
141 accounts: BTreeMap::new(),
142 storages: BTreeMap::new(),
143 tstorages: BTreeMap::new(),
144 deletes: BTreeSet::new(),
145 creates: BTreeSet::new(),
146 };
147 mem::swap(&mut entering, self);
148
149 self.parent = Some(Box::new(entering));
150 }
151
152 pub fn exit_commit(&mut self) -> Result<(), ExitError> {
168 let mut exited = *self.parent.take().expect("Cannot commit on root substate");
169 mem::swap(&mut exited, self);
170
171 self.metadata.swallow_commit(exited.metadata)?;
172 self.logs.append(&mut exited.logs);
173
174 let mut resets = BTreeSet::new();
175 for (address, account) in &exited.accounts {
176 if account.reset {
177 resets.insert(*address);
178 }
179 }
180 let mut reset_keys = BTreeSet::new();
181 for (address, key) in self.storages.keys() {
182 if resets.contains(address) {
183 reset_keys.insert((*address, *key));
184 }
185 }
186 for (address, key) in reset_keys {
187 self.storages.remove(&(address, key));
188 }
189
190 self.accounts.append(&mut exited.accounts);
191 self.storages.append(&mut exited.storages);
192 self.tstorages.append(&mut exited.tstorages);
193 self.deletes.append(&mut exited.deletes);
194 self.creates.append(&mut exited.creates);
195 Ok(())
196 }
197
198 pub fn exit_revert(&mut self) -> Result<(), ExitError> {
206 let mut exited = *self.parent.take().expect("Cannot discard on root substate");
207 mem::swap(&mut exited, self);
208 self.metadata.swallow_revert(&exited.metadata)?;
209 Ok(())
210 }
211
212 pub fn exit_discard(&mut self) -> Result<(), ExitError> {
220 let mut exited = *self.parent.take().expect("Cannot discard on root substate");
221 mem::swap(&mut exited, self);
222 self.metadata.swallow_discard(&exited.metadata);
223 Ok(())
224 }
225
226 pub fn known_account(&self, address: H160) -> Option<&MemoryStackAccount> {
227 self.accounts.get(&address).map_or_else(
228 || {
229 self.parent
230 .as_ref()
231 .and_then(|parent| parent.known_account(address))
232 },
233 Some,
234 )
235 }
236
237 #[must_use]
238 pub fn known_basic(&self, address: H160) -> Option<Basic> {
239 self.known_account(address).map(|acc| acc.basic.clone())
240 }
241
242 #[must_use]
243 pub fn known_code(&self, address: H160) -> Option<Vec<u8>> {
244 self.known_account(address).and_then(|acc| acc.code.clone())
245 }
246
247 #[must_use]
248 pub fn known_empty(&self, address: H160) -> Option<bool> {
249 if let Some(account) = self.known_account(address) {
250 if account.basic.balance != U256_ZERO {
251 return Some(false);
252 }
253
254 if account.basic.nonce != U256_ZERO {
255 return Some(false);
256 }
257
258 if let Some(code) = &account.code {
259 return Some(
260 account.basic.balance == U256_ZERO
261 && account.basic.nonce == U256_ZERO
262 && code.is_empty(),
263 );
264 }
265 }
266
267 None
268 }
269
270 #[must_use]
271 pub fn known_storage(&self, address: H160, key: H256) -> Option<H256> {
272 if let Some(value) = self.storages.get(&(address, key)) {
273 return Some(*value);
274 }
275
276 if let Some(account) = self.accounts.get(&address) {
277 if account.reset {
278 return Some(H256::default());
279 }
280 }
281
282 if let Some(parent) = self.parent.as_ref() {
283 return parent.known_storage(address, key);
284 }
285
286 None
287 }
288
289 #[must_use]
290 pub fn known_original_storage(&self, address: H160) -> Option<H256> {
291 if let Some(account) = self.accounts.get(&address) {
292 if account.reset {
293 return Some(H256::default());
294 }
295 }
296
297 if let Some(parent) = self.parent.as_ref() {
298 return parent.known_original_storage(address);
299 }
300
301 None
302 }
303
304 #[must_use]
305 pub fn is_cold(&self, address: H160) -> bool {
306 self.recursive_is_cold(&|a| a.accessed_addresses.contains(&address))
307 }
308
309 #[must_use]
310 pub fn is_storage_cold(&self, address: H160, key: H256) -> bool {
311 self.recursive_is_cold(&|a: &Accessed| a.accessed_storage.contains(&(address, key)))
312 }
313
314 fn recursive_is_cold<F: Fn(&Accessed) -> bool>(&self, f: &F) -> bool {
315 let local_is_accessed = self.metadata.accessed().as_ref().is_some_and(f);
316 if local_is_accessed {
317 false
318 } else {
319 self.parent.as_ref().is_none_or(|p| p.recursive_is_cold(f))
320 }
321 }
322
323 #[must_use]
324 pub fn deleted(&self, address: H160) -> bool {
325 if self.deletes.contains(&address) {
326 return true;
327 }
328
329 if let Some(parent) = self.parent.as_ref() {
330 return parent.deleted(address);
331 }
332
333 false
334 }
335
336 #[allow(clippy::map_entry)]
337 fn account_mut<B: Backend>(&mut self, address: H160, backend: &B) -> &mut MemoryStackAccount {
338 if !self.accounts.contains_key(&address) {
339 let account = self.known_account(address).cloned().map_or_else(
340 || MemoryStackAccount {
341 basic: backend.basic(address),
342 code: None::<Vec<_>>,
343 reset: false,
344 },
345 |mut v| {
346 v.reset = false;
347 v
348 },
349 );
350 self.accounts.insert(address, account);
351 }
352
353 self.accounts
354 .get_mut(&address)
355 .expect("New account was just inserted")
356 }
357
358 pub fn inc_nonce<B: Backend>(&mut self, address: H160, backend: &B) -> Result<(), ExitError> {
361 let nonce = &mut self.account_mut(address, backend).basic.nonce;
362 if *nonce >= U64_MAX {
363 return Err(ExitError::MaxNonce);
364 }
365 *nonce += U256_ONE;
366 Ok(())
367 }
368
369 pub fn set_storage(&mut self, address: H160, key: H256, value: H256) {
370 #[cfg(feature = "print-debug")]
371 println!(" [SSTORE {address:?}] {key:?}:{value:?}");
372 self.storages.insert((address, key), value);
373 }
374
375 pub fn reset_storage<B: Backend>(&mut self, address: H160, backend: &B) {
376 let mut removing = Vec::new();
377
378 for (oa, ok) in self.storages.keys() {
379 if *oa == address {
380 removing.push(*ok);
381 }
382 }
383
384 for ok in removing {
385 self.storages.remove(&(address, ok));
386 }
387 self.account_mut(address, backend).reset = true;
388 }
389
390 pub fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
391 self.logs.push(Log {
392 address,
393 topics,
394 data,
395 });
396 }
397
398 pub fn set_deleted(&mut self, address: H160) {
399 self.deletes.insert(address);
400 }
401
402 pub fn set_created(&mut self, address: H160) {
403 self.creates.insert(address);
404 }
405
406 #[must_use]
407 pub fn is_created(&self, address: H160) -> bool {
408 if self.creates.contains(&address) {
409 return true;
410 }
411
412 if let Some(parent) = self.parent.as_ref() {
413 return parent.is_created(address);
414 }
415
416 false
417 }
418
419 pub fn set_code<B: Backend>(&mut self, address: H160, code: Vec<u8>, backend: &B) {
420 self.account_mut(address, backend).code = Some(code);
421 }
422
423 pub fn transfer<B: Backend>(
426 &mut self,
427 transfer: &Transfer,
428 backend: &B,
429 ) -> Result<(), ExitError> {
430 {
431 let source = self.account_mut(transfer.source, backend);
432 if source.basic.balance < transfer.value {
433 return Err(ExitError::OutOfFund);
434 }
435 source.basic.balance -= transfer.value;
436 }
437
438 {
439 let target = self.account_mut(transfer.target, backend);
440 target.basic.balance = target.basic.balance.saturating_add(transfer.value);
441 }
442
443 Ok(())
444 }
445
446 pub fn withdraw<B: Backend>(
450 &mut self,
451 address: H160,
452 value: U256,
453 backend: &B,
454 ) -> Result<(), ExitError> {
455 let source = self.account_mut(address, backend);
456 if source.basic.balance < value {
457 return Err(ExitError::OutOfFund);
458 }
459 source.basic.balance -= value;
460
461 Ok(())
462 }
463
464 pub fn deposit<B: Backend>(&mut self, address: H160, value: U256, backend: &B) {
466 let target = self.account_mut(address, backend);
467 target.basic.balance = target.basic.balance.saturating_add(value);
468 }
469
470 pub fn reset_balance<B: Backend>(&mut self, address: H160, backend: &B) {
471 self.account_mut(address, backend).basic.balance = U256_ZERO;
472 }
473
474 pub fn touch<B: Backend>(&mut self, address: H160, backend: &B) {
475 self.account_mut(address, backend);
476 }
477
478 #[must_use]
479 pub fn get_tstorage(&self, address: H160, key: H256) -> U256 {
480 self.known_tstorage(address, key).unwrap_or_default()
481 }
482
483 #[must_use]
484 pub fn known_tstorage(&self, address: H160, key: H256) -> Option<U256> {
485 if let Some(value) = self.tstorages.get(&(address, key)) {
486 return Some(*value);
487 }
488 if let Some(parent) = self.parent.as_ref() {
489 return parent.known_tstorage(address, key);
490 }
491 None
492 }
493
494 pub fn set_tstorage(&mut self, address: H160, key: H256, value: U256) {
495 self.tstorages.insert((address, key), value);
496 }
497
498 fn get_authority_target_recursive(&self, authority: H160) -> Option<H160> {
501 if let Some(target) = self
502 .metadata
503 .accessed()
504 .as_ref()
505 .and_then(|accessed| accessed.get_authority_target(authority))
506 {
507 return Some(target);
508 }
509 self.parent
510 .as_ref()
511 .and_then(|p| p.get_authority_target_recursive(authority))
512 }
513}
514
515#[derive(Clone, Debug)]
516pub struct MemoryStackState<'backend, 'config, B> {
517 backend: &'backend B,
518 substate: MemoryStackSubstate<'config>,
519}
520
521impl<B: Backend> Backend for MemoryStackState<'_, '_, B> {
522 fn gas_price(&self) -> U256 {
523 self.backend.gas_price()
524 }
525 fn origin(&self) -> H160 {
526 self.backend.origin()
527 }
528 fn block_hash(&self, number: U256) -> H256 {
529 self.backend.block_hash(number)
530 }
531 fn block_number(&self) -> U256 {
532 self.backend.block_number()
533 }
534 fn block_coinbase(&self) -> H160 {
535 self.backend.block_coinbase()
536 }
537 fn block_timestamp(&self) -> U256 {
538 self.backend.block_timestamp()
539 }
540 fn block_difficulty(&self) -> U256 {
541 self.backend.block_difficulty()
542 }
543 fn block_randomness(&self) -> Option<H256> {
544 self.backend.block_randomness()
545 }
546 fn block_gas_limit(&self) -> U256 {
547 self.backend.block_gas_limit()
548 }
549 fn block_base_fee_per_gas(&self) -> U256 {
550 self.backend.block_base_fee_per_gas()
551 }
552
553 fn chain_id(&self) -> U256 {
554 self.backend.chain_id()
555 }
556
557 fn exists(&self, address: H160) -> bool {
558 self.substate.known_account(address).is_some() || self.backend.exists(address)
559 }
560
561 fn basic(&self, address: H160) -> Basic {
562 self.substate
563 .known_basic(address)
564 .unwrap_or_else(|| self.backend.basic(address))
565 }
566
567 fn code(&self, address: H160) -> Vec<u8> {
568 self.substate
569 .known_code(address)
570 .unwrap_or_else(|| self.backend.code(address))
571 }
572
573 fn storage(&self, address: H160, key: H256) -> H256 {
574 self.substate
575 .known_storage(address, key)
576 .unwrap_or_else(|| self.backend.storage(address, key))
577 }
578
579 fn is_empty_storage(&self, address: H160) -> bool {
580 self.backend.is_empty_storage(address)
581 }
582
583 fn original_storage(&self, address: H160, key: H256) -> Option<H256> {
584 if let Some(value) = self.substate.known_original_storage(address) {
585 return Some(value);
586 }
587
588 self.backend.original_storage(address, key)
589 }
590 fn blob_gas_price(&self) -> Option<u128> {
591 self.backend.blob_gas_price()
592 }
593 fn get_blob_hash(&self, index: usize) -> Option<U256> {
594 self.backend.get_blob_hash(index)
595 }
596}
597
598impl<'config, B: Backend> StackState<'config> for MemoryStackState<'_, 'config, B> {
599 fn metadata(&self) -> &StackSubstateMetadata<'config> {
600 self.substate.metadata()
601 }
602
603 fn metadata_mut(&mut self) -> &mut StackSubstateMetadata<'config> {
604 self.substate.metadata_mut()
605 }
606
607 fn enter(&mut self, gas_limit: u64, is_static: bool) {
608 self.substate.enter(gas_limit, is_static);
609 }
610
611 fn exit_commit(&mut self) -> Result<(), ExitError> {
612 self.substate.exit_commit()
613 }
614
615 fn exit_revert(&mut self) -> Result<(), ExitError> {
616 self.substate.exit_revert()
617 }
618
619 fn exit_discard(&mut self) -> Result<(), ExitError> {
620 self.substate.exit_discard()
621 }
622
623 fn is_empty(&self, address: H160) -> bool {
624 if let Some(known_empty) = self.substate.known_empty(address) {
625 return known_empty;
626 }
627
628 self.backend.basic(address).balance == U256_ZERO
629 && self.backend.basic(address).nonce == U256_ZERO
630 && self.backend.code(address).is_empty()
631 }
632
633 fn deleted(&self, address: H160) -> bool {
634 self.substate.deleted(address)
635 }
636
637 fn is_cold(&self, address: H160) -> bool {
638 self.substate.is_cold(address)
639 }
640
641 fn is_storage_cold(&self, address: H160, key: H256) -> bool {
642 self.substate.is_storage_cold(address, key)
643 }
644
645 fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError> {
646 self.substate.inc_nonce(address, self.backend)
647 }
648
649 fn set_storage(&mut self, address: H160, key: H256, value: H256) {
650 self.substate.set_storage(address, key, value);
651 }
652
653 fn reset_storage(&mut self, address: H160) {
654 self.substate.reset_storage(address, self.backend);
655 }
656
657 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
658 self.substate.log(address, topics, data);
659 }
660
661 fn set_deleted(&mut self, address: H160) {
662 self.substate.set_deleted(address);
663 }
664
665 fn set_created(&mut self, address: H160) {
666 self.substate.set_created(address);
667 }
668
669 fn is_created(&self, address: H160) -> bool {
670 self.substate.is_created(address)
671 }
672
673 fn set_code(&mut self, address: H160, code: Vec<u8>) {
674 self.substate.set_code(address, code, self.backend);
675 }
676
677 fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> {
678 self.substate.transfer(&transfer, self.backend)
679 }
680
681 fn reset_balance(&mut self, address: H160) {
682 self.substate.reset_balance(address, self.backend);
683 }
684
685 fn touch(&mut self, address: H160) {
686 self.substate.touch(address, self.backend);
687 }
688
689 fn tload(&mut self, address: H160, index: H256) -> Result<U256, ExitError> {
690 Ok(self.substate.get_tstorage(address, index))
691 }
692
693 fn tstore(&mut self, address: H160, index: H256, value: U256) -> Result<(), ExitError> {
694 self.substate.set_tstorage(address, index, value);
695 Ok(())
696 }
697
698 fn is_authority_cold(&mut self, address: H160) -> Option<bool> {
700 self.get_authority_target(address)
701 .map(|target| self.is_cold(target))
702 }
703
704 fn get_authority_target(&mut self, authority: H160) -> Option<H160> {
709 if let Some(target_address) = self.substate.get_authority_target_recursive(authority) {
711 Some(target_address)
712 } else {
713 let authority_code = self.code(authority);
716 if let Some(target) = Authorization::get_delegated_address(&authority_code) {
717 self.metadata_mut().add_authority(authority, target);
719 return Some(target);
720 }
721 None
722 }
723 }
724}
725
726impl<'backend, 'config, B: Backend> MemoryStackState<'backend, 'config, B> {
727 pub const fn new(metadata: StackSubstateMetadata<'config>, backend: &'backend B) -> Self {
728 Self {
729 backend,
730 substate: MemoryStackSubstate::new(metadata),
731 }
732 }
733
734 pub fn account_mut(&mut self, address: H160) -> &mut MemoryStackAccount {
736 self.substate.account_mut(address, self.backend)
737 }
738
739 #[must_use]
740 pub fn deconstruct(
741 self,
742 ) -> (
743 impl IntoIterator<Item = Apply<impl IntoIterator<Item = (H256, H256)>>>,
744 impl IntoIterator<Item = Log>,
745 ) {
746 self.substate.deconstruct(self.backend)
747 }
748
749 pub fn withdraw(&mut self, address: H160, value: U256) -> Result<(), ExitError> {
752 self.substate.withdraw(address, value, self.backend)
753 }
754
755 pub fn deposit(&mut self, address: H160, value: U256) {
756 self.substate.deposit(address, value, self.backend);
757 }
758}