Skip to main content

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