1use crate::backend::Backend;
2use crate::{
3 Capture, Config, Context, CreateScheme, ExitError, ExitReason, ExitSucceed, Handler, Opcode,
4 Runtime, Stack, Transfer,
5};
6use alloc::{
7 collections::{BTreeMap, BTreeSet},
8 rc::Rc,
9 vec::Vec,
10};
11use core::convert::Infallible;
12use ethereum::Log;
13use evm_core::{ExitFatal, ExitRevert};
14use primitive_types::{H160, H256, U256};
15use sha3::{Digest, Keccak256};
16
17pub enum StackExitKind {
18 Succeeded,
19 Reverted,
20 Failed,
21}
22
23#[derive(Default, Clone, Debug)]
24pub struct Accessed {
25 pub accessed_addresses: BTreeSet<H160>,
26 pub accessed_storage: BTreeSet<(H160, H256)>,
27}
28
29impl Accessed {
30 pub fn access_address(&mut self, address: H160) {
31 self.accessed_addresses.insert(address);
32 }
33
34 pub fn access_addresses<I>(&mut self, addresses: I)
35 where
36 I: Iterator<Item = H160>,
37 {
38 for address in addresses {
39 self.accessed_addresses.insert(address);
40 }
41 }
42
43 pub fn access_storages<I>(&mut self, storages: I)
44 where
45 I: Iterator<Item = (H160, H256)>,
46 {
47 for storage in storages {
48 self.accessed_storage.insert((storage.0, storage.1));
49 }
50 }
51}
52
53#[derive(Clone, Debug)]
54pub struct StackSubstateMetadata {
55 is_static: bool,
56 depth: Option<usize>,
57 accessed: Option<Accessed>,
58}
59
60impl StackSubstateMetadata {
61 pub fn new(config: &Config) -> Self {
62 let accessed = if config.increase_state_access_gas {
63 Some(Accessed::default())
64 } else {
65 None
66 };
67 Self {
68 is_static: false,
69 depth: None,
70 accessed,
71 }
72 }
73
74 pub fn swallow_commit(&mut self, other: Self) -> Result<(), ExitError> {
75 if let (Some(mut other_accessed), Some(self_accessed)) =
76 (other.accessed, self.accessed.as_mut())
77 {
78 self_accessed
79 .accessed_addresses
80 .append(&mut other_accessed.accessed_addresses);
81 self_accessed
82 .accessed_storage
83 .append(&mut other_accessed.accessed_storage);
84 }
85
86 Ok(())
87 }
88
89 pub fn swallow_revert(&mut self, _other: Self) -> Result<(), ExitError> {
90 Ok(())
91 }
92
93 pub fn swallow_discard(&mut self, _other: Self) -> Result<(), ExitError> {
94 Ok(())
95 }
96
97 pub fn spit_child(&self, is_static: bool) -> Self {
98 Self {
99 is_static: is_static || self.is_static,
100 depth: match self.depth {
101 None => Some(0),
102 Some(n) => Some(n + 1),
103 },
104 accessed: self.accessed.as_ref().map(|_| Accessed::default()),
105 }
106 }
107
108 pub fn is_static(&self) -> bool {
109 self.is_static
110 }
111
112 pub fn depth(&self) -> Option<usize> {
113 self.depth
114 }
115
116 pub fn access_address(&mut self, address: H160) {
117 if let Some(accessed) = &mut self.accessed {
118 accessed.access_address(address)
119 }
120 }
121
122 pub fn access_addresses<I>(&mut self, addresses: I)
123 where
124 I: Iterator<Item = H160>,
125 {
126 if let Some(accessed) = &mut self.accessed {
127 accessed.access_addresses(addresses);
128 }
129 }
130
131 pub fn access_storage(&mut self, address: H160, key: H256) {
132 if let Some(accessed) = &mut self.accessed {
133 accessed.accessed_storage.insert((address, key));
134 }
135 }
136
137 pub fn access_storages<I>(&mut self, storages: I)
138 where
139 I: Iterator<Item = (H160, H256)>,
140 {
141 if let Some(accessed) = &mut self.accessed {
142 accessed.access_storages(storages);
143 }
144 }
145
146 pub fn accessed(&self) -> &Option<Accessed> {
147 &self.accessed
148 }
149}
150
151#[auto_impl::auto_impl(&mut, Box)]
152pub trait StackState: Backend {
153 fn metadata(&self) -> &StackSubstateMetadata;
154 fn metadata_mut(&mut self) -> &mut StackSubstateMetadata;
155
156 fn enter(&mut self, is_static: bool);
157 fn exit_commit(&mut self) -> Result<(), ExitError>;
158 fn exit_revert(&mut self) -> Result<(), ExitError>;
159 fn exit_discard(&mut self) -> Result<(), ExitError>;
160
161 fn is_empty(&self, address: H160) -> bool;
162 fn deleted(&self, address: H160) -> bool;
163 fn is_cold(&self, address: H160) -> bool;
164 fn is_storage_cold(&self, address: H160, key: H256) -> bool;
165
166 fn inc_nonce(&mut self, address: H160);
167 fn set_storage(&mut self, address: H160, key: H256, value: H256);
168 fn reset_storage(&mut self, address: H160);
169 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>);
170 fn set_deleted(&mut self, address: H160);
171 fn set_code(&mut self, address: H160, code: Vec<u8>);
172 fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError>;
173 fn reset_balance(&mut self, address: H160);
174 fn touch(&mut self, address: H160);
175}
176
177#[derive(Debug, Eq, PartialEq, Clone)]
179pub struct PrecompileOutput {
180 pub exit_status: ExitSucceed,
181 pub output: Vec<u8>,
182 pub logs: Vec<Log>,
183}
184
185#[derive(Debug, Eq, PartialEq, Clone)]
187pub enum PrecompileFailure {
188 Error { exit_status: ExitError },
190 Revert {
193 exit_status: ExitRevert,
194 output: Vec<u8>,
195 },
196 Fatal { exit_status: ExitFatal },
198}
199
200pub type PrecompileResult = Result<PrecompileOutput, PrecompileFailure>;
202
203pub trait PrecompileSet {
207 fn execute(
210 &self,
211 address: H160,
212 input: &[u8],
213 context: &Context,
214 is_static: bool,
215 ) -> Option<PrecompileResult>;
216
217 fn is_precompile(&self, address: H160) -> bool;
221}
222
223impl PrecompileSet for () {
224 fn execute(&self, _: H160, _: &[u8], _: &Context, _: bool) -> Option<PrecompileResult> {
225 None
226 }
227
228 fn is_precompile(&self, _: H160) -> bool {
229 false
230 }
231}
232
233pub type PrecompileFn = fn(&[u8], &Context, bool) -> PrecompileResult;
239
240impl PrecompileSet for BTreeMap<H160, PrecompileFn> {
241 fn execute(
242 &self,
243 address: H160,
244 input: &[u8],
245 context: &Context,
246 is_static: bool,
247 ) -> Option<PrecompileResult> {
248 self.get(&address)
249 .map(|precompile| (*precompile)(input, context, is_static))
250 }
251
252 fn is_precompile(&self, address: H160) -> bool {
256 self.contains_key(&address)
257 }
258}
259
260pub struct StackExecutor<'config, 'precompiles, S, P> {
262 config: &'config Config,
263 state: S,
264 precompile_set: &'precompiles P,
265}
266
267impl<'config, 'precompiles, S: StackState, P: PrecompileSet>
268 StackExecutor<'config, 'precompiles, S, P>
269{
270 pub fn config(&self) -> &'config Config {
272 self.config
273 }
274
275 pub fn precompiles(&self) -> &'precompiles P {
277 self.precompile_set
278 }
279
280 pub fn new_with_precompiles(
282 state: S,
283 config: &'config Config,
284 precompile_set: &'precompiles P,
285 ) -> Self {
286 Self {
287 config,
288 state,
289 precompile_set,
290 }
291 }
292
293 pub fn state(&self) -> &S {
294 &self.state
295 }
296
297 pub fn state_mut(&mut self) -> &mut S {
298 &mut self.state
299 }
300
301 pub fn into_state(self) -> S {
302 self.state
303 }
304
305 pub fn enter_substate(&mut self, is_static: bool) {
307 self.state.enter(is_static);
308 }
309
310 pub fn exit_substate(&mut self, kind: StackExitKind) -> Result<(), ExitError> {
312 match kind {
313 StackExitKind::Succeeded => self.state.exit_commit(),
314 StackExitKind::Reverted => self.state.exit_revert(),
315 StackExitKind::Failed => self.state.exit_discard(),
316 }
317 }
318
319 pub fn execute(&mut self, runtime: &mut Runtime) -> ExitReason {
321 match runtime.run(self) {
322 Capture::Exit(s) => s,
323 Capture::Trap(_) => unreachable!("Trap is Infallible"),
324 }
325 }
326
327 pub fn transact_create(
329 &mut self,
330 caller: H160,
331 value: U256,
332 init_code: Vec<u8>,
333 access_list: Vec<(H160, Vec<H256>)>, ) -> (ExitReason, Vec<u8>) {
335 self.initialize_with_access_list(access_list);
336
337 match self.create_inner(caller, CreateScheme::Legacy { caller }, value, init_code) {
338 Capture::Exit((r, _, v)) => (r, v),
339 Capture::Trap(_) => unreachable!(),
340 }
341 }
342
343 pub fn transact_create2(
345 &mut self,
346 caller: H160,
347 value: U256,
348 init_code: Vec<u8>,
349 salt: H256,
350 access_list: Vec<(H160, Vec<H256>)>, ) -> (ExitReason, Vec<u8>) {
352 let code_hash = H256::from_slice(Keccak256::digest(&init_code).as_slice());
353 self.initialize_with_access_list(access_list);
354
355 match self.create_inner(
356 caller,
357 CreateScheme::Create2 {
358 caller,
359 code_hash,
360 salt,
361 },
362 value,
363 init_code,
364 ) {
365 Capture::Exit((r, _, v)) => (r, v),
366 Capture::Trap(_) => unreachable!(),
367 }
368 }
369
370 pub fn transact_call(
377 &mut self,
378 caller: H160,
379 address: H160,
380 value: U256,
381 data: Vec<u8>,
382 access_list: Vec<(H160, Vec<H256>)>,
383 ) -> (ExitReason, Vec<u8>) {
384 if self.config.increase_state_access_gas {
386 let addresses = core::iter::once(caller).chain(core::iter::once(address));
387 self.state.metadata_mut().access_addresses(addresses);
388
389 self.initialize_with_access_list(access_list);
390 }
391
392 self.state.inc_nonce(caller);
393
394 let context = Context {
395 caller,
396 address,
397 apparent_value: value,
398 };
399
400 match self.call_inner(
401 address,
402 Some(Transfer {
403 source: caller,
404 target: address,
405 value,
406 }),
407 data,
408 false,
409 context,
410 ) {
411 Capture::Exit((r, v)) => (r, v),
412 Capture::Trap(_) => unreachable!(),
413 }
414 }
415
416 pub fn nonce(&self, address: H160) -> U256 {
418 self.state.basic(address).nonce
419 }
420
421 pub fn create_address(&self, scheme: CreateScheme) -> H160 {
423 match scheme {
424 CreateScheme::Create2 {
425 caller,
426 code_hash,
427 salt,
428 } => {
429 let mut hasher = Keccak256::new();
430 hasher.input(&[0xff]);
431 hasher.input(&caller[..]);
432 hasher.input(&salt[..]);
433 hasher.input(&code_hash[..]);
434 H256::from_slice(hasher.result().as_slice()).into()
435 }
436 CreateScheme::Legacy { caller } => {
437 let nonce = self.nonce(caller);
438 let mut stream = rlp::RlpStream::new_list(2);
439 stream.append(&caller);
440 stream.append(&nonce);
441 H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into()
442 }
443 CreateScheme::Fixed(naddress) => naddress,
444 }
445 }
446
447 pub fn initialize_with_access_list(&mut self, access_list: Vec<(H160, Vec<H256>)>) {
448 let addresses = access_list.iter().map(|a| a.0);
449 self.state.metadata_mut().access_addresses(addresses);
450
451 let storage_keys = access_list
452 .into_iter()
453 .flat_map(|(address, keys)| keys.into_iter().map(move |key| (address, key)));
454 self.state.metadata_mut().access_storages(storage_keys);
455 }
456
457 fn create_inner(
458 &mut self,
459 caller: H160,
460 scheme: CreateScheme,
461 value: U256,
462 init_code: Vec<u8>,
463 ) -> Capture<(ExitReason, Option<H160>, Vec<u8>), Infallible> {
464 macro_rules! try_or_fail {
465 ( $e:expr ) => {
466 match $e {
467 Ok(v) => v,
468 Err(e) => return Capture::Exit((e.into(), None, Vec::new())),
469 }
470 };
471 }
472
473 fn check_first_byte(config: &Config, code: &[u8]) -> Result<(), ExitError> {
474 if config.disallow_executable_format {
475 if let Some(0xef) = code.get(0) {
476 return Err(ExitError::InvalidCode);
477 }
478 }
479 Ok(())
480 }
481
482 let address = self.create_address(scheme);
483
484 self.state.metadata_mut().access_address(caller);
485 self.state.metadata_mut().access_address(address);
486
487 if let Some(depth) = self.state.metadata().depth {
488 if depth > self.config.call_stack_limit {
489 return Capture::Exit((ExitError::CallTooDeep.into(), None, Vec::new()));
490 }
491 }
492
493 if self.balance(caller) < value {
494 return Capture::Exit((ExitError::OutOfFund.into(), None, Vec::new()));
495 }
496
497 self.state.inc_nonce(caller);
498
499 self.enter_substate(false);
500
501 {
502 if self.code_size(address) != U256::zero() {
503 let _ = self.exit_substate(StackExitKind::Failed);
504 return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new()));
505 }
506
507 if self.nonce(address) > U256::zero() {
508 let _ = self.exit_substate(StackExitKind::Failed);
509 return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new()));
510 }
511
512 self.state.reset_storage(address);
513 }
514
515 let context = Context {
516 address,
517 caller,
518 apparent_value: value,
519 };
520 let transfer = Transfer {
521 source: caller,
522 target: address,
523 value,
524 };
525 match self.state.transfer(transfer) {
526 Ok(()) => (),
527 Err(e) => {
528 let _ = self.exit_substate(StackExitKind::Reverted);
529 return Capture::Exit((ExitReason::Error(e), None, Vec::new()));
530 }
531 }
532
533 if self.config.create_increase_nonce {
534 self.state.inc_nonce(address);
535 }
536
537 let mut runtime = Runtime::new(
538 Rc::new(init_code),
539 Rc::new(Vec::new()),
540 context,
541 self.config,
542 );
543
544 let reason = self.execute(&mut runtime);
545 log::debug!(target: "evm", "Create execution using address {}: {:?}", address, reason);
546
547 match reason {
548 ExitReason::Succeed(s) => {
549 let out = runtime.machine().return_value();
550
551 if let Err(e) = check_first_byte(self.config, &out) {
553 let _ = self.exit_substate(StackExitKind::Failed);
554 return Capture::Exit((e.into(), None, Vec::new()));
555 }
556
557 if let Some(limit) = self.config.create_contract_limit {
558 if out.len() > limit {
559 let _ = self.exit_substate(StackExitKind::Failed);
560 return Capture::Exit((
561 ExitError::CreateContractLimit.into(),
562 None,
563 Vec::new(),
564 ));
565 }
566 }
567
568 let e = self.exit_substate(StackExitKind::Succeeded);
569 self.state.set_code(address, out);
570 try_or_fail!(e);
571 Capture::Exit((ExitReason::Succeed(s), Some(address), Vec::new()))
572 }
573 ExitReason::Error(e) => {
574 let _ = self.exit_substate(StackExitKind::Failed);
575 Capture::Exit((ExitReason::Error(e), None, Vec::new()))
576 }
577 ExitReason::Revert(e) => {
578 let _ = self.exit_substate(StackExitKind::Reverted);
579 Capture::Exit((
580 ExitReason::Revert(e),
581 None,
582 runtime.machine().return_value(),
583 ))
584 }
585 ExitReason::Fatal(e) => {
586 let _ = self.exit_substate(StackExitKind::Failed);
587 Capture::Exit((ExitReason::Fatal(e), None, Vec::new()))
588 }
589 }
590 }
591
592 fn call_inner(
593 &mut self,
594 code_address: H160,
595 transfer: Option<Transfer>,
596 input: Vec<u8>,
597 is_static: bool,
598 context: Context,
599 ) -> Capture<(ExitReason, Vec<u8>), Infallible> {
600 let code = self.code(code_address);
601
602 self.enter_substate(is_static);
603 self.state.touch(context.address);
604
605 if let Some(depth) = self.state.metadata().depth {
606 if depth > self.config.call_stack_limit {
607 let _ = self.exit_substate(StackExitKind::Reverted);
608 return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
609 }
610 }
611
612 if let Some(transfer) = transfer {
613 match self.state.transfer(transfer) {
614 Ok(()) => (),
615 Err(e) => {
616 let _ = self.exit_substate(StackExitKind::Reverted);
617 return Capture::Exit((ExitReason::Error(e), Vec::new()));
618 }
619 }
620 }
621
622 if let Some(result) = self
623 .precompile_set
624 .execute(code_address, &input, &context, is_static)
625 {
626 return match result {
627 Ok(PrecompileOutput {
628 exit_status,
629 output,
630 logs,
631 }) => {
632 for Log {
633 address,
634 topics,
635 data,
636 } in logs
637 {
638 match self.log(address, topics, data) {
639 Ok(_) => continue,
640 Err(error) => {
641 return Capture::Exit((ExitReason::Error(error), output));
642 }
643 }
644 }
645
646 let _ = self.exit_substate(StackExitKind::Succeeded);
647 Capture::Exit((ExitReason::Succeed(exit_status), output))
648 }
649 Err(PrecompileFailure::Error { exit_status }) => {
650 let _ = self.exit_substate(StackExitKind::Failed);
651 Capture::Exit((ExitReason::Error(exit_status), Vec::new()))
652 }
653 Err(PrecompileFailure::Revert {
654 exit_status,
655 output,
656 }) => {
657 let _ = self.exit_substate(StackExitKind::Reverted);
658 Capture::Exit((ExitReason::Revert(exit_status), output))
659 }
660 Err(PrecompileFailure::Fatal { exit_status }) => {
661 let _ = self.exit_substate(StackExitKind::Failed);
662 Capture::Exit((ExitReason::Fatal(exit_status), Vec::new()))
663 }
664 };
665 }
666
667 let mut runtime = Runtime::new(Rc::new(code), Rc::new(input), context, self.config);
668
669 let reason = self.execute(&mut runtime);
670 log::debug!(target: "evm", "Call execution using address {}: {:?}", code_address, reason);
671
672 match reason {
673 ExitReason::Succeed(s) => {
674 let _ = self.exit_substate(StackExitKind::Succeeded);
675 Capture::Exit((ExitReason::Succeed(s), runtime.machine().return_value()))
676 }
677 ExitReason::Error(e) => {
678 let _ = self.exit_substate(StackExitKind::Failed);
679 Capture::Exit((ExitReason::Error(e), Vec::new()))
680 }
681 ExitReason::Revert(e) => {
682 let _ = self.exit_substate(StackExitKind::Reverted);
683 Capture::Exit((ExitReason::Revert(e), runtime.machine().return_value()))
684 }
685 ExitReason::Fatal(e) => {
686 let _ = self.exit_substate(StackExitKind::Failed);
687 Capture::Exit((ExitReason::Fatal(e), Vec::new()))
688 }
689 }
690 }
691}
692
693impl<'config, 'precompiles, S: StackState, P: PrecompileSet> Handler
694 for StackExecutor<'config, 'precompiles, S, P>
695{
696 type CreateInterrupt = Infallible;
697 type CreateFeedback = Infallible;
698 type CallInterrupt = Infallible;
699 type CallFeedback = Infallible;
700
701 fn balance(&self, address: H160) -> U256 {
702 self.state.basic(address).balance
703 }
704
705 fn code_size(&self, address: H160) -> U256 {
706 U256::from(self.state.code(address).len())
707 }
708
709 fn code_hash(&self, address: H160) -> H256 {
710 if !self.exists(address) {
711 return H256::default();
712 }
713
714 H256::from_slice(Keccak256::digest(&self.state.code(address)).as_slice())
715 }
716
717 fn code(&self, address: H160) -> Vec<u8> {
718 self.state.code(address)
719 }
720
721 fn storage(&self, address: H160, index: H256) -> H256 {
722 self.state.storage(address, index)
723 }
724
725 fn original_storage(&self, address: H160, index: H256) -> H256 {
726 self.state
727 .original_storage(address, index)
728 .unwrap_or_default()
729 }
730
731 fn exists(&self, address: H160) -> bool {
732 if self.config.empty_considered_exists {
733 self.state.exists(address)
734 } else {
735 self.state.exists(address) && !self.state.is_empty(address)
736 }
737 }
738
739 fn is_cold(&self, address: H160, maybe_index: Option<H256>) -> bool {
740 match maybe_index {
741 None => !self.precompile_set.is_precompile(address) && self.state.is_cold(address),
742 Some(index) => self.state.is_storage_cold(address, index),
743 }
744 }
745
746 fn gas_left(&self) -> U256 {
747 self.state.gas_left()
748 }
749
750 fn gas_price(&self) -> U256 {
751 self.state.gas_price()
752 }
753 fn origin(&self) -> H160 {
754 self.state.origin()
755 }
756 fn block_hash(&self, number: U256) -> H256 {
757 self.state.block_hash(number)
758 }
759 fn block_number(&self) -> U256 {
760 self.state.block_number()
761 }
762 fn block_coinbase(&self) -> H160 {
763 self.state.block_coinbase()
764 }
765 fn block_timestamp(&self) -> U256 {
766 self.state.block_timestamp()
767 }
768 fn block_difficulty(&self) -> U256 {
769 self.state.block_difficulty()
770 }
771 fn block_gas_limit(&self) -> U256 {
772 self.state.block_gas_limit()
773 }
774 fn block_base_fee_per_gas(&self) -> U256 {
775 self.state.block_base_fee_per_gas()
776 }
777 fn chain_id(&self) -> U256 {
778 self.state.chain_id()
779 }
780
781 fn deleted(&self, address: H160) -> bool {
782 self.state.deleted(address)
783 }
784
785 fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError> {
786 self.state.set_storage(address, index, value);
787 Ok(())
788 }
789
790 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
791 self.state.log(address, topics, data);
792 Ok(())
793 }
794
795 fn mark_delete(&mut self, address: H160, target: H160) -> Result<(), ExitError> {
796 let balance = self.balance(address);
797
798 self.state.transfer(Transfer {
799 source: address,
800 target,
801 value: balance,
802 })?;
803 self.state.reset_balance(address);
804 self.state.set_deleted(address);
805
806 Ok(())
807 }
808
809 fn create(
810 &mut self,
811 caller: H160,
812 scheme: CreateScheme,
813 value: U256,
814 init_code: Vec<u8>,
815 _target_gas: Option<u64>,
816 ) -> Capture<(ExitReason, Option<H160>, Vec<u8>), Self::CreateInterrupt> {
817 self.create_inner(caller, scheme, value, init_code)
818 }
819
820 fn call(
821 &mut self,
822 code_address: H160,
823 transfer: Option<Transfer>,
824 input: Vec<u8>,
825 _target_gas: Option<u64>,
826 is_static: bool,
827 context: Context,
828 ) -> Capture<(ExitReason, Vec<u8>), Self::CallInterrupt> {
829 self.call_inner(code_address, transfer, input, is_static, context)
830 }
831
832 #[inline]
833 fn pre_validate(
834 &mut self,
835 _context: &Context,
836 _opcode: Opcode,
837 _stack: &Stack,
838 ) -> Result<(), ExitError> {
839 Ok(())
840 }
841}