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 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 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 = 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    /// Execute a `CALL` transaction with a given parameters
760    ///
761    /// ## Notes
762    /// - `access_list` associated to [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
763    /// - `authorization_list` associated to [EIP-7702: Authorized accounts](https://eips.ethereum.org/EIPS/eip-7702)
764    #[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        // EIP-7702. authorized accounts
801        // NOTE: it must be after `inc_nonce`
802        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    /// Get used gas for the current executor, given the price.
837    pub fn used_gas(&self) -> u64 {
838        // Avoid uncontrolled `u64` casting
839        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        // EIP-7623: max(total_used_gas, floor_gas)
848        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    /// Get fee needed for the current executor, given the price.
858    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    /// Get account nonce.
864    /// NOTE: we don't need to cache it as by default it's `MemoryStackState` with cache flow
865    pub fn nonce(&self, address: H160) -> U256 {
866        self.state.basic(address).nonce
867    }
868
869    /// Check if the existing account is "create collision".
870    /// [EIP-7610](https://eips.ethereum.org/EIPS/eip-7610)
871    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    /// Get the created address from given scheme.
878    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    /// According to `EIP-2930` - `access_list` should be warmed.
904    /// This function warms addresses and storage keys.
905    ///
906    /// [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
907    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    /// Warm addresses and storage keys.
918    /// - According to `EIP-2929` the addresses should be warmed:
919    ///   1. caller (tx.sender)
920    ///   2. address (tx.to or the address being created if it is a contract creation transaction)
921    /// - Warm coinbase according to `EIP-3651`
922    /// - Warm `access_list` according to `EIP-2931`
923    ///
924    /// ## References
925    /// - [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929)
926    /// - [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930)
927    /// - [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651)
928    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                // Warm coinbase address for EIP-3651
937                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    /// Authorized accounts behavior.
952    ///
953    /// According to `EIP-7702` behavior section should be several steps of verifications.
954    /// Current function includes steps 2.4-9 from the spec:
955    /// 2. Verify the `nonce` is less than `2**64 - 1`.
956    /// 4. Add `authority` to `accessed_addresses`
957    /// 5. Verify the code of `authority` is either empty or already delegated.
958    /// 6. Verify the `nonce` of `authority` is equal to `nonce` (of address).
959    /// 7. Add `PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST` gas to the global refund counter if authority exists in the trie.
960    /// 8. Set the code of `authority` to be `0xef0100 || address`. This is a delegation designation.
961    /// 9. Increase the `nonce` of `authority` by one.
962    ///
963    /// It means, that steps 1,3 of spec must be passed before calling this function:
964    /// 1. Verify the chain id is either 0 or the chain’s current ID.
965    /// 3. `authority = ecrecover(...)`
966    ///
967    /// See: [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702#behavior)
968    ///
969    /// ## Errors
970    /// Return error if nonce increment return error.
971    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 EIP-7702 Spec validation steps 1, 3 return false.
984            if !authority.is_valid {
985                continue;
986            }
987
988            // 2. Verify the `nonce` is less than `2**64 - 1`.
989            if U256::from(authority.nonce) >= U64_MAX {
990                continue;
991            }
992
993            // 4. Add authority to accessed_addresses (as defined in EIP-2929)
994            warm_authority.push(authority.authority);
995            // 5. Verify the code of authority is either empty or already delegated.
996            let authority_code = state.code(authority.authority);
997            if !authority_code.is_empty() && !Authorization::is_delegated(&authority_code) {
998                continue;
999            }
1000
1001            // 6. Verify the nonce of authority is equal to nonce.
1002            if state.basic(authority.authority).nonce != U256::from(authority.nonce) {
1003                continue;
1004            }
1005
1006            // 7. Add PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST gas to the global refund counter if authority exists in the trie.
1007            if !state.is_empty(authority.authority) {
1008                refunded_accounts += 1;
1009            }
1010            // 8. Set the code of authority to be `0xef0100 || address`. This is a delegation designation.
1011            // * As a special case, if address is 0x0000000000000000000000000000000000000000 do not write the designation.
1012            //   Clear the account’s code.
1013            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            // 9. Increase the nonce of authority by one.
1021            state.inc_nonce(authority.authority)?;
1022
1023            // Add/Remove to authority access list cache
1024            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        // Warm addresses for [Step 4].
1033        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    /// Calculate gas limit and record it in the gasometer.
1044    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        // Warm address for EIP-2929
1081        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            // As Depth incremented in `enter_substate` we must check depth counter
1097            // early to verify exceeding Stack limit. It allows avoid
1098            // issue with wrong detection `CallTooDeep` for Create.
1099            if depth + 1 > self.config.call_stack_limit {
1100                return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new()));
1101            }
1102        }
1103
1104        // Check is transfer value is enough
1105        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        // Check nonce and increment it for caller
1112        try_or_fail!(self.state.inc_nonce(caller));
1113
1114        // Check create collision: EIP-7610
1115        if self.is_create_collision(address) {
1116            return Capture::Exit((ExitError::CreateCollision.into(), Vec::new()));
1117        }
1118
1119        // Enter to execution substate
1120        self.enter_substate(gas_limit, false);
1121
1122        // Check nonce and increment it for created address after  entering substate
1123        if self.config.create_increase_nonce {
1124            try_or_fail!(self.state.inc_nonce(address));
1125        }
1126
1127        // Transfer funds if needed
1128        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        // It needed for CANCUN hard fork EIP-6780 we should mark account as created
1141        // to handle SELFDESTRUCT in the same transaction
1142        self.state.set_created(address);
1143
1144        // Init EVM runtime in Context
1145        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        // Set Runtime kind with pre-init Runtime and return Trap, that mean continue execution
1159        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        // EIP-7702 - get delegated designation address code
1195        // Detect loop for Delegated designation
1196        let code = self.authority_code(code_address);
1197        // Warm Delegated address after access
1198        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        // Transfer funds if needed
1213        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        // At this point, the state has been modified in enter_substate to
1224        // reflect both the is_static parameter of this call and the is_static
1225        // of the caller context.
1226        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        // EIP-3541: Reject new contract code starting with the 0xEF byte (EOF Magic)
1283        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                // As of EIP-3541 code starting with 0xef cannot be deployed
1297                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    /// Check whether an address has already been created.
1381    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    /// Get account balance
1468    /// NOTE: we don't need to cache it as by default it's `MemoryStackState` with cache flow
1469    fn balance(&self, address: H160) -> U256 {
1470        self.state.basic(address).balance
1471    }
1472
1473    /// Fetch the code size of an address.
1474    /// Provide a default implementation by fetching the code.
1475    ///
1476    /// According to EIP-7702, the code size of an address is the size of the
1477    /// delegated address code size.
1478    /// <https://eips.ethereum.org/EIPS/eip-7702#delegation-designation>
1479    fn code_size(&mut self, address: H160) -> U256 {
1480        let target_code = self.code(address);
1481        U256::from(target_code.len())
1482    }
1483
1484    /// Fetch the code hash of an address.
1485    /// Provide a default implementation by fetching the code.
1486    ///
1487    /// According to EIP-7702, the code hash of an address is the hash of the
1488    /// delegated address code hash.
1489    /// <https://eips.ethereum.org/EIPS/eip-7702#delegation-designation>
1490    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    /// Get account code
1499    fn code(&self, address: H160) -> Vec<u8> {
1500        self.state.code(address)
1501    }
1502
1503    /// Get account storage by index
1504    fn storage(&self, address: H160, index: H256) -> H256 {
1505        self.state.storage(address, index)
1506    }
1507
1508    /// Check is account storage empty
1509    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    /// Check is account exists on backend side
1520    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    /// Mark account as deleted
1589    /// - SELFDESTRUCT - CANCUN hard fork: EIP-6780
1590    fn mark_delete(&mut self, address: H160, target: H160) -> Result<(), ExitError> {
1591        let is_created = self.is_created(address);
1592        // SELFDESTRUCT - CANCUN hard fork: EIP-6780 - selfdestruct only if contract is created in the same tx
1593        if self.config.has_restricted_selfdestruct && !is_created && address == target {
1594            // State is not changed:
1595            // * if we are after Cancun upgrade specify the target is
1596            // same as selfdestructed account. The balance stays unchanged.
1597            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        // For CANCUN hard fork SELFDESTRUCT (EIP-6780) state is not changed
1615        // or if SELFDESTRUCT in the same TX - account should selfdestruct
1616        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    /// Returns `None` if `Cancun` hard fork is not enabled
1719    /// via `has_blob_base_fee` config.
1720    ///
1721    /// [EIP-4844]: Shard Blob Transactions
1722    /// [EIP-7516]: BLOBBASEFEE instruction
1723    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    /// Return the target address of the authority delegation designation (EIP-7702).
1756    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    /// Get delegation designator code for the authority code.
1765    /// If the code of address is delegation designator, then retrieve code
1766    /// from the designation address for the `authority`.
1767    /// Detect delegated designation loop and return basic byte code for loop.
1768    ///
1769    /// It's related to [EIP-7702 Delegation Designation](https://eips.ethereum.org/EIPS/eip-7702#delegation-designation)
1770    /// When authority code is found, it should set delegated address to `authority_access` array for
1771    /// calculating additional gas cost. Gas must be charged for the authority address and
1772    /// for delegated address, for detection is address warm or cold.
1773    fn authority_code(&mut self, authority: H160) -> Vec<u8> {
1774        if !self.config.has_authorization_list {
1775            return self.code(authority);
1776        }
1777        // Check if it is a loop for Delegated designation
1778        self.get_authority_target(authority).map_or_else(
1779            || self.code(authority),
1780            |target_address| self.code(target_address),
1781        )
1782    }
1783
1784    // Warm target according to EIP-2929
1785    // It warm up the target address or storage value by key. If in the target tuple
1786    // the storage is `None` then it's warming up the address.
1787    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    // Perform subcall in provided context.
1808    /// Precompile specifies in which context the subcall is executed.
1809    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        // For normal calls the cost is recorded at opcode level.
1819        // Since we don't go through opcodes we need manually record the call
1820        // cost. Not doing so will make the code panic as recording the call stipend
1821        // will do an underflow.
1822        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        // We record the length of the input.
1837        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        // Perform the subcall
1862        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                // Ideally this would pass the interrupt back to the executor so it could be
1874                // handled like any other call, however the type signature of this function does
1875                // not allow it. For now we'll make a recursive call instead of making a breaking
1876                // change to the precompile API. But this means a custom precompile could still
1877                // potentially cause a stack overflow if you're not careful.
1878                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    /// Record cost to the Runtime gasometer.
1888    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    /// Record Substrate specific cost.
1897    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    /// Refund Substrate specific cost.
1909    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    /// Retrieve the remaining gas.
1916    fn remaining_gas(&self) -> u64 {
1917        self.executor.state.metadata().gasometer.gas()
1918    }
1919
1920    /// Record a log.
1921    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    /// Retrieve the code address (what is the address of the precompile being called).
1926    fn code_address(&self) -> H160 {
1927        self.code_address
1928    }
1929
1930    /// Retrieve the input data the precompile is called with.
1931    fn input(&self) -> &[u8] {
1932        self.input
1933    }
1934
1935    /// Retrieve the context in which the precompile is executed.
1936    fn context(&self) -> &Context {
1937        self.context
1938    }
1939
1940    /// Is the precompile call is done statically.
1941    fn is_static(&self) -> bool {
1942        self.is_static
1943    }
1944
1945    /// Retrieve the gas limit of this call.
1946    fn gas_limit(&self) -> Option<u64> {
1947        self.gas_limit
1948    }
1949}