aurora_evm/executor/stack/
executor.rs

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/// `Authorization` contains already prepared data for EIP-7702.
62/// - `authority`is `ecrecovered` authority address.
63/// - `address` is delegation destination address.
64/// - `nonce` is the `nonce` value which `authority.nonce` should be equal.
65/// - `is_valid` is the flag that indicates the validity of the authorization. It is used to
66///   charge gas for each authorization item, but if it's invalid exclude from EVM `authority_list` flow.
67#[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    /// Create a new `Authorization` with given `authority`, `address`, and `nonce`.
77    #[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    /// Returns `true` if `authority` is delegated to `address`.
88    /// `0xef0100 ++ address`, and it is always 23 bytes.
89    #[must_use]
90    pub fn is_delegated(code: &[u8]) -> bool {
91        code.len() == 23 && code.starts_with(&[0xEF, 0x01, 0x00])
92    }
93
94    /// Get `authority` delegated `address`.
95    /// It checks, is it delegation designation (EIP-7702).
96    #[must_use]
97    pub fn get_delegated_address(code: &[u8]) -> Option<H160> {
98        if Self::is_delegated(code) {
99            // `code` size is always 23 bytes.
100            Some(H160::from_slice(&code[3..]))
101        } else {
102            None
103        }
104    }
105
106    /// Returns the delegation code as composing: `0xef0100 ++ address`.
107    /// Result code is always 23 bytes.
108    #[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    /// Add authority to the accessed authority list (EIP-7702).
146    pub fn add_authority(&mut self, authority: H160, address: H160) {
147        self.authority.insert(authority, address);
148    }
149
150    /// Remove authority from the accessed authority list (EIP-7702).
151    pub fn remove_authority(&mut self, authority: H160) {
152        self.authority.remove(&authority);
153    }
154
155    /// Get authority from the accessed authority list (EIP-7702).
156    #[must_use]
157    pub fn get_authority_target(&self, authority: H160) -> Option<H160> {
158        self.authority.get(&authority).copied()
159    }
160
161    /// Check if authority is in the accessed authority list (EIP-7702).
162    #[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    /// Swallow commit implements part of logic for `exit_commit`:
193    /// - Record opcode stipend.
194    /// - Record an explicit refund.
195    /// - Merge warmed accounts and storages
196    ///
197    /// # Errors
198    /// Return `ExitError` that is thrown by gasometer gas calculation errors.
199    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        // Merge warmed accounts and storages
205        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    /// Swallow revert implements part of logic for `exit_commit`:
223    /// - Record opcode stipend.
224    ///
225    /// # Errors
226    /// Return `ExitError` that is thrown by gasometer gas calculation errors.
227    pub fn swallow_revert(&mut self, other: &Self) -> Result<(), ExitError> {
228        self.gasometer.record_stipend(other.gasometer.gas())
229    }
230
231    /// Swallow revert implements part of logic for `exit_commit`:
232    /// At the moment, it does nothing.
233    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    /// Used for gas calculation logic.
295    /// It's most significant for `cold/warm` gas calculation as warmed addresses spent less gas.
296    #[must_use]
297    pub const fn accessed(&self) -> &Option<Accessed> {
298        &self.accessed
299    }
300
301    /// Add authority to accessed list (related to EIP-7702)
302    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    /// Remove authority from accessed list (related to EIP-7702)
309    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    /// # Errors
323    /// Return `ExitError`
324    fn exit_commit(&mut self) -> Result<(), ExitError>;
325    /// # Errors
326    /// Return `ExitError`
327    fn exit_revert(&mut self) -> Result<(), ExitError>;
328    /// # Errors
329    /// Return `ExitError`
330    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    /// # Errors
339    /// Return `ExitError`
340    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    /// # Errors
348    /// Return `ExitError`
349    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    /// # Errors
354    /// Return `ExitError`
355    fn record_external_operation(
356        &mut self,
357        #[allow(clippy::used_underscore_binding)] _op: crate::ExternalOperation,
358    ) -> Result<(), ExitError> {
359        Ok(())
360    }
361
362    /// # Errors
363    /// Return `ExitError`
364    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    /// # Errors
374    /// Return `ExitError`
375    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    /// Set tstorage value of address at index.
392    /// EIP-1153: Transient storage
393    ///
394    /// # Errors
395    /// Return `ExitError`
396    fn tstore(&mut self, address: H160, index: H256, value: U256) -> Result<(), ExitError>;
397    /// Get tstorage value of address at index.
398    /// EIP-1153: Transient storage
399    ///
400    /// # Errors
401    /// Return `ExitError`
402    fn tload(&mut self, address: H160, index: H256) -> Result<U256, ExitError>;
403
404    /// EIP-7702 - check is authority cold.
405    fn is_authority_cold(&mut self, address: H160) -> Option<bool>;
406
407    /// EIP-7702 - get authority target address.
408    fn get_authority_target(&mut self, address: H160) -> Option<H160>;
409}
410
411/// Stack-based executor.
412pub 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    /// Return a reference of the Config.
422    pub const fn config(&self) -> &'config Config {
423        self.config
424    }
425
426    /// Return a reference to the precompile set.
427    pub const fn precompiles(&self) -> &'precompiles P {
428        self.precompile_set
429    }
430
431    /// Create a new stack-based executor with given precompiles.
432    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    /// Create a substate executor from the current executor.
458    pub fn enter_substate(&mut self, gas_limit: u64, is_static: bool) {
459        self.state.enter(gas_limit, is_static);
460    }
461
462    /// Exit a substate.
463    ///
464    /// # Panics
465    /// Panic occurs if a result is an empty `substate` stack.
466    ///
467    /// # Errors
468    /// Return `ExitError`
469    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    /// Execute the runtime until it returns.
478    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    /// Execute using Runtimes on the `call_stack` until it returns.
489    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        // This `interrupt_runtime` is used to pass the runtime obtained from the
494        // `Capture::Trap` branch in the match below back to the top of the call stack.
495        // The reason we can't simply `push` the runtime directly onto the stack in the
496        // `Capture::Trap` branch is because the borrow-checker complains that the stack
497        // is already borrowed as long as we hold a pointer on the last element
498        // (i.e. the currently executing runtime).
499        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            // We're done with that runtime now, so can pop it off the call stack
546            call_stack.pop();
547            // Now pass the results from that runtime on to the next one in the stack
548            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            // Early exit if passing on the result caused an error
562            if let Err(e) = maybe_error {
563                return (e, None, Vec::new());
564            }
565        }
566    }
567
568    /// Get remaining gas.
569    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            // EIP-3860
586            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    /// Execute a `CREATE` transaction.
600    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>)>, // See EIP-2930
607    ) -> (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    /// Same as `CREATE` but uses a specified address for created smart contract.
654    #[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>)>, // See EIP-2930
663    ) -> (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    /// Execute a `CREATE2` transaction.
699    #[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>)>, // See EIP-2930
708    ) -> (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    /// Execute a `CALL` transaction with a given parameters
761    ///
762    /// ## Notes
763    /// - `access_list` associated to [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
764    /// - `authorization_list` associated to [EIP-7702: Authorized accounts](https://eips.ethereum.org/EIPS/eip-7702)
765    #[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        // EIP-7702. authorized accounts
802        // NOTE: it must be after `inc_nonce`
803        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    /// Get used gas for the current executor, given the price.
838    pub fn used_gas(&self) -> u64 {
839        // Avoid uncontrolled `u64` casting
840        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        // EIP-7623: max(total_used_gas, floor_gas)
849        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    /// Get fee needed for the current executor, given the price.
859    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    /// Get account nonce.
865    /// NOTE: we don't need to cache it as by default it's `MemoryStackState` with cache flow
866    pub fn nonce(&self, address: H160) -> U256 {
867        self.state.basic(address).nonce
868    }
869
870    /// Check if the existing account is "create collision".
871    /// [EIP-7610](https://eips.ethereum.org/EIPS/eip-7610)
872    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    /// Get the created address from given scheme.
879    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    /// According to `EIP-2930` - `access_list` should be warmed.
906    /// This function warms addresses and storage keys.
907    ///
908    /// [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
909    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    /// Warm addresses and storage keys.
920    /// - According to `EIP-2929` the addresses should be warmed:
921    ///   1. caller (tx.sender)
922    ///   2. address (tx.to or the address being created if it is a contract creation transaction)
923    /// - Warm coinbase according to `EIP-3651`
924    /// - Warm `access_list` according to `EIP-2931`
925    ///
926    /// ## References
927    /// - [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929)
928    /// - [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
929    /// - [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651)
930    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                // Warm coinbase address for EIP-3651
939                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    /// Authorized accounts behavior.
954    ///
955    /// According to `EIP-7702` behavior section should be several steps of verifications.
956    /// Current function includes steps 2.4-9 from the spec:
957    /// 2. Verify the `nonce` is less than `2**64 - 1`.
958    /// 4. Add `authority` to `accessed_addresses`
959    /// 5. Verify the code of `authority` is either empty or already delegated.
960    /// 6. Verify the `nonce` of `authority` is equal to `nonce` (of address).
961    /// 7. Add `PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST` gas to the global refund counter if authority exists in the trie.
962    /// 8. Set the code of `authority` to be `0xef0100 || address`. This is a delegation designation.
963    /// 9. Increase the `nonce` of `authority` by one.
964    ///
965    /// It means, that steps 1,3 of spec must be passed before calling this function:
966    /// 1. Verify the chain id is either 0 or the chain’s current ID.
967    /// 3. `authority = ecrecover(...)`
968    ///
969    /// See: [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702#behavior)
970    ///
971    /// ## Errors
972    /// Return error if nonce increment return error.
973    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 EIP-7702 Spec validation steps 1, 3 return false.
986            if !authority.is_valid {
987                continue;
988            }
989
990            // 2. Verify the `nonce` is less than `2**64 - 1`.
991            if U256::from(authority.nonce) >= U64_MAX {
992                continue;
993            }
994
995            // 4. Add authority to accessed_addresses (as defined in EIP-2929)
996            warm_authority.push(authority.authority);
997            // 5. Verify the code of authority is either empty or already delegated.
998            let authority_code = state.code(authority.authority);
999            if !authority_code.is_empty() && !Authorization::is_delegated(&authority_code) {
1000                continue;
1001            }
1002
1003            // 6. Verify the nonce of authority is equal to nonce.
1004            if state.basic(authority.authority).nonce != U256::from(authority.nonce) {
1005                continue;
1006            }
1007
1008            // 7. Add PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST gas to the global refund counter if authority exists in the trie.
1009            if !state.is_empty(authority.authority) {
1010                refunded_accounts += 1;
1011            }
1012            // 8. Set the code of authority to be `0xef0100 || address`. This is a delegation designation.
1013            // * As a special case, if address is 0x0000000000000000000000000000000000000000 do not write the designation.
1014            //   Clear the account’s code.
1015            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            // 9. Increase the nonce of authority by one.
1023            state.inc_nonce(authority.authority)?;
1024
1025            // Add/Remove to authority access list cache
1026            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        // Warm addresses for [Step 4].
1035        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    /// Calculate gas limit and record it in the gasometer.
1046    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        // Warm address for EIP-2929
1083        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            // As Depth incremented in `enter_substate` we must check depth counter
1099            // early to verify exceeding Stack limit. It allows avoid
1100            // issue with wrong detection `CallTooDeep` for Create.
1101            if depth + 1 > self.config.call_stack_limit {
1102                return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
1103            }
1104        }
1105
1106        // Check is transfer value is enough
1107        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        // Check nonce and increment it for caller
1114        try_or_fail!(self.state.inc_nonce(caller));
1115
1116        // Check create collision: EIP-7610
1117        if self.is_create_collision(address) {
1118            return Capture::Exit((ExitError::CreateCollision.into(), Vec::new()));
1119        }
1120
1121        // Enter to execution substate
1122        self.enter_substate(gas_limit, false);
1123
1124        // Check nonce and increment it for created address after  entering substate
1125        if self.config.create_increase_nonce {
1126            try_or_fail!(self.state.inc_nonce(address));
1127        }
1128
1129        // Transfer funds if needed
1130        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        // It needed for CANCUN hard fork EIP-6780 we should mark account as created
1143        // to handle SELFDESTRUCT in the same transaction
1144        self.state.set_created(address);
1145
1146        // Init EVM runtime in Context
1147        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        // Set Runtime kind with pre-init Runtime and return Trap, that mean continue execution
1161        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        // EIP-7702 - get delegated designation address code
1197        // Detect loop for Delegated designation
1198        let code = self.authority_code(code_address);
1199        // Warm Delegated address after access
1200        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        // Transfer funds if needed
1215        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        // At this point, the state has been modified in enter_substate to
1226        // reflect both the is_static parameter of this call and the is_static
1227        // of the caller context.
1228        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        // EIP-3541: Reject new contract code starting with the 0xEF byte (EOF Magic)
1285        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                // As of EIP-3541 code starting with 0xef cannot be deployed
1299                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    /// Check whether an address has already been created.
1383    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    /// Get account balance
1470    /// NOTE: we don't need to cache it as by default it's `MemoryStackState` with cache flow
1471    fn balance(&self, address: H160) -> U256 {
1472        self.state.basic(address).balance
1473    }
1474
1475    /// Fetch the code size of an address.
1476    /// Provide a default implementation by fetching the code.
1477    ///
1478    /// According to EIP-7702, the code size of an address is the size of the
1479    /// delegated address code size.
1480    /// <https://eips.ethereum.org/EIPS/eip-7702#delegation-designation>
1481    fn code_size(&mut self, address: H160) -> U256 {
1482        let target_code = self.code(address);
1483        U256::from(target_code.len())
1484    }
1485
1486    /// Fetch the code hash of an address.
1487    /// Provide a default implementation by fetching the code.
1488    ///
1489    /// According to EIP-7702, the code hash of an address is the hash of the
1490    /// delegated address code hash.
1491    /// <https://eips.ethereum.org/EIPS/eip-7702#delegation-designation>
1492    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    /// Get account code
1501    fn code(&self, address: H160) -> Vec<u8> {
1502        self.state.code(address)
1503    }
1504
1505    /// Get account storage by index
1506    fn storage(&self, address: H160, index: H256) -> H256 {
1507        self.state.storage(address, index)
1508    }
1509
1510    /// Check is account storage empty
1511    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    /// Check is account exists on backend side
1522    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    /// Mark account as deleted
1591    /// - SELFDESTRUCT - CANCUN hard fork: EIP-6780
1592    fn mark_delete(&mut self, address: H160, target: H160) -> Result<(), ExitError> {
1593        let is_created = self.is_created(address);
1594        // SELFDESTRUCT - CANCUN hard fork: EIP-6780 - selfdestruct only if contract is created in the same tx
1595        if self.config.has_restricted_selfdestruct && !is_created && address == target {
1596            // State is not changed:
1597            // * if we are after Cancun upgrade specify the target is
1598            // same as selfdestructed account. The balance stays unchanged.
1599            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        // For CANCUN hard fork SELFDESTRUCT (EIP-6780) state is not changed
1617        // or if SELFDESTRUCT in the same TX - account should selfdestruct
1618        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    /// Returns `None` if `Cancun` hard fork is not enabled
1721    /// via `has_blob_base_fee` config.
1722    ///
1723    /// [EIP-4844]: Shard Blob Transactions
1724    /// [EIP-7516]: BLOBBASEFEE instruction
1725    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    /// Return the target address of the authority delegation designation (EIP-7702).
1758    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    /// Get delegation designator code for the authority code.
1767    /// If the code of address is delegation designator, then retrieve code
1768    /// from the designation address for the `authority`.
1769    /// Detect delegated designation loop and return basic byte code for loop.
1770    ///
1771    /// It's related to [EIP-7702 Delegation Designation](https://eips.ethereum.org/EIPS/eip-7702#delegation-designation)
1772    /// When authority code is found, it should set delegated address to `authority_access` array for
1773    /// calculating additional gas cost. Gas must be charged for the authority address and
1774    /// for delegated address, for detection is address warm or cold.
1775    fn authority_code(&mut self, authority: H160) -> Vec<u8> {
1776        if !self.config.has_authorization_list {
1777            return self.code(authority);
1778        }
1779        // Check if it is a loop for Delegated designation
1780        self.get_authority_target(authority).map_or_else(
1781            || self.code(authority),
1782            |target_address| self.code(target_address),
1783        )
1784    }
1785
1786    // Warm target according to EIP-2929
1787    // It warm up the target address or storage value by key. If in the target tuple
1788    // the storage is `None` then it's warming up the address.
1789    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    // Perform subcall in provided context.
1810    /// Precompile specifies in which context the subcall is executed.
1811    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        // For normal calls the cost is recorded at opcode level.
1821        // Since we don't go through opcodes we need manually record the call
1822        // cost. Not doing so will make the code panic as recording the call stipend
1823        // will do an underflow.
1824        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        // We record the length of the input.
1839        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        // Perform the subcall
1864        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                // Ideally this would pass the interrupt back to the executor so it could be
1876                // handled like any other call, however the type signature of this function does
1877                // not allow it. For now we'll make a recursive call instead of making a breaking
1878                // change to the precompile API. But this means a custom precompile could still
1879                // potentially cause a stack overflow if you're not careful.
1880                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    /// Record cost to the Runtime gasometer.
1890    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    /// Record Substrate specific cost.
1899    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    /// Refund Substrate specific cost.
1911    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    /// Retrieve the remaining gas.
1918    fn remaining_gas(&self) -> u64 {
1919        self.executor.state.metadata().gasometer.gas()
1920    }
1921
1922    /// Record a log.
1923    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    /// Retrieve the code address (what is the address of the precompile being called).
1928    fn code_address(&self) -> H160 {
1929        self.code_address
1930    }
1931
1932    /// Retrieve the input data the precompile is called with.
1933    fn input(&self) -> &[u8] {
1934        self.input
1935    }
1936
1937    /// Retrieve the context in which the precompile is executed.
1938    fn context(&self) -> &Context {
1939        self.context
1940    }
1941
1942    /// Is the precompile call is done statically.
1943    fn is_static(&self) -> bool {
1944        self.is_static
1945    }
1946
1947    /// Retrieve the gas limit of this call.
1948    fn gas_limit(&self) -> Option<u64> {
1949        self.gas_limit
1950    }
1951}