1use crate::backend::Backend;
2use crate::core::utils::{U256_ZERO, U64_MAX};
3use crate::core::{ExitFatal, InterpreterHandler, Machine};
4use crate::executor::stack::precompile::{
5 PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileSet,
6};
7use crate::executor::stack::tagged_runtime::{RuntimeKind, TaggedRuntime};
8use crate::gasometer::{self, Gasometer, StorageTarget};
9use crate::maybe_borrowed::MaybeBorrowed;
10use crate::prelude::*;
11use crate::runtime::Resolve;
12use crate::{
13 Capture, Config, Context, CreateScheme, ExitError, ExitReason, Handler, Opcode, Runtime,
14 Transfer,
15};
16use core::{cmp::min, convert::Infallible};
17use primitive_types::{H160, H256, U256};
18use sha3::{Digest, Keccak256};
19use smallvec::{smallvec, SmallVec};
20
21macro_rules! emit_exit {
22 ($reason:expr) => {{
23 let reason = $reason;
24 event!(Exit {
25 reason: &reason,
26 return_value: &Vec::new(),
27 });
28 reason
29 }};
30 ($reason:expr, $return_value:expr) => {{
31 let reason = $reason;
32 let return_value = $return_value;
33 event!(Exit {
34 reason: &reason,
35 return_value: &return_value,
36 });
37 (reason, return_value)
38 }};
39}
40macro_rules! try_or_fail {
41 ( $e:expr ) => {
42 match $e {
43 Ok(v) => v,
44 Err(e) => return Capture::Exit((e.into(), Vec::new())),
45 }
46 };
47}
48
49const DEFAULT_CALL_STACK_CAPACITY: usize = 4;
50
51const fn l64(gas: u64) -> u64 {
52 gas - gas / 64
53}
54
55pub enum StackExitKind {
56 Succeeded,
57 Reverted,
58 Failed,
59}
60
61#[derive(Default, Clone, Debug, PartialEq, Eq)]
68pub struct Authorization {
69 pub authority: H160,
70 pub address: H160,
71 pub nonce: u64,
72 pub is_valid: bool,
73}
74
75impl Authorization {
76 #[must_use]
78 pub const fn new(authority: H160, address: H160, nonce: u64, is_valid: bool) -> Self {
79 Self {
80 authority,
81 address,
82 nonce,
83 is_valid,
84 }
85 }
86
87 #[must_use]
90 pub fn is_delegated(code: &[u8]) -> bool {
91 code.len() == 23 && code.starts_with(&[0xEF, 0x01, 0x00])
92 }
93
94 #[must_use]
97 pub fn get_delegated_address(code: &[u8]) -> Option<H160> {
98 if Self::is_delegated(code) {
99 Some(H160::from_slice(&code[3..]))
101 } else {
102 None
103 }
104 }
105
106 #[must_use]
109 pub fn delegation_code(&self) -> Vec<u8> {
110 let mut code = Vec::with_capacity(23);
111 code.extend(&[0xEF, 0x01, 0x00]);
112 code.extend(self.address.as_bytes());
113 code
114 }
115}
116
117#[derive(Default, Clone, Debug)]
118pub struct Accessed {
119 pub accessed_addresses: BTreeSet<H160>,
120 pub accessed_storage: BTreeSet<(H160, H256)>,
121 pub authority: BTreeMap<H160, H160>,
122}
123
124impl Accessed {
125 pub fn access_address(&mut self, address: H160) {
126 self.accessed_addresses.insert(address);
127 }
128
129 pub fn access_addresses<I>(&mut self, addresses: I)
130 where
131 I: Iterator<Item = H160>,
132 {
133 self.accessed_addresses.extend(addresses);
134 }
135
136 pub fn access_storages<I>(&mut self, storages: I)
137 where
138 I: Iterator<Item = (H160, H256)>,
139 {
140 for storage in storages {
141 self.accessed_storage.insert((storage.0, storage.1));
142 }
143 }
144
145 pub fn add_authority(&mut self, authority: H160, address: H160) {
147 self.authority.insert(authority, address);
148 }
149
150 pub fn remove_authority(&mut self, authority: H160) {
152 self.authority.remove(&authority);
153 }
154
155 #[must_use]
157 pub fn get_authority_target(&self, authority: H160) -> Option<H160> {
158 self.authority.get(&authority).copied()
159 }
160
161 #[must_use]
163 pub fn is_authority(&self, authority: H160) -> bool {
164 self.authority.contains_key(&authority)
165 }
166}
167
168#[derive(Clone, Debug)]
169pub struct StackSubstateMetadata<'config> {
170 gasometer: Gasometer<'config>,
171 is_static: bool,
172 depth: Option<usize>,
173 accessed: Option<Accessed>,
174}
175
176impl<'config> StackSubstateMetadata<'config> {
177 #[must_use]
178 pub fn new(gas_limit: u64, config: &'config Config) -> Self {
179 let accessed = if config.increase_state_access_gas {
180 Some(Accessed::default())
181 } else {
182 None
183 };
184 Self {
185 gasometer: Gasometer::new(gas_limit, config),
186 is_static: false,
187 depth: None,
188 accessed,
189 }
190 }
191
192 pub fn swallow_commit(&mut self, other: Self) -> Result<(), ExitError> {
200 self.gasometer.record_stipend(other.gasometer.gas())?;
201 self.gasometer
202 .record_refund(other.gasometer.refunded_gas())?;
203
204 if let (Some(mut other_accessed), Some(self_accessed)) =
206 (other.accessed, self.accessed.as_mut())
207 {
208 self_accessed
209 .accessed_addresses
210 .append(&mut other_accessed.accessed_addresses);
211 self_accessed
212 .accessed_storage
213 .append(&mut other_accessed.accessed_storage);
214 self_accessed
215 .authority
216 .append(&mut other_accessed.authority);
217 }
218
219 Ok(())
220 }
221
222 pub fn swallow_revert(&mut self, other: &Self) -> Result<(), ExitError> {
228 self.gasometer.record_stipend(other.gasometer.gas())
229 }
230
231 pub const fn swallow_discard(&self, _other: &Self) {}
234
235 #[must_use]
236 pub fn spit_child(&self, gas_limit: u64, is_static: bool) -> Self {
237 Self {
238 gasometer: Gasometer::new(gas_limit, self.gasometer.config()),
239 is_static: is_static || self.is_static,
240 depth: self.depth.map_or(Some(0), |n| Some(n + 1)),
241 accessed: self.accessed.as_ref().map(|_| Accessed::default()),
242 }
243 }
244
245 #[must_use]
246 pub const fn gasometer(&self) -> &Gasometer<'config> {
247 &self.gasometer
248 }
249
250 pub const fn gasometer_mut(&mut self) -> &mut Gasometer<'config> {
251 &mut self.gasometer
252 }
253
254 #[must_use]
255 pub const fn is_static(&self) -> bool {
256 self.is_static
257 }
258
259 #[must_use]
260 pub const fn depth(&self) -> Option<usize> {
261 self.depth
262 }
263
264 pub fn access_address(&mut self, address: H160) {
265 if let Some(accessed) = &mut self.accessed {
266 accessed.access_address(address);
267 }
268 }
269
270 pub fn access_addresses<I>(&mut self, addresses: I)
271 where
272 I: Iterator<Item = H160>,
273 {
274 if let Some(accessed) = &mut self.accessed {
275 accessed.access_addresses(addresses);
276 }
277 }
278
279 pub fn access_storage(&mut self, address: H160, key: H256) {
280 if let Some(accessed) = &mut self.accessed {
281 accessed.accessed_storage.insert((address, key));
282 }
283 }
284
285 pub fn access_storages<I>(&mut self, storages: I)
286 where
287 I: Iterator<Item = (H160, H256)>,
288 {
289 if let Some(accessed) = &mut self.accessed {
290 accessed.access_storages(storages);
291 }
292 }
293
294 #[must_use]
297 pub const fn accessed(&self) -> &Option<Accessed> {
298 &self.accessed
299 }
300
301 pub fn add_authority(&mut self, authority: H160, address: H160) {
303 if let Some(accessed) = &mut self.accessed {
304 accessed.add_authority(authority, address);
305 }
306 }
307
308 pub fn remove_authority(&mut self, authority: H160) {
310 if let Some(accessed) = &mut self.accessed {
311 accessed.remove_authority(authority);
312 }
313 }
314}
315
316#[auto_impl::auto_impl(& mut, Box)]
317pub trait StackState<'config>: Backend {
318 fn metadata(&self) -> &StackSubstateMetadata<'config>;
319 fn metadata_mut(&mut self) -> &mut StackSubstateMetadata<'config>;
320
321 fn enter(&mut self, gas_limit: u64, is_static: bool);
322 fn exit_commit(&mut self) -> Result<(), ExitError>;
325 fn exit_revert(&mut self) -> Result<(), ExitError>;
328 fn exit_discard(&mut self) -> Result<(), ExitError>;
331
332 fn is_empty(&self, address: H160) -> bool;
333 fn deleted(&self, address: H160) -> bool;
334 fn is_created(&self, address: H160) -> bool;
335 fn is_cold(&self, address: H160) -> bool;
336 fn is_storage_cold(&self, address: H160, key: H256) -> bool;
337
338 fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError>;
341 fn set_storage(&mut self, address: H160, key: H256, value: H256);
342 fn reset_storage(&mut self, address: H160);
343 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>);
344 fn set_deleted(&mut self, address: H160);
345 fn set_created(&mut self, address: H160);
346 fn set_code(&mut self, address: H160, code: Vec<u8>);
347 fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError>;
350 fn reset_balance(&mut self, address: H160);
351 fn touch(&mut self, address: H160);
352
353 fn record_external_operation(
356 &mut self,
357 #[allow(clippy::used_underscore_binding)] _op: crate::ExternalOperation,
358 ) -> Result<(), ExitError> {
359 Ok(())
360 }
361
362 fn record_external_dynamic_opcode_cost(
365 &mut self,
366 #[allow(clippy::used_underscore_binding)] _opcode: Opcode,
367 #[allow(clippy::used_underscore_binding)] _gas_cost: gasometer::GasCost,
368 #[allow(clippy::used_underscore_binding)] _target: StorageTarget,
369 ) -> Result<(), ExitError> {
370 Ok(())
371 }
372
373 fn record_external_cost(
376 &mut self,
377 #[allow(clippy::used_underscore_binding)] _ref_time: Option<u64>,
378 #[allow(clippy::used_underscore_binding)] _proof_size: Option<u64>,
379 #[allow(clippy::used_underscore_binding)] _storage_growth: Option<u64>,
380 ) -> Result<(), ExitError> {
381 Ok(())
382 }
383
384 fn refund_external_cost(
385 &mut self,
386 #[allow(clippy::used_underscore_binding)] _ref_time: Option<u64>,
387 #[allow(clippy::used_underscore_binding)] _proof_size: Option<u64>,
388 ) {
389 }
390
391 fn tstore(&mut self, address: H160, index: H256, value: U256) -> Result<(), ExitError>;
397 fn tload(&mut self, address: H160, index: H256) -> Result<U256, ExitError>;
403
404 fn is_authority_cold(&mut self, address: H160) -> Option<bool>;
406
407 fn get_authority_target(&mut self, address: H160) -> Option<H160>;
409}
410
411pub struct StackExecutor<'config, 'precompiles, S, P> {
413 config: &'config Config,
414 state: S,
415 precompile_set: &'precompiles P,
416}
417
418impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
419 StackExecutor<'config, 'precompiles, S, P>
420{
421 pub const fn config(&self) -> &'config Config {
423 self.config
424 }
425
426 pub const fn precompiles(&self) -> &'precompiles P {
428 self.precompile_set
429 }
430
431 pub const fn new_with_precompiles(
433 state: S,
434 config: &'config Config,
435 precompile_set: &'precompiles P,
436 ) -> Self {
437 Self {
438 config,
439 state,
440 precompile_set,
441 }
442 }
443
444 pub const fn state(&self) -> &S {
445 &self.state
446 }
447
448 pub const fn state_mut(&mut self) -> &mut S {
449 &mut self.state
450 }
451
452 #[allow(clippy::missing_const_for_fn)]
453 pub fn into_state(self) -> S {
454 self.state
455 }
456
457 pub fn enter_substate(&mut self, gas_limit: u64, is_static: bool) {
459 self.state.enter(gas_limit, is_static);
460 }
461
462 pub fn exit_substate(&mut self, kind: &StackExitKind) -> Result<(), ExitError> {
470 match kind {
471 StackExitKind::Succeeded => self.state.exit_commit(),
472 StackExitKind::Reverted => self.state.exit_revert(),
473 StackExitKind::Failed => self.state.exit_discard(),
474 }
475 }
476
477 pub fn execute(&mut self, runtime: &mut Runtime) -> ExitReason {
479 let mut call_stack: SmallVec<[TaggedRuntime; DEFAULT_CALL_STACK_CAPACITY]> =
480 smallvec!(TaggedRuntime {
481 kind: RuntimeKind::Execute,
482 inner: MaybeBorrowed::Borrowed(runtime),
483 });
484 let (reason, _, _) = self.execute_with_call_stack(&mut call_stack);
485 reason
486 }
487
488 fn execute_with_call_stack(
490 &mut self,
491 call_stack: &mut SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]>,
492 ) -> (ExitReason, Option<H160>, Vec<u8>) {
493 let mut interrupt_runtime = None;
500 loop {
501 if let Some(rt) = interrupt_runtime.take() {
502 call_stack.push(rt);
503 }
504 let Some(runtime) = call_stack.last_mut() else {
505 return (
506 ExitReason::Fatal(ExitFatal::UnhandledInterrupt),
507 None,
508 Vec::new(),
509 );
510 };
511 let reason = {
512 let inner_runtime = &mut runtime.inner;
513 match inner_runtime.run(self) {
514 Capture::Exit(reason) => reason,
515 Capture::Trap(Resolve::Call(rt, _)) => {
516 interrupt_runtime = Some(rt.0);
517 continue;
518 }
519 Capture::Trap(Resolve::Create(rt, _)) => {
520 interrupt_runtime = Some(rt.0);
521 continue;
522 }
523 }
524 };
525 let runtime_kind = runtime.kind;
526 let (reason, maybe_address, return_data) = match runtime_kind {
527 RuntimeKind::Create(created_address) => {
528 let (reason, maybe_address, return_data) = self.exit_substate_for_create(
529 created_address,
530 reason,
531 runtime.inner.machine().return_value(),
532 );
533 (reason, maybe_address, return_data)
534 }
535 RuntimeKind::Call(code_address) => {
536 let return_data = self.exit_substate_for_call(
537 code_address,
538 &reason,
539 runtime.inner.machine().return_value(),
540 );
541 (reason, None, return_data)
542 }
543 RuntimeKind::Execute => (reason, None, runtime.inner.machine().return_value()),
544 };
545 call_stack.pop();
547 let Some(runtime) = call_stack.last_mut() else {
549 return (reason, None, return_data);
550 };
551 emit_exit!(&reason, &return_data);
552 let inner_runtime = &mut runtime.inner;
553 let maybe_error = match runtime_kind {
554 RuntimeKind::Create(_) => {
555 inner_runtime.finish_create(reason, maybe_address, return_data)
556 }
557 RuntimeKind::Call(_) | RuntimeKind::Execute => {
558 inner_runtime.finish_call(reason, return_data)
559 }
560 };
561 if let Err(e) = maybe_error {
563 return (e, None, Vec::new());
564 }
565 }
566 }
567
568 pub fn gas(&self) -> u64 {
570 self.state.metadata().gasometer.gas()
571 }
572
573 fn record_create_transaction_cost(
574 &mut self,
575 init_code: &[u8],
576 access_list: &[(H160, Vec<H256>)],
577 ) -> Result<(), ExitError> {
578 let transaction_cost = gasometer::create_transaction_cost(init_code, access_list);
579 let gasometer = &mut self.state.metadata_mut().gasometer;
580 gasometer.record_transaction(transaction_cost)
581 }
582
583 fn maybe_record_init_code_cost(&mut self, init_code: &[u8]) -> Result<(), ExitError> {
584 if let Some(limit) = self.config.max_initcode_size {
585 if init_code.len() > limit {
587 self.state.metadata_mut().gasometer.fail();
588 return Err(ExitError::CreateContractLimit);
589 }
590 return self
591 .state
592 .metadata_mut()
593 .gasometer
594 .record_cost(gasometer::init_code_cost(init_code));
595 }
596 Ok(())
597 }
598
599 pub fn transact_create(
601 &mut self,
602 caller: H160,
603 value: U256,
604 init_code: Vec<u8>,
605 gas_limit: u64,
606 access_list: Vec<(H160, Vec<H256>)>, ) -> (ExitReason, Vec<u8>) {
608 if self.nonce(caller) >= U64_MAX {
609 return (ExitError::MaxNonce.into(), Vec::new());
610 }
611
612 let address = self.create_address(CreateScheme::Legacy { caller });
613
614 event!(TransactCreate {
615 caller,
616 value,
617 init_code: &init_code,
618 gas_limit,
619 address,
620 });
621
622 if let Some(limit) = self.config.max_initcode_size {
623 if init_code.len() > limit {
624 self.state.metadata_mut().gasometer.fail();
625 return emit_exit!(ExitError::CreateContractLimit.into(), Vec::new());
626 }
627 }
628
629 if let Err(e) = self.record_create_transaction_cost(&init_code, &access_list) {
630 return emit_exit!(e.into(), Vec::new());
631 }
632
633 self.warm_addresses_and_storage(caller, address, access_list);
634
635 match self.create_inner(
636 caller,
637 CreateScheme::Legacy { caller },
638 value,
639 init_code,
640 Some(gas_limit),
641 false,
642 ) {
643 Capture::Exit((s, v)) => emit_exit!(s, v),
644 Capture::Trap(rt) => {
645 let mut cs: SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]> =
646 smallvec!(rt.0);
647 let (s, _, v) = self.execute_with_call_stack(&mut cs);
648 emit_exit!(s, v)
649 }
650 }
651 }
652
653 #[cfg(feature = "create-fixed")]
655 pub fn transact_create_fixed(
656 &mut self,
657 caller: H160,
658 address: H160,
659 value: U256,
660 init_code: Vec<u8>,
661 gas_limit: u64,
662 access_list: Vec<(H160, Vec<H256>)>, ) -> (ExitReason, Vec<u8>) {
664 let address = self.create_address(CreateScheme::Fixed(address));
665
666 event!(TransactCreate {
667 caller,
668 value,
669 init_code: &init_code,
670 gas_limit,
671 address
672 });
673
674 if let Err(e) = self.record_create_transaction_cost(&init_code, &access_list) {
675 return emit_exit!(e.into(), Vec::new());
676 }
677
678 self.warm_addresses_and_storage(caller, address, access_list);
679
680 match self.create_inner(
681 caller,
682 CreateScheme::Fixed(address),
683 value,
684 init_code,
685 Some(gas_limit),
686 false,
687 ) {
688 Capture::Exit((s, v)) => emit_exit!(s, v),
689 Capture::Trap(rt) => {
690 let mut cs: SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]> =
691 smallvec!(rt.0);
692 let (s, _, v) = self.execute_with_call_stack(&mut cs);
693 emit_exit!(s, v)
694 }
695 }
696 }
697
698 #[allow(clippy::too_many_arguments)]
700 pub fn transact_create2(
701 &mut self,
702 caller: H160,
703 value: U256,
704 init_code: Vec<u8>,
705 salt: H256,
706 gas_limit: u64,
707 access_list: Vec<(H160, Vec<H256>)>, ) -> (ExitReason, Vec<u8>) {
709 if let Some(limit) = self.config.max_initcode_size {
710 if init_code.len() > limit {
711 self.state.metadata_mut().gasometer.fail();
712 return emit_exit!(ExitError::CreateContractLimit.into(), Vec::new());
713 }
714 }
715
716 let code_hash =
717 H256::from_slice(<[u8; 32]>::from(Keccak256::digest(&init_code)).as_slice());
718 let address = self.create_address(CreateScheme::Create2 {
719 caller,
720 code_hash,
721 salt,
722 });
723 event!(TransactCreate2 {
724 caller,
725 value,
726 init_code: &init_code,
727 salt,
728 gas_limit,
729 address,
730 });
731
732 if let Err(e) = self.record_create_transaction_cost(&init_code, &access_list) {
733 return emit_exit!(e.into(), Vec::new());
734 }
735
736 self.warm_addresses_and_storage(caller, address, access_list);
737
738 match self.create_inner(
739 caller,
740 CreateScheme::Create2 {
741 caller,
742 code_hash,
743 salt,
744 },
745 value,
746 init_code,
747 Some(gas_limit),
748 false,
749 ) {
750 Capture::Exit((s, v)) => emit_exit!(s, v),
751 Capture::Trap(rt) => {
752 let mut cs: SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]> =
753 smallvec!(rt.0);
754 let (s, _, v) = self.execute_with_call_stack(&mut cs);
755 emit_exit!(s, v)
756 }
757 }
758 }
759
760 #[allow(clippy::too_many_arguments)]
766 pub fn transact_call(
767 &mut self,
768 caller: H160,
769 address: H160,
770 value: U256,
771 data: Vec<u8>,
772 gas_limit: u64,
773 access_list: Vec<(H160, Vec<H256>)>,
774 authorization_list: Vec<Authorization>,
775 ) -> (ExitReason, Vec<u8>) {
776 event!(TransactCall {
777 caller,
778 address,
779 value,
780 data: &data,
781 gas_limit,
782 });
783
784 if self.nonce(caller) >= U64_MAX {
785 return (ExitError::MaxNonce.into(), Vec::new());
786 }
787
788 let transaction_cost =
789 gasometer::call_transaction_cost(&data, &access_list, authorization_list.len());
790 let gasometer = &mut self.state.metadata_mut().gasometer;
791 match gasometer.record_transaction(transaction_cost) {
792 Ok(()) => (),
793 Err(e) => return emit_exit!(e.into(), Vec::new()),
794 }
795
796 if let Err(e) = self.state.inc_nonce(caller) {
797 return (e.into(), Vec::new());
798 }
799
800 self.warm_addresses_and_storage(caller, address, access_list);
801 if let Err(e) = self.authorized_accounts(authorization_list) {
804 return (e.into(), Vec::new());
805 }
806
807 let context = Context {
808 caller,
809 address,
810 apparent_value: value,
811 };
812
813 match self.call_inner(
814 address,
815 Some(Transfer {
816 source: caller,
817 target: address,
818 value,
819 }),
820 data,
821 Some(gas_limit),
822 false,
823 false,
824 false,
825 context,
826 ) {
827 Capture::Exit((s, v)) => emit_exit!(s, v),
828 Capture::Trap(rt) => {
829 let mut cs: SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]> =
830 smallvec!(rt.0);
831 let (s, _, v) = self.execute_with_call_stack(&mut cs);
832 emit_exit!(s, v)
833 }
834 }
835 }
836
837 pub fn used_gas(&self) -> u64 {
839 let refunded_gas =
841 u64::try_from(self.state.metadata().gasometer.refunded_gas()).unwrap_or_default();
842 let total_used_gas = self.state.metadata().gasometer.total_used_gas();
843 let total_used_gas_refunded = self.state.metadata().gasometer.total_used_gas()
844 - min(
845 total_used_gas / self.config.max_refund_quotient,
846 refunded_gas,
847 );
848 if self.config.has_floor_gas
850 && total_used_gas_refunded < self.state.metadata().gasometer.floor_gas()
851 {
852 self.state.metadata().gasometer.floor_gas()
853 } else {
854 total_used_gas_refunded
855 }
856 }
857
858 pub fn fee(&self, price: U256) -> U256 {
860 let used_gas = self.used_gas();
861 U256::from(used_gas).saturating_mul(price)
862 }
863
864 pub fn nonce(&self, address: H160) -> U256 {
867 self.state.basic(address).nonce
868 }
869
870 pub fn is_create_collision(&self, address: H160) -> bool {
873 !self.code(address).is_empty()
874 || self.nonce(address) > U256_ZERO
875 || !self.state.is_empty_storage(address)
876 }
877
878 pub fn create_address(&self, scheme: CreateScheme) -> H160 {
880 match scheme {
881 CreateScheme::Create2 {
882 caller,
883 code_hash,
884 salt,
885 } => {
886 let mut hasher = Keccak256::new();
887 hasher.update([0xff]);
888 hasher.update(&caller[..]);
889 hasher.update(&salt[..]);
890 hasher.update(&code_hash[..]);
891 H256::from_slice(<[u8; 32]>::from(hasher.finalize()).as_slice()).into()
892 }
893 CreateScheme::Legacy { caller } => {
894 let nonce = self.nonce(caller);
895 let mut stream = rlp::RlpStream::new_list(2);
896 stream.append(&caller);
897 stream.append(&nonce);
898 H256::from_slice(<[u8; 32]>::from(Keccak256::digest(stream.out())).as_slice())
899 .into()
900 }
901 CreateScheme::Fixed(address) => address,
902 }
903 }
904
905 pub fn warm_access_list(&mut self, access_list: Vec<(H160, Vec<H256>)>) {
910 let addresses = access_list.iter().map(|a| a.0);
911 self.state.metadata_mut().access_addresses(addresses);
912
913 let storage_keys = access_list
914 .into_iter()
915 .flat_map(|(address, keys)| keys.into_iter().map(move |key| (address, key)));
916 self.state.metadata_mut().access_storages(storage_keys);
917 }
918
919 fn warm_addresses_and_storage(
931 &mut self,
932 caller: H160,
933 address: H160,
934 access_list: Vec<(H160, Vec<H256>)>,
935 ) {
936 if self.config.increase_state_access_gas {
937 if self.config.warm_coinbase_address {
938 let coinbase = self.block_coinbase();
940 self.state
941 .metadata_mut()
942 .access_addresses([caller, address, coinbase].iter().copied());
943 } else {
944 self.state
945 .metadata_mut()
946 .access_addresses([caller, address].iter().copied());
947 }
948
949 self.warm_access_list(access_list);
950 }
951 }
952
953 fn authorized_accounts(
974 &mut self,
975 authorization_list: Vec<Authorization>,
976 ) -> Result<(), ExitError> {
977 if !self.config.has_authorization_list {
978 return Ok(());
979 }
980 let mut refunded_accounts = 0;
981
982 let state = self.state_mut();
983 let mut warm_authority: Vec<H160> = Vec::with_capacity(authorization_list.len());
984 for authority in authorization_list {
985 if !authority.is_valid {
987 continue;
988 }
989
990 if U256::from(authority.nonce) >= U64_MAX {
992 continue;
993 }
994
995 warm_authority.push(authority.authority);
997 let authority_code = state.code(authority.authority);
999 if !authority_code.is_empty() && !Authorization::is_delegated(&authority_code) {
1000 continue;
1001 }
1002
1003 if state.basic(authority.authority).nonce != U256::from(authority.nonce) {
1005 continue;
1006 }
1007
1008 if !state.is_empty(authority.authority) {
1010 refunded_accounts += 1;
1011 }
1012 let delegation_clearing = if authority.address.is_zero() {
1016 state.set_code(authority.authority, Vec::new());
1017 true
1018 } else {
1019 state.set_code(authority.authority, authority.delegation_code());
1020 false
1021 };
1022 state.inc_nonce(authority.authority)?;
1024
1025 if delegation_clearing {
1027 state.metadata_mut().remove_authority(authority.authority);
1028 } else {
1029 state
1030 .metadata_mut()
1031 .add_authority(authority.authority, authority.address);
1032 }
1033 }
1034 self.state
1036 .metadata_mut()
1037 .access_addresses(warm_authority.into_iter());
1038
1039 self.state
1040 .metadata_mut()
1041 .gasometer
1042 .record_authority_refund(refunded_accounts)
1043 }
1044
1045 fn calc_gas_limit_and_record(
1047 &mut self,
1048 target_gas: Option<u64>,
1049 take_l64: bool,
1050 ) -> Result<u64, ExitError> {
1051 let initial_after_gas = self.state.metadata().gasometer.gas();
1052 let after_gas = if take_l64 && self.config.call_l64_after_gas {
1053 if self.config.estimate {
1054 let diff = initial_after_gas - l64(initial_after_gas);
1055 self.state.metadata_mut().gasometer.record_cost(diff)?;
1056 initial_after_gas
1057 } else {
1058 l64(initial_after_gas)
1059 }
1060 } else {
1061 initial_after_gas
1062 };
1063 let target_gas = target_gas.unwrap_or(after_gas);
1064 let gas_limit = min(target_gas, after_gas);
1065 self.state.metadata_mut().gasometer.record_cost(gas_limit)?;
1066 Ok(gas_limit)
1067 }
1068
1069 fn create_inner(
1070 &mut self,
1071 caller: H160,
1072 scheme: CreateScheme,
1073 value: U256,
1074 init_code: Vec<u8>,
1075 target_gas: Option<u64>,
1076 take_l64: bool,
1077 ) -> Capture<(ExitReason, Vec<u8>), StackExecutorCreateInterrupt<'static>> {
1078 if self.nonce(caller) >= U64_MAX {
1079 return Capture::Exit((ExitError::MaxNonce.into(), Vec::new()));
1080 }
1081
1082 let address = self.create_address(scheme);
1084 self.state
1085 .metadata_mut()
1086 .access_addresses([caller, address].iter().copied());
1087
1088 event!(Create {
1089 caller,
1090 address,
1091 scheme,
1092 value,
1093 init_code: &init_code,
1094 target_gas
1095 });
1096
1097 if let Some(depth) = self.state.metadata().depth {
1098 if depth + 1 > self.config.call_stack_limit {
1102 return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
1103 }
1104 }
1105
1106 if self.balance(caller) < value {
1108 return Capture::Exit((ExitError::OutOfFund.into(), Vec::new()));
1109 }
1110
1111 let gas_limit = try_or_fail!(self.calc_gas_limit_and_record(target_gas, take_l64));
1112
1113 try_or_fail!(self.state.inc_nonce(caller));
1115
1116 if self.is_create_collision(address) {
1118 return Capture::Exit((ExitError::CreateCollision.into(), Vec::new()));
1119 }
1120
1121 self.enter_substate(gas_limit, false);
1123
1124 if self.config.create_increase_nonce {
1126 try_or_fail!(self.state.inc_nonce(address));
1127 }
1128
1129 let transfer = Transfer {
1131 source: caller,
1132 target: address,
1133 value,
1134 };
1135 match self.state.transfer(transfer) {
1136 Ok(()) => (),
1137 Err(e) => {
1138 let _ = self.exit_substate(&StackExitKind::Reverted);
1139 return Capture::Exit((ExitReason::Error(e), Vec::new()));
1140 }
1141 }
1142 self.state.set_created(address);
1145
1146 let context = Context {
1148 address,
1149 caller,
1150 apparent_value: value,
1151 };
1152 let runtime = Runtime::new(
1153 Rc::new(init_code),
1154 Rc::new(Vec::new()),
1155 context,
1156 self.config.stack_limit,
1157 self.config.memory_limit,
1158 );
1159
1160 Capture::Trap(StackExecutorCreateInterrupt(TaggedRuntime {
1162 kind: RuntimeKind::Create(address),
1163 inner: MaybeBorrowed::Owned(runtime),
1164 }))
1165 }
1166
1167 #[allow(clippy::too_many_arguments, clippy::too_many_lines)]
1168 fn call_inner(
1169 &mut self,
1170 code_address: H160,
1171 transfer: Option<Transfer>,
1172 input: Vec<u8>,
1173 target_gas: Option<u64>,
1174 is_static: bool,
1175 take_l64: bool,
1176 take_stipend: bool,
1177 context: Context,
1178 ) -> Capture<(ExitReason, Vec<u8>), StackExecutorCallInterrupt<'static>> {
1179 event!(Call {
1180 code_address,
1181 transfer: &transfer,
1182 input: &input,
1183 target_gas,
1184 is_static,
1185 context: &context,
1186 });
1187
1188 let mut gas_limit = try_or_fail!(self.calc_gas_limit_and_record(target_gas, take_l64));
1189
1190 if let Some(transfer) = transfer.as_ref() {
1191 if take_stipend && transfer.value != U256_ZERO {
1192 gas_limit = gas_limit.saturating_add(self.config.call_stipend);
1193 }
1194 }
1195
1196 let code = self.authority_code(code_address);
1199 if let Some(target_address) = self.get_authority_target(code_address) {
1201 self.warm_target((target_address, None));
1202 }
1203
1204 self.enter_substate(gas_limit, is_static);
1205 self.state.touch(context.address);
1206
1207 if let Some(depth) = self.state.metadata().depth {
1208 if depth > self.config.call_stack_limit {
1209 let _ = self.exit_substate(&StackExitKind::Reverted);
1210 return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
1211 }
1212 }
1213
1214 if let Some(transfer) = transfer {
1216 match self.state.transfer(transfer) {
1217 Ok(()) => (),
1218 Err(e) => {
1219 let _ = self.exit_substate(&StackExitKind::Reverted);
1220 return Capture::Exit((ExitReason::Error(e), Vec::new()));
1221 }
1222 }
1223 }
1224
1225 let precompile_is_static = self.state.metadata().is_static();
1229 if let Some(result) = self.precompile_set.execute(&mut StackExecutorHandle {
1230 executor: self,
1231 code_address,
1232 input: &input,
1233 gas_limit: Some(gas_limit),
1234 context: &context,
1235 is_static: precompile_is_static,
1236 }) {
1237 return match result {
1238 Ok(PrecompileOutput {
1239 exit_status,
1240 output,
1241 }) => {
1242 let _ = self.exit_substate(&StackExitKind::Succeeded);
1243 Capture::Exit((ExitReason::Succeed(exit_status), output))
1244 }
1245 Err(PrecompileFailure::Error { exit_status }) => {
1246 let _ = self.exit_substate(&StackExitKind::Failed);
1247 Capture::Exit((ExitReason::Error(exit_status), Vec::new()))
1248 }
1249 Err(PrecompileFailure::Revert {
1250 exit_status,
1251 output,
1252 }) => {
1253 let _ = self.exit_substate(&StackExitKind::Reverted);
1254 Capture::Exit((ExitReason::Revert(exit_status), output))
1255 }
1256 Err(PrecompileFailure::Fatal { exit_status }) => {
1257 self.state.metadata_mut().gasometer.fail();
1258 let _ = self.exit_substate(&StackExitKind::Failed);
1259 Capture::Exit((ExitReason::Fatal(exit_status), Vec::new()))
1260 }
1261 };
1262 }
1263
1264 let runtime = Runtime::new(
1265 Rc::new(code),
1266 Rc::new(input),
1267 context,
1268 self.config.stack_limit,
1269 self.config.memory_limit,
1270 );
1271
1272 Capture::Trap(StackExecutorCallInterrupt(TaggedRuntime {
1273 kind: RuntimeKind::Call(code_address),
1274 inner: MaybeBorrowed::Owned(runtime),
1275 }))
1276 }
1277
1278 fn exit_substate_for_create(
1279 &mut self,
1280 created_address: H160,
1281 reason: ExitReason,
1282 return_data: Vec<u8>,
1283 ) -> (ExitReason, Option<H160>, Vec<u8>) {
1284 fn check_first_byte_eof_magic(config: &Config, code: &[u8]) -> Result<(), ExitError> {
1286 if config.disallow_executable_format && Some(&0xEF) == code.first() {
1287 return Err(ExitError::CreateContractStartingWithEF);
1288 }
1289 Ok(())
1290 }
1291
1292 log::debug!(target: "evm", "Create execution using address {created_address}: {reason:?}");
1293
1294 match reason {
1295 ExitReason::Succeed(s) => {
1296 let out = return_data;
1297 let address = created_address;
1298 if let Err(e) = check_first_byte_eof_magic(self.config, &out) {
1300 self.state.metadata_mut().gasometer.fail();
1301 let _ = self.exit_substate(&StackExitKind::Failed);
1302 return (e.into(), None, Vec::new());
1303 }
1304
1305 if let Some(limit) = self.config.create_contract_limit {
1306 if out.len() > limit {
1307 self.state.metadata_mut().gasometer.fail();
1308 let _ = self.exit_substate(&StackExitKind::Failed);
1309 return (ExitError::CreateContractLimit.into(), None, Vec::new());
1310 }
1311 }
1312
1313 match self
1314 .state
1315 .metadata_mut()
1316 .gasometer
1317 .record_deposit(out.len())
1318 {
1319 Ok(()) => {
1320 let exit_result = self.exit_substate(&StackExitKind::Succeeded);
1321 event!(CreateOutput {
1322 address,
1323 code: &out,
1324 });
1325 self.state.set_code(address, out);
1326 if let Err(e) = exit_result {
1327 return (e.into(), None, Vec::new());
1328 }
1329 (ExitReason::Succeed(s), Some(address), Vec::new())
1330 }
1331 Err(e) => {
1332 let _ = self.exit_substate(&StackExitKind::Failed);
1333 (ExitReason::Error(e), None, Vec::new())
1334 }
1335 }
1336 }
1337 ExitReason::Error(e) => {
1338 self.state.metadata_mut().gasometer.fail();
1339 let _ = self.exit_substate(&StackExitKind::Failed);
1340 (ExitReason::Error(e), None, Vec::new())
1341 }
1342 ExitReason::Revert(e) => {
1343 let _ = self.exit_substate(&StackExitKind::Reverted);
1344 (ExitReason::Revert(e), None, return_data)
1345 }
1346 ExitReason::Fatal(e) => {
1347 self.state.metadata_mut().gasometer.fail();
1348 let _ = self.exit_substate(&StackExitKind::Failed);
1349 (ExitReason::Fatal(e), None, Vec::new())
1350 }
1351 }
1352 }
1353
1354 fn exit_substate_for_call(
1355 &mut self,
1356 code_address: H160,
1357 reason: &ExitReason,
1358 return_data: Vec<u8>,
1359 ) -> Vec<u8> {
1360 log::debug!(target: "evm", "Call execution using address {code_address}: {reason:?}");
1361 match reason {
1362 ExitReason::Succeed(_) => {
1363 let _ = self.exit_substate(&StackExitKind::Succeeded);
1364 return_data
1365 }
1366 ExitReason::Error(_) => {
1367 let _ = self.exit_substate(&StackExitKind::Failed);
1368 Vec::new()
1369 }
1370 ExitReason::Revert(_) => {
1371 let _ = self.exit_substate(&StackExitKind::Reverted);
1372 return_data
1373 }
1374 ExitReason::Fatal(_) => {
1375 self.state.metadata_mut().gasometer.fail();
1376 let _ = self.exit_substate(&StackExitKind::Failed);
1377 Vec::new()
1378 }
1379 }
1380 }
1381
1382 fn is_created(&self, address: H160) -> bool {
1384 self.state.is_created(address)
1385 }
1386}
1387
1388impl<'config, S: StackState<'config>, P: PrecompileSet> InterpreterHandler
1389 for StackExecutor<'config, '_, S, P>
1390{
1391 #[inline]
1392 fn before_bytecode(
1393 &mut self,
1394 opcode: Opcode,
1395 _pc: usize,
1396 machine: &Machine,
1397 address: &H160,
1398 ) -> Result<(), ExitError> {
1399 #[cfg(feature = "tracing")]
1400 {
1401 use crate::runtime::tracing::Event::Step;
1402 crate::runtime::tracing::with(|listener| {
1403 #[allow(clippy::used_underscore_binding)]
1404 listener.event(Step {
1405 address: *address,
1406 opcode,
1407 position: &Ok(_pc),
1408 stack: machine.stack(),
1409 memory: machine.memory(),
1410 });
1411 });
1412 }
1413
1414 #[cfg(feature = "print-debug")]
1415 println!("### {opcode}");
1416 if let Some(cost) = gasometer::static_opcode_cost(opcode) {
1417 self.state
1418 .metadata_mut()
1419 .gasometer
1420 .record_cost(u64::from(cost))?;
1421 } else {
1422 let is_static = self.state.metadata().is_static;
1423 let (gas_cost, memory_cost) = gasometer::dynamic_opcode_cost(
1424 *address,
1425 opcode,
1426 machine.stack(),
1427 is_static,
1428 self.config,
1429 self,
1430 )?;
1431
1432 self.state
1433 .metadata_mut()
1434 .gasometer
1435 .record_dynamic_cost(gas_cost, memory_cost)?;
1436 }
1437 Ok(())
1438 }
1439
1440 #[cfg(feature = "tracing")]
1441 #[inline]
1442 fn after_bytecode(
1443 &mut self,
1444 result: &Result<(), Capture<ExitReason, crate::core::Trap>>,
1445 machine: &Machine,
1446 ) {
1447 use crate::runtime::tracing::Event::StepResult;
1448 crate::runtime::tracing::with(|listener| {
1449 listener.event(StepResult {
1450 result,
1451 return_value: machine.return_value().as_slice(),
1452 });
1453 });
1454 }
1455}
1456
1457pub struct StackExecutorCallInterrupt<'borrow>(TaggedRuntime<'borrow>);
1458
1459pub struct StackExecutorCreateInterrupt<'borrow>(TaggedRuntime<'borrow>);
1460
1461impl<'config, S: StackState<'config>, P: PrecompileSet> Handler
1462 for StackExecutor<'config, '_, S, P>
1463{
1464 type CreateInterrupt = StackExecutorCreateInterrupt<'static>;
1465 type CreateFeedback = Infallible;
1466 type CallInterrupt = StackExecutorCallInterrupt<'static>;
1467 type CallFeedback = Infallible;
1468
1469 fn balance(&self, address: H160) -> U256 {
1472 self.state.basic(address).balance
1473 }
1474
1475 fn code_size(&mut self, address: H160) -> U256 {
1482 let target_code = self.code(address);
1483 U256::from(target_code.len())
1484 }
1485
1486 fn code_hash(&mut self, address: H160) -> H256 {
1493 if !self.exists(address) {
1494 return H256::default();
1495 }
1496 let code = self.code(address);
1497 H256::from_slice(<[u8; 32]>::from(Keccak256::digest(code)).as_slice())
1498 }
1499
1500 fn code(&self, address: H160) -> Vec<u8> {
1502 self.state.code(address)
1503 }
1504
1505 fn storage(&self, address: H160, index: H256) -> H256 {
1507 self.state.storage(address, index)
1508 }
1509
1510 fn is_empty_storage(&self, address: H160) -> bool {
1512 self.state.is_empty(address)
1513 }
1514
1515 fn original_storage(&self, address: H160, index: H256) -> H256 {
1516 self.state
1517 .original_storage(address, index)
1518 .unwrap_or_default()
1519 }
1520
1521 fn exists(&self, address: H160) -> bool {
1523 if self.config.empty_considered_exists {
1524 self.state.exists(address)
1525 } else {
1526 self.state.exists(address) && !self.state.is_empty(address)
1527 }
1528 }
1529
1530 fn is_cold(&mut self, address: H160, maybe_index: Option<H256>) -> bool {
1531 match maybe_index {
1532 None => !self.precompile_set.is_precompile(address) && self.state.is_cold(address),
1533 Some(index) => self.state.is_storage_cold(address, index),
1534 }
1535 }
1536
1537 fn gas_left(&self) -> U256 {
1538 U256::from(self.state.metadata().gasometer.gas())
1539 }
1540
1541 fn gas_price(&self) -> U256 {
1542 self.state.gas_price()
1543 }
1544
1545 fn origin(&self) -> H160 {
1546 self.state.origin()
1547 }
1548
1549 fn block_hash(&self, number: U256) -> H256 {
1550 self.state.block_hash(number)
1551 }
1552 fn block_number(&self) -> U256 {
1553 self.state.block_number()
1554 }
1555 fn block_coinbase(&self) -> H160 {
1556 self.state.block_coinbase()
1557 }
1558 fn block_timestamp(&self) -> U256 {
1559 self.state.block_timestamp()
1560 }
1561 fn block_difficulty(&self) -> U256 {
1562 self.state.block_difficulty()
1563 }
1564 fn block_randomness(&self) -> Option<H256> {
1565 self.state.block_randomness()
1566 }
1567 fn block_gas_limit(&self) -> U256 {
1568 self.state.block_gas_limit()
1569 }
1570 fn block_base_fee_per_gas(&self) -> U256 {
1571 self.state.block_base_fee_per_gas()
1572 }
1573 fn chain_id(&self) -> U256 {
1574 self.state.chain_id()
1575 }
1576 fn deleted(&self, address: H160) -> bool {
1577 self.state.deleted(address)
1578 }
1579
1580 fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError> {
1581 self.state.set_storage(address, index, value);
1582 Ok(())
1583 }
1584
1585 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
1586 self.state.log(address, topics, data);
1587 Ok(())
1588 }
1589
1590 fn mark_delete(&mut self, address: H160, target: H160) -> Result<(), ExitError> {
1593 let is_created = self.is_created(address);
1594 if self.config.has_restricted_selfdestruct && !is_created && address == target {
1596 return Ok(());
1600 }
1601
1602 let balance = self.balance(address);
1603
1604 event!(Suicide {
1605 target,
1606 address,
1607 balance,
1608 });
1609
1610 self.state.transfer(Transfer {
1611 source: address,
1612 target,
1613 value: balance,
1614 })?;
1615 self.state.reset_balance(address);
1616 if !self.config.has_restricted_selfdestruct || self.is_created(address) {
1619 self.state.set_deleted(address);
1620 }
1621
1622 Ok(())
1623 }
1624
1625 #[cfg(not(feature = "tracing"))]
1626 fn create(
1627 &mut self,
1628 caller: H160,
1629 scheme: CreateScheme,
1630 value: U256,
1631 init_code: Vec<u8>,
1632 target_gas: Option<u64>,
1633 ) -> Capture<(ExitReason, Vec<u8>), Self::CreateInterrupt> {
1634 if let Err(e) = self.maybe_record_init_code_cost(&init_code) {
1635 let reason: ExitReason = e.into();
1636 emit_exit!(reason.clone());
1637 return Capture::Exit((reason, Vec::new()));
1638 }
1639 self.create_inner(caller, scheme, value, init_code, target_gas, true)
1640 }
1641
1642 #[cfg(feature = "tracing")]
1643 fn create(
1644 &mut self,
1645 caller: H160,
1646 scheme: CreateScheme,
1647 value: U256,
1648 init_code: Vec<u8>,
1649 target_gas: Option<u64>,
1650 ) -> Capture<(ExitReason, Vec<u8>), Self::CreateInterrupt> {
1651 if let Err(e) = self.maybe_record_init_code_cost(&init_code) {
1652 let reason: ExitReason = e.into();
1653 emit_exit!(reason.clone());
1654 return Capture::Exit((reason, Vec::new()));
1655 }
1656
1657 let capture = self.create_inner(caller, scheme, value, init_code, target_gas, true);
1658
1659 if let Capture::Exit((ref reason, ref return_value)) = capture {
1660 emit_exit!(reason, return_value);
1661 }
1662
1663 capture
1664 }
1665
1666 #[cfg(not(feature = "tracing"))]
1667 fn call(
1668 &mut self,
1669 code_address: H160,
1670 transfer: Option<Transfer>,
1671 input: Vec<u8>,
1672 target_gas: Option<u64>,
1673 is_static: bool,
1674 context: Context,
1675 ) -> Capture<(ExitReason, Vec<u8>), Self::CallInterrupt> {
1676 self.call_inner(
1677 code_address,
1678 transfer,
1679 input,
1680 target_gas,
1681 is_static,
1682 true,
1683 true,
1684 context,
1685 )
1686 }
1687
1688 #[cfg(feature = "tracing")]
1689 fn call(
1690 &mut self,
1691 code_address: H160,
1692 transfer: Option<Transfer>,
1693 input: Vec<u8>,
1694 target_gas: Option<u64>,
1695 is_static: bool,
1696 context: Context,
1697 ) -> Capture<(ExitReason, Vec<u8>), Self::CallInterrupt> {
1698 let capture = self.call_inner(
1699 code_address,
1700 transfer,
1701 input,
1702 target_gas,
1703 is_static,
1704 true,
1705 true,
1706 context,
1707 );
1708
1709 if let Capture::Exit((ref reason, ref return_value)) = capture {
1710 emit_exit!(reason, return_value);
1711 }
1712
1713 capture
1714 }
1715
1716 fn record_external_operation(&mut self, op: crate::ExternalOperation) -> Result<(), ExitError> {
1717 self.state.record_external_operation(op)
1718 }
1719
1720 fn blob_base_fee(&self) -> Option<u128> {
1726 if self.config.has_blob_base_fee {
1727 self.state.blob_gas_price()
1728 } else {
1729 None
1730 }
1731 }
1732
1733 fn get_blob_hash(&self, index: usize) -> Option<U256> {
1734 if self.config.has_shard_blob_transactions {
1735 self.state.get_blob_hash(index)
1736 } else {
1737 None
1738 }
1739 }
1740
1741 fn tstore(&mut self, address: H160, index: H256, value: U256) -> Result<(), ExitError> {
1742 if self.config.has_transient_storage {
1743 self.state.tstore(address, index, value)
1744 } else {
1745 Err(ExitError::InvalidCode(Opcode::TSTORE))
1746 }
1747 }
1748
1749 fn tload(&mut self, address: H160, index: H256) -> Result<U256, ExitError> {
1750 if self.config.has_transient_storage {
1751 self.state.tload(address, index)
1752 } else {
1753 Err(ExitError::InvalidCode(Opcode::TLOAD))
1754 }
1755 }
1756
1757 fn get_authority_target(&mut self, address: H160) -> Option<H160> {
1759 if self.config.has_authorization_list {
1760 self.state.get_authority_target(address)
1761 } else {
1762 None
1763 }
1764 }
1765
1766 fn authority_code(&mut self, authority: H160) -> Vec<u8> {
1776 if !self.config.has_authorization_list {
1777 return self.code(authority);
1778 }
1779 self.get_authority_target(authority).map_or_else(
1781 || self.code(authority),
1782 |target_address| self.code(target_address),
1783 )
1784 }
1785
1786 fn warm_target(&mut self, target: (H160, Option<H256>)) {
1790 match target {
1791 (address, None) => self.state.metadata_mut().access_address(address),
1792 (address, Some(key)) => self.state.metadata_mut().access_storage(address, key),
1793 }
1794 }
1795}
1796
1797struct StackExecutorHandle<'inner, 'config, 'precompiles, S, P> {
1798 executor: &'inner mut StackExecutor<'config, 'precompiles, S, P>,
1799 code_address: H160,
1800 input: &'inner [u8],
1801 gas_limit: Option<u64>,
1802 context: &'inner Context,
1803 is_static: bool,
1804}
1805
1806impl<'config, S: StackState<'config>, P: PrecompileSet> PrecompileHandle
1807 for StackExecutorHandle<'_, 'config, '_, S, P>
1808{
1809 fn call(
1812 &mut self,
1813 code_address: H160,
1814 transfer: Option<Transfer>,
1815 input: Vec<u8>,
1816 gas_limit: Option<u64>,
1817 is_static: bool,
1818 context: &Context,
1819 ) -> (ExitReason, Vec<u8>) {
1820 let target_is_cold = self.executor.is_cold(code_address, None);
1825 let delegated_designator_is_cold = self
1826 .executor
1827 .get_authority_target(code_address)
1828 .map(|target| self.executor.is_cold(target, None));
1829
1830 let gas_cost = gasometer::GasCost::Call {
1831 value: transfer.clone().map_or(U256_ZERO, |x| x.value),
1832 gas: U256::from(gas_limit.unwrap_or(u64::MAX)),
1833 target_is_cold,
1834 delegated_designator_is_cold,
1835 target_exists: self.executor.exists(code_address),
1836 };
1837
1838 let memory_cost = Some(gasometer::MemoryCost {
1840 offset: 0,
1841 len: input.len(),
1842 });
1843
1844 if let Err(error) = self
1845 .executor
1846 .state
1847 .metadata_mut()
1848 .gasometer
1849 .record_dynamic_cost(gas_cost, memory_cost)
1850 {
1851 return (ExitReason::Error(error), Vec::new());
1852 }
1853
1854 event!(PrecompileSubcall {
1855 code_address,
1856 transfer: &transfer,
1857 input: &input,
1858 target_gas: gas_limit,
1859 is_static,
1860 context
1861 });
1862
1863 match Handler::call(
1865 self.executor,
1866 code_address,
1867 transfer,
1868 input,
1869 gas_limit,
1870 is_static,
1871 context.clone(),
1872 ) {
1873 Capture::Exit((s, v)) => (s, v),
1874 Capture::Trap(rt) => {
1875 let mut call_stack: SmallVec<[TaggedRuntime; DEFAULT_CALL_STACK_CAPACITY]> =
1881 smallvec!(rt.0);
1882 let (reason, _, return_data) =
1883 self.executor.execute_with_call_stack(&mut call_stack);
1884 emit_exit!(reason, return_data)
1885 }
1886 }
1887 }
1888
1889 fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> {
1891 self.executor
1892 .state
1893 .metadata_mut()
1894 .gasometer
1895 .record_cost(cost)
1896 }
1897
1898 fn record_external_cost(
1900 &mut self,
1901 ref_time: Option<u64>,
1902 proof_size: Option<u64>,
1903 storage_growth: Option<u64>,
1904 ) -> Result<(), ExitError> {
1905 self.executor
1906 .state
1907 .record_external_cost(ref_time, proof_size, storage_growth)
1908 }
1909
1910 fn refund_external_cost(&mut self, ref_time: Option<u64>, proof_size: Option<u64>) {
1912 self.executor
1913 .state
1914 .refund_external_cost(ref_time, proof_size);
1915 }
1916
1917 fn remaining_gas(&self) -> u64 {
1919 self.executor.state.metadata().gasometer.gas()
1920 }
1921
1922 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
1924 Handler::log(self.executor, address, topics, data)
1925 }
1926
1927 fn code_address(&self) -> H160 {
1929 self.code_address
1930 }
1931
1932 fn input(&self) -> &[u8] {
1934 self.input
1935 }
1936
1937 fn context(&self) -> &Context {
1939 self.context
1940 }
1941
1942 fn is_static(&self) -> bool {
1944 self.is_static
1945 }
1946
1947 fn gas_limit(&self) -> Option<u64> {
1949 self.gas_limit
1950 }
1951}