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 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 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 = H256::from_slice(Keccak256::digest(&init_code).as_slice());
717 let address = self.create_address(CreateScheme::Create2 {
718 caller,
719 code_hash,
720 salt,
721 });
722 event!(TransactCreate2 {
723 caller,
724 value,
725 init_code: &init_code,
726 salt,
727 gas_limit,
728 address,
729 });
730
731 if let Err(e) = self.record_create_transaction_cost(&init_code, &access_list) {
732 return emit_exit!(e.into(), Vec::new());
733 }
734
735 self.warm_addresses_and_storage(caller, address, access_list);
736
737 match self.create_inner(
738 caller,
739 CreateScheme::Create2 {
740 caller,
741 code_hash,
742 salt,
743 },
744 value,
745 init_code,
746 Some(gas_limit),
747 false,
748 ) {
749 Capture::Exit((s, v)) => emit_exit!(s, v),
750 Capture::Trap(rt) => {
751 let mut cs: SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]> =
752 smallvec!(rt.0);
753 let (s, _, v) = self.execute_with_call_stack(&mut cs);
754 emit_exit!(s, v)
755 }
756 }
757 }
758
759 #[allow(clippy::too_many_arguments)]
765 pub fn transact_call(
766 &mut self,
767 caller: H160,
768 address: H160,
769 value: U256,
770 data: Vec<u8>,
771 gas_limit: u64,
772 access_list: Vec<(H160, Vec<H256>)>,
773 authorization_list: Vec<Authorization>,
774 ) -> (ExitReason, Vec<u8>) {
775 event!(TransactCall {
776 caller,
777 address,
778 value,
779 data: &data,
780 gas_limit,
781 });
782
783 if self.nonce(caller) >= U64_MAX {
784 return (ExitError::MaxNonce.into(), Vec::new());
785 }
786
787 let transaction_cost =
788 gasometer::call_transaction_cost(&data, &access_list, authorization_list.len());
789 let gasometer = &mut self.state.metadata_mut().gasometer;
790 match gasometer.record_transaction(transaction_cost) {
791 Ok(()) => (),
792 Err(e) => return emit_exit!(e.into(), Vec::new()),
793 }
794
795 if let Err(e) = self.state.inc_nonce(caller) {
796 return (e.into(), Vec::new());
797 }
798
799 self.warm_addresses_and_storage(caller, address, access_list);
800 if let Err(e) = self.authorized_accounts(authorization_list) {
803 return (e.into(), Vec::new());
804 }
805
806 let context = Context {
807 caller,
808 address,
809 apparent_value: value,
810 };
811
812 match self.call_inner(
813 address,
814 Some(Transfer {
815 source: caller,
816 target: address,
817 value,
818 }),
819 data,
820 Some(gas_limit),
821 false,
822 false,
823 false,
824 context,
825 ) {
826 Capture::Exit((s, v)) => emit_exit!(s, v),
827 Capture::Trap(rt) => {
828 let mut cs: SmallVec<[TaggedRuntime<'_>; DEFAULT_CALL_STACK_CAPACITY]> =
829 smallvec!(rt.0);
830 let (s, _, v) = self.execute_with_call_stack(&mut cs);
831 emit_exit!(s, v)
832 }
833 }
834 }
835
836 pub fn used_gas(&self) -> u64 {
838 let refunded_gas =
840 u64::try_from(self.state.metadata().gasometer.refunded_gas()).unwrap_or_default();
841 let total_used_gas = self.state.metadata().gasometer.total_used_gas();
842 let total_used_gas_refunded = self.state.metadata().gasometer.total_used_gas()
843 - min(
844 total_used_gas / self.config.max_refund_quotient,
845 refunded_gas,
846 );
847 if self.config.has_floor_gas
849 && total_used_gas_refunded < self.state.metadata().gasometer.floor_gas()
850 {
851 self.state.metadata().gasometer.floor_gas()
852 } else {
853 total_used_gas_refunded
854 }
855 }
856
857 pub fn fee(&self, price: U256) -> U256 {
859 let used_gas = self.used_gas();
860 U256::from(used_gas).saturating_mul(price)
861 }
862
863 pub fn nonce(&self, address: H160) -> U256 {
866 self.state.basic(address).nonce
867 }
868
869 pub fn is_create_collision(&self, address: H160) -> bool {
872 !self.code(address).is_empty()
873 || self.nonce(address) > U256_ZERO
874 || !self.state.is_empty_storage(address)
875 }
876
877 pub fn create_address(&self, scheme: CreateScheme) -> H160 {
879 match scheme {
880 CreateScheme::Create2 {
881 caller,
882 code_hash,
883 salt,
884 } => {
885 let mut hasher = Keccak256::new();
886 hasher.update([0xff]);
887 hasher.update(&caller[..]);
888 hasher.update(&salt[..]);
889 hasher.update(&code_hash[..]);
890 H256::from_slice(hasher.finalize().as_slice()).into()
891 }
892 CreateScheme::Legacy { caller } => {
893 let nonce = self.nonce(caller);
894 let mut stream = rlp::RlpStream::new_list(2);
895 stream.append(&caller);
896 stream.append(&nonce);
897 H256::from_slice(Keccak256::digest(stream.out()).as_slice()).into()
898 }
899 CreateScheme::Fixed(address) => address,
900 }
901 }
902
903 pub fn warm_access_list(&mut self, access_list: Vec<(H160, Vec<H256>)>) {
908 let addresses = access_list.iter().map(|a| a.0);
909 self.state.metadata_mut().access_addresses(addresses);
910
911 let storage_keys = access_list
912 .into_iter()
913 .flat_map(|(address, keys)| keys.into_iter().map(move |key| (address, key)));
914 self.state.metadata_mut().access_storages(storage_keys);
915 }
916
917 fn warm_addresses_and_storage(
929 &mut self,
930 caller: H160,
931 address: H160,
932 access_list: Vec<(H160, Vec<H256>)>,
933 ) {
934 if self.config.increase_state_access_gas {
935 if self.config.warm_coinbase_address {
936 let coinbase = self.block_coinbase();
938 self.state
939 .metadata_mut()
940 .access_addresses([caller, address, coinbase].iter().copied());
941 } else {
942 self.state
943 .metadata_mut()
944 .access_addresses([caller, address].iter().copied());
945 };
946
947 self.warm_access_list(access_list);
948 }
949 }
950
951 fn authorized_accounts(
972 &mut self,
973 authorization_list: Vec<Authorization>,
974 ) -> Result<(), ExitError> {
975 if !self.config.has_authorization_list {
976 return Ok(());
977 }
978 let mut refunded_accounts = 0;
979
980 let state = self.state_mut();
981 let mut warm_authority: Vec<H160> = Vec::with_capacity(authorization_list.len());
982 for authority in authorization_list {
983 if !authority.is_valid {
985 continue;
986 }
987
988 if U256::from(authority.nonce) >= U64_MAX {
990 continue;
991 }
992
993 warm_authority.push(authority.authority);
995 let authority_code = state.code(authority.authority);
997 if !authority_code.is_empty() && !Authorization::is_delegated(&authority_code) {
998 continue;
999 }
1000
1001 if state.basic(authority.authority).nonce != U256::from(authority.nonce) {
1003 continue;
1004 }
1005
1006 if !state.is_empty(authority.authority) {
1008 refunded_accounts += 1;
1009 }
1010 let delegation_clearing = if authority.address.is_zero() {
1014 state.set_code(authority.authority, Vec::new());
1015 true
1016 } else {
1017 state.set_code(authority.authority, authority.delegation_code());
1018 false
1019 };
1020 state.inc_nonce(authority.authority)?;
1022
1023 if delegation_clearing {
1025 state.metadata_mut().remove_authority(authority.authority);
1026 } else {
1027 state
1028 .metadata_mut()
1029 .add_authority(authority.authority, authority.address);
1030 }
1031 }
1032 self.state
1034 .metadata_mut()
1035 .access_addresses(warm_authority.into_iter());
1036
1037 self.state
1038 .metadata_mut()
1039 .gasometer
1040 .record_authority_refund(refunded_accounts)
1041 }
1042
1043 fn calc_gas_limit_and_record(
1045 &mut self,
1046 target_gas: Option<u64>,
1047 take_l64: bool,
1048 ) -> Result<u64, ExitError> {
1049 let initial_after_gas = self.state.metadata().gasometer.gas();
1050 let after_gas = if take_l64 && self.config.call_l64_after_gas {
1051 if self.config.estimate {
1052 let diff = initial_after_gas - l64(initial_after_gas);
1053 self.state.metadata_mut().gasometer.record_cost(diff)?;
1054 initial_after_gas
1055 } else {
1056 l64(initial_after_gas)
1057 }
1058 } else {
1059 initial_after_gas
1060 };
1061 let target_gas = target_gas.unwrap_or(after_gas);
1062 let gas_limit = min(target_gas, after_gas);
1063 self.state.metadata_mut().gasometer.record_cost(gas_limit)?;
1064 Ok(gas_limit)
1065 }
1066
1067 fn create_inner(
1068 &mut self,
1069 caller: H160,
1070 scheme: CreateScheme,
1071 value: U256,
1072 init_code: Vec<u8>,
1073 target_gas: Option<u64>,
1074 take_l64: bool,
1075 ) -> Capture<(ExitReason, Vec<u8>), StackExecutorCreateInterrupt<'static>> {
1076 if self.nonce(caller) >= U64_MAX {
1077 return Capture::Exit((ExitError::MaxNonce.into(), Vec::new()));
1078 }
1079
1080 let address = self.create_address(scheme);
1082 self.state
1083 .metadata_mut()
1084 .access_addresses([caller, address].iter().copied());
1085
1086 event!(Create {
1087 caller,
1088 address,
1089 scheme,
1090 value,
1091 init_code: &init_code,
1092 target_gas
1093 });
1094
1095 if let Some(depth) = self.state.metadata().depth {
1096 if depth + 1 > self.config.call_stack_limit {
1100 return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
1101 }
1102 }
1103
1104 if self.balance(caller) < value {
1106 return Capture::Exit((ExitError::OutOfFund.into(), Vec::new()));
1107 }
1108
1109 let gas_limit = try_or_fail!(self.calc_gas_limit_and_record(target_gas, take_l64));
1110
1111 try_or_fail!(self.state.inc_nonce(caller));
1113
1114 if self.is_create_collision(address) {
1116 return Capture::Exit((ExitError::CreateCollision.into(), Vec::new()));
1117 }
1118
1119 self.enter_substate(gas_limit, false);
1121
1122 if self.config.create_increase_nonce {
1124 try_or_fail!(self.state.inc_nonce(address));
1125 }
1126
1127 let transfer = Transfer {
1129 source: caller,
1130 target: address,
1131 value,
1132 };
1133 match self.state.transfer(transfer) {
1134 Ok(()) => (),
1135 Err(e) => {
1136 let _ = self.exit_substate(&StackExitKind::Reverted);
1137 return Capture::Exit((ExitReason::Error(e), Vec::new()));
1138 }
1139 }
1140 self.state.set_created(address);
1143
1144 let context = Context {
1146 address,
1147 caller,
1148 apparent_value: value,
1149 };
1150 let runtime = Runtime::new(
1151 Rc::new(init_code),
1152 Rc::new(Vec::new()),
1153 context,
1154 self.config.stack_limit,
1155 self.config.memory_limit,
1156 );
1157
1158 Capture::Trap(StackExecutorCreateInterrupt(TaggedRuntime {
1160 kind: RuntimeKind::Create(address),
1161 inner: MaybeBorrowed::Owned(runtime),
1162 }))
1163 }
1164
1165 #[allow(clippy::too_many_arguments, clippy::too_many_lines)]
1166 fn call_inner(
1167 &mut self,
1168 code_address: H160,
1169 transfer: Option<Transfer>,
1170 input: Vec<u8>,
1171 target_gas: Option<u64>,
1172 is_static: bool,
1173 take_l64: bool,
1174 take_stipend: bool,
1175 context: Context,
1176 ) -> Capture<(ExitReason, Vec<u8>), StackExecutorCallInterrupt<'static>> {
1177 event!(Call {
1178 code_address,
1179 transfer: &transfer,
1180 input: &input,
1181 target_gas,
1182 is_static,
1183 context: &context,
1184 });
1185
1186 let mut gas_limit = try_or_fail!(self.calc_gas_limit_and_record(target_gas, take_l64));
1187
1188 if let Some(transfer) = transfer.as_ref() {
1189 if take_stipend && transfer.value != U256_ZERO {
1190 gas_limit = gas_limit.saturating_add(self.config.call_stipend);
1191 }
1192 }
1193
1194 let code = self.authority_code(code_address);
1197 if let Some(target_address) = self.get_authority_target(code_address) {
1199 self.warm_target((target_address, None));
1200 }
1201
1202 self.enter_substate(gas_limit, is_static);
1203 self.state.touch(context.address);
1204
1205 if let Some(depth) = self.state.metadata().depth {
1206 if depth > self.config.call_stack_limit {
1207 let _ = self.exit_substate(&StackExitKind::Reverted);
1208 return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
1209 }
1210 }
1211
1212 if let Some(transfer) = transfer {
1214 match self.state.transfer(transfer) {
1215 Ok(()) => (),
1216 Err(e) => {
1217 let _ = self.exit_substate(&StackExitKind::Reverted);
1218 return Capture::Exit((ExitReason::Error(e), Vec::new()));
1219 }
1220 }
1221 }
1222
1223 let precompile_is_static = self.state.metadata().is_static();
1227 if let Some(result) = self.precompile_set.execute(&mut StackExecutorHandle {
1228 executor: self,
1229 code_address,
1230 input: &input,
1231 gas_limit: Some(gas_limit),
1232 context: &context,
1233 is_static: precompile_is_static,
1234 }) {
1235 return match result {
1236 Ok(PrecompileOutput {
1237 exit_status,
1238 output,
1239 }) => {
1240 let _ = self.exit_substate(&StackExitKind::Succeeded);
1241 Capture::Exit((ExitReason::Succeed(exit_status), output))
1242 }
1243 Err(PrecompileFailure::Error { exit_status }) => {
1244 let _ = self.exit_substate(&StackExitKind::Failed);
1245 Capture::Exit((ExitReason::Error(exit_status), Vec::new()))
1246 }
1247 Err(PrecompileFailure::Revert {
1248 exit_status,
1249 output,
1250 }) => {
1251 let _ = self.exit_substate(&StackExitKind::Reverted);
1252 Capture::Exit((ExitReason::Revert(exit_status), output))
1253 }
1254 Err(PrecompileFailure::Fatal { exit_status }) => {
1255 self.state.metadata_mut().gasometer.fail();
1256 let _ = self.exit_substate(&StackExitKind::Failed);
1257 Capture::Exit((ExitReason::Fatal(exit_status), Vec::new()))
1258 }
1259 };
1260 }
1261
1262 let runtime = Runtime::new(
1263 Rc::new(code),
1264 Rc::new(input),
1265 context,
1266 self.config.stack_limit,
1267 self.config.memory_limit,
1268 );
1269
1270 Capture::Trap(StackExecutorCallInterrupt(TaggedRuntime {
1271 kind: RuntimeKind::Call(code_address),
1272 inner: MaybeBorrowed::Owned(runtime),
1273 }))
1274 }
1275
1276 fn exit_substate_for_create(
1277 &mut self,
1278 created_address: H160,
1279 reason: ExitReason,
1280 return_data: Vec<u8>,
1281 ) -> (ExitReason, Option<H160>, Vec<u8>) {
1282 fn check_first_byte_eof_magic(config: &Config, code: &[u8]) -> Result<(), ExitError> {
1284 if config.disallow_executable_format && Some(&0xEF) == code.first() {
1285 return Err(ExitError::CreateContractStartingWithEF);
1286 }
1287 Ok(())
1288 }
1289
1290 log::debug!(target: "evm", "Create execution using address {}: {:?}", created_address, reason);
1291
1292 match reason {
1293 ExitReason::Succeed(s) => {
1294 let out = return_data;
1295 let address = created_address;
1296 if let Err(e) = check_first_byte_eof_magic(self.config, &out) {
1298 self.state.metadata_mut().gasometer.fail();
1299 let _ = self.exit_substate(&StackExitKind::Failed);
1300 return (e.into(), None, Vec::new());
1301 }
1302
1303 if let Some(limit) = self.config.create_contract_limit {
1304 if out.len() > limit {
1305 self.state.metadata_mut().gasometer.fail();
1306 let _ = self.exit_substate(&StackExitKind::Failed);
1307 return (ExitError::CreateContractLimit.into(), None, Vec::new());
1308 }
1309 }
1310
1311 match self
1312 .state
1313 .metadata_mut()
1314 .gasometer
1315 .record_deposit(out.len())
1316 {
1317 Ok(()) => {
1318 let exit_result = self.exit_substate(&StackExitKind::Succeeded);
1319 event!(CreateOutput {
1320 address,
1321 code: &out,
1322 });
1323 self.state.set_code(address, out);
1324 if let Err(e) = exit_result {
1325 return (e.into(), None, Vec::new());
1326 }
1327 (ExitReason::Succeed(s), Some(address), Vec::new())
1328 }
1329 Err(e) => {
1330 let _ = self.exit_substate(&StackExitKind::Failed);
1331 (ExitReason::Error(e), None, Vec::new())
1332 }
1333 }
1334 }
1335 ExitReason::Error(e) => {
1336 self.state.metadata_mut().gasometer.fail();
1337 let _ = self.exit_substate(&StackExitKind::Failed);
1338 (ExitReason::Error(e), None, Vec::new())
1339 }
1340 ExitReason::Revert(e) => {
1341 let _ = self.exit_substate(&StackExitKind::Reverted);
1342 (ExitReason::Revert(e), None, return_data)
1343 }
1344 ExitReason::Fatal(e) => {
1345 self.state.metadata_mut().gasometer.fail();
1346 let _ = self.exit_substate(&StackExitKind::Failed);
1347 (ExitReason::Fatal(e), None, Vec::new())
1348 }
1349 }
1350 }
1351
1352 fn exit_substate_for_call(
1353 &mut self,
1354 code_address: H160,
1355 reason: &ExitReason,
1356 return_data: Vec<u8>,
1357 ) -> Vec<u8> {
1358 log::debug!(target: "evm", "Call execution using address {}: {:?}", code_address, reason);
1359 match reason {
1360 ExitReason::Succeed(_) => {
1361 let _ = self.exit_substate(&StackExitKind::Succeeded);
1362 return_data
1363 }
1364 ExitReason::Error(_) => {
1365 let _ = self.exit_substate(&StackExitKind::Failed);
1366 Vec::new()
1367 }
1368 ExitReason::Revert(_) => {
1369 let _ = self.exit_substate(&StackExitKind::Reverted);
1370 return_data
1371 }
1372 ExitReason::Fatal(_) => {
1373 self.state.metadata_mut().gasometer.fail();
1374 let _ = self.exit_substate(&StackExitKind::Failed);
1375 Vec::new()
1376 }
1377 }
1378 }
1379
1380 fn is_created(&self, address: H160) -> bool {
1382 self.state.is_created(address)
1383 }
1384}
1385
1386impl<'config, S: StackState<'config>, P: PrecompileSet> InterpreterHandler
1387 for StackExecutor<'config, '_, S, P>
1388{
1389 #[inline]
1390 fn before_bytecode(
1391 &mut self,
1392 opcode: Opcode,
1393 _pc: usize,
1394 machine: &Machine,
1395 address: &H160,
1396 ) -> Result<(), ExitError> {
1397 #[cfg(feature = "tracing")]
1398 {
1399 use crate::runtime::tracing::Event::Step;
1400 crate::runtime::tracing::with(|listener| {
1401 #[allow(clippy::used_underscore_binding)]
1402 listener.event(Step {
1403 address: *address,
1404 opcode,
1405 position: &Ok(_pc),
1406 stack: machine.stack(),
1407 memory: machine.memory(),
1408 });
1409 });
1410 }
1411
1412 #[cfg(feature = "print-debug")]
1413 println!("### {opcode}");
1414 if let Some(cost) = gasometer::static_opcode_cost(opcode) {
1415 self.state
1416 .metadata_mut()
1417 .gasometer
1418 .record_cost(u64::from(cost))?;
1419 } else {
1420 let is_static = self.state.metadata().is_static;
1421 let (gas_cost, memory_cost) = gasometer::dynamic_opcode_cost(
1422 *address,
1423 opcode,
1424 machine.stack(),
1425 is_static,
1426 self.config,
1427 self,
1428 )?;
1429
1430 self.state
1431 .metadata_mut()
1432 .gasometer
1433 .record_dynamic_cost(gas_cost, memory_cost)?;
1434 }
1435 Ok(())
1436 }
1437
1438 #[cfg(feature = "tracing")]
1439 #[inline]
1440 fn after_bytecode(
1441 &mut self,
1442 result: &Result<(), Capture<ExitReason, crate::core::Trap>>,
1443 machine: &Machine,
1444 ) {
1445 use crate::runtime::tracing::Event::StepResult;
1446 crate::runtime::tracing::with(|listener| {
1447 listener.event(StepResult {
1448 result,
1449 return_value: machine.return_value().as_slice(),
1450 });
1451 });
1452 }
1453}
1454
1455pub struct StackExecutorCallInterrupt<'borrow>(TaggedRuntime<'borrow>);
1456
1457pub struct StackExecutorCreateInterrupt<'borrow>(TaggedRuntime<'borrow>);
1458
1459impl<'config, S: StackState<'config>, P: PrecompileSet> Handler
1460 for StackExecutor<'config, '_, S, P>
1461{
1462 type CreateInterrupt = StackExecutorCreateInterrupt<'static>;
1463 type CreateFeedback = Infallible;
1464 type CallInterrupt = StackExecutorCallInterrupt<'static>;
1465 type CallFeedback = Infallible;
1466
1467 fn balance(&self, address: H160) -> U256 {
1470 self.state.basic(address).balance
1471 }
1472
1473 fn code_size(&mut self, address: H160) -> U256 {
1480 let target_code = self.code(address);
1481 U256::from(target_code.len())
1482 }
1483
1484 fn code_hash(&mut self, address: H160) -> H256 {
1491 if !self.exists(address) {
1492 return H256::default();
1493 }
1494 let code = self.code(address);
1495 H256::from_slice(Keccak256::digest(code).as_slice())
1496 }
1497
1498 fn code(&self, address: H160) -> Vec<u8> {
1500 self.state.code(address)
1501 }
1502
1503 fn storage(&self, address: H160, index: H256) -> H256 {
1505 self.state.storage(address, index)
1506 }
1507
1508 fn is_empty_storage(&self, address: H160) -> bool {
1510 self.state.is_empty(address)
1511 }
1512
1513 fn original_storage(&self, address: H160, index: H256) -> H256 {
1514 self.state
1515 .original_storage(address, index)
1516 .unwrap_or_default()
1517 }
1518
1519 fn exists(&self, address: H160) -> bool {
1521 if self.config.empty_considered_exists {
1522 self.state.exists(address)
1523 } else {
1524 self.state.exists(address) && !self.state.is_empty(address)
1525 }
1526 }
1527
1528 fn is_cold(&mut self, address: H160, maybe_index: Option<H256>) -> bool {
1529 match maybe_index {
1530 None => !self.precompile_set.is_precompile(address) && self.state.is_cold(address),
1531 Some(index) => self.state.is_storage_cold(address, index),
1532 }
1533 }
1534
1535 fn gas_left(&self) -> U256 {
1536 U256::from(self.state.metadata().gasometer.gas())
1537 }
1538
1539 fn gas_price(&self) -> U256 {
1540 self.state.gas_price()
1541 }
1542
1543 fn origin(&self) -> H160 {
1544 self.state.origin()
1545 }
1546
1547 fn block_hash(&self, number: U256) -> H256 {
1548 self.state.block_hash(number)
1549 }
1550 fn block_number(&self) -> U256 {
1551 self.state.block_number()
1552 }
1553 fn block_coinbase(&self) -> H160 {
1554 self.state.block_coinbase()
1555 }
1556 fn block_timestamp(&self) -> U256 {
1557 self.state.block_timestamp()
1558 }
1559 fn block_difficulty(&self) -> U256 {
1560 self.state.block_difficulty()
1561 }
1562 fn block_randomness(&self) -> Option<H256> {
1563 self.state.block_randomness()
1564 }
1565 fn block_gas_limit(&self) -> U256 {
1566 self.state.block_gas_limit()
1567 }
1568 fn block_base_fee_per_gas(&self) -> U256 {
1569 self.state.block_base_fee_per_gas()
1570 }
1571 fn chain_id(&self) -> U256 {
1572 self.state.chain_id()
1573 }
1574 fn deleted(&self, address: H160) -> bool {
1575 self.state.deleted(address)
1576 }
1577
1578 fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError> {
1579 self.state.set_storage(address, index, value);
1580 Ok(())
1581 }
1582
1583 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
1584 self.state.log(address, topics, data);
1585 Ok(())
1586 }
1587
1588 fn mark_delete(&mut self, address: H160, target: H160) -> Result<(), ExitError> {
1591 let is_created = self.is_created(address);
1592 if self.config.has_restricted_selfdestruct && !is_created && address == target {
1594 return Ok(());
1598 }
1599
1600 let balance = self.balance(address);
1601
1602 event!(Suicide {
1603 target,
1604 address,
1605 balance,
1606 });
1607
1608 self.state.transfer(Transfer {
1609 source: address,
1610 target,
1611 value: balance,
1612 })?;
1613 self.state.reset_balance(address);
1614 if !self.config.has_restricted_selfdestruct || self.is_created(address) {
1617 self.state.set_deleted(address);
1618 }
1619
1620 Ok(())
1621 }
1622
1623 #[cfg(not(feature = "tracing"))]
1624 fn create(
1625 &mut self,
1626 caller: H160,
1627 scheme: CreateScheme,
1628 value: U256,
1629 init_code: Vec<u8>,
1630 target_gas: Option<u64>,
1631 ) -> Capture<(ExitReason, Vec<u8>), Self::CreateInterrupt> {
1632 if let Err(e) = self.maybe_record_init_code_cost(&init_code) {
1633 let reason: ExitReason = e.into();
1634 emit_exit!(reason.clone());
1635 return Capture::Exit((reason, Vec::new()));
1636 }
1637 self.create_inner(caller, scheme, value, init_code, target_gas, true)
1638 }
1639
1640 #[cfg(feature = "tracing")]
1641 fn create(
1642 &mut self,
1643 caller: H160,
1644 scheme: CreateScheme,
1645 value: U256,
1646 init_code: Vec<u8>,
1647 target_gas: Option<u64>,
1648 ) -> Capture<(ExitReason, Vec<u8>), Self::CreateInterrupt> {
1649 if let Err(e) = self.maybe_record_init_code_cost(&init_code) {
1650 let reason: ExitReason = e.into();
1651 emit_exit!(reason.clone());
1652 return Capture::Exit((reason, Vec::new()));
1653 }
1654
1655 let capture = self.create_inner(caller, scheme, value, init_code, target_gas, true);
1656
1657 if let Capture::Exit((ref reason, ref return_value)) = capture {
1658 emit_exit!(reason, return_value);
1659 }
1660
1661 capture
1662 }
1663
1664 #[cfg(not(feature = "tracing"))]
1665 fn call(
1666 &mut self,
1667 code_address: H160,
1668 transfer: Option<Transfer>,
1669 input: Vec<u8>,
1670 target_gas: Option<u64>,
1671 is_static: bool,
1672 context: Context,
1673 ) -> Capture<(ExitReason, Vec<u8>), Self::CallInterrupt> {
1674 self.call_inner(
1675 code_address,
1676 transfer,
1677 input,
1678 target_gas,
1679 is_static,
1680 true,
1681 true,
1682 context,
1683 )
1684 }
1685
1686 #[cfg(feature = "tracing")]
1687 fn call(
1688 &mut self,
1689 code_address: H160,
1690 transfer: Option<Transfer>,
1691 input: Vec<u8>,
1692 target_gas: Option<u64>,
1693 is_static: bool,
1694 context: Context,
1695 ) -> Capture<(ExitReason, Vec<u8>), Self::CallInterrupt> {
1696 let capture = self.call_inner(
1697 code_address,
1698 transfer,
1699 input,
1700 target_gas,
1701 is_static,
1702 true,
1703 true,
1704 context,
1705 );
1706
1707 if let Capture::Exit((ref reason, ref return_value)) = capture {
1708 emit_exit!(reason, return_value);
1709 }
1710
1711 capture
1712 }
1713
1714 fn record_external_operation(&mut self, op: crate::ExternalOperation) -> Result<(), ExitError> {
1715 self.state.record_external_operation(op)
1716 }
1717
1718 fn blob_base_fee(&self) -> Option<u128> {
1724 if self.config.has_blob_base_fee {
1725 self.state.blob_gas_price()
1726 } else {
1727 None
1728 }
1729 }
1730
1731 fn get_blob_hash(&self, index: usize) -> Option<U256> {
1732 if self.config.has_shard_blob_transactions {
1733 self.state.get_blob_hash(index)
1734 } else {
1735 None
1736 }
1737 }
1738
1739 fn tstore(&mut self, address: H160, index: H256, value: U256) -> Result<(), ExitError> {
1740 if self.config.has_transient_storage {
1741 self.state.tstore(address, index, value)
1742 } else {
1743 Err(ExitError::InvalidCode(Opcode::TSTORE))
1744 }
1745 }
1746
1747 fn tload(&mut self, address: H160, index: H256) -> Result<U256, ExitError> {
1748 if self.config.has_transient_storage {
1749 self.state.tload(address, index)
1750 } else {
1751 Err(ExitError::InvalidCode(Opcode::TLOAD))
1752 }
1753 }
1754
1755 fn get_authority_target(&mut self, address: H160) -> Option<H160> {
1757 if self.config.has_authorization_list {
1758 self.state.get_authority_target(address)
1759 } else {
1760 None
1761 }
1762 }
1763
1764 fn authority_code(&mut self, authority: H160) -> Vec<u8> {
1774 if !self.config.has_authorization_list {
1775 return self.code(authority);
1776 }
1777 self.get_authority_target(authority).map_or_else(
1779 || self.code(authority),
1780 |target_address| self.code(target_address),
1781 )
1782 }
1783
1784 fn warm_target(&mut self, target: (H160, Option<H256>)) {
1788 match target {
1789 (address, None) => self.state.metadata_mut().access_address(address),
1790 (address, Some(key)) => self.state.metadata_mut().access_storage(address, key),
1791 }
1792 }
1793}
1794
1795struct StackExecutorHandle<'inner, 'config, 'precompiles, S, P> {
1796 executor: &'inner mut StackExecutor<'config, 'precompiles, S, P>,
1797 code_address: H160,
1798 input: &'inner [u8],
1799 gas_limit: Option<u64>,
1800 context: &'inner Context,
1801 is_static: bool,
1802}
1803
1804impl<'config, S: StackState<'config>, P: PrecompileSet> PrecompileHandle
1805 for StackExecutorHandle<'_, 'config, '_, S, P>
1806{
1807 fn call(
1810 &mut self,
1811 code_address: H160,
1812 transfer: Option<Transfer>,
1813 input: Vec<u8>,
1814 gas_limit: Option<u64>,
1815 is_static: bool,
1816 context: &Context,
1817 ) -> (ExitReason, Vec<u8>) {
1818 let target_is_cold = self.executor.is_cold(code_address, None);
1823 let delegated_designator_is_cold = self
1824 .executor
1825 .get_authority_target(code_address)
1826 .map(|target| self.executor.is_cold(target, None));
1827
1828 let gas_cost = gasometer::GasCost::Call {
1829 value: transfer.clone().map_or(U256_ZERO, |x| x.value),
1830 gas: U256::from(gas_limit.unwrap_or(u64::MAX)),
1831 target_is_cold,
1832 delegated_designator_is_cold,
1833 target_exists: self.executor.exists(code_address),
1834 };
1835
1836 let memory_cost = Some(gasometer::MemoryCost {
1838 offset: 0,
1839 len: input.len(),
1840 });
1841
1842 if let Err(error) = self
1843 .executor
1844 .state
1845 .metadata_mut()
1846 .gasometer
1847 .record_dynamic_cost(gas_cost, memory_cost)
1848 {
1849 return (ExitReason::Error(error), Vec::new());
1850 }
1851
1852 event!(PrecompileSubcall {
1853 code_address,
1854 transfer: &transfer,
1855 input: &input,
1856 target_gas: gas_limit,
1857 is_static,
1858 context
1859 });
1860
1861 match Handler::call(
1863 self.executor,
1864 code_address,
1865 transfer,
1866 input,
1867 gas_limit,
1868 is_static,
1869 context.clone(),
1870 ) {
1871 Capture::Exit((s, v)) => (s, v),
1872 Capture::Trap(rt) => {
1873 let mut call_stack: SmallVec<[TaggedRuntime; DEFAULT_CALL_STACK_CAPACITY]> =
1879 smallvec!(rt.0);
1880 let (reason, _, return_data) =
1881 self.executor.execute_with_call_stack(&mut call_stack);
1882 emit_exit!(reason, return_data)
1883 }
1884 }
1885 }
1886
1887 fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> {
1889 self.executor
1890 .state
1891 .metadata_mut()
1892 .gasometer
1893 .record_cost(cost)
1894 }
1895
1896 fn record_external_cost(
1898 &mut self,
1899 ref_time: Option<u64>,
1900 proof_size: Option<u64>,
1901 storage_growth: Option<u64>,
1902 ) -> Result<(), ExitError> {
1903 self.executor
1904 .state
1905 .record_external_cost(ref_time, proof_size, storage_growth)
1906 }
1907
1908 fn refund_external_cost(&mut self, ref_time: Option<u64>, proof_size: Option<u64>) {
1910 self.executor
1911 .state
1912 .refund_external_cost(ref_time, proof_size);
1913 }
1914
1915 fn remaining_gas(&self) -> u64 {
1917 self.executor.state.metadata().gasometer.gas()
1918 }
1919
1920 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError> {
1922 Handler::log(self.executor, address, topics, data)
1923 }
1924
1925 fn code_address(&self) -> H160 {
1927 self.code_address
1928 }
1929
1930 fn input(&self) -> &[u8] {
1932 self.input
1933 }
1934
1935 fn context(&self) -> &Context {
1937 self.context
1938 }
1939
1940 fn is_static(&self) -> bool {
1942 self.is_static
1943 }
1944
1945 fn gas_limit(&self) -> Option<u64> {
1947 self.gas_limit
1948 }
1949}