referrerpolicy=no-referrer-when-downgrade

pallet_revive/
exec.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{
19	AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf,
20	CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET,
21	Pallet as Contracts, RuntimeCosts,
22	access_list::{AccessEntry, AccessList, StorageOp, Warmth},
23	address::{self, AddressMapper},
24	deposit_payment::Deposit as _,
25	evm::{block_storage, fees::InfoT as _, transfer_with_dust},
26	limits,
27	metering::{ChargedAmount, Diff, FrameMeter, ResourceMeter, State, Token, TransactionMeter},
28	precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
29	primitives::{ExecConfig, ExecReturnValue, StorageDeposit},
30	runtime_decl_for_revive_api::{Decode, Encode, TypeInfo},
31	storage::{AccountIdOrAddress, AccountType, WriteOutcome},
32	tracing::if_tracing,
33	transient_storage::TransientStorage,
34};
35use alloc::{
36	collections::{BTreeMap, BTreeSet, btree_map},
37	vec::Vec,
38};
39use core::{cmp, fmt::Debug, marker::PhantomData, mem, ops::ControlFlow};
40use frame_support::{
41	Blake2_128Concat, BoundedVec, DebugNoBound, StorageHasher,
42	crypto::ecdsa::ECDSAExt,
43	defensive,
44	dispatch::DispatchResult,
45	ensure,
46	storage::{TransactionOutcome, with_transaction},
47	traits::{
48		Time,
49		fungible::{Balanced as _, Inspect, Mutate},
50		tokens::Preservation,
51	},
52	weights::Weight,
53};
54use frame_system::{
55	Pallet as System, RawOrigin,
56	pallet_prelude::{BlockNumberFor, OriginFor},
57};
58use sp_core::{
59	ConstU32, Get, H160, H256, U256,
60	ecdsa::Public as ECDSAPublic,
61	sr25519::{Public as SR25519Public, Signature as SR25519Signature},
62};
63use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
64use sp_runtime::{
65	DispatchError, SaturatedConversion,
66	traits::{BadOrigin, Saturating, TrailingZeroInput, Zero},
67};
68
69#[cfg(test)]
70mod tests;
71
72#[cfg(test)]
73pub mod mock_ext;
74
75pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
76pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
77pub type ExecResult = Result<ExecReturnValue, ExecError>;
78
79/// Type for variable sized storage key. Used for transparent hashing.
80type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
81
82const FRAME_ALWAYS_EXISTS_ON_INSTANTIATE: &str = "The return value is only `None` if no contract exists at the specified address. This cannot happen on instantiate or delegate; qed";
83
84/// Code hash of existing account without code (keccak256 hash of empty data).
85pub const EMPTY_CODE_HASH: H256 =
86	H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
87
88/// Combined key type for both fixed and variable sized storage keys.
89#[derive(Debug)]
90pub enum Key {
91	/// Variant for fixed sized keys.
92	Fix([u8; 32]),
93	/// Variant for variable sized keys.
94	Var(VarSizedKey),
95}
96
97impl Key {
98	/// Reference to the raw unhashed key.
99	pub fn unhashed(&self) -> &[u8] {
100		match self {
101			Key::Fix(v) => v.as_ref(),
102			Key::Var(v) => v.as_ref(),
103		}
104	}
105
106	/// The hashed key that has be used as actual key to the storage trie.
107	pub fn hash(&self) -> Vec<u8> {
108		match self {
109			Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
110			Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
111		}
112	}
113
114	pub fn from_fixed(v: [u8; 32]) -> Self {
115		Self::Fix(v)
116	}
117
118	pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
119		VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
120	}
121}
122
123/// Level of reentrancy protection.
124///
125/// This needs to be specifed when a contract makes a message call. This way the calling contract
126/// can specify the level of re-entrancy protection while the callee (and it's recursive callees) is
127/// executing.
128#[derive(Copy, Clone, PartialEq, Debug)]
129pub enum ReentrancyProtection {
130	/// Don't activate reentrancy protection
131	AllowReentry,
132	/// Activate strict reentrancy protection. The direct callee and none of its own recursive
133	/// callees must be the calling contract.
134	Strict,
135	/// Activate reentrancy protection where the direct callee can be the same contract as the
136	/// caller but none of the recursive callees of the callee must be the caller.
137	///
138	/// This is used for calls that transfer value but restrict gas so that the callee only has a
139	/// stipend gas amount. In Ethereum that is not sufficient for the callee to make another call.
140	/// However, due to gas scale differences that guarantee does not automatically hold in revive
141	/// and we enforce it explicitly here.
142	AllowNext,
143}
144
145/// Origin of the error.
146///
147/// Call or instantiate both called into other contracts and pass through errors happening
148/// in those to the caller. This enum is for the caller to distinguish whether the error
149/// happened during the execution of the callee or in the current execution context.
150#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
151pub enum ErrorOrigin {
152	/// Caller error origin.
153	///
154	/// The error happened in the current execution context rather than in the one
155	/// of the contract that is called into.
156	Caller,
157	/// The error happened during execution of the called contract.
158	Callee,
159}
160
161/// Error returned by contract execution.
162#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
163pub struct ExecError {
164	/// The reason why the execution failed.
165	pub error: DispatchError,
166	/// Origin of the error.
167	pub origin: ErrorOrigin,
168}
169
170impl<T: Into<DispatchError>> From<T> for ExecError {
171	fn from(error: T) -> Self {
172		Self { error: error.into(), origin: ErrorOrigin::Caller }
173	}
174}
175
176/// The type of origins supported by the revive pallet.
177#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, DebugNoBound)]
178pub enum Origin<T: Config> {
179	Root,
180	Signed(T::AccountId),
181}
182
183impl<T: Config> Origin<T> {
184	/// Creates a new Signed Caller from an AccountId.
185	pub fn from_account_id(account_id: T::AccountId) -> Self {
186		Origin::Signed(account_id)
187	}
188
189	/// Creates a new Origin from a `RuntimeOrigin`.
190	pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
191		match o.into() {
192			Ok(RawOrigin::Root) => Ok(Self::Root),
193			Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
194			_ => Err(BadOrigin.into()),
195		}
196	}
197
198	/// Returns the AccountId of a Signed Origin or an error if the origin is Root.
199	pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
200		match self {
201			Origin::Signed(id) => Ok(id),
202			Origin::Root => Err(DispatchError::RootNotAllowed),
203		}
204	}
205
206	/// Make sure that this origin is mapped.
207	///
208	/// We require an origin to be mapped in order to be used in a `Stack`. Otherwise
209	/// [`Stack::caller`] returns an address that can't be reverted to the original address.
210	fn ensure_mapped(&self) -> DispatchResult {
211		match self {
212			Self::Root => Ok(()),
213			Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
214			Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
215		}
216	}
217}
218
219/// Argument passed by a contact to describe the amount of resources allocated to a cross contact
220/// call.
221#[derive(DebugNoBound)]
222pub enum CallResources<T: Config> {
223	/// Resources are not limited
224	NoLimits,
225	/// Resources encoded using their actual values.
226	WeightDeposit { weight: Weight, deposit_limit: BalanceOf<T> },
227	/// Resources encoded as unified ethereum gas.
228	Ethereum { gas: BalanceOf<T>, add_stipend: bool },
229}
230
231impl<T: Config> CallResources<T> {
232	/// Creates a new `CallResources` with weight and deposit limits.
233	pub fn from_weight_and_deposit(weight: Weight, deposit_limit: U256) -> Self {
234		Self::WeightDeposit {
235			weight,
236			deposit_limit: deposit_limit.saturated_into::<BalanceOf<T>>(),
237		}
238	}
239
240	/// Creates a new `CallResources` from Ethereum gas limits.
241	pub fn from_ethereum_gas(gas: U256, add_stipend: bool) -> Self {
242		Self::Ethereum { gas: gas.saturated_into::<BalanceOf<T>>(), add_stipend }
243	}
244}
245
246impl<T: Config> Default for CallResources<T> {
247	fn default() -> Self {
248		Self::WeightDeposit { weight: Default::default(), deposit_limit: Default::default() }
249	}
250}
251
252/// Stored inside the `Stack` for each contract that is scheduled for termination.
253struct TerminateArgs<T: Config> {
254	/// Where to send the free balance of the terminated contract.
255	beneficiary: T::AccountId,
256	/// Triggered by the EVM opcode.
257	only_if_same_tx: bool,
258	/// The storage deposit already refunded when the termination was scheduled.
259	refunded: BalanceOf<T>,
260}
261
262/// Environment functions only available to host functions.
263pub trait Ext: PrecompileWithInfoExt {
264	/// Execute code in the current frame.
265	///
266	/// Returns the code size of the called contract.
267	fn delegate_call(
268		&mut self,
269		call_resources: &CallResources<Self::T>,
270		address: H160,
271		input_data: Vec<u8>,
272	) -> Result<(), ExecError>;
273
274	/// Register the contract for destruction at the end of the call stack.
275	///
276	/// Transfer all funds to `beneficiary`.
277	/// Contract is deleted only if it was created in the same call stack.
278	///
279	/// This function will fail if called from constructor.
280	fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
281
282	/// Returns the code hash of the contract being executed.
283	#[allow(dead_code)]
284	fn own_code_hash(&mut self) -> &H256;
285
286	/// This query is free as it does not need to load the immutable data from storage.
287	/// Useful when we need a constant time lookup of the length.
288	/// For foreign code (delegate call, EIP-7702 delegated EOA) returns the `IMMUTABLE_BYTES` cap.
289	fn immutable_data_len(&mut self) -> u32;
290
291	/// Returns the immutable data of the current contract.
292	///
293	/// Returns `Err(InvalidImmutableAccess)` if called from a constructor.
294	fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
295
296	/// Set the immutable data of the current contract.
297	///
298	/// Returns `Err(InvalidImmutableAccess)` if not called from a constructor.
299	///
300	/// Note: Requires &mut self to access the contract info.
301	fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
302}
303
304/// Environment functions which are available to pre-compiles with `HAS_CONTRACT_INFO = true`.
305pub trait PrecompileWithInfoExt: PrecompileExt {
306	/// Instantiate a contract from the given code.
307	///
308	/// Returns the original code size of the called contract.
309	/// The newly created account will be associated with `code`. `value` specifies the amount of
310	/// value transferred from the caller to the newly created account.
311	fn instantiate(
312		&mut self,
313		limits: &CallResources<Self::T>,
314		code: Code,
315		value: U256,
316		input_data: Vec<u8>,
317		salt: Option<&[u8; 32]>,
318	) -> Result<H160, ExecError>;
319}
320
321/// Environment functions which are available to all pre-compiles.
322pub trait PrecompileExt: sealing::Sealed {
323	type T: Config;
324
325	/// Charges the weight meter with the given weight.
326	fn charge(&mut self, weight: Weight) -> Result<ChargedAmount, DispatchError> {
327		self.frame_meter_mut().charge_weight_token(RuntimeCosts::Precompile(weight))
328	}
329
330	/// Reconcile an earlier gas charge with the actual weight consumed.
331	/// This updates the current weight meter to reflect the real cost of the token.
332	fn adjust_gas(&mut self, charged: ChargedAmount, actual_weight: Weight) {
333		self.frame_meter_mut()
334			.adjust_weight(charged, RuntimeCosts::Precompile(actual_weight));
335	}
336
337	/// Charges the weight meter with the given token or halts execution if not enough weight is
338	/// left.
339	#[inline]
340	fn charge_or_halt<Tok: Token<Self::T>>(
341		&mut self,
342		token: Tok,
343	) -> ControlFlow<crate::vm::evm::Halt, ChargedAmount> {
344		self.frame_meter_mut().charge_or_halt(token)
345	}
346
347	/// Call (possibly transferring some amount of funds) into the specified account.
348	fn call(
349		&mut self,
350		call_resources: &CallResources<Self::T>,
351		to: &H160,
352		value: U256,
353		input_data: Vec<u8>,
354		reentrancy: ReentrancyProtection,
355		read_only: bool,
356	) -> Result<(), ExecError>;
357
358	/// Returns the transient storage entry of the executing account for the given `key`.
359	///
360	/// Returns `None` if the `key` wasn't previously set by `set_transient_storage` or
361	/// was deleted.
362	fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
363
364	/// Returns `Some(len)` (in bytes) if a transient storage item exists at `key`.
365	///
366	/// Returns `None` if the `key` wasn't previously set by `set_transient_storage` or
367	/// was deleted.
368	fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
369
370	/// Sets the transient storage entry for the given key to the specified value. If `value` is
371	/// `None` then the storage entry is deleted.
372	fn set_transient_storage(
373		&mut self,
374		key: &Key,
375		value: Option<Vec<u8>>,
376		take_old: bool,
377	) -> Result<WriteOutcome, DispatchError>;
378
379	/// Returns the caller.
380	fn caller(&self) -> Origin<Self::T>;
381
382	/// Returns the caller of the caller.
383	fn caller_of_caller(&self) -> Origin<Self::T>;
384
385	/// Return the origin of the whole call stack.
386	fn origin(&self) -> &Origin<Self::T>;
387
388	/// Returns the account id for the given `address`.
389	fn to_account_id(&self, address: &H160) -> AccountIdOf<Self::T>;
390
391	/// Returns the code hash of the contract for the given `address`.
392	/// If not a contract but account exists then `keccak_256([])` is returned, otherwise `zero`.
393	fn code_hash(&self, address: &H160) -> H256;
394
395	/// Returns the code size of the contract at the given `address` or zero.
396	fn code_size(&self, address: &H160) -> u64;
397
398	/// Check if the caller of the current contract is the origin of the whole call stack.
399	fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool;
400
401	/// Check if the caller is origin, and this origin is root.
402	fn caller_is_root(&self, use_caller_of_caller: bool) -> bool;
403
404	/// Check if the origin of the whole call stack is root.
405	///
406	/// Unlike [`Self::caller_is_root`], this does not require the caller to be the origin: any
407	/// number of intermediate frames may sit between this contract and the original dispatch.
408	fn origin_is_root(&self) -> bool;
409
410	/// Returns a reference to the account id of the current contract.
411	fn account_id(&self) -> &AccountIdOf<Self::T>;
412
413	/// Returns a reference to the [`H160`] address of the current contract.
414	fn address(&self) -> H160 {
415		<Self::T as Config>::AddressMapper::to_address(self.account_id())
416	}
417
418	/// Returns the balance of the current contract.
419	///
420	/// The `value_transferred` is already added.
421	fn balance(&self) -> U256;
422
423	/// Returns the balance of the supplied account.
424	///
425	/// The `value_transferred` is already added.
426	fn balance_of(&self, address: &H160) -> U256;
427
428	/// Returns the value transferred along with this call.
429	fn value_transferred(&self) -> U256;
430
431	/// Returns the timestamp of the current block in seconds.
432	fn now(&self) -> U256;
433
434	/// Returns the minimum balance that is required for creating an account.
435	fn minimum_balance(&self) -> U256;
436
437	/// Deposit an event with the given topics.
438	///
439	/// There should not be any duplicates in `topics`.
440	fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
441
442	/// Returns the current block number.
443	fn block_number(&self) -> U256;
444
445	/// Returns the block hash at the given `block_number` or `None` if
446	/// `block_number` isn't within the range of the previous 256 blocks.
447	fn block_hash(&self, block_number: U256) -> Option<H256>;
448
449	/// Returns the author of the current block.
450	fn block_author(&self) -> H160;
451
452	/// Returns the block gas limit.
453	fn gas_limit(&self) -> u64;
454
455	/// Returns the chain id.
456	fn chain_id(&self) -> u64;
457
458	/// Get an immutable reference to the nested resource meter of the frame.
459	#[deprecated(note = "Renamed to `frame_meter`; this alias will be removed in future versions")]
460	fn gas_meter(&self) -> &FrameMeter<Self::T>;
461
462	/// Get a mutable reference to the nested resource meter of the frame.
463	#[deprecated(
464		note = "Renamed to `frame_meter_mut`; this alias will be removed in future versions"
465	)]
466	fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
467
468	/// Get an immutable reference to the nested resource meter of the frame.
469	fn frame_meter(&self) -> &FrameMeter<Self::T>;
470
471	/// Get a mutable reference to the nested resource meter of the frame.
472	fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T>;
473
474	/// Recovers ECDSA compressed public key based on signature and message hash.
475	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
476
477	/// Verify a sr25519 signature.
478	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
479
480	/// Returns Ethereum address from the ECDSA compressed public key.
481	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError>;
482
483	/// Tests sometimes need to modify and inspect the contract info directly.
484	#[cfg(any(test, feature = "runtime-benchmarks"))]
485	fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
486
487	/// Get a mutable reference to the transient storage.
488	/// Useful in benchmarks when it is sometimes necessary to modify and inspect the transient
489	/// storage directly.
490	#[cfg(any(feature = "runtime-benchmarks", test))]
491	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
492
493	/// Check if running in read-only context.
494	fn is_read_only(&self) -> bool;
495
496	/// Check if running as a delegate call.
497	fn is_delegate_call(&self) -> bool;
498
499	/// Returns an immutable reference to the output of the last executed call frame.
500	fn last_frame_output(&self) -> &ExecReturnValue;
501
502	/// Returns a mutable reference to the output of the last executed call frame.
503	fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
504
505	/// Copies a slice of the contract's code at `address` into the provided buffer.
506	///
507	/// EVM CODECOPY semantics:
508	/// - If `buf.len()` = 0: Nothing happens
509	/// - If `code_offset` >= code size: `len` bytes of zero are written to memory
510	/// - If `code_offset + buf.len()` extends beyond code: Available code copied, remaining bytes
511	///   are filled with zeros
512	fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize);
513
514	/// Register the caller of the current contract for destruction.
515	/// Destruction happens at the end of the call stack.
516	/// This is supposed to be used by the terminate precompile.
517	///
518	/// Transfer all funds to `beneficiary`.
519	/// Contract is deleted at the end of the call stack.
520	///
521	/// This function will fail if called from constructor.
522	fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError>;
523
524	/// Returns the effective gas price of this transaction.
525	fn effective_gas_price(&self) -> U256;
526
527	/// The amount of gas left in eth gas units.
528	fn gas_left(&self) -> u64;
529
530	/// Returns the storage entry of the executing account by the given `key`.
531	///
532	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
533	/// was deleted.
534	fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
535
536	/// Returns `Some(len)` (in bytes) if a storage item exists at `key`.
537	///
538	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
539	/// was deleted.
540	fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
541
542	/// Sets the storage entry by the given key to the specified value. If `value` is `None` then
543	/// the storage entry is deleted.
544	fn set_storage(
545		&mut self,
546		key: &Key,
547		value: Option<Vec<u8>>,
548		take_old: bool,
549	) -> Result<WriteOutcome, DispatchError>;
550
551	/// Checks if the persistent storage slot `key` was already accessed in this transaction
552	/// and inserts it otherwise, so subsequent accesses to the same slot bill as hot. Returns
553	/// the slot's [`Warmth`]. `op` is the operation being performed: a write upgrades a slot
554	/// that had only paid for a read.
555	fn touch_storage_access(&mut self, key: &Key, op: StorageOp) -> Warmth;
556
557	/// Non-mutating sibling of `touch_storage_access`: reports the persistent storage
558	/// slot's warmth without warming it.
559	fn peek_storage_access(&self, key: &Key) -> Warmth;
560
561	/// Charges `diff` from the meter.
562	fn charge_storage(&mut self, diff: &Diff) -> DispatchResult;
563}
564
565/// Describes the different functions that can be exported by an [`Executable`].
566#[derive(
567	Copy,
568	Clone,
569	PartialEq,
570	Eq,
571	Debug,
572	codec::Decode,
573	codec::Encode,
574	codec::MaxEncodedLen,
575	scale_info::TypeInfo,
576)]
577pub enum ExportedFunction {
578	/// The constructor function which is executed on deployment of a contract.
579	Constructor,
580	/// The function which is executed when a contract is called.
581	Call,
582}
583
584/// A trait that represents something that can be executed.
585///
586/// In the on-chain environment this would be represented by a vm binary module. This trait exists
587/// in order to be able to mock the vm logic for testing.
588pub trait Executable<T: Config>: Sized {
589	/// Load the executable from storage.
590	///
591	/// # Note
592	/// Charges size base load weight from the weight meter.
593	fn from_storage<S: State>(
594		code_hash: H256,
595		meter: &mut ResourceMeter<T, S>,
596	) -> Result<Self, DispatchError>;
597
598	/// Load the executable from EVM bytecode
599	fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
600
601	/// Execute the specified exported function and return the result.
602	///
603	/// When the specified function is `Constructor` the executable is stored and its
604	/// refcount incremented.
605	///
606	/// # Note
607	///
608	/// This functions expects to be executed in a storage transaction that rolls back
609	/// all of its emitted storage changes.
610	fn execute<E: Ext<T = T>>(
611		self,
612		ext: &mut E,
613		function: ExportedFunction,
614		input_data: Vec<u8>,
615	) -> ExecResult;
616
617	/// The code info of the executable.
618	fn code_info(&self) -> &CodeInfo<T>;
619
620	/// The raw code of the executable.
621	fn code(&self) -> &[u8];
622
623	/// The code hash of the executable.
624	fn code_hash(&self) -> &H256;
625}
626
627/// The complete call stack of a contract execution.
628///
629/// The call stack is initiated by either a signed origin or one of the contract RPC calls.
630/// This type implements `Ext` and by that exposes the business logic of contract execution to
631/// the runtime module which interfaces with the contract (the vm contract blob) itself.
632pub struct Stack<'a, T: Config, E> {
633	/// The origin that initiated the call stack. It could either be a Signed plain account that
634	/// holds an account id or Root.
635	///
636	/// # Note
637	///
638	/// Please note that it is possible that the id of a Signed origin belongs to a contract rather
639	/// than a plain account when being called through one of the contract RPCs where the
640	/// client can freely choose the origin. This usually makes no sense but is still possible.
641	origin: Origin<T>,
642	/// The resource meter that tracks all resource usage before the first frame starts.
643	transaction_meter: &'a mut TransactionMeter<T>,
644	/// The timestamp at the point of call stack instantiation.
645	timestamp: MomentOf<T>,
646	/// The block number at the time of call stack instantiation.
647	block_number: BlockNumberFor<T>,
648	/// The actual call stack. One entry per nested contract called/instantiated.
649	/// This does **not** include the [`Self::first_frame`].
650	frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
651	/// Statically guarantee that each call stack has at least one frame.
652	first_frame: Frame<T>,
653	/// Transient storage used to store data, which is kept for the duration of a transaction.
654	transient_storage: TransientStorage<T>,
655	/// Per-transaction cold/hot access list for storage slots (EIP-2929 style).
656	access_list: AccessList,
657	/// Global behavior determined by the creater of this stack.
658	exec_config: &'a ExecConfig<T>,
659	/// No executable is held by the struct but influences its behaviour.
660	_phantom: PhantomData<E>,
661}
662
663/// Represents one entry in the call stack.
664///
665/// For each nested contract call or instantiate one frame is created. It holds specific
666/// information for the said call and caches the in-storage `ContractInfo` data structure.
667struct Frame<T: Config> {
668	/// The address of the executing contract.
669	account_id: T::AccountId,
670	/// The cached in-storage data of the contract.
671	contract_info: CachedContract<T>,
672	/// The EVM balance transferred by the caller as part of the call.
673	value_transferred: U256,
674	/// Determines whether this is a call or instantiate frame.
675	entry_point: ExportedFunction,
676	/// The resource meter that tracks all resource usage of this frame.
677	frame_meter: FrameMeter<T>,
678	/// If `false` the contract enabled its defense against reentrance attacks.
679	allows_reentry: bool,
680	/// If `true` subsequent calls cannot modify storage.
681	read_only: bool,
682	/// The delegate call info of the currently executing frame which was spawned by
683	/// `delegate_call`.
684	delegate: Option<DelegateInfo<T>>,
685	/// The address where the code (and immutable data) originates from.
686	///
687	/// For regular contracts, this equals the contract's own address.
688	/// For delegated accounts (EIP-7702), this is the delegation target's address.
689	/// For explicit delegate_call, this is the callee's address.
690	code_address: H160,
691	/// The output of the last executed call frame.
692	last_frame_output: ExecReturnValue,
693	/// The set of contracts that were created during this call stack.
694	contracts_created: BTreeSet<T::AccountId>,
695	/// The set of contracts that are registered for destruction at the end of this call stack.
696	contracts_to_be_destroyed: BTreeMap<T::AccountId, TerminateArgs<T>>,
697}
698
699/// This structure is used to represent the arguments in a delegate call frame in order to
700/// distinguish who delegated the call and where it was delegated to.
701#[derive(Clone, DebugNoBound)]
702pub struct DelegateInfo<T: Config> {
703	/// The caller of the contract.
704	pub caller: Origin<T>,
705	/// The address of the contract the call was delegated to.
706	pub callee: H160,
707}
708
709/// When calling an address it can either lead to execution of contract code or a pre-compile.
710enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
711	/// Contract code.
712	Executable(E),
713	/// Code inside the runtime (so called pre-compile).
714	Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
715}
716
717impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
718	fn as_executable(&self) -> Option<&E> {
719		if let Self::Executable(executable) = self { Some(executable) } else { None }
720	}
721
722	fn is_pvm(&self) -> bool {
723		match self {
724			Self::Executable(e) => e.code_info().is_pvm(),
725			_ => false,
726		}
727	}
728
729	fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
730		if let Self::Precompile { instance, .. } = self { Some(instance) } else { None }
731	}
732
733	#[cfg(any(feature = "runtime-benchmarks", test))]
734	fn into_executable(self) -> Option<E> {
735		if let Self::Executable(executable) = self { Some(executable) } else { None }
736	}
737}
738
739/// Parameter passed in when creating a new `Frame`.
740///
741/// It determines whether the new frame is for a call or an instantiate.
742enum FrameArgs<'a, T: Config, E> {
743	Call {
744		/// The account id of the contract that is to be called.
745		dest: T::AccountId,
746		/// If `None` the contract info needs to be reloaded from storage.
747		cached_info: Option<ContractInfo<T>>,
748		/// This frame was created by `seal_delegate_call` and hence uses different code than
749		/// what is stored at [`Self::Call::dest`]. Its caller ([`DelegatedCall::caller`]) is the
750		/// account which called the caller contract
751		delegated_call: Option<DelegateInfo<T>>,
752	},
753	Instantiate {
754		/// The contract or signed origin which instantiates the new contract.
755		sender: T::AccountId,
756		/// The executable whose `deploy` function is run.
757		executable: E,
758		/// A salt used in the contract address derivation of the new contract.
759		salt: Option<&'a [u8; 32]>,
760		/// The input data is used in the contract address derivation of the new contract.
761		input_data: &'a [u8],
762	},
763}
764
765/// Describes the different states of a contract as contained in a `Frame`.
766enum CachedContract<T: Config> {
767	/// The cached contract is up to date with the in-storage value.
768	Cached(ContractInfo<T>),
769	/// A recursive call into the same contract did write to the contract info.
770	///
771	/// In this case the cached contract is stale and needs to be reloaded from storage.
772	Invalidated,
773	/// The frame is associated with pre-compile that has no contract info.
774	None,
775}
776
777impl<T: Config> Frame<T> {
778	/// Return the `contract_info` of the current contract.
779	fn contract_info(&mut self) -> &mut ContractInfo<T> {
780		self.contract_info.get(&self.account_id)
781	}
782
783	/// Schedule `account_id` for termination at the end of the call stack.
784	///
785	/// A contract can be scheduled more than once, for example by `System.terminate` followed by
786	/// `SELFDESTRUCT`. A later termination must never downgrade an earlier one: once any of them
787	/// is unconditional the contract is deleted, since `System.terminate` already refunded the
788	/// deposit when it was called. The refunds add up, so the transaction meter sees each one.
789	/// The `beneficiary` comes from the later termination, since it is the one the contract named
790	/// last.
791	fn schedule_termination(&mut self, account_id: T::AccountId, args: TerminateArgs<T>) {
792		match self.contracts_to_be_destroyed.entry(account_id) {
793			btree_map::Entry::Occupied(mut entry) => {
794				let old = entry.get();
795				let only_if_same_tx = old.only_if_same_tx && args.only_if_same_tx;
796				let refunded = old.refunded.saturating_add(args.refunded);
797				entry.insert(TerminateArgs { only_if_same_tx, refunded, ..args });
798			},
799			btree_map::Entry::Vacant(entry) => {
800				entry.insert(args);
801			},
802		}
803	}
804}
805
806/// Extract the contract info after loading it from storage.
807///
808/// This assumes that `load` was executed before calling this macro.
809macro_rules! get_cached_or_panic_after_load {
810	($c:expr) => {{
811		if let CachedContract::Cached(contract) = $c {
812			contract
813		} else {
814			panic!(
815				"It is impossible to remove a contract that is on the call stack;\
816				See implementations of terminate;\
817				Therefore fetching a contract will never fail while using an account id
818				that is currently active on the call stack;\
819				qed"
820			);
821		}
822	}};
823}
824
825/// Same as [`Stack::top_frame`].
826///
827/// We need this access as a macro because sometimes hiding the lifetimes behind
828/// a function won't work out.
829macro_rules! top_frame {
830	($stack:expr) => {
831		$stack.frames.last().unwrap_or(&$stack.first_frame)
832	};
833}
834
835/// Same as [`Stack::top_frame_mut`].
836///
837/// We need this access as a macro because sometimes hiding the lifetimes behind
838/// a function won't work out.
839macro_rules! top_frame_mut {
840	($stack:expr) => {
841		$stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
842	};
843}
844
845impl<T: Config> CachedContract<T> {
846	/// Return `Some(ContractInfo)` if the contract is in cached state. `None` otherwise.
847	fn into_contract(self) -> Option<ContractInfo<T>> {
848		if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
849	}
850
851	/// Return `Some(&mut ContractInfo)` if the contract is in cached state. `None` otherwise.
852	fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
853		if let CachedContract::Cached(contract) = self { Some(contract) } else { None }
854	}
855
856	/// Load the `contract_info` from storage if necessary.
857	fn load(&mut self, account_id: &T::AccountId) {
858		if let CachedContract::Invalidated = self &&
859			let Some(contract) =
860				AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
861		{
862			*self = CachedContract::Cached(contract);
863		}
864	}
865
866	/// Return the cached contract_info.
867	fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
868		self.load(account_id);
869		get_cached_or_panic_after_load!(self)
870	}
871
872	/// Set the status to invalidate if is cached.
873	fn invalidate(&mut self) {
874		if matches!(self, CachedContract::Cached(_)) {
875			*self = CachedContract::Invalidated;
876		}
877	}
878}
879
880impl<'a, T, E> Stack<'a, T, E>
881where
882	T: Config,
883	E: Executable<T>,
884{
885	/// Create and run a new call stack by calling into `dest`.
886	///
887	/// # Return Value
888	///
889	/// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)>
890	pub fn run_call(
891		origin: Origin<T>,
892		dest: H160,
893		transaction_meter: &'a mut TransactionMeter<T>,
894		value: U256,
895		input_data: Vec<u8>,
896		exec_config: &ExecConfig<T>,
897	) -> ExecResult {
898		let dest = T::AddressMapper::to_account_id(&dest);
899		if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
900			FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
901			origin.clone(),
902			transaction_meter,
903			value,
904			exec_config,
905			&input_data,
906		)? {
907			stack.run(executable, input_data).map(|_| stack.first_frame.last_frame_output)
908		} else {
909			if_tracing(|t| {
910				t.enter_child_span(
911					origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
912					T::AddressMapper::to_address(&dest),
913					None,
914					false,
915					false,
916					value,
917					&input_data,
918					Default::default(),
919				);
920			});
921
922			let result = if let Some(mock_answer) =
923				exec_config.mock_handler.as_ref().and_then(|handler| {
924					handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
925				}) {
926				Ok(mock_answer)
927			} else {
928				Self::transfer_from_origin(
929					&origin,
930					&origin,
931					&dest,
932					value,
933					transaction_meter,
934					exec_config,
935				)
936			};
937
938			if_tracing(|t| {
939				let gas_used =
940					transaction_meter.total_consumed_gas().try_into().unwrap_or(u64::MAX);
941				let weight_consumed = transaction_meter.weight_consumed();
942				match result {
943					Ok(ref output) => t.exit_child_span(&output, gas_used, weight_consumed),
944					Err(e) => {
945						t.exit_child_span_with_error(e.error.into(), gas_used, weight_consumed)
946					},
947				}
948			});
949
950			log::trace!(target: LOG_TARGET, "call finished with: {result:?}");
951
952			result
953		}
954	}
955
956	/// Create and run a new call stack by instantiating a new contract.
957	///
958	/// # Return Value
959	///
960	/// Result<(NewContractAccountId, ExecReturnValue), ExecError)>
961	pub fn run_instantiate(
962		origin: T::AccountId,
963		executable: E,
964		transaction_meter: &'a mut TransactionMeter<T>,
965		value: U256,
966		input_data: Vec<u8>,
967		salt: Option<&[u8; 32]>,
968		exec_config: &ExecConfig<T>,
969	) -> Result<(H160, ExecReturnValue), ExecError> {
970		let deployer = T::AddressMapper::to_address(&origin);
971		let (mut stack, executable) = Stack::<'_, T, E>::new(
972			FrameArgs::Instantiate {
973				sender: origin.clone(),
974				executable,
975				salt,
976				input_data: input_data.as_ref(),
977			},
978			Origin::from_account_id(origin),
979			transaction_meter,
980			value,
981			exec_config,
982			&input_data,
983		)?
984		.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
985		let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
986		let result = stack
987			.run(executable, input_data)
988			.map(|_| (address, stack.first_frame.last_frame_output));
989		if let Ok((contract, output)) = &result &&
990			!output.did_revert()
991		{
992			Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract: *contract });
993		}
994		log::trace!(target: LOG_TARGET, "instantiate finished with: {result:?}");
995		result
996	}
997
998	#[cfg(any(feature = "runtime-benchmarks", test))]
999	pub fn bench_new_call(
1000		dest: H160,
1001		origin: Origin<T>,
1002		transaction_meter: &'a mut TransactionMeter<T>,
1003		value: BalanceOf<T>,
1004		exec_config: &'a ExecConfig<T>,
1005		read_only: bool,
1006		delegate_call: bool,
1007	) -> (Self, E) {
1008		let call = Self::new(
1009			FrameArgs::Call {
1010				dest: T::AddressMapper::to_account_id(&dest),
1011				cached_info: None,
1012				delegated_call: None,
1013			},
1014			origin,
1015			transaction_meter,
1016			value.into(),
1017			exec_config,
1018			&Default::default(),
1019		)
1020		.unwrap()
1021		.unwrap();
1022		let mut stack = call.0;
1023		if read_only {
1024			stack.top_frame_mut().read_only = true;
1025		}
1026		if delegate_call {
1027			let frame = stack.top_frame_mut();
1028			frame.delegate = Some(DelegateInfo {
1029				caller: Origin::from_account_id(frame.account_id.clone()),
1030				callee: H160::zero(),
1031			});
1032		}
1033		(stack, call.1.into_executable().unwrap())
1034	}
1035
1036	/// Create a new call stack.
1037	///
1038	/// Returns `None` when calling a non existent contract. This is not an error case
1039	/// since this will result in a value transfer.
1040	fn new(
1041		args: FrameArgs<T, E>,
1042		origin: Origin<T>,
1043		transaction_meter: &'a mut TransactionMeter<T>,
1044		value: U256,
1045		exec_config: &'a ExecConfig<T>,
1046		input_data: &Vec<u8>,
1047	) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1048		origin.ensure_mapped()?;
1049		let Some((first_frame, executable)) = Self::new_frame(
1050			args,
1051			value,
1052			transaction_meter,
1053			&CallResources::NoLimits,
1054			false,
1055			true,
1056			input_data,
1057			exec_config,
1058		)?
1059		else {
1060			return Ok(None);
1061		};
1062
1063		let mut timestamp = T::Time::now();
1064		let mut block_number = <frame_system::Pallet<T>>::block_number();
1065		// if dry run with timestamp override is provided we simulate the run in a `pending` block
1066		if let Some(timestamp_override) =
1067			exec_config.is_dry_run.as_ref().and_then(|cfg| cfg.timestamp_override)
1068		{
1069			block_number = block_number.saturating_add(1u32.into());
1070			// Delta is in milliseconds; increment timestamp by one second
1071			let delta = 1000u32.into();
1072			timestamp = cmp::max(timestamp.saturating_add(delta), timestamp_override);
1073		}
1074
1075		let stack = Self {
1076			origin,
1077			transaction_meter,
1078			timestamp,
1079			block_number,
1080			first_frame,
1081			frames: Default::default(),
1082			transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
1083			access_list: AccessList::new(),
1084			exec_config,
1085			_phantom: Default::default(),
1086		};
1087		Ok(Some((stack, executable)))
1088	}
1089
1090	/// EIP-7702 chained delegation check for an account with no loadable code.
1091	///
1092	/// A chained delegation always surfaces with an empty snapshot: `set_delegation` only
1093	/// snapshots a `code_hash` when the target is a deployed contract, and a contract can
1094	/// never become delegated. So when `load_contract_with_delegation` returns no contract
1095	/// info but a delegation target, one read of the target decides: if the target is itself
1096	/// delegated, the spec resolves one hop, retrieves the target's indicator bytes
1097	/// `0xef0100 || ..`, and traps on the leading `0xef` invalid opcode. Otherwise the
1098	/// resolved code is genuinely empty and the call falls through to the transfer path.
1099	fn fail_if_chained_delegation(target: Option<H160>) -> Result<(), ExecError> {
1100		if let Some(target) = target &&
1101			AccountInfo::<T>::is_delegated(&target)
1102		{
1103			return Err(ExecError {
1104				error: <Error<T>>::ContractTrapped.into(),
1105				origin: ErrorOrigin::Callee,
1106			});
1107		}
1108		Ok(())
1109	}
1110
1111	/// Construct a new frame.
1112	///
1113	/// This does not take `self` because when constructing the first frame `self` is
1114	/// not initialized, yet.
1115	fn new_frame<S: State>(
1116		frame_args: FrameArgs<T, E>,
1117		value_transferred: U256,
1118		meter: &mut ResourceMeter<T, S>,
1119		call_resources: &CallResources<T>,
1120		read_only: bool,
1121		origin_is_caller: bool,
1122		input_data: &[u8],
1123		exec_config: &ExecConfig<T>,
1124	) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
1125		// `Some` once the account entry has been read: the delegation target it carried, so
1126		// `code_address` below does not decode the same entry a second time.
1127		let mut read_delegation: Option<Option<H160>> = None;
1128		// `Some` when this is a delegate call whose callee is an EIP-7702 delegated EOA: the
1129		// callee's delegation target, which is where the executed code (and therefore its
1130		// immutable data) lives.
1131		let mut delegate_code_target: Option<H160> = None;
1132
1133		let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
1134			FrameArgs::Call { dest, cached_info, delegated_call } => {
1135				let address = T::AddressMapper::to_address(&dest);
1136				let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
1137
1138				// which contract info to load is unaffected by the fact if this
1139				// is a delegate call or not
1140				let mut contract = match (cached_info, &precompile) {
1141					(Some(info), _) => CachedContract::Cached(info),
1142					(None, None) => {
1143						let (info, target) =
1144							AccountInfo::<T>::load_contract_with_delegation(&address);
1145						read_delegation = Some(target);
1146						if let Some(info) = info {
1147							CachedContract::Cached(info)
1148						} else {
1149							Self::fail_if_chained_delegation(target)?;
1150							return Ok(None);
1151						}
1152					},
1153					(None, Some(precompile)) if precompile.has_contract_info() => {
1154						log::trace!(target: LOG_TARGET, "found precompile for address {address:?}");
1155						let (info, target) =
1156							AccountInfo::<T>::load_contract_with_delegation(&address);
1157						read_delegation = Some(target);
1158						if let Some(info) = info {
1159							CachedContract::Cached(info)
1160						} else {
1161							let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
1162							CachedContract::Cached(info)
1163						}
1164					},
1165					// A precompile address can never be delegated: skip the `code_address`
1166					// delegation lookup below.
1167					(None, Some(_)) => {
1168						read_delegation = Some(None);
1169						CachedContract::None
1170					},
1171				};
1172
1173				let delegated_call = delegated_call.or_else(|| {
1174					exec_config.mock_handler.as_ref().and_then(|mock_handler| {
1175						mock_handler.mock_delegated_caller(address, input_data)
1176					})
1177				});
1178				// in case of delegate the executable is not the one at `address`
1179				let executable = if let Some(delegated_call) = &delegated_call {
1180					if let Some(precompile) =
1181						<AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
1182					{
1183						ExecutableOrPrecompile::Precompile {
1184							instance: precompile,
1185							_phantom: Default::default(),
1186						}
1187					} else {
1188						let (info, target) =
1189							AccountInfo::<T>::load_contract_with_delegation(&delegated_call.callee);
1190						let Some(info) = info else {
1191							Self::fail_if_chained_delegation(target)?;
1192							return Ok(None);
1193						};
1194						delegate_code_target = target;
1195						let executable = E::from_storage(info.code_hash, meter)?;
1196						ExecutableOrPrecompile::Executable(executable)
1197					}
1198				} else {
1199					if let Some(precompile) = precompile {
1200						ExecutableOrPrecompile::Precompile {
1201							instance: precompile,
1202							_phantom: Default::default(),
1203						}
1204					} else {
1205						let executable = E::from_storage(
1206							contract
1207								.as_contract()
1208								.expect("When not a precompile the contract was loaded above; qed")
1209								.code_hash,
1210							meter,
1211						)?;
1212						ExecutableOrPrecompile::Executable(executable)
1213					}
1214				};
1215
1216				(dest, contract, executable, delegated_call, ExportedFunction::Call)
1217			},
1218			FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1219				let deployer = T::AddressMapper::to_address(&sender);
1220				let account_nonce = <System<T>>::account_nonce(&sender);
1221				let address = if let Some(salt) = salt {
1222					address::create2(&deployer, executable.code(), input_data, salt)
1223				} else {
1224					use sp_runtime::Saturating;
1225					address::create1(
1226						&deployer,
1227						// the Nonce from the origin has been incremented pre-dispatch, so we
1228						// need to subtract 1 to get the nonce at the time of the call.
1229						if origin_is_caller {
1230							account_nonce.saturating_sub(1u32.into()).saturated_into()
1231						} else {
1232							account_nonce.saturated_into()
1233						},
1234					)
1235				};
1236				let contract = ContractInfo::new(
1237					&address,
1238					<System<T>>::account_nonce(&sender),
1239					*executable.code_hash(),
1240				)?;
1241				(
1242					T::AddressMapper::to_fallback_account_id(&address),
1243					CachedContract::Cached(contract),
1244					ExecutableOrPrecompile::Executable(executable),
1245					None,
1246					ExportedFunction::Constructor,
1247				)
1248			},
1249		};
1250
1251		// Compute the code_address: the address where the code (and immutable data) comes from.
1252		// For delegate_call this is the callee โ€” or the callee's delegation target when the
1253		// callee is itself a delegated EOA. For a call to an EIP-7702 delegated account it's
1254		// the delegation target, otherwise it's the account's own address.
1255		let address = T::AddressMapper::to_address(&account_id);
1256		let code_address = delegate
1257			.as_ref()
1258			.map(|d| delegate_code_target.unwrap_or(d.callee))
1259			.or_else(|| {
1260				// Constructors can't be delegated, skip the storage read.
1261				if entry_point == ExportedFunction::Constructor {
1262					return None;
1263				}
1264				read_delegation.unwrap_or_else(|| AccountInfo::<T>::get_delegation_target(&address))
1265			})
1266			.unwrap_or(address);
1267
1268		// A constructor frame creates its contract in this transaction. Marking it here covers
1269		// the first frame of `run_instantiate` as well as nested instantiations.
1270		let mut contracts_created = BTreeSet::new();
1271		if entry_point == ExportedFunction::Constructor {
1272			contracts_created.insert(account_id.clone());
1273		}
1274
1275		let frame = Frame {
1276			delegate,
1277			value_transferred,
1278			contract_info,
1279			account_id,
1280			entry_point,
1281			code_address,
1282			frame_meter: meter.new_nested(call_resources)?,
1283			allows_reentry: true,
1284			read_only,
1285			last_frame_output: Default::default(),
1286			contracts_created,
1287			contracts_to_be_destroyed: Default::default(),
1288		};
1289
1290		Ok(Some((frame, executable)))
1291	}
1292
1293	/// Create a subsequent nested frame.
1294	fn push_frame(
1295		&mut self,
1296		frame_args: FrameArgs<T, E>,
1297		value_transferred: U256,
1298		call_resources: &CallResources<T>,
1299		read_only: bool,
1300		input_data: &[u8],
1301	) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1302		if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1303			return Err(Error::<T>::MaxCallDepthReached.into());
1304		}
1305
1306		// We need to make sure that changes made to the contract info are not discarded.
1307		// See the `in_memory_changes_not_discarded` test for more information.
1308		// We do not store on instantiate because we do not allow to call into a contract
1309		// from its own constructor.
1310		//
1311		// Additionally, we need to apply pending storage changes to the ContractInfo before
1312		// saving it, so that child frames can correctly calculate storage deposit refunds.
1313		// See: <https://github.com/paritytech/contract-issues/issues/213>
1314		let frame = self.top_frame();
1315		if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1316			(&frame.contract_info, frame.entry_point)
1317		{
1318			let mut contract_with_pending_changes = contract.clone();
1319			frame
1320				.frame_meter
1321				.apply_pending_storage_changes(&mut contract_with_pending_changes);
1322			AccountInfo::<T>::insert_contract(
1323				&T::AddressMapper::to_address(&frame.account_id),
1324				contract_with_pending_changes,
1325			);
1326		}
1327
1328		let frame = top_frame_mut!(self);
1329		let meter = &mut frame.frame_meter;
1330		if let Some((frame, executable)) = Self::new_frame(
1331			frame_args,
1332			value_transferred,
1333			meter,
1334			call_resources,
1335			read_only,
1336			false,
1337			input_data,
1338			self.exec_config,
1339		)? {
1340			// EIP-684: an in-construction address is not in `AccountInfoOf` yet, so the
1341			// `is_contract` guard in `ContractInfo::new` misses this re-entrant collision.
1342			if frame.entry_point == ExportedFunction::Constructor &&
1343				self.frames().any(|f| {
1344					f.entry_point == ExportedFunction::Constructor &&
1345						f.account_id == frame.account_id
1346				}) {
1347				return Err(Error::<T>::DuplicateContract.into());
1348			}
1349			self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1350			Ok(Some(executable))
1351		} else {
1352			Ok(None)
1353		}
1354	}
1355
1356	/// Run the current (top) frame.
1357	///
1358	/// This can be either a call or an instantiate.
1359	fn run(
1360		&mut self,
1361		executable: ExecutableOrPrecompile<T, E, Self>,
1362		input_data: Vec<u8>,
1363	) -> Result<(), ExecError> {
1364		let frame = self.top_frame();
1365		let entry_point = frame.entry_point;
1366		let is_pvm = executable.is_pvm();
1367
1368		if_tracing(|tracer| {
1369			// For DELEGATECALL, `from` is the contract making the delegatecall and
1370			// `to` is the target contract whose code is being executed.
1371			let (from, to) = match frame.delegate.as_ref() {
1372				Some(delegate) => {
1373					(T::AddressMapper::to_address(&frame.account_id), delegate.callee)
1374				},
1375				None => (
1376					self.caller()
1377						.account_id()
1378						.map(T::AddressMapper::to_address)
1379						.unwrap_or_default(),
1380					T::AddressMapper::to_address(&frame.account_id),
1381				),
1382			};
1383			tracer.enter_child_span(
1384				from,
1385				to,
1386				(frame.code_address != to).then_some(frame.code_address),
1387				frame.delegate.is_some(),
1388				frame.read_only,
1389				frame.value_transferred,
1390				&input_data,
1391				frame
1392					.frame_meter
1393					.eth_gas_left()
1394					.unwrap_or_default()
1395					.try_into()
1396					.unwrap_or_default(),
1397			);
1398		});
1399		let mock_answer = self.exec_config.mock_handler.as_ref().and_then(|handler| {
1400			handler.mock_call(
1401				frame
1402					.delegate
1403					.as_ref()
1404					.map(|delegate| delegate.callee)
1405					.unwrap_or(T::AddressMapper::to_address(&frame.account_id)),
1406				&input_data,
1407				frame.value_transferred,
1408			)
1409		});
1410		// The output of the caller frame will be replaced by the output of this run.
1411		// It is also not accessible from nested frames.
1412		// Hence we drop it early to save the memory.
1413		let frames_len = self.frames.len();
1414		if let Some(caller_frame) = match frames_len {
1415			0 => None,
1416			1 => Some(&mut self.first_frame.last_frame_output),
1417			_ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1418		} {
1419			*caller_frame = Default::default();
1420		}
1421
1422		self.with_transient_storage_mut(|transient_storage| {
1423			transient_storage.start_transaction();
1424		});
1425		let is_first_frame = self.frames.is_empty();
1426		let access_list_checkpoints_len = self.access_list.frame_depth();
1427		// Open an access-list frame for nested CALL/CREATE. The first frame
1428		// is skipped; its touches land in the bare journal and persist
1429		// for the whole transaction.
1430		if !is_first_frame {
1431			self.access_list.enter_frame();
1432		}
1433
1434		let do_transaction = || -> ExecResult {
1435			let caller = self.caller();
1436			let bump_nonce = self.exec_config.bump_nonce;
1437			let frame = top_frame_mut!(self);
1438			let account_id = &frame.account_id.clone();
1439
1440			if u32::try_from(input_data.len())
1441				.map(|len| len > limits::CALLDATA_BYTES)
1442				.unwrap_or(true)
1443			{
1444				Err(<Error<T>>::CallDataTooLarge)?;
1445			}
1446
1447			// We need to make sure that the contract's account exists before calling its
1448			// constructor.
1449			if entry_point == ExportedFunction::Constructor {
1450				if !frame_system::Pallet::<T>::account_exists(&account_id) {
1451					T::Deposit::init_contract(account_id)?;
1452				}
1453
1454				// A consumer is added at account creation and removed it on termination, otherwise
1455				// the runtime could remove the account. As long as a contract exists its
1456				// account must exist. With the consumer, a correct runtime cannot remove the
1457				// account.
1458				<System<T>>::inc_consumers(account_id)?;
1459
1460				// Contracts nonce starts at 1
1461				<System<T>>::inc_account_nonce(account_id);
1462
1463				if bump_nonce || !is_first_frame {
1464					// Needs to be incremented before calling into the code so that it is visible
1465					// in case of recursion.
1466					<System<T>>::inc_account_nonce(caller.account_id()?);
1467				}
1468				// The incremented refcount should be visible to the constructor.
1469				if is_pvm {
1470					<CodeInfo<T>>::increment_refcount(
1471						*executable
1472							.as_executable()
1473							.expect("Precompiles cannot be instantiated; qed")
1474							.code_hash(),
1475					)?;
1476				}
1477			}
1478
1479			// Every non delegate call or instantiate also optionally transfers the balance.
1480			// If it is a delegate call, then we've already transferred tokens in the
1481			// last non-delegate frame.
1482			if frame.delegate.is_none() {
1483				Self::transfer_from_origin(
1484					&self.origin,
1485					&caller,
1486					account_id,
1487					frame.value_transferred,
1488					&mut frame.frame_meter,
1489					self.exec_config,
1490				)?;
1491			}
1492
1493			// We need to make sure that the pre-compiles contract exist before executing it.
1494			// A few more conditionals:
1495			// 	- Only contracts with extended API (has_contract_info) are guaranteed to have an
1496			//    account.
1497			//  - Only when not delegate calling we are executing in the context of the pre-compile.
1498			//    Pre-compiles itself cannot delegate call.
1499			if let Some(precompile) = executable.as_precompile() &&
1500				precompile.has_contract_info() &&
1501				frame.delegate.is_none() &&
1502				!<System<T>>::account_exists(account_id)
1503			{
1504				// prefix matching pre-compiles cannot have a contract info
1505				// hence we only mint once per pre-compile
1506				T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1507				// make sure the pre-compile does not destroy its account by accident
1508				<System<T>>::inc_consumers(account_id)?;
1509			}
1510
1511			let mut code_deposit = executable
1512				.as_executable()
1513				.map(|exec| exec.code_info().deposit())
1514				.unwrap_or_default();
1515
1516			let mut output = match executable {
1517				ExecutableOrPrecompile::Executable(executable) => {
1518					executable.execute(self, entry_point, input_data)
1519				},
1520				ExecutableOrPrecompile::Precompile { instance, .. } => {
1521					instance.call(input_data, self)
1522				},
1523			}
1524			.and_then(|output| {
1525				if u32::try_from(output.data.len())
1526					.map(|len| len > limits::CALLDATA_BYTES)
1527					.unwrap_or(true)
1528				{
1529					Err(<Error<T>>::ReturnDataTooLarge)?;
1530				}
1531				Ok(output)
1532			})
1533			.map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1534
1535			// Avoid useless work that would be reverted anyways.
1536			if output.did_revert() {
1537				return Ok(output);
1538			}
1539
1540			// The deposit we charge for a contract depends on the size of the immutable data.
1541			// Hence we need to delay charging the base deposit after execution.
1542			let frame = if entry_point == ExportedFunction::Constructor {
1543				let frame = top_frame_mut!(self);
1544				// if we are dealing with EVM bytecode
1545				// We upload the new runtime code, and update the code
1546				if !is_pvm {
1547					// Only keep return data for tracing and for dry runs.
1548					// When a dry-run simulates contract deployment, keep the execution result's
1549					// data.
1550					let data = if crate::tracing::if_tracing(|_| {}).is_none() &&
1551						self.exec_config.is_dry_run.is_none()
1552					{
1553						core::mem::replace(&mut output.data, Default::default())
1554					} else {
1555						output.data.clone()
1556					};
1557
1558					// Under Root there is no origin account to attribute the upload
1559					// deposit to: use the pallet's own account as a sentinel owner
1560					// with zero deposit so charge/refund are no-ops.
1561					let mut module = match &self.origin {
1562						Origin::Signed(o) => {
1563							crate::ContractBlob::<T>::from_evm_runtime_code(data, o.clone())?
1564						},
1565						Origin::Root => {
1566							crate::ContractBlob::<T>::from_evm_runtime_code_with_deposit(
1567								data,
1568								crate::Pallet::<T>::account_id(),
1569								Zero::zero(),
1570							)?
1571						},
1572					};
1573					module.store_code(&self.exec_config, &mut frame.frame_meter)?;
1574					code_deposit = module.code_info().deposit();
1575
1576					let code_hash = *module.code_hash();
1577					frame.contract_info().code_hash = code_hash;
1578					<CodeInfo<T>>::increment_refcount(code_hash)?;
1579				}
1580
1581				let deposit = frame.contract_info().update_base_deposit(code_deposit);
1582				frame.frame_meter.charge_contract_deposit_and_transfer(
1583					frame.account_id.clone(),
1584					StorageDeposit::Charge(deposit),
1585				)?;
1586				frame
1587			} else {
1588				self.top_frame_mut()
1589			};
1590
1591			// The storage deposit is only charged at the end of every call stack.
1592			// To make sure that no sub call uses more than it is allowed to,
1593			// the limit is manually enforced here.
1594			let contract = frame.contract_info.as_contract();
1595			frame
1596				.frame_meter
1597				.finalize(contract)
1598				.map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1599
1600			Ok(output)
1601		};
1602
1603		// All changes performed by the contract are executed under a storage transaction.
1604		// This allows for roll back on error. Changes to the cached contract_info are
1605		// committed or rolled back when popping the frame.
1606		//
1607		// `with_transactional` may return an error caused by a limit in the
1608		// transactional storage depth.
1609		let transaction_outcome =
1610			with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1611				let output = if let Some(mock_answer) = mock_answer {
1612					Ok(mock_answer)
1613				} else {
1614					do_transaction()
1615				};
1616				match &output {
1617					Ok(result) if !result.did_revert() => {
1618						TransactionOutcome::Commit(Ok((true, output)))
1619					},
1620					_ => TransactionOutcome::Rollback(Ok((false, output))),
1621				}
1622			});
1623
1624		let (success, output) = match transaction_outcome {
1625			// `with_transactional` executed successfully, and we have the expected output.
1626			Ok((success, output)) => {
1627				if_tracing(|tracer| {
1628					let frame_meter = &top_frame!(self).frame_meter;
1629
1630					// we treat the initial frame meter differently to address
1631					// https://github.com/paritytech/polkadot-sdk/issues/8362
1632					let gas_consumed = if is_first_frame {
1633						frame_meter.total_consumed_gas()
1634					} else {
1635						frame_meter.eth_gas_consumed()
1636					};
1637
1638					let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1639					let weight_consumed = frame_meter.weight_consumed();
1640
1641					match &output {
1642						Ok(output) => {
1643							tracer.exit_child_span(&output, gas_consumed, weight_consumed)
1644						},
1645						Err(e) => tracer.exit_child_span_with_error(
1646							e.error.into(),
1647							gas_consumed,
1648							weight_consumed,
1649						),
1650					}
1651				});
1652
1653				(success, output)
1654			},
1655			// `with_transactional` returned an error, and we propagate that error and note no state
1656			// has changed.
1657			Err(error) => {
1658				if_tracing(|tracer| {
1659					let frame_meter = &top_frame!(self).frame_meter;
1660
1661					// we treat the initial frame meter differently to address
1662					// https://github.com/paritytech/polkadot-sdk/issues/8362
1663					let gas_consumed = if is_first_frame {
1664						frame_meter.total_consumed_gas()
1665					} else {
1666						frame_meter.eth_gas_consumed()
1667					};
1668
1669					let gas_consumed: u64 = gas_consumed.try_into().unwrap_or(u64::MAX);
1670					let weight_consumed = frame_meter.weight_consumed();
1671					tracer.exit_child_span_with_error(error.into(), gas_consumed, weight_consumed);
1672				});
1673
1674				(false, Err(error.into()))
1675			},
1676		};
1677		self.with_transient_storage_mut(|transient_storage| {
1678			if success {
1679				transient_storage.commit_transaction();
1680			} else {
1681				transient_storage.rollback_transaction();
1682			}
1683		});
1684		// For the first frame, only log the final metrics since it doesn't open a
1685		// checkpoint. Nested frames commit or roll back the checkpoint they opened.
1686		if is_first_frame {
1687			let m = self.access_list.metrics();
1688			log::trace!(
1689				target: LOG_TARGET,
1690				"access list metrics: size={size} cold={cold} hot={hot}",
1691				size = m.size, cold = m.cold, hot = m.hot,
1692			);
1693		} else if success {
1694			self.access_list.commit_frame();
1695		} else {
1696			self.access_list.rollback_frame();
1697		}
1698		debug_assert_eq!(
1699			self.access_list.frame_depth(),
1700			access_list_checkpoints_len,
1701			"this frame closed exactly the checkpoint it opened",
1702		);
1703		log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1704
1705		self.pop_frame(success);
1706		output.map(|output| {
1707			self.top_frame_mut().last_frame_output = output;
1708		})
1709	}
1710
1711	/// Remove the current (top) frame from the stack.
1712	///
1713	/// This is called after running the current frame. It commits cached values to storage
1714	/// and invalidates all stale references to it that might exist further down the call stack.
1715	fn pop_frame(&mut self, persist: bool) {
1716		/// Bank the pending storage diff into the cached `ContractInfo`, then invalidate.
1717		///
1718		/// The `load` covers the case where an earlier same-contract reentry already
1719		/// invalidated this frame; without it a removal-bearing diff would be banked with
1720		/// no info and silently drop the refund pro-rata. A `None` after `load` means the
1721		/// frame is a precompile with no contract info, which has nothing to bank.
1722		fn bank_pending_changes_and_invalidate<T: Config>(f: &mut Frame<T>) {
1723			let contract = f.account_id.clone();
1724			f.contract_info.load(&f.account_id);
1725			if let Some(info) = f.contract_info.as_contract() {
1726				f.frame_meter.bank_pending_storage_changes(contract, info);
1727			}
1728			// `invalidate` drops the in-memory update `bank` made to `info`; that is safe
1729			// because storage already reflects it. Additions and `set_storage` removals leave
1730			// the frame `Cached` (write reloads the cache), so `push_frame` preview-persists
1731			// them before we get here. The only diff not yet in storage would be a removal on
1732			// an already-invalidated frame โ€” reachable solely via `charge_storage`, which has
1733			// no contract-level caller. If that changes, persist here instead of invalidating.
1734			f.contract_info.invalidate();
1735		}
1736
1737		// Pop the current frame from the stack and return it in case it needs to interact
1738		// with duplicates that might exist on the stack.
1739		// A `None` means that we are returning from the `first_frame`.
1740		let frame = self.frames.pop();
1741
1742		// Both branches do essentially the same with the exception. The difference is that
1743		// the else branch does consume the hardcoded `first_frame`.
1744		if let Some(mut frame) = frame {
1745			let account_id = &frame.account_id;
1746			let prev = top_frame_mut!(self);
1747
1748			// Only weight counter changes are persisted in case of a failure.
1749			if !persist {
1750				prev.frame_meter.absorb_weight_meter_only(frame.frame_meter);
1751				return;
1752			}
1753
1754			// Record the storage meter changes of the nested call into the parent meter.
1755			// If the dropped frame's contract has a contract info we update the deposit
1756			// counter in its contract info. The load is necessary to pull it from storage in case
1757			// it was invalidated.
1758			frame.contract_info.load(account_id);
1759			let mut contract = frame.contract_info.into_contract();
1760			prev.frame_meter
1761				.absorb_all_meters(frame.frame_meter, account_id, contract.as_mut());
1762
1763			// only on success inherit the created and to be destroyed contracts
1764			prev.contracts_created.extend(frame.contracts_created);
1765			for (account, args) in frame.contracts_to_be_destroyed {
1766				prev.schedule_termination(account, args);
1767			}
1768
1769			if let Some(contract) = contract {
1770				// Persist the info and invalidate the first stale cache we find.
1771				// This triggers a reload from storage on next use. Only the first
1772				// cache needs to be invalidated because that one will invalidate the next cache
1773				// when it is popped from the stack.
1774				AccountInfo::<T>::insert_contract(
1775					&T::AddressMapper::to_address(account_id),
1776					contract,
1777				);
1778				if let Some(f) = self.frames_mut().find(|f| f.account_id == *account_id) {
1779					// Bank before invalidating so finalize doesn't apply the diff a second time.
1780					bank_pending_changes_and_invalidate(f);
1781				}
1782			}
1783		} else {
1784			if !persist {
1785				self.transaction_meter
1786					.absorb_weight_meter_only(mem::take(&mut self.first_frame.frame_meter));
1787				return;
1788			}
1789
1790			let mut contract = self.first_frame.contract_info.as_contract();
1791			self.transaction_meter.absorb_all_meters(
1792				mem::take(&mut self.first_frame.frame_meter),
1793				&self.first_frame.account_id,
1794				contract.as_deref_mut(),
1795			);
1796
1797			if let Some(contract) = contract {
1798				AccountInfo::<T>::insert_contract(
1799					&T::AddressMapper::to_address(&self.first_frame.account_id),
1800					contract.clone(),
1801				);
1802			}
1803			// End of the callstack: destroy scheduled contracts in line with EVM semantics.
1804			let contracts_created = mem::take(&mut self.first_frame.contracts_created);
1805			let contracts_to_destroy = mem::take(&mut self.first_frame.contracts_to_be_destroyed);
1806			for (contract_account, args) in contracts_to_destroy {
1807				if args.only_if_same_tx && !contracts_created.contains(&contract_account) {
1808					continue;
1809				}
1810				Self::do_terminate(
1811					&mut self.transaction_meter,
1812					self.exec_config,
1813					&contract_account,
1814					&self.origin,
1815					&args,
1816				);
1817			}
1818		}
1819	}
1820
1821	/// Transfer some funds from `from` to `to`.
1822	///
1823	/// This is a no-op for zero `value`, avoiding events to be emitted for zero balance transfers.
1824	///
1825	/// If the destination account does not exist, it is pulled into existence by transferring the
1826	/// ED from `origin` to the new account. The total amount transferred to `to` will be ED +
1827	/// `value`. This makes the ED fully transparent for contracts.
1828	/// The ED transfer is executed atomically with the actual transfer, avoiding the possibility of
1829	/// the ED transfer succeeding but the actual transfer failing. In other words, if the `to` does
1830	/// not exist, the transfer does fail and nothing will be sent to `to` if either `origin` can
1831	/// not provide the ED or transferring `value` from `from` to `to` fails.
1832	/// Note: This will also fail if `origin` is root.
1833	fn transfer<S: State>(
1834		origin: &Origin<T>,
1835		from: &T::AccountId,
1836		to: &T::AccountId,
1837		value: U256,
1838		preservation: Preservation,
1839		meter: &mut ResourceMeter<T, S>,
1840		exec_config: &ExecConfig<T>,
1841	) -> DispatchResult {
1842		let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)
1843			.map_err(|_| Error::<T>::BalanceConversionFailed)?;
1844		if value.is_zero() {
1845			return Ok(());
1846		}
1847
1848		if <System<T>>::account_exists(to) {
1849			return transfer_with_dust::<T>(from, to, value, preservation);
1850		}
1851
1852		let origin = origin.account_id()?;
1853		let ed = <T as Config>::Currency::minimum_balance();
1854		let is_eth_tx = exec_config.collect_deposit_from_hold.is_some();
1855		with_transaction(|| -> TransactionOutcome<DispatchResult> {
1856			// Meter the ED deposit only after the transfer succeeds: the meter is not rolled
1857			// back, so metering earlier would count an ED for an account never created.
1858			match Ok::<(), DispatchError>(())
1859				.and_then(|_| {
1860					if is_eth_tx {
1861						let credit = T::FeeInfo::withdraw_txfee(ed)
1862							.ok_or(Error::<T>::StorageDepositNotEnoughFunds)?;
1863						T::Currency::resolve(to, credit)
1864							.map_err(|_| Error::<T>::StorageDepositNotEnoughFunds)?;
1865						Ok(())
1866					} else {
1867						T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1868							.map(|_| ())
1869							.map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1870					}
1871				})
1872				.and_then(|_| transfer_with_dust::<T>(from, to, value, preservation))
1873				.and_then(|_| meter.charge_deposit(&StorageDeposit::Charge(ed)))
1874			{
1875				Ok(_) => TransactionOutcome::Commit(Ok(())),
1876				Err(err) => TransactionOutcome::Rollback(Err(err)),
1877			}
1878		})
1879	}
1880
1881	/// Same as `transfer` but `from` is an `Origin`.
1882	fn transfer_from_origin<S: State>(
1883		origin: &Origin<T>,
1884		from: &Origin<T>,
1885		to: &T::AccountId,
1886		value: U256,
1887		meter: &mut ResourceMeter<T, S>,
1888		exec_config: &ExecConfig<T>,
1889	) -> ExecResult {
1890		// If the from address is root there is no account to transfer from, and therefore we can't
1891		// take any `value` other than 0.
1892		let from = match from {
1893			Origin::Signed(caller) => caller,
1894			Origin::Root if value.is_zero() => return Ok(Default::default()),
1895			Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1896		};
1897		Self::transfer(origin, from, to, value, Preservation::Preserve, meter, exec_config)
1898			.map(|_| Default::default())
1899			.map_err(Into::into)
1900	}
1901
1902	/// Performs the actual deletion of a contract at the end of a call stack.
1903	///
1904	/// The contract that asked for the termination is no longer on the call stack, so an error
1905	/// here cannot be reported to it. Every balance step is therefore best effort: if it fails it
1906	/// is rolled back and the teardown carries on. The contract itself is always deleted.
1907	fn do_terminate(
1908		transaction_meter: &mut TransactionMeter<T>,
1909		exec_config: &ExecConfig<T>,
1910		contract_account: &T::AccountId,
1911		origin: &Origin<T>,
1912		args: &TerminateArgs<T>,
1913	) {
1914		let contract_address = T::AddressMapper::to_address(contract_account);
1915		// Every scheduled contract has its info stored by now: popping its frame wrote it.
1916		let account_info = AccountInfoOf::<T>::get(contract_address).unwrap_or_default();
1917
1918		// `System.terminate` refunded the deposit when it was called, as far as the freeze on
1919		// the account allowed. This refunds what is still held. A freeze can keep part of it on
1920		// hold. That part stays on the account.
1921		let refund = Self::best_effort(&contract_address, "refund the storage deposit", || {
1922			Self::refund_on_terminate(exec_config, contract_account, origin)
1923		})
1924		.unwrap_or_default();
1925
1926		// we added this consumer manually when instantiating
1927		System::<T>::dec_consumers(contract_account);
1928
1929		// Send the balance that arrived after the termination was scheduled. `Preserve` leaves
1930		// the ED and anything a lock, freeze or hold pins on the account. The beneficiary
1931		// therefore gets all of the late funds only if the balance covers the lock or freeze. If
1932		// it does not, for example with a lock larger than the whole balance, nothing but the
1933		// dust is sent and the rest of the late funds stays on the account. If the transfer fails
1934		// they stay as well.
1935		//
1936		// If the contract named itself as the beneficiary, the sweep is a no-op and the balance
1937		// stays on the account, as in EIP-8246.
1938		let origin = Self::termination_origin(origin);
1939		let balance = <Contracts<T>>::convert_native_to_evm(
1940			account_info.balance(contract_account, Preservation::Preserve),
1941		);
1942		Self::best_effort(&contract_address, "send the remaining balance", || {
1943			Self::transfer(
1944				&origin,
1945				contract_account,
1946				&args.beneficiary,
1947				balance,
1948				Preservation::Preserve,
1949				transaction_meter,
1950				exec_config,
1951			)
1952		});
1953
1954		// A sweep to another beneficiary moves the dust, so it is read only now.
1955		let dust = AccountInfoOf::<T>::get(contract_address)
1956			.map(|info| info.dust)
1957			.unwrap_or_default();
1958
1959		// ED was minted when the account was brought into existence. Burn it only if the account
1960		// holds nothing besides it: no other balance and no dust. Otherwise the ED is kept and
1961		// the account stays in place as a plain account, so the balance left on it does not
1962		// change. A contract deployed to the same address later takes it over. A hold counts
1963		// towards the total balance, and while the account has no other provider its free
1964		// balance cannot drop below the ED, so a hold normally skips the burn. A lock or freeze
1965		// rolls the burn back, and so does a consumer another pallet placed while the account
1966		// has no other provider. A provider or sufficient reference another pallet placed does
1967		// not roll it back: the burn goes through and the account stays alive on that reference.
1968		if dust == 0 &&
1969			T::Currency::total_balance(contract_account) == T::Currency::minimum_balance()
1970		{
1971			Self::best_effort(&contract_address, "burn the existential deposit", || {
1972				T::Deposit::destroy_contract(contract_account)
1973			});
1974		}
1975
1976		if let Some(info) = account_info.account_type.contract_info() {
1977			// this deletes the code if refcount drops to zero
1978			Self::best_effort(&contract_address, "release the code", || {
1979				CodeInfo::<T>::decrement_refcount(info.code_hash)
1980			});
1981			ContractInfo::<T>::queue_for_deletion(info.trie_id, contract_account.clone());
1982		} else {
1983			defensive!("Terminated contract has no contract info", contract_address);
1984		}
1985		// The dust is part of the balance left on the account, so it stays with it.
1986		AccountInfoOf::<T>::set(
1987			contract_address,
1988			(dust != 0).then(|| AccountInfo { account_type: AccountType::EOA, dust }),
1989		);
1990		ImmutableDataOf::<T>::remove(contract_address);
1991
1992		// the meter needs to discard all deposits interacting with the terminated contract
1993		transaction_meter.terminate(contract_account.clone(), args.refunded.saturating_add(refund));
1994
1995		log::trace!(target: LOG_TARGET, "Terminated {contract_address:?}");
1996	}
1997
1998	/// The origin that receives the refunds of a terminated contract.
1999	///
2000	/// If root created the contract we need to use the pallet account_id because root has no
2001	/// account.
2002	fn termination_origin(origin: &Origin<T>) -> Origin<T> {
2003		match origin {
2004			Origin::Signed(o) => Origin::Signed(o.clone()),
2005			Origin::Root => Origin::from_account_id(crate::Pallet::<T>::account_id()),
2006		}
2007	}
2008
2009	/// The storage deposit refund that `System.terminate` does when it is called.
2010	///
2011	/// Refunds the deposit held on `contract_account` to the termination origin, as far as the
2012	/// freezes on the account allow, and returns the amount refunded.
2013	fn refund_on_terminate(
2014		exec_config: &ExecConfig<T>,
2015		contract_account: &T::AccountId,
2016		origin: &Origin<T>,
2017	) -> Result<BalanceOf<T>, DispatchError> {
2018		let origin = Self::termination_origin(origin);
2019		T::Deposit::refund_all(contract_account, exec_config.funds(origin.account_id()?))
2020	}
2021
2022	/// Runs `f` in its own storage transaction.
2023	///
2024	/// If `f` fails, its changes are rolled back and `None` is returned, so that the caller can
2025	/// carry on without them.
2026	fn best_effort<R>(
2027		contract_address: &H160,
2028		step: &str,
2029		f: impl FnOnce() -> Result<R, DispatchError>,
2030	) -> Option<R> {
2031		with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
2032			match f() {
2033				Ok(value) => TransactionOutcome::Commit(Ok(Some(value))),
2034				Err(e) => {
2035					log::debug!(
2036						target: LOG_TARGET,
2037						"Terminating {contract_address:?}: failed to {step}: {e:?}",
2038					);
2039					TransactionOutcome::Rollback(Ok(None))
2040				},
2041			}
2042		})
2043		.ok()
2044		.flatten()
2045	}
2046
2047	/// Reference to the current (top) frame.
2048	fn top_frame(&self) -> &Frame<T> {
2049		top_frame!(self)
2050	}
2051
2052	/// Mutable reference to the current (top) frame.
2053	fn top_frame_mut(&mut self) -> &mut Frame<T> {
2054		top_frame_mut!(self)
2055	}
2056
2057	/// Iterator over all frames.
2058	///
2059	/// The iterator starts with the top frame and ends with the root frame.
2060	fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
2061		core::iter::once(&self.first_frame).chain(&self.frames).rev()
2062	}
2063
2064	/// Same as `frames` but with a mutable reference as iterator item.
2065	fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
2066		core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
2067	}
2068
2069	/// Caller of the frame at `depth`, counting from the top frame.
2070	///
2071	/// A delegate frame runs as the delegating contract, so its caller is the one recorded in
2072	/// its [`DelegateInfo`]. Any other frame is called by the frame below it, or by the origin
2073	/// when it is the first frame.
2074	fn caller_at(&self, depth: usize) -> Origin<T> {
2075		let Some(frame) = self.frames().nth(depth) else { return self.origin.clone() };
2076		if let Some(DelegateInfo { caller, .. }) = &frame.delegate {
2077			caller.clone()
2078		} else {
2079			self.frames()
2080				.nth(depth + 1)
2081				.map(|f| Origin::from_account_id(f.account_id.clone()))
2082				.unwrap_or(self.origin.clone())
2083		}
2084	}
2085
2086	/// Returns whether the specified contract allows to be reentered right now.
2087	fn allows_reentry(&self, id: &T::AccountId) -> bool {
2088		!self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
2089	}
2090
2091	/// Returns the *free* balance of the supplied AccountId.
2092	fn account_balance(&self, who: &T::AccountId) -> U256 {
2093		let balance = AccountInfo::<T>::balance_of(AccountIdOrAddress::AccountId(who.clone()));
2094		crate::Pallet::<T>::convert_native_to_evm(balance)
2095	}
2096
2097	/// Certain APIs, e.g. `{set,get}_immutable_data` behave differently depending
2098	/// on the configured entry point. Thus, we allow setting the export manually.
2099	#[cfg(feature = "runtime-benchmarks")]
2100	pub(crate) fn override_export(&mut self, export: ExportedFunction) {
2101		self.top_frame_mut().entry_point = export;
2102	}
2103
2104	#[cfg(feature = "runtime-benchmarks")]
2105	pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
2106		self.block_number = block_number;
2107	}
2108
2109	fn block_hash(&self, block_number: U256) -> Option<H256> {
2110		let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
2111			return None;
2112		};
2113		if block_number >= self.block_number {
2114			return None;
2115		}
2116		if block_number < self.block_number.saturating_sub(256u32.into()) {
2117			return None;
2118		}
2119
2120		// Fallback to the system block hash for older blocks
2121		// 256 entries should suffice for all use cases, this mostly ensures
2122		// our benchmarks are passing.
2123		match crate::Pallet::<T>::eth_block_hash_from_number(block_number.into()) {
2124			Some(hash) => Some(hash),
2125			None => {
2126				use codec::Decode;
2127				let block_hash = System::<T>::block_hash(&block_number);
2128				Decode::decode(&mut TrailingZeroInput::new(block_hash.as_ref())).ok()
2129			},
2130		}
2131	}
2132
2133	/// Returns true if the current context has contract info.
2134	/// This is the case if `no_precompile || precompile_with_info`.
2135	fn has_contract_info(&self) -> bool {
2136		let address = self.address();
2137		let precompile = <AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes());
2138		if let Some(precompile) = precompile {
2139			return precompile.has_contract_info();
2140		}
2141		true
2142	}
2143
2144	fn with_transient_storage_mut<R, F: FnOnce(&mut TransientStorage<T>) -> R>(
2145		&mut self,
2146		f: F,
2147	) -> R {
2148		if let Some(transient) = &self.exec_config.test_env_transient_storage {
2149			f(&mut transient.borrow_mut())
2150		} else {
2151			f(&mut self.transient_storage)
2152		}
2153	}
2154	fn with_transient_storage<R, F: FnOnce(&TransientStorage<T>) -> R>(&self, f: F) -> R {
2155		if let Some(transient) = &self.exec_config.test_env_transient_storage {
2156			f(&transient.borrow())
2157		} else {
2158			f(&self.transient_storage)
2159		}
2160	}
2161
2162	/// Resolves where the code reported for `address` comes from, with a single
2163	/// `AccountInfoOf` read.
2164	///
2165	/// Single source of truth for `code_hash`, `code_size` and `copy_code_slice`, which
2166	/// must all resolve code from the same sources in the same priority order.
2167	fn code_source(&self, address: &H160) -> Option<CodeSource<'_>> {
2168		if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()).or_else(|| {
2169			self.exec_config
2170				.mock_handler
2171				.as_ref()
2172				.and_then(|handler| handler.mocked_code(*address))
2173		}) {
2174			return Some(CodeSource::Virtual(code));
2175		}
2176
2177		let (contract, target) = <AccountInfo<T>>::load_contract_with_delegation(address);
2178
2179		// EIP-7702: delegated EOAs return `0xef0100 || target` as their code.
2180		//
2181		// PVM caveat: resolc lowers CODESIZE to the `code_size` host function, so inside
2182		// a delegated EOA's execution CODESIZE reports 23 instead of the size of the
2183		// target's PVM blob. Fixing that needs a separate host function and a matching
2184		// resolc change; tracked as a follow-up.
2185		if let Some(target) = target {
2186			return Some(CodeSource::Indicator(<AccountInfo<T>>::delegation_indicator(&target)));
2187		}
2188
2189		contract.map(|contract| CodeSource::Contract(contract.code_hash))
2190	}
2191}
2192
2193/// Where the code reported for an address comes from.
2194enum CodeSource<'a> {
2195	/// A precompile's code stub or mocked code. Never stored in `PristineCode`.
2196	Virtual(&'a [u8]),
2197	/// The EIP-7702 delegation indicator `0xef0100 || target`.
2198	Indicator([u8; 23]),
2199	/// The code hash of a deployed contract whose code is stored in `PristineCode`.
2200	Contract(H256),
2201}
2202
2203impl<'a, T, E> Ext for Stack<'a, T, E>
2204where
2205	T: Config,
2206	E: Executable<T>,
2207{
2208	fn delegate_call(
2209		&mut self,
2210		call_resources: &CallResources<T>,
2211		address: H160,
2212		input_data: Vec<u8>,
2213	) -> Result<(), ExecError> {
2214		// We reset the return data now, so it is cleared out even if no new frame was executed.
2215		// This is for example the case for unknown code hashes or creating the frame fails.
2216		*self.last_frame_output_mut() = Default::default();
2217
2218		let top_frame = self.top_frame_mut();
2219		// Clone the contract info and apply pending storage changes so that
2220		// the child frame can correctly calculate storage deposit refunds.
2221		// See: <https://github.com/paritytech/contract-issues/issues/213>
2222		let mut contract_info = top_frame.contract_info().clone();
2223		top_frame.frame_meter.apply_pending_storage_changes(&mut contract_info);
2224		let account_id = top_frame.account_id.clone();
2225		let value = top_frame.value_transferred;
2226		if let Some(executable) = self.push_frame(
2227			FrameArgs::Call {
2228				dest: account_id,
2229				cached_info: Some(contract_info),
2230				delegated_call: Some(DelegateInfo {
2231					caller: self.caller().clone(),
2232					callee: address,
2233				}),
2234			},
2235			value,
2236			call_resources,
2237			self.is_read_only(),
2238			&input_data,
2239		)? {
2240			self.run(executable, input_data)
2241		} else {
2242			// Delegate-calls to non-contract accounts are considered success.
2243			Ok(())
2244		}
2245	}
2246
2247	fn terminate_if_same_tx(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
2248		if_tracing(|tracer| {
2249			let addr = T::AddressMapper::to_address(self.account_id());
2250			tracer.terminate(
2251				addr,
2252				*beneficiary,
2253				self.top_frame()
2254					.frame_meter
2255					.eth_gas_left()
2256					.unwrap_or_default()
2257					.try_into()
2258					.unwrap_or_default(),
2259				crate::Pallet::<T>::evm_balance(&addr),
2260			);
2261		});
2262		let frame = top_frame_mut!(self);
2263		let contract_address = T::AddressMapper::to_address(&frame.account_id);
2264		let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2265
2266		// balance transfer is immediate
2267		Self::transfer(
2268			&self.origin,
2269			&frame.account_id,
2270			&beneficiary,
2271			<Contracts<T>>::evm_balance(&contract_address),
2272			Preservation::Preserve,
2273			&mut frame.frame_meter,
2274			self.exec_config,
2275		)?;
2276
2277		// schedule for delayed deletion
2278		let account_id = frame.account_id.clone();
2279		self.top_frame_mut().schedule_termination(
2280			account_id,
2281			TerminateArgs { beneficiary, only_if_same_tx: true, refunded: Zero::zero() },
2282		);
2283		Ok(CodeRemoved::Yes)
2284	}
2285
2286	fn own_code_hash(&mut self) -> &H256 {
2287		&self.top_frame_mut().contract_info().code_hash
2288	}
2289
2290	fn immutable_data_len(&mut self) -> u32 {
2291		let frame = self.top_frame_mut();
2292		if frame.code_address == T::AddressMapper::to_address(&frame.account_id) {
2293			frame.contract_info().immutable_data_len()
2294		} else {
2295			limits::IMMUTABLE_BYTES
2296		}
2297	}
2298
2299	fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
2300		if self.top_frame().entry_point == ExportedFunction::Constructor {
2301			return Err(Error::<T>::InvalidImmutableAccess.into());
2302		}
2303
2304		// Immutable data is read from the address where the code originates.
2305		// This handles regular contracts, delegated accounts (EIP-7702), and delegate_call.
2306		let address = self.top_frame().code_address;
2307		Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
2308	}
2309
2310	fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
2311		let frame = self.top_frame_mut();
2312		if frame.entry_point == ExportedFunction::Call || data.is_empty() {
2313			return Err(Error::<T>::InvalidImmutableAccess.into());
2314		}
2315		frame.contract_info().set_immutable_data_len(data.len() as u32);
2316		<ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
2317		Ok(())
2318	}
2319}
2320
2321impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
2322where
2323	T: Config,
2324	E: Executable<T>,
2325{
2326	fn instantiate(
2327		&mut self,
2328		call_resources: &CallResources<T>,
2329		mut code: Code,
2330		value: U256,
2331		input_data: Vec<u8>,
2332		salt: Option<&[u8; 32]>,
2333	) -> Result<H160, ExecError> {
2334		// We reset the return data now, so it is cleared out even if no new frame was executed.
2335		// This is for example the case when creating the frame fails.
2336		*self.last_frame_output_mut() = Default::default();
2337
2338		let sender = self.top_frame().account_id.clone();
2339		let executable = {
2340			let executable = match &mut code {
2341				Code::Upload(initcode) => {
2342					if !T::AllowEVMBytecode::get() {
2343						return Err(<Error<T>>::CodeRejected.into());
2344					}
2345					ensure!(input_data.is_empty(), <Error<T>>::EvmConstructorNonEmptyData);
2346					let initcode = crate::tracing::if_tracing(|_| initcode.clone())
2347						.unwrap_or_else(|| mem::take(initcode));
2348					E::from_evm_init_code(initcode, sender.clone())?
2349				},
2350				Code::Existing(hash) => {
2351					let executable = E::from_storage(*hash, self.frame_meter_mut())?;
2352					ensure!(executable.code_info().is_pvm(), <Error<T>>::EvmConstructedFromHash);
2353					executable
2354				},
2355			};
2356			self.push_frame(
2357				FrameArgs::Instantiate {
2358					sender,
2359					executable,
2360					salt,
2361					input_data: input_data.as_ref(),
2362				},
2363				value,
2364				call_resources,
2365				self.is_read_only(),
2366				&input_data,
2367			)?
2368		};
2369		let executable = executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
2370
2371		let address = T::AddressMapper::to_address(&self.top_frame().account_id);
2372		if_tracing(|t| t.instantiate_code(&code, salt));
2373		self.run(executable, input_data).map(|_| address)
2374	}
2375}
2376
2377impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
2378where
2379	T: Config,
2380	E: Executable<T>,
2381{
2382	type T = T;
2383
2384	fn call(
2385		&mut self,
2386		call_resources: &CallResources<T>,
2387		dest_addr: &H160,
2388		value: U256,
2389		input_data: Vec<u8>,
2390		allows_reentry: ReentrancyProtection,
2391		read_only: bool,
2392	) -> Result<(), ExecError> {
2393		// We reset the return data now, so it is cleared out even if no new frame was executed.
2394		// This is for example the case for balance transfers or when creating the frame fails.
2395		*self.last_frame_output_mut() = Default::default();
2396
2397		// Before pushing the new frame: Protect the caller contract against reentrancy attacks.
2398		// It is important to do this before calling `allows_reentry` so that a direct recursion
2399		// is caught by it.
2400
2401		if allows_reentry == ReentrancyProtection::Strict {
2402			self.top_frame_mut().allows_reentry = false;
2403		}
2404
2405		let try_call = || {
2406			// Enable read-only access if requested; cannot disable it if already set.
2407			let is_read_only = read_only || self.is_read_only();
2408
2409			// We can skip the stateful lookup for pre-compiles.
2410			let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
2411				T::AddressMapper::to_fallback_account_id(dest_addr)
2412			} else {
2413				T::AddressMapper::to_account_id(dest_addr)
2414			};
2415
2416			if !self.allows_reentry(&dest) {
2417				return Err(<Error<T>>::ReentranceDenied.into());
2418			}
2419
2420			if allows_reentry == ReentrancyProtection::AllowNext {
2421				self.top_frame_mut().allows_reentry = false;
2422			}
2423
2424			// We ignore instantiate frames in our search for a cached contract.
2425			// Otherwise it would be possible to recursively call a contract from its own
2426			// constructor: We disallow calling not fully constructed contracts.
2427			//
2428			// When cloning the cached contract, we apply pending storage changes so that
2429			// the child frame can correctly calculate storage deposit refunds.
2430			// See: <https://github.com/paritytech/contract-issues/issues/213>
2431			let cached_info = self
2432				.frames()
2433				.find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
2434				.and_then(|f| match &f.contract_info {
2435					CachedContract::Cached(contract) => {
2436						let mut contract_with_pending = contract.clone();
2437						f.frame_meter.apply_pending_storage_changes(&mut contract_with_pending);
2438						Some(contract_with_pending)
2439					},
2440					_ => None,
2441				});
2442
2443			if let Some(executable) = self.push_frame(
2444				FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
2445				value,
2446				call_resources,
2447				is_read_only,
2448				&input_data,
2449			)? {
2450				self.run(executable, input_data)
2451			} else {
2452				if_tracing(|t| {
2453					t.enter_child_span(
2454						T::AddressMapper::to_address(self.account_id()),
2455						T::AddressMapper::to_address(&dest),
2456						None,
2457						false,
2458						is_read_only,
2459						value,
2460						&input_data,
2461						Default::default(),
2462					);
2463				});
2464
2465				let snapshot = if_tracing(|_| top_frame!(self).frame_meter.snapshot());
2466
2467				let result = if let Some(mock_answer) =
2468					self.exec_config.mock_handler.as_ref().and_then(|handler| {
2469						handler.mock_call(T::AddressMapper::to_address(&dest), &input_data, value)
2470					}) {
2471					*self.last_frame_output_mut() = mock_answer.clone();
2472					Ok(mock_answer)
2473				} else if is_read_only && value.is_zero() {
2474					Ok(Default::default())
2475				} else if is_read_only {
2476					Err(Error::<T>::StateChangeDenied.into())
2477				} else {
2478					let account_id = self.account_id().clone();
2479					let frame = top_frame_mut!(self);
2480					Self::transfer_from_origin(
2481						&self.origin,
2482						&Origin::from_account_id(account_id),
2483						&dest,
2484						value,
2485						&mut frame.frame_meter,
2486						self.exec_config,
2487					)
2488				};
2489
2490				if_tracing(|t| {
2491					let snapshot = snapshot.as_ref().expect(
2492						"snapshot is taken inside if_tracing above; tracing state cannot \
2493						 change mid-call, so it is Some whenever this closure runs; qed",
2494					);
2495					let (gas_used, weight_delta) =
2496						top_frame!(self).frame_meter.delta_since(snapshot);
2497					match result {
2498						Ok(ref output) => t.exit_child_span(&output, gas_used, weight_delta),
2499						Err(e) => {
2500							t.exit_child_span_with_error(e.error.into(), gas_used, weight_delta)
2501						},
2502					}
2503				});
2504
2505				result.map(|_| ())
2506			}
2507		};
2508
2509		// We need to make sure to reset `allows_reentry` even on failure.
2510		let result = try_call();
2511
2512		// Protection is on a per call basis.
2513		self.top_frame_mut().allows_reentry = true;
2514
2515		result
2516	}
2517
2518	fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
2519		self.with_transient_storage(|transient_storage| {
2520			transient_storage.read(self.account_id(), key)
2521		})
2522	}
2523
2524	fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
2525		self.with_transient_storage(|transient_storage| {
2526			transient_storage.read(self.account_id(), key).map(|value| value.len() as _)
2527		})
2528	}
2529
2530	fn set_transient_storage(
2531		&mut self,
2532		key: &Key,
2533		value: Option<Vec<u8>>,
2534		take_old: bool,
2535	) -> Result<WriteOutcome, DispatchError> {
2536		let account_id = self.account_id().clone();
2537		self.with_transient_storage_mut(|transient_storage| {
2538			transient_storage.write(&account_id, key, value, take_old)
2539		})
2540	}
2541
2542	fn account_id(&self) -> &T::AccountId {
2543		&self.top_frame().account_id
2544	}
2545
2546	fn caller(&self) -> Origin<T> {
2547		if let Some(Ok(mock_caller)) = self
2548			.exec_config
2549			.mock_handler
2550			.as_ref()
2551			.and_then(|mock_handler| mock_handler.mock_caller(self.frames.len()))
2552			.map(|mock_caller| Origin::<T>::from_runtime_origin(mock_caller))
2553		{
2554			return mock_caller;
2555		}
2556
2557		self.caller_at(0)
2558	}
2559
2560	fn caller_of_caller(&self) -> Origin<T> {
2561		self.caller_at(1)
2562	}
2563
2564	fn origin(&self) -> &Origin<T> {
2565		if let Some(mock_origin) = self
2566			.exec_config
2567			.mock_handler
2568			.as_ref()
2569			.and_then(|mock_handler| mock_handler.mock_origin())
2570		{
2571			return mock_origin;
2572		}
2573
2574		&self.origin
2575	}
2576
2577	fn to_account_id(&self, address: &H160) -> T::AccountId {
2578		T::AddressMapper::to_account_id(address)
2579	}
2580
2581	fn code_hash(&self, address: &H160) -> H256 {
2582		match self.code_source(address) {
2583			Some(CodeSource::Virtual(code)) => sp_io::hashing::keccak_256(code).into(),
2584			Some(CodeSource::Indicator(indicator)) => sp_io::hashing::keccak_256(&indicator).into(),
2585			Some(CodeSource::Contract(code_hash)) => code_hash,
2586			None if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) => {
2587				EMPTY_CODE_HASH
2588			},
2589			None => H256::zero(),
2590		}
2591	}
2592
2593	fn code_size(&self, address: &H160) -> u64 {
2594		match self.code_source(address) {
2595			Some(CodeSource::Virtual(code)) => code.len() as u64,
2596			Some(CodeSource::Indicator(indicator)) => indicator.len() as u64,
2597			Some(CodeSource::Contract(code_hash)) => {
2598				CodeInfoOf::<T>::get(code_hash).map(|info| info.code_len()).unwrap_or_default()
2599			},
2600			None => 0,
2601		}
2602	}
2603
2604	fn caller_is_origin(&self, use_caller_of_caller: bool) -> bool {
2605		let caller = if use_caller_of_caller { self.caller_of_caller() } else { self.caller() };
2606		self.origin == caller
2607	}
2608
2609	fn caller_is_root(&self, use_caller_of_caller: bool) -> bool {
2610		// if the caller isn't origin, then it can't be root.
2611		self.caller_is_origin(use_caller_of_caller) && self.origin == Origin::Root
2612	}
2613
2614	fn origin_is_root(&self) -> bool {
2615		self.origin == Origin::Root
2616	}
2617
2618	fn balance(&self) -> U256 {
2619		self.account_balance(&self.top_frame().account_id)
2620	}
2621
2622	fn balance_of(&self, address: &H160) -> U256 {
2623		let balance =
2624			self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2625		if_tracing(|tracer| {
2626			tracer.balance_read(address, balance);
2627		});
2628		balance
2629	}
2630
2631	fn value_transferred(&self) -> U256 {
2632		self.top_frame().value_transferred.into()
2633	}
2634
2635	fn now(&self) -> U256 {
2636		(self.timestamp / 1000u32.into()).into()
2637	}
2638
2639	fn minimum_balance(&self) -> U256 {
2640		let min = T::Currency::minimum_balance();
2641		crate::Pallet::<T>::convert_native_to_evm(min)
2642	}
2643
2644	fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2645		let contract = T::AddressMapper::to_address(self.account_id());
2646		if_tracing(|tracer| {
2647			let log_index = frame_system::Pallet::<Self::T>::event_count();
2648			tracer.log_event(contract, &topics, &data, log_index);
2649		});
2650
2651		block_storage::capture_frame_log::<T>(&contract, &data, &topics);
2652
2653		Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2654	}
2655
2656	fn block_number(&self) -> U256 {
2657		self.block_number.into()
2658	}
2659
2660	fn block_hash(&self, block_number: U256) -> Option<H256> {
2661		self.block_hash(block_number)
2662	}
2663
2664	fn block_author(&self) -> H160 {
2665		Contracts::<Self::T>::block_author()
2666	}
2667
2668	fn gas_limit(&self) -> u64 {
2669		<Contracts<T>>::evm_block_gas_limit().saturated_into()
2670	}
2671
2672	fn chain_id(&self) -> u64 {
2673		<T as Config>::ChainId::get()
2674	}
2675
2676	fn gas_meter(&self) -> &FrameMeter<Self::T> {
2677		&self.top_frame().frame_meter
2678	}
2679
2680	#[inline]
2681	fn gas_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2682		&mut self.top_frame_mut().frame_meter
2683	}
2684
2685	fn frame_meter(&self) -> &FrameMeter<Self::T> {
2686		&self.top_frame().frame_meter
2687	}
2688
2689	#[inline]
2690	fn frame_meter_mut(&mut self) -> &mut FrameMeter<Self::T> {
2691		&mut self.top_frame_mut().frame_meter
2692	}
2693
2694	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2695		secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2696	}
2697
2698	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2699		sp_io::crypto::sr25519_verify(
2700			&SR25519Signature::from(*signature),
2701			message,
2702			&SR25519Public::from(*pub_key),
2703		)
2704	}
2705
2706	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], DispatchError> {
2707		Ok(ECDSAPublic::from(*pk)
2708			.to_eth_address()
2709			.or_else(|()| Err(Error::<T>::EcdsaRecoveryFailed))?)
2710	}
2711
2712	#[cfg(any(test, feature = "runtime-benchmarks"))]
2713	fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2714		self.top_frame_mut().contract_info()
2715	}
2716
2717	#[cfg(any(feature = "runtime-benchmarks", test))]
2718	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2719		&mut self.transient_storage
2720	}
2721
2722	fn is_read_only(&self) -> bool {
2723		self.top_frame().read_only
2724	}
2725
2726	fn is_delegate_call(&self) -> bool {
2727		self.top_frame().delegate.is_some()
2728	}
2729
2730	fn last_frame_output(&self) -> &ExecReturnValue {
2731		&self.top_frame().last_frame_output
2732	}
2733
2734	fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2735		&mut self.top_frame_mut().last_frame_output
2736	}
2737
2738	fn copy_code_slice(&mut self, buf: &mut [u8], address: &H160, code_offset: usize) {
2739		fn copy_padded(buf: &mut [u8], code: &[u8], code_offset: usize) {
2740			let code = code.get(code_offset..).unwrap_or_default();
2741			let len = buf.len().min(code.len());
2742			buf[..len].copy_from_slice(&code[..len]);
2743			buf[len..].fill(0);
2744		}
2745
2746		if buf.is_empty() {
2747			return;
2748		}
2749
2750		match self.code_source(address) {
2751			Some(CodeSource::Virtual(code)) => copy_padded(buf, code, code_offset),
2752			Some(CodeSource::Indicator(indicator)) => copy_padded(buf, &indicator, code_offset),
2753			Some(CodeSource::Contract(code_hash)) => copy_padded(
2754				buf,
2755				&crate::PristineCode::<T>::get(&code_hash).unwrap_or_default(),
2756				code_offset,
2757			),
2758			None => buf.fill(0),
2759		}
2760	}
2761
2762	fn terminate_caller(&mut self, beneficiary: &H160) -> Result<(), DispatchError> {
2763		ensure!(self.top_frame().delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2764		let parent = self.frames_mut().nth(1).ok_or_else(|| Error::<T>::ContractNotFound)?;
2765		ensure!(parent.entry_point == ExportedFunction::Call, Error::<T>::TerminatedInConstructor);
2766		ensure!(parent.delegate.is_none(), Error::<T>::PrecompileDelegateDenied);
2767
2768		let contract_address = T::AddressMapper::to_address(&parent.account_id);
2769
2770		// EIP-7702: delegated EOAs cannot be destroyed via the system precompile.
2771		ensure!(
2772			!AccountInfo::<T>::is_delegated(&contract_address),
2773			Error::<T>::CannotTerminateDelegatedAccount,
2774		);
2775
2776		let beneficiary = T::AddressMapper::to_account_id(beneficiary);
2777
2778		let parent_account_id = parent.account_id.clone();
2779
2780		// Refund the storage deposit before the payout. The hold counts towards any freeze on
2781		// the account, so after the payout it would be needed to cover the freeze. Released now,
2782		// it is paid back as far as the freeze allows, and only the remainder stays on hold.
2783		let refunded =
2784			Self::refund_on_terminate(&self.exec_config, &parent_account_id, &self.origin)?;
2785
2786		// balance transfer is immediate
2787		Self::transfer(
2788			&self.origin,
2789			&parent_account_id,
2790			&beneficiary,
2791			<Contracts<T>>::evm_balance(&contract_address),
2792			Preservation::Preserve,
2793			&mut top_frame_mut!(self).frame_meter,
2794			&self.exec_config,
2795		)?;
2796
2797		// schedule for delayed deletion
2798		let args = TerminateArgs { beneficiary, only_if_same_tx: false, refunded };
2799		self.top_frame_mut().schedule_termination(parent_account_id, args);
2800
2801		Ok(())
2802	}
2803
2804	fn effective_gas_price(&self) -> U256 {
2805		self.exec_config
2806			.effective_gas_price
2807			.unwrap_or_else(|| <Contracts<T>>::evm_base_fee())
2808	}
2809
2810	fn gas_left(&self) -> u64 {
2811		let frame = self.top_frame();
2812
2813		frame.frame_meter.eth_gas_left().unwrap_or_default().saturated_into::<u64>()
2814	}
2815
2816	fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
2817		assert!(self.has_contract_info());
2818		self.top_frame_mut().contract_info().read(key)
2819	}
2820
2821	fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
2822		assert!(self.has_contract_info());
2823		self.top_frame_mut().contract_info().size(key.into())
2824	}
2825
2826	fn set_storage(
2827		&mut self,
2828		key: &Key,
2829		value: Option<Vec<u8>>,
2830		take_old: bool,
2831	) -> Result<WriteOutcome, DispatchError> {
2832		assert!(self.has_contract_info());
2833		let frame = self.top_frame_mut();
2834		frame.contract_info.get(&frame.account_id).write(
2835			key.into(),
2836			value,
2837			Some(&mut frame.frame_meter),
2838			take_old,
2839		)
2840	}
2841
2842	fn touch_storage_access(&mut self, key: &Key, op: StorageOp) -> Warmth {
2843		let address = self.address();
2844		self.access_list.touch(AccessEntry { address, slot: key.into() }, op)
2845	}
2846
2847	fn peek_storage_access(&self, key: &Key) -> Warmth {
2848		let address = self.address();
2849		self.access_list.peek(&AccessEntry { address, slot: key.into() })
2850	}
2851
2852	fn charge_storage(&mut self, diff: &Diff) -> DispatchResult {
2853		assert!(self.has_contract_info());
2854		self.top_frame_mut().frame_meter.record_contract_storage_changes(diff)
2855	}
2856}
2857
2858/// Returns true if the address has a precompile contract, else false.
2859pub fn is_precompile<T: Config, E: Executable<T>>(address: &H160) -> bool {
2860	<AllPrecompiles<T>>::get::<Stack<'_, T, E>>(address.as_fixed_bytes()).is_some()
2861}
2862
2863/// Runs the balance work of a termination: the storage deposit refund that `System.terminate`
2864/// does when it is called, followed by the teardown at the end of the call stack. `SELFDESTRUCT`
2865/// (`only_if_same_tx`) does not refund when it is called, so the refund is skipped for it.
2866#[cfg(feature = "runtime-benchmarks")]
2867pub fn bench_do_terminate<T: Config>(
2868	transaction_meter: &mut TransactionMeter<T>,
2869	exec_config: &ExecConfig<T>,
2870	contract_account: &T::AccountId,
2871	origin: &Origin<T>,
2872	beneficiary: T::AccountId,
2873	only_if_same_tx: bool,
2874) -> Result<(), DispatchError> {
2875	type BenchStack<'a, T> = Stack<'a, T, crate::ContractBlob<T>>;
2876	let refunded = if only_if_same_tx {
2877		Zero::zero()
2878	} else {
2879		BenchStack::<T>::refund_on_terminate(exec_config, contract_account, origin)?
2880	};
2881	BenchStack::<T>::do_terminate(
2882		transaction_meter,
2883		exec_config,
2884		contract_account,
2885		origin,
2886		&TerminateArgs { beneficiary, only_if_same_tx, refunded },
2887	);
2888	Ok(())
2889}
2890
2891mod sealing {
2892	use super::*;
2893
2894	pub trait Sealed {}
2895	impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2896
2897	#[cfg(test)]
2898	impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2899}