referrerpolicy=no-referrer-when-downgrade

pallet_revive/
exec.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{
19	address::{self, AddressMapper},
20	gas::GasMeter,
21	limits,
22	precompiles::{All as AllPrecompiles, Instance as PrecompileInstance, Precompiles},
23	primitives::{BumpNonce, ExecReturnValue, StorageDeposit},
24	runtime_decl_for_revive_api::{Decode, Encode, RuntimeDebugNoBound, TypeInfo},
25	storage::{self, meter::Diff, AccountIdOrAddress, WriteOutcome},
26	tracing::if_tracing,
27	transient_storage::TransientStorage,
28	AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf,
29	CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf,
30	Pallet as Contracts, RuntimeCosts, LOG_TARGET,
31};
32use alloc::vec::Vec;
33use core::{fmt::Debug, marker::PhantomData, mem};
34use frame_support::{
35	crypto::ecdsa::ECDSAExt,
36	dispatch::DispatchResult,
37	storage::{with_transaction, TransactionOutcome},
38	traits::{
39		fungible::{Inspect, Mutate},
40		tokens::{Fortitude, Precision, Preservation},
41		Time,
42	},
43	weights::Weight,
44	Blake2_128Concat, BoundedVec, StorageHasher,
45};
46use frame_system::{
47	pallet_prelude::{BlockNumberFor, OriginFor},
48	Pallet as System, RawOrigin,
49};
50use sp_core::{
51	ecdsa::Public as ECDSAPublic,
52	sr25519::{Public as SR25519Public, Signature as SR25519Signature},
53	ConstU32, Get, H160, H256, U256,
54};
55use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
56use sp_runtime::{
57	traits::{BadOrigin, Bounded, Convert, Saturating, Zero},
58	DispatchError, SaturatedConversion,
59};
60
61#[cfg(test)]
62mod tests;
63
64#[cfg(test)]
65pub mod mock_ext;
66
67pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
68pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
69pub type ExecResult = Result<ExecReturnValue, ExecError>;
70
71/// Type for variable sized storage key. Used for transparent hashing.
72type VarSizedKey = BoundedVec<u8, ConstU32<{ limits::STORAGE_KEY_BYTES }>>;
73
74const 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";
75
76/// Code hash of existing account without code (keccak256 hash of empty data).
77pub const EMPTY_CODE_HASH: H256 =
78	H256(sp_core::hex2array!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
79
80/// Combined key type for both fixed and variable sized storage keys.
81pub enum Key {
82	/// Variant for fixed sized keys.
83	Fix([u8; 32]),
84	/// Variant for variable sized keys.
85	Var(VarSizedKey),
86}
87
88impl Key {
89	/// Reference to the raw unhashed key.
90	pub fn unhashed(&self) -> &[u8] {
91		match self {
92			Key::Fix(v) => v.as_ref(),
93			Key::Var(v) => v.as_ref(),
94		}
95	}
96
97	/// The hashed key that has be used as actual key to the storage trie.
98	pub fn hash(&self) -> Vec<u8> {
99		match self {
100			Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
101			Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
102		}
103	}
104
105	pub fn from_fixed(v: [u8; 32]) -> Self {
106		Self::Fix(v)
107	}
108
109	pub fn try_from_var(v: Vec<u8>) -> Result<Self, ()> {
110		VarSizedKey::try_from(v).map(Self::Var).map_err(|_| ())
111	}
112}
113
114/// Origin of the error.
115///
116/// Call or instantiate both called into other contracts and pass through errors happening
117/// in those to the caller. This enum is for the caller to distinguish whether the error
118/// happened during the execution of the callee or in the current execution context.
119#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
120pub enum ErrorOrigin {
121	/// Caller error origin.
122	///
123	/// The error happened in the current execution context rather than in the one
124	/// of the contract that is called into.
125	Caller,
126	/// The error happened during execution of the called contract.
127	Callee,
128}
129
130/// Error returned by contract execution.
131#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
132pub struct ExecError {
133	/// The reason why the execution failed.
134	pub error: DispatchError,
135	/// Origin of the error.
136	pub origin: ErrorOrigin,
137}
138
139impl<T: Into<DispatchError>> From<T> for ExecError {
140	fn from(error: T) -> Self {
141		Self { error: error.into(), origin: ErrorOrigin::Caller }
142	}
143}
144
145/// The type of origins supported by the revive pallet.
146#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
147pub enum Origin<T: Config> {
148	Root,
149	Signed(T::AccountId),
150}
151
152impl<T: Config> Origin<T> {
153	/// Creates a new Signed Caller from an AccountId.
154	pub fn from_account_id(account_id: T::AccountId) -> Self {
155		Origin::Signed(account_id)
156	}
157	/// Creates a new Origin from a `RuntimeOrigin`.
158	pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
159		match o.into() {
160			Ok(RawOrigin::Root) => Ok(Self::Root),
161			Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
162			_ => Err(BadOrigin.into()),
163		}
164	}
165	/// Returns the AccountId of a Signed Origin or an error if the origin is Root.
166	pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
167		match self {
168			Origin::Signed(id) => Ok(id),
169			Origin::Root => Err(DispatchError::RootNotAllowed),
170		}
171	}
172
173	/// Make sure that this origin is mapped.
174	///
175	/// We require an origin to be mapped in order to be used in a `Stack`. Otherwise
176	/// [`Stack::caller`] returns an address that can't be reverted to the original address.
177	fn ensure_mapped(&self) -> DispatchResult {
178		match self {
179			Self::Root => Ok(()),
180			Self::Signed(account_id) if T::AddressMapper::is_mapped(account_id) => Ok(()),
181			Self::Signed(_) => Err(<Error<T>>::AccountUnmapped.into()),
182		}
183	}
184}
185/// Environment functions only available to host functions.
186pub trait Ext: PrecompileWithInfoExt {
187	/// Execute code in the current frame.
188	///
189	/// Returns the code size of the called contract.
190	fn delegate_call(
191		&mut self,
192		gas_limit: Weight,
193		deposit_limit: U256,
194		address: H160,
195		input_data: Vec<u8>,
196	) -> Result<(), ExecError>;
197
198	/// Transfer all funds to `beneficiary` and delete the contract.
199	///
200	/// Since this function removes the self contract eagerly, if succeeded, no further actions
201	/// should be performed on this `Ext` instance.
202	///
203	/// This function will fail if the same contract is present on the contract
204	/// call stack.
205	fn terminate(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError>;
206
207	/// Returns the code hash of the contract being executed.
208	fn own_code_hash(&mut self) -> &H256;
209
210	/// Sets new code hash and immutable data for an existing contract.
211	/// Returns whether the old code was removed as a result of this operation.
212	fn set_code_hash(&mut self, hash: H256) -> Result<CodeRemoved, DispatchError>;
213
214	/// Get the length of the immutable data.
215	///
216	/// This query is free as it does not need to load the immutable data from storage.
217	/// Useful when we need a constant time lookup of the length.
218	fn immutable_data_len(&mut self) -> u32;
219
220	/// Returns the immutable data of the current contract.
221	///
222	/// Returns `Err(InvalidImmutableAccess)` if called from a constructor.
223	fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError>;
224
225	/// Set the immutable data of the current contract.
226	///
227	/// Returns `Err(InvalidImmutableAccess)` if not called from a constructor.
228	///
229	/// Note: Requires &mut self to access the contract info.
230	fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError>;
231}
232
233/// Environment functions which are available to pre-compiles with `HAS_CONTRACT_INFO = true`.
234pub trait PrecompileWithInfoExt: PrecompileExt {
235	/// Returns the storage entry of the executing account by the given `key`.
236	///
237	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
238	/// was deleted.
239	fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>>;
240
241	/// Returns `Some(len)` (in bytes) if a storage item exists at `key`.
242	///
243	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
244	/// was deleted.
245	fn get_storage_size(&mut self, key: &Key) -> Option<u32>;
246
247	/// Sets the storage entry by the given key to the specified value. If `value` is `None` then
248	/// the storage entry is deleted.
249	fn set_storage(
250		&mut self,
251		key: &Key,
252		value: Option<Vec<u8>>,
253		take_old: bool,
254	) -> Result<WriteOutcome, DispatchError>;
255
256	/// Charges `diff` from the meter.
257	fn charge_storage(&mut self, diff: &Diff);
258
259	/// Instantiate a contract from the given code.
260	///
261	/// Returns the original code size of the called contract.
262	/// The newly created account will be associated with `code`. `value` specifies the amount of
263	/// value transferred from the caller to the newly created account.
264	fn instantiate(
265		&mut self,
266		gas_limit: Weight,
267		deposit_limit: U256,
268		code: Code,
269		value: U256,
270		input_data: Vec<u8>,
271		salt: Option<&[u8; 32]>,
272	) -> Result<H160, ExecError>;
273}
274
275/// Environment functions which are available to all pre-compiles.
276pub trait PrecompileExt: sealing::Sealed {
277	type T: Config;
278
279	/// Charges the gas meter with the given weight.
280	fn charge(&mut self, weight: Weight) -> Result<crate::gas::ChargedAmount, DispatchError> {
281		self.gas_meter_mut().charge(RuntimeCosts::Precompile(weight))
282	}
283
284	fn adjust_gas(&mut self, charged: crate::gas::ChargedAmount, actual_weight: Weight) {
285		self.gas_meter_mut()
286			.adjust_gas(charged, RuntimeCosts::Precompile(actual_weight));
287	}
288
289	/// Call (possibly transferring some amount of funds) into the specified account.
290	///
291	/// Returns the code size of the called contract.
292	fn call(
293		&mut self,
294		gas_limit: Weight,
295		deposit_limit: U256,
296		to: &H160,
297		value: U256,
298		input_data: Vec<u8>,
299		allows_reentry: bool,
300		read_only: bool,
301	) -> Result<(), ExecError>;
302
303	/// Returns the transient storage entry of the executing account for the given `key`.
304	///
305	/// Returns `None` if the `key` wasn't previously set by `set_transient_storage` or
306	/// was deleted.
307	fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>>;
308
309	/// Returns `Some(len)` (in bytes) if a transient storage item exists at `key`.
310	///
311	/// Returns `None` if the `key` wasn't previously set by `set_transient_storage` or
312	/// was deleted.
313	fn get_transient_storage_size(&self, key: &Key) -> Option<u32>;
314
315	/// Sets the transient storage entry for the given key to the specified value. If `value` is
316	/// `None` then the storage entry is deleted.
317	fn set_transient_storage(
318		&mut self,
319		key: &Key,
320		value: Option<Vec<u8>>,
321		take_old: bool,
322	) -> Result<WriteOutcome, DispatchError>;
323
324	/// Returns the caller.
325	fn caller(&self) -> Origin<Self::T>;
326
327	/// Return the origin of the whole call stack.
328	fn origin(&self) -> &Origin<Self::T>;
329
330	/// Returns the code hash of the contract for the given `address`.
331	/// If not a contract but account exists then `keccak_256([])` is returned, otherwise `zero`.
332	fn code_hash(&self, address: &H160) -> H256;
333
334	/// Returns the code size of the contract at the given `address` or zero.
335	fn code_size(&self, address: &H160) -> u64;
336
337	/// Check if the caller of the current contract is the origin of the whole call stack.
338	fn caller_is_origin(&self) -> bool;
339
340	/// Check if the caller is origin, and this origin is root.
341	fn caller_is_root(&self) -> bool;
342
343	/// Returns a reference to the account id of the current contract.
344	fn account_id(&self) -> &AccountIdOf<Self::T>;
345
346	/// Returns a reference to the [`H160`] address of the current contract.
347	fn address(&self) -> H160 {
348		<Self::T as Config>::AddressMapper::to_address(self.account_id())
349	}
350
351	/// Returns the balance of the current contract.
352	///
353	/// The `value_transferred` is already added.
354	fn balance(&self) -> U256;
355
356	/// Returns the balance of the supplied account.
357	///
358	/// The `value_transferred` is already added.
359	fn balance_of(&self, address: &H160) -> U256;
360
361	/// Returns the value transferred along with this call.
362	fn value_transferred(&self) -> U256;
363
364	/// Returns the timestamp of the current block in seconds.
365	fn now(&self) -> U256;
366
367	/// Returns the minimum balance that is required for creating an account.
368	fn minimum_balance(&self) -> U256;
369
370	/// Deposit an event with the given topics.
371	///
372	/// There should not be any duplicates in `topics`.
373	fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>);
374
375	/// Returns the current block number.
376	fn block_number(&self) -> U256;
377
378	/// Returns the block hash at the given `block_number` or `None` if
379	/// `block_number` isn't within the range of the previous 256 blocks.
380	fn block_hash(&self, block_number: U256) -> Option<H256>;
381
382	/// Returns the author of the current block.
383	fn block_author(&self) -> Option<H160>;
384
385	/// Returns the block gas limit.
386	fn gas_limit(&self) -> u64;
387
388	/// Returns the chain id.
389	fn chain_id(&self) -> u64;
390
391	/// Returns the maximum allowed size of a storage item.
392	fn max_value_size(&self) -> u32;
393
394	/// Returns the price for the specified amount of weight.
395	fn get_weight_price(&self, weight: Weight) -> U256;
396
397	/// Get an immutable reference to the nested gas meter.
398	fn gas_meter(&self) -> &GasMeter<Self::T>;
399
400	/// Get a mutable reference to the nested gas meter.
401	fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T>;
402
403	/// Recovers ECDSA compressed public key based on signature and message hash.
404	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
405
406	/// Verify a sr25519 signature.
407	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
408
409	/// Returns Ethereum address from the ECDSA compressed public key.
410	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()>;
411
412	/// Tests sometimes need to modify and inspect the contract info directly.
413	#[cfg(any(test, feature = "runtime-benchmarks"))]
414	fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
415
416	/// Get a mutable reference to the transient storage.
417	/// Useful in benchmarks when it is sometimes necessary to modify and inspect the transient
418	/// storage directly.
419	#[cfg(any(feature = "runtime-benchmarks", test))]
420	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
421
422	/// Check if running in read-only context.
423	fn is_read_only(&self) -> bool;
424
425	/// Returns an immutable reference to the output of the last executed call frame.
426	fn last_frame_output(&self) -> &ExecReturnValue;
427
428	/// Returns a mutable reference to the output of the last executed call frame.
429	fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue;
430}
431
432/// Describes the different functions that can be exported by an [`Executable`].
433#[derive(
434	Copy,
435	Clone,
436	PartialEq,
437	Eq,
438	sp_core::RuntimeDebug,
439	codec::Decode,
440	codec::Encode,
441	codec::MaxEncodedLen,
442	scale_info::TypeInfo,
443)]
444pub enum ExportedFunction {
445	/// The constructor function which is executed on deployment of a contract.
446	Constructor,
447	/// The function which is executed when a contract is called.
448	Call,
449}
450
451/// A trait that represents something that can be executed.
452///
453/// In the on-chain environment this would be represented by a vm binary module. This trait exists
454/// in order to be able to mock the vm logic for testing.
455pub trait Executable<T: Config>: Sized {
456	/// Load the executable from storage.
457	///
458	/// # Note
459	/// Charges size base load weight from the gas meter.
460	fn from_storage(code_hash: H256, gas_meter: &mut GasMeter<T>) -> Result<Self, DispatchError>;
461
462	/// Load the executable from EVM bytecode
463	fn from_evm_init_code(code: Vec<u8>, owner: AccountIdOf<T>) -> Result<Self, DispatchError>;
464
465	/// Execute the specified exported function and return the result.
466	///
467	/// When the specified function is `Constructor` the executable is stored and its
468	/// refcount incremented.
469	///
470	/// # Note
471	///
472	/// This functions expects to be executed in a storage transaction that rolls back
473	/// all of its emitted storage changes.
474	fn execute<E: Ext<T = T>>(
475		self,
476		ext: &mut E,
477		function: ExportedFunction,
478		input_data: Vec<u8>,
479	) -> ExecResult;
480
481	/// The code info of the executable.
482	fn code_info(&self) -> &CodeInfo<T>;
483
484	/// The raw code of the executable.
485	fn code(&self) -> &[u8];
486
487	/// The code hash of the executable.
488	fn code_hash(&self) -> &H256;
489}
490
491/// The complete call stack of a contract execution.
492///
493/// The call stack is initiated by either a signed origin or one of the contract RPC calls.
494/// This type implements `Ext` and by that exposes the business logic of contract execution to
495/// the runtime module which interfaces with the contract (the vm contract blob) itself.
496pub struct Stack<'a, T: Config, E> {
497	/// The origin that initiated the call stack. It could either be a Signed plain account that
498	/// holds an account id or Root.
499	///
500	/// # Note
501	///
502	/// Please note that it is possible that the id of a Signed origin belongs to a contract rather
503	/// than a plain account when being called through one of the contract RPCs where the
504	/// client can freely choose the origin. This usually makes no sense but is still possible.
505	origin: Origin<T>,
506	/// The gas meter where costs are charged to.
507	gas_meter: &'a mut GasMeter<T>,
508	/// The storage meter makes sure that the storage deposit limit is obeyed.
509	storage_meter: &'a mut storage::meter::Meter<T>,
510	/// The timestamp at the point of call stack instantiation.
511	timestamp: MomentOf<T>,
512	/// The block number at the time of call stack instantiation.
513	block_number: BlockNumberFor<T>,
514	/// The actual call stack. One entry per nested contract called/instantiated.
515	/// This does **not** include the [`Self::first_frame`].
516	frames: BoundedVec<Frame<T>, ConstU32<{ limits::CALL_STACK_DEPTH }>>,
517	/// Statically guarantee that each call stack has at least one frame.
518	first_frame: Frame<T>,
519	/// Transient storage used to store data, which is kept for the duration of a transaction.
520	transient_storage: TransientStorage<T>,
521	/// Whether or not actual transfer of funds should be performed.
522	/// This is set to `true` exclusively when we simulate a call through eth_transact.
523	skip_transfer: bool,
524	/// No executable is held by the struct but influences its behaviour.
525	_phantom: PhantomData<E>,
526}
527
528/// Represents one entry in the call stack.
529///
530/// For each nested contract call or instantiate one frame is created. It holds specific
531/// information for the said call and caches the in-storage `ContractInfo` data structure.
532struct Frame<T: Config> {
533	/// The address of the executing contract.
534	account_id: T::AccountId,
535	/// The cached in-storage data of the contract.
536	contract_info: CachedContract<T>,
537	/// The EVM balance transferred by the caller as part of the call.
538	value_transferred: U256,
539	/// Determines whether this is a call or instantiate frame.
540	entry_point: ExportedFunction,
541	/// The gas meter capped to the supplied gas limit.
542	nested_gas: GasMeter<T>,
543	/// The storage meter for the individual call.
544	nested_storage: storage::meter::NestedMeter<T>,
545	/// If `false` the contract enabled its defense against reentrance attacks.
546	allows_reentry: bool,
547	/// If `true` subsequent calls cannot modify storage.
548	read_only: bool,
549	/// The delegate call info of the currently executing frame which was spawned by
550	/// `delegate_call`.
551	delegate: Option<DelegateInfo<T>>,
552	/// The output of the last executed call frame.
553	last_frame_output: ExecReturnValue,
554}
555
556/// This structure is used to represent the arguments in a delegate call frame in order to
557/// distinguish who delegated the call and where it was delegated to.
558struct DelegateInfo<T: Config> {
559	/// The caller of the contract.
560	pub caller: Origin<T>,
561	/// The address of the contract the call was delegated to.
562	pub callee: H160,
563}
564
565/// When calling an address it can either lead to execution of contract code or a pre-compile.
566enum ExecutableOrPrecompile<T: Config, E: Executable<T>, Env> {
567	/// Contract code.
568	Executable(E),
569	/// Code inside the runtime (so called pre-compile).
570	Precompile { instance: PrecompileInstance<Env>, _phantom: PhantomData<T> },
571}
572
573impl<T: Config, E: Executable<T>, Env> ExecutableOrPrecompile<T, E, Env> {
574	fn as_executable(&self) -> Option<&E> {
575		if let Self::Executable(executable) = self {
576			Some(executable)
577		} else {
578			None
579		}
580	}
581
582	fn is_pvm(&self) -> bool {
583		match self {
584			Self::Executable(e) => e.code_info().is_pvm(),
585			_ => false,
586		}
587	}
588
589	fn as_precompile(&self) -> Option<&PrecompileInstance<Env>> {
590		if let Self::Precompile { instance, .. } = self {
591			Some(instance)
592		} else {
593			None
594		}
595	}
596
597	#[cfg(any(feature = "runtime-benchmarks", test))]
598	fn into_executable(self) -> Option<E> {
599		if let Self::Executable(executable) = self {
600			Some(executable)
601		} else {
602			None
603		}
604	}
605}
606
607/// Parameter passed in when creating a new `Frame`.
608///
609/// It determines whether the new frame is for a call or an instantiate.
610enum FrameArgs<'a, T: Config, E> {
611	Call {
612		/// The account id of the contract that is to be called.
613		dest: T::AccountId,
614		/// If `None` the contract info needs to be reloaded from storage.
615		cached_info: Option<ContractInfo<T>>,
616		/// This frame was created by `seal_delegate_call` and hence uses different code than
617		/// what is stored at [`Self::Call::dest`]. Its caller ([`DelegatedCall::caller`]) is the
618		/// account which called the caller contract
619		delegated_call: Option<DelegateInfo<T>>,
620	},
621	Instantiate {
622		/// The contract or signed origin which instantiates the new contract.
623		sender: T::AccountId,
624		/// The executable whose `deploy` function is run.
625		executable: E,
626		/// A salt used in the contract address derivation of the new contract.
627		salt: Option<&'a [u8; 32]>,
628		/// The input data is used in the contract address derivation of the new contract.
629		input_data: &'a [u8],
630	},
631}
632
633/// Describes the different states of a contract as contained in a `Frame`.
634enum CachedContract<T: Config> {
635	/// The cached contract is up to date with the in-storage value.
636	Cached(ContractInfo<T>),
637	/// A recursive call into the same contract did write to the contract info.
638	///
639	/// In this case the cached contract is stale and needs to be reloaded from storage.
640	Invalidated,
641	/// The current contract executed `terminate` and removed the contract.
642	///
643	/// In this case a reload is neither allowed nor possible. Please note that recursive
644	/// calls cannot remove a contract as this is checked and denied.
645	Terminated,
646	/// The frame is associated with pre-compile that has no contract info.
647	None,
648}
649
650impl<T: Config> Frame<T> {
651	/// Return the `contract_info` of the current contract.
652	fn contract_info(&mut self) -> &mut ContractInfo<T> {
653		self.contract_info.get(&self.account_id)
654	}
655
656	/// Terminate and return the `contract_info` of the current contract.
657	///
658	/// # Note
659	///
660	/// Under no circumstances the contract is allowed to access the `contract_info` after
661	/// a call to this function. This would constitute a programming error in the exec module.
662	fn terminate(&mut self) -> ContractInfo<T> {
663		self.contract_info.terminate(&self.account_id)
664	}
665}
666
667/// Extract the contract info after loading it from storage.
668///
669/// This assumes that `load` was executed before calling this macro.
670macro_rules! get_cached_or_panic_after_load {
671	($c:expr) => {{
672		if let CachedContract::Cached(contract) = $c {
673			contract
674		} else {
675			panic!(
676				"It is impossible to remove a contract that is on the call stack;\
677				See implementations of terminate;\
678				Therefore fetching a contract will never fail while using an account id
679				that is currently active on the call stack;\
680				qed"
681			);
682		}
683	}};
684}
685
686/// Same as [`Stack::top_frame`].
687///
688/// We need this access as a macro because sometimes hiding the lifetimes behind
689/// a function won't work out.
690macro_rules! top_frame {
691	($stack:expr) => {
692		$stack.frames.last().unwrap_or(&$stack.first_frame)
693	};
694}
695
696/// Same as [`Stack::top_frame_mut`].
697///
698/// We need this access as a macro because sometimes hiding the lifetimes behind
699/// a function won't work out.
700macro_rules! top_frame_mut {
701	($stack:expr) => {
702		$stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
703	};
704}
705
706impl<T: Config> CachedContract<T> {
707	/// Return `Some(ContractInfo)` if the contract is in cached state. `None` otherwise.
708	fn into_contract(self) -> Option<ContractInfo<T>> {
709		if let CachedContract::Cached(contract) = self {
710			Some(contract)
711		} else {
712			None
713		}
714	}
715
716	/// Return `Some(&mut ContractInfo)` if the contract is in cached state. `None` otherwise.
717	fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
718		if let CachedContract::Cached(contract) = self {
719			Some(contract)
720		} else {
721			None
722		}
723	}
724
725	/// Load the `contract_info` from storage if necessary.
726	fn load(&mut self, account_id: &T::AccountId) {
727		if let CachedContract::Invalidated = self {
728			if let Some(contract) =
729				AccountInfo::<T>::load_contract(&T::AddressMapper::to_address(account_id))
730			{
731				*self = CachedContract::Cached(contract);
732			}
733		}
734	}
735
736	/// Return the cached contract_info.
737	fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
738		self.load(account_id);
739		get_cached_or_panic_after_load!(self)
740	}
741
742	/// Terminate and return the contract info.
743	fn terminate(&mut self, account_id: &T::AccountId) -> ContractInfo<T> {
744		self.load(account_id);
745		get_cached_or_panic_after_load!(mem::replace(self, Self::Terminated))
746	}
747
748	/// Set the status to invalidate if is cached.
749	fn invalidate(&mut self) {
750		if matches!(self, CachedContract::Cached(_)) {
751			*self = CachedContract::Invalidated;
752		}
753	}
754}
755
756impl<'a, T, E> Stack<'a, T, E>
757where
758	T: Config,
759	BalanceOf<T>: Into<U256> + TryFrom<U256>,
760	MomentOf<T>: Into<U256>,
761	E: Executable<T>,
762	T::Hash: frame_support::traits::IsType<H256>,
763{
764	/// Create and run a new call stack by calling into `dest`.
765	///
766	/// # Return Value
767	///
768	/// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)>
769	pub fn run_call(
770		origin: Origin<T>,
771		dest: H160,
772		gas_meter: &mut GasMeter<T>,
773		storage_meter: &mut storage::meter::Meter<T>,
774		value: U256,
775		input_data: Vec<u8>,
776		skip_transfer: bool,
777	) -> ExecResult {
778		let dest = T::AddressMapper::to_account_id(&dest);
779		if let Some((mut stack, executable)) = Stack::<'_, T, E>::new(
780			FrameArgs::Call { dest: dest.clone(), cached_info: None, delegated_call: None },
781			origin.clone(),
782			gas_meter,
783			storage_meter,
784			value,
785			skip_transfer,
786		)? {
787			stack
788				.run(executable, input_data, BumpNonce::Yes)
789				.map(|_| stack.first_frame.last_frame_output)
790		} else {
791			if_tracing(|t| {
792				t.enter_child_span(
793					origin.account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
794					T::AddressMapper::to_address(&dest),
795					false,
796					false,
797					value,
798					&input_data,
799					Weight::zero(),
800				);
801			});
802
803			let result = Self::transfer_from_origin(&origin, &origin, &dest, value, storage_meter);
804
805			if_tracing(|t| match result {
806				Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
807				Err(e) => t.exit_child_span_with_error(e.error.into(), Weight::zero()),
808			});
809
810			result
811		}
812	}
813
814	/// Create and run a new call stack by instantiating a new contract.
815	///
816	/// # Return Value
817	///
818	/// Result<(NewContractAccountId, ExecReturnValue), ExecError)>
819	pub fn run_instantiate(
820		origin: T::AccountId,
821		executable: E,
822		gas_meter: &mut GasMeter<T>,
823		storage_meter: &mut storage::meter::Meter<T>,
824		value: U256,
825		input_data: Vec<u8>,
826		salt: Option<&[u8; 32]>,
827		skip_transfer: bool,
828		bump_nonce: BumpNonce,
829	) -> Result<(H160, ExecReturnValue), ExecError> {
830		let deployer = T::AddressMapper::to_address(&origin);
831		let (mut stack, executable) = Stack::<'_, T, E>::new(
832			FrameArgs::Instantiate {
833				sender: origin.clone(),
834				executable,
835				salt,
836				input_data: input_data.as_ref(),
837			},
838			Origin::from_account_id(origin),
839			gas_meter,
840			storage_meter,
841			value,
842			skip_transfer,
843		)?
844		.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE);
845		let address = T::AddressMapper::to_address(&stack.top_frame().account_id);
846		let result = stack
847			.run(executable, input_data, bump_nonce)
848			.map(|_| (address, stack.first_frame.last_frame_output));
849		if let Ok((contract, ref output)) = result {
850			if !output.did_revert() {
851				Contracts::<T>::deposit_event(Event::Instantiated { deployer, contract });
852			}
853		}
854		result
855	}
856
857	#[cfg(any(feature = "runtime-benchmarks", test))]
858	pub fn bench_new_call(
859		dest: H160,
860		origin: Origin<T>,
861		gas_meter: &'a mut GasMeter<T>,
862		storage_meter: &'a mut storage::meter::Meter<T>,
863		value: BalanceOf<T>,
864	) -> (Self, E) {
865		let call = Self::new(
866			FrameArgs::Call {
867				dest: T::AddressMapper::to_account_id(&dest),
868				cached_info: None,
869				delegated_call: None,
870			},
871			origin,
872			gas_meter,
873			storage_meter,
874			value.into(),
875			false,
876		)
877		.unwrap()
878		.unwrap();
879		(call.0, call.1.into_executable().unwrap())
880	}
881
882	/// Create a new call stack.
883	///
884	/// Returns `None` when calling a non existent contract. This is not an error case
885	/// since this will result in a value transfer.
886	fn new(
887		args: FrameArgs<T, E>,
888		origin: Origin<T>,
889		gas_meter: &'a mut GasMeter<T>,
890		storage_meter: &'a mut storage::meter::Meter<T>,
891		value: U256,
892		skip_transfer: bool,
893	) -> Result<Option<(Self, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
894		origin.ensure_mapped()?;
895		let Some((first_frame, executable)) = Self::new_frame(
896			args,
897			value,
898			gas_meter,
899			Weight::max_value(),
900			storage_meter,
901			BalanceOf::<T>::max_value(),
902			false,
903			true,
904		)?
905		else {
906			return Ok(None);
907		};
908
909		let stack = Self {
910			origin,
911			gas_meter,
912			storage_meter,
913			timestamp: T::Time::now(),
914			block_number: <frame_system::Pallet<T>>::block_number(),
915			first_frame,
916			frames: Default::default(),
917			transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES),
918			skip_transfer,
919			_phantom: Default::default(),
920		};
921
922		Ok(Some((stack, executable)))
923	}
924
925	/// Construct a new frame.
926	///
927	/// This does not take `self` because when constructing the first frame `self` is
928	/// not initialized, yet.
929	fn new_frame<S: storage::meter::State + Default + Debug>(
930		frame_args: FrameArgs<T, E>,
931		value_transferred: U256,
932		gas_meter: &mut GasMeter<T>,
933		gas_limit: Weight,
934		storage_meter: &mut storage::meter::GenericMeter<T, S>,
935		deposit_limit: BalanceOf<T>,
936		read_only: bool,
937		origin_is_caller: bool,
938	) -> Result<Option<(Frame<T>, ExecutableOrPrecompile<T, E, Self>)>, ExecError> {
939		let (account_id, contract_info, executable, delegate, entry_point) = match frame_args {
940			FrameArgs::Call { dest, cached_info, delegated_call } => {
941				let address = T::AddressMapper::to_address(&dest);
942				let precompile = <AllPrecompiles<T>>::get(address.as_fixed_bytes());
943
944				// which contract info to load is unaffected by the fact if this
945				// is a delegate call or not
946				let mut contract = match (cached_info, &precompile) {
947					(Some(info), _) => CachedContract::Cached(info),
948					(None, None) =>
949						if let Some(info) = AccountInfo::<T>::load_contract(&address) {
950							CachedContract::Cached(info)
951						} else {
952							return Ok(None);
953						},
954					(None, Some(precompile)) if precompile.has_contract_info() => {
955						if let Some(info) = AccountInfo::<T>::load_contract(&address) {
956							CachedContract::Cached(info)
957						} else {
958							let info = ContractInfo::new(&address, 0u32.into(), H256::zero())?;
959							CachedContract::Cached(info)
960						}
961					},
962					(None, Some(_)) => CachedContract::None,
963				};
964
965				// in case of delegate the executable is not the one at `address`
966				let executable = if let Some(delegated_call) = &delegated_call {
967					if let Some(precompile) =
968						<AllPrecompiles<T>>::get(delegated_call.callee.as_fixed_bytes())
969					{
970						ExecutableOrPrecompile::Precompile {
971							instance: precompile,
972							_phantom: Default::default(),
973						}
974					} else {
975						let Some(info) = AccountInfo::<T>::load_contract(&delegated_call.callee)
976						else {
977							return Ok(None);
978						};
979						let executable = E::from_storage(info.code_hash, gas_meter)?;
980						ExecutableOrPrecompile::Executable(executable)
981					}
982				} else {
983					if let Some(precompile) = precompile {
984						ExecutableOrPrecompile::Precompile {
985							instance: precompile,
986							_phantom: Default::default(),
987						}
988					} else {
989						let executable = E::from_storage(
990							contract
991								.as_contract()
992								.expect("When not a precompile the contract was loaded above; qed")
993								.code_hash,
994							gas_meter,
995						)?;
996						ExecutableOrPrecompile::Executable(executable)
997					}
998				};
999
1000				(dest, contract, executable, delegated_call, ExportedFunction::Call)
1001			},
1002			FrameArgs::Instantiate { sender, executable, salt, input_data } => {
1003				let deployer = T::AddressMapper::to_address(&sender);
1004				let account_nonce = <System<T>>::account_nonce(&sender);
1005				let address = if let Some(salt) = salt {
1006					address::create2(&deployer, executable.code(), input_data, salt)
1007				} else {
1008					use sp_runtime::Saturating;
1009					address::create1(
1010						&deployer,
1011						// the Nonce from the origin has been incremented pre-dispatch, so we
1012						// need to subtract 1 to get the nonce at the time of the call.
1013						if origin_is_caller {
1014							account_nonce.saturating_sub(1u32.into()).saturated_into()
1015						} else {
1016							account_nonce.saturated_into()
1017						},
1018					)
1019				};
1020				let contract = ContractInfo::new(
1021					&address,
1022					<System<T>>::account_nonce(&sender),
1023					*executable.code_hash(),
1024				)?;
1025				(
1026					T::AddressMapper::to_fallback_account_id(&address),
1027					CachedContract::Cached(contract),
1028					ExecutableOrPrecompile::Executable(executable),
1029					None,
1030					ExportedFunction::Constructor,
1031				)
1032			},
1033		};
1034
1035		let frame = Frame {
1036			delegate,
1037			value_transferred,
1038			contract_info,
1039			account_id,
1040			entry_point,
1041			nested_gas: gas_meter.nested(gas_limit),
1042			nested_storage: storage_meter.nested(deposit_limit),
1043			allows_reentry: true,
1044			read_only,
1045			last_frame_output: Default::default(),
1046		};
1047
1048		Ok(Some((frame, executable)))
1049	}
1050
1051	/// Create a subsequent nested frame.
1052	fn push_frame(
1053		&mut self,
1054		frame_args: FrameArgs<T, E>,
1055		value_transferred: U256,
1056		gas_limit: Weight,
1057		deposit_limit: BalanceOf<T>,
1058		read_only: bool,
1059	) -> Result<Option<ExecutableOrPrecompile<T, E, Self>>, ExecError> {
1060		if self.frames.len() as u32 == limits::CALL_STACK_DEPTH {
1061			return Err(Error::<T>::MaxCallDepthReached.into());
1062		}
1063
1064		// We need to make sure that changes made to the contract info are not discarded.
1065		// See the `in_memory_changes_not_discarded` test for more information.
1066		// We do not store on instantiate because we do not allow to call into a contract
1067		// from its own constructor.
1068		let frame = self.top_frame();
1069		if let (CachedContract::Cached(contract), ExportedFunction::Call) =
1070			(&frame.contract_info, frame.entry_point)
1071		{
1072			AccountInfo::<T>::insert_contract(
1073				&T::AddressMapper::to_address(&frame.account_id),
1074				contract.clone(),
1075			);
1076		}
1077
1078		let frame = top_frame_mut!(self);
1079		let nested_gas = &mut frame.nested_gas;
1080		let nested_storage = &mut frame.nested_storage;
1081		if let Some((frame, executable)) = Self::new_frame(
1082			frame_args,
1083			value_transferred,
1084			nested_gas,
1085			gas_limit,
1086			nested_storage,
1087			deposit_limit,
1088			read_only,
1089			false,
1090		)? {
1091			self.frames.try_push(frame).map_err(|_| Error::<T>::MaxCallDepthReached)?;
1092			Ok(Some(executable))
1093		} else {
1094			Ok(None)
1095		}
1096	}
1097
1098	/// Run the current (top) frame.
1099	///
1100	/// This can be either a call or an instantiate.
1101	fn run(
1102		&mut self,
1103		executable: ExecutableOrPrecompile<T, E, Self>,
1104		input_data: Vec<u8>,
1105		bump_nonce: BumpNonce,
1106	) -> Result<(), ExecError> {
1107		let frame = self.top_frame();
1108		let entry_point = frame.entry_point;
1109		let is_pvm = executable.is_pvm();
1110
1111		if_tracing(|tracer| {
1112			tracer.enter_child_span(
1113				self.caller().account_id().map(T::AddressMapper::to_address).unwrap_or_default(),
1114				T::AddressMapper::to_address(&frame.account_id),
1115				frame.delegate.is_some(),
1116				frame.read_only,
1117				frame.value_transferred,
1118				&input_data,
1119				frame.nested_gas.gas_left(),
1120			);
1121		});
1122
1123		// The output of the caller frame will be replaced by the output of this run.
1124		// It is also not accessible from nested frames.
1125		// Hence we drop it early to save the memory.
1126		let frames_len = self.frames.len();
1127		if let Some(caller_frame) = match frames_len {
1128			0 => None,
1129			1 => Some(&mut self.first_frame.last_frame_output),
1130			_ => self.frames.get_mut(frames_len - 2).map(|frame| &mut frame.last_frame_output),
1131		} {
1132			*caller_frame = Default::default();
1133		}
1134
1135		self.transient_storage.start_transaction();
1136
1137		let do_transaction = || -> ExecResult {
1138			let caller = self.caller();
1139			let skip_transfer = self.skip_transfer;
1140			let frame = top_frame_mut!(self);
1141			let account_id = &frame.account_id.clone();
1142
1143			if u32::try_from(input_data.len())
1144				.map(|len| len > limits::CALLDATA_BYTES)
1145				.unwrap_or(true)
1146			{
1147				Err(<Error<T>>::CallDataTooLarge)?;
1148			}
1149
1150			// We need to make sure that the contract's account exists before calling its
1151			// constructor.
1152			if entry_point == ExportedFunction::Constructor {
1153				// Root origin can't be used to instantiate a contract, so it is safe to assume that
1154				// if we reached this point the origin has an associated account.
1155				let origin = &self.origin.account_id()?;
1156
1157				let ed = <Contracts<T>>::min_balance();
1158				frame.nested_storage.record_charge(&StorageDeposit::Charge(ed))?;
1159				if self.skip_transfer {
1160					T::Currency::set_balance(account_id, ed);
1161				} else {
1162					T::Currency::transfer(origin, account_id, ed, Preservation::Preserve)
1163						.map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
1164				}
1165
1166				// A consumer is added at account creation and removed it on termination, otherwise
1167				// the runtime could remove the account. As long as a contract exists its
1168				// account must exist. With the consumer, a correct runtime cannot remove the
1169				// account.
1170				<System<T>>::inc_consumers(account_id)?;
1171
1172				// Contracts nonce starts at 1
1173				<System<T>>::inc_account_nonce(account_id);
1174
1175				if matches!(bump_nonce, BumpNonce::Yes) {
1176					// Needs to be incremented before calling into the code so that it is visible
1177					// in case of recursion.
1178					<System<T>>::inc_account_nonce(caller.account_id()?);
1179				}
1180				// The incremented refcount should be visible to the constructor.
1181				if is_pvm {
1182					<CodeInfo<T>>::increment_refcount(
1183						*executable
1184							.as_executable()
1185							.expect("Precompiles cannot be instantiated; qed")
1186							.code_hash(),
1187					)?;
1188				}
1189			}
1190
1191			// Every non delegate call or instantiate also optionally transfers the balance.
1192			// If it is a delegate call, then we've already transferred tokens in the
1193			// last non-delegate frame.
1194			if frame.delegate.is_none() {
1195				Self::transfer_from_origin(
1196					&self.origin,
1197					&caller,
1198					account_id,
1199					frame.value_transferred,
1200					&mut frame.nested_storage,
1201				)?;
1202			}
1203
1204			// We need to make sure that the pre-compiles contract exist before executing it.
1205			// A few more conditionals:
1206			// 	- Only contracts with extended API (has_contract_info) are guaranteed to have an
1207			//    account.
1208			//  - Only when not delegate calling we are executing in the context of the pre-compile.
1209			//    Pre-compiles itself cannot delegate call.
1210			if let Some(precompile) = executable.as_precompile() {
1211				if precompile.has_contract_info() &&
1212					frame.delegate.is_none() &&
1213					!<System<T>>::account_exists(account_id)
1214				{
1215					// prefix matching pre-compiles cannot have a contract info
1216					// hence we only mint once per pre-compile
1217					T::Currency::mint_into(account_id, T::Currency::minimum_balance())?;
1218					// make sure the pre-compile does not destroy its account by accident
1219					<System<T>>::inc_consumers(account_id)?;
1220				}
1221			}
1222
1223			let mut code_deposit = executable
1224				.as_executable()
1225				.map(|exec| exec.code_info().deposit())
1226				.unwrap_or_default();
1227
1228			let mut output = match executable {
1229				ExecutableOrPrecompile::Executable(executable) =>
1230					executable.execute(self, entry_point, input_data),
1231				ExecutableOrPrecompile::Precompile { instance, .. } =>
1232					instance.call(input_data, self),
1233			}
1234			.and_then(|output| {
1235				if u32::try_from(output.data.len())
1236					.map(|len| len > limits::CALLDATA_BYTES)
1237					.unwrap_or(true)
1238				{
1239					Err(<Error<T>>::ReturnDataTooLarge)?;
1240				}
1241				Ok(output)
1242			})
1243			.map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
1244
1245			// Avoid useless work that would be reverted anyways.
1246			if output.did_revert() {
1247				return Ok(output);
1248			}
1249
1250			let frame = self.top_frame_mut();
1251
1252			// The deposit we charge for a contract depends on the size of the immutable data.
1253			// Hence we need to delay charging the base deposit after execution.
1254			if entry_point == ExportedFunction::Constructor {
1255				let contract_info = frame.contract_info();
1256				// if we are dealing with EVM bytecode
1257				// We upload the new runtime code, and update the code
1258				if !is_pvm {
1259					// Only keep return data for tracing
1260					let data = if crate::tracing::if_tracing(|_| {}).is_none() {
1261						core::mem::replace(&mut output.data, Default::default())
1262					} else {
1263						output.data.clone()
1264					};
1265
1266					let mut module = crate::ContractBlob::<T>::from_evm_runtime_code(
1267						data,
1268						caller.account_id()?.clone(),
1269					)?;
1270					module.store_code(skip_transfer)?;
1271					code_deposit = module.code_info().deposit();
1272					contract_info.code_hash = *module.code_hash();
1273
1274					<CodeInfo<T>>::increment_refcount(contract_info.code_hash)?;
1275				}
1276
1277				let deposit = contract_info.update_base_deposit(code_deposit);
1278				frame
1279					.nested_storage
1280					.charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit));
1281			}
1282
1283			// The storage deposit is only charged at the end of every call stack.
1284			// To make sure that no sub call uses more than it is allowed to,
1285			// the limit is manually enforced here.
1286			let contract = frame.contract_info.as_contract();
1287			frame
1288				.nested_storage
1289				.enforce_limit(contract)
1290				.map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?;
1291
1292			Ok(output)
1293		};
1294
1295		// All changes performed by the contract are executed under a storage transaction.
1296		// This allows for roll back on error. Changes to the cached contract_info are
1297		// committed or rolled back when popping the frame.
1298		//
1299		// `with_transactional` may return an error caused by a limit in the
1300		// transactional storage depth.
1301		let transaction_outcome =
1302			with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1303				let output = do_transaction();
1304				match &output {
1305					Ok(result) if !result.did_revert() =>
1306						TransactionOutcome::Commit(Ok((true, output))),
1307					_ => TransactionOutcome::Rollback(Ok((false, output))),
1308				}
1309			});
1310
1311		let (success, output) = match transaction_outcome {
1312			// `with_transactional` executed successfully, and we have the expected output.
1313			Ok((success, output)) => {
1314				if_tracing(|tracer| {
1315					let gas_consumed = top_frame!(self).nested_gas.gas_consumed();
1316					match &output {
1317						Ok(output) => tracer.exit_child_span(&output, gas_consumed),
1318						Err(e) => tracer.exit_child_span_with_error(e.error.into(), gas_consumed),
1319					}
1320				});
1321
1322				(success, output)
1323			},
1324			// `with_transactional` returned an error, and we propagate that error and note no state
1325			// has changed.
1326			Err(error) => {
1327				if_tracing(|tracer| {
1328					let gas_consumed = top_frame!(self).nested_gas.gas_consumed();
1329					tracer.exit_child_span_with_error(error.into(), gas_consumed);
1330				});
1331
1332				(false, Err(error.into()))
1333			},
1334		};
1335
1336		if success {
1337			self.transient_storage.commit_transaction();
1338		} else {
1339			self.transient_storage.rollback_transaction();
1340		}
1341
1342		log::trace!(target: LOG_TARGET, "frame finished with: {output:?}");
1343
1344		self.pop_frame(success);
1345		output.map(|output| {
1346			self.top_frame_mut().last_frame_output = output;
1347		})
1348	}
1349
1350	/// Remove the current (top) frame from the stack.
1351	///
1352	/// This is called after running the current frame. It commits cached values to storage
1353	/// and invalidates all stale references to it that might exist further down the call stack.
1354	fn pop_frame(&mut self, persist: bool) {
1355		// Pop the current frame from the stack and return it in case it needs to interact
1356		// with duplicates that might exist on the stack.
1357		// A `None` means that we are returning from the `first_frame`.
1358		let frame = self.frames.pop();
1359
1360		// Both branches do essentially the same with the exception. The difference is that
1361		// the else branch does consume the hardcoded `first_frame`.
1362		if let Some(mut frame) = frame {
1363			let account_id = &frame.account_id;
1364			let prev = top_frame_mut!(self);
1365
1366			prev.nested_gas.absorb_nested(frame.nested_gas);
1367
1368			// Only gas counter changes are persisted in case of a failure.
1369			if !persist {
1370				return;
1371			}
1372
1373			// Record the storage meter changes of the nested call into the parent meter.
1374			// If the dropped frame's contract has a contract info we update the deposit
1375			// counter in its contract info. The load is necessary to pull it from storage in case
1376			// it was invalidated.
1377			frame.contract_info.load(account_id);
1378			let mut contract = frame.contract_info.into_contract();
1379			prev.nested_storage.absorb(frame.nested_storage, account_id, contract.as_mut());
1380
1381			// In case the contract wasn't terminated we need to persist changes made to it.
1382			if let Some(contract) = contract {
1383				// optimization: Predecessor is the same contract.
1384				// We can just copy the contract into the predecessor without a storage write.
1385				// This is possible when there is no other contract in-between that could
1386				// trigger a rollback.
1387				if prev.account_id == *account_id {
1388					prev.contract_info = CachedContract::Cached(contract);
1389					return;
1390				}
1391
1392				// Predecessor is a different contract: We persist the info and invalidate the first
1393				// stale cache we find. This triggers a reload from storage on next use. We skip(1)
1394				// because that case is already handled by the optimization above. Only the first
1395				// cache needs to be invalidated because that one will invalidate the next cache
1396				// when it is popped from the stack.
1397				AccountInfo::<T>::insert_contract(
1398					&T::AddressMapper::to_address(account_id),
1399					contract,
1400				);
1401				if let Some(f) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) {
1402					f.contract_info.invalidate();
1403				}
1404			}
1405		} else {
1406			self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas));
1407			if !persist {
1408				return;
1409			}
1410			let mut contract = self.first_frame.contract_info.as_contract();
1411			self.storage_meter.absorb(
1412				mem::take(&mut self.first_frame.nested_storage),
1413				&self.first_frame.account_id,
1414				contract.as_deref_mut(),
1415			);
1416			if let Some(contract) = contract {
1417				AccountInfo::<T>::insert_contract(
1418					&T::AddressMapper::to_address(&self.first_frame.account_id),
1419					contract.clone(),
1420				);
1421			}
1422		}
1423	}
1424
1425	/// Transfer some funds from `from` to `to`.
1426	///
1427	/// This is a no-op for zero `value`, avoiding events to be emitted for zero balance transfers.
1428	///
1429	/// If the destination account does not exist, it is pulled into existence by transferring the
1430	/// ED from `origin` to the new account. The total amount transferred to `to` will be ED +
1431	/// `value`. This makes the ED fully transparent for contracts.
1432	/// The ED transfer is executed atomically with the actual transfer, avoiding the possibility of
1433	/// the ED transfer succeeding but the actual transfer failing. In other words, if the `to` does
1434	/// not exist, the transfer does fail and nothing will be sent to `to` if either `origin` can
1435	/// not provide the ED or transferring `value` from `from` to `to` fails.
1436	/// Note: This will also fail if `origin` is root.
1437	fn transfer<S: storage::meter::State + Default + Debug>(
1438		origin: &Origin<T>,
1439		from: &T::AccountId,
1440		to: &T::AccountId,
1441		value: U256,
1442		storage_meter: &mut storage::meter::GenericMeter<T, S>,
1443	) -> DispatchResult {
1444		fn transfer_with_dust<T: Config>(
1445			from: &AccountIdOf<T>,
1446			to: &AccountIdOf<T>,
1447			value: BalanceWithDust<BalanceOf<T>>,
1448		) -> DispatchResult {
1449			let (value, dust) = value.deconstruct();
1450
1451			fn transfer_balance<T: Config>(
1452				from: &AccountIdOf<T>,
1453				to: &AccountIdOf<T>,
1454				value: BalanceOf<T>,
1455			) -> DispatchResult {
1456				T::Currency::transfer(from, to, value, Preservation::Preserve)
1457				.map_err(|err| {
1458					log::debug!(target: crate::LOG_TARGET, "Transfer failed: from {from:?} to {to:?} (value: ${value:?}). Err: {err:?}");
1459					Error::<T>::TransferFailed
1460				})?;
1461				Ok(())
1462			}
1463
1464			fn transfer_dust<T: Config>(
1465				from: &mut AccountInfo<T>,
1466				to: &mut AccountInfo<T>,
1467				dust: u32,
1468			) -> DispatchResult {
1469				from.dust =
1470					from.dust.checked_sub(dust).ok_or_else(|| Error::<T>::TransferFailed)?;
1471				to.dust = to.dust.checked_add(dust).ok_or_else(|| Error::<T>::TransferFailed)?;
1472				Ok(())
1473			}
1474
1475			if dust.is_zero() {
1476				return transfer_balance::<T>(from, to, value)
1477			}
1478
1479			let from_addr = <T::AddressMapper as AddressMapper<T>>::to_address(from);
1480			let mut from_info = AccountInfoOf::<T>::get(&from_addr).unwrap_or_default();
1481
1482			let to_addr = <T::AddressMapper as AddressMapper<T>>::to_address(to);
1483			let mut to_info = AccountInfoOf::<T>::get(&to_addr).unwrap_or_default();
1484
1485			let plank = T::NativeToEthRatio::get();
1486
1487			if from_info.dust < dust {
1488				T::Currency::burn_from(
1489					from,
1490					1u32.into(),
1491					Preservation::Preserve,
1492					Precision::Exact,
1493					Fortitude::Polite,
1494				)
1495				.map_err(|err| {
1496					log::debug!(target: crate::LOG_TARGET, "Burning 1 plank from {from:?} failed. Err: {err:?}");
1497					Error::<T>::TransferFailed
1498				})?;
1499
1500				from_info.dust =
1501					from_info.dust.checked_add(plank).ok_or_else(|| Error::<T>::TransferFailed)?;
1502			}
1503
1504			transfer_balance::<T>(from, to, value)?;
1505			transfer_dust::<T>(&mut from_info, &mut to_info, dust)?;
1506
1507			if to_info.dust >= plank {
1508				T::Currency::mint_into(to, 1u32.into())?;
1509				to_info.dust =
1510					to_info.dust.checked_sub(plank).ok_or_else(|| Error::<T>::TransferFailed)?;
1511			}
1512
1513			AccountInfoOf::<T>::set(&from_addr, Some(from_info));
1514			AccountInfoOf::<T>::set(&to_addr, Some(to_info));
1515
1516			Ok(())
1517		}
1518
1519		let value = BalanceWithDust::<BalanceOf<T>>::from_value::<T>(value)?;
1520		if value.is_zero() {
1521			return Ok(());
1522		}
1523
1524		if <System<T>>::account_exists(to) {
1525			return transfer_with_dust::<T>(from, to, value)
1526		}
1527
1528		let origin = origin.account_id()?;
1529		let ed = <T as Config>::Currency::minimum_balance();
1530		with_transaction(|| -> TransactionOutcome<DispatchResult> {
1531			match storage_meter
1532				.record_charge(&StorageDeposit::Charge(ed))
1533				.and_then(|_| {
1534					T::Currency::transfer(origin, to, ed, Preservation::Preserve)
1535						.map_err(|_| Error::<T>::StorageDepositNotEnoughFunds.into())
1536				})
1537				.and_then(|_| transfer_with_dust::<T>(from, to, value))
1538			{
1539				Ok(_) => TransactionOutcome::Commit(Ok(())),
1540				Err(err) => TransactionOutcome::Rollback(Err(err)),
1541			}
1542		})
1543	}
1544
1545	/// Same as `transfer` but `from` is an `Origin`.
1546	fn transfer_from_origin<S: storage::meter::State + Default + Debug>(
1547		origin: &Origin<T>,
1548		from: &Origin<T>,
1549		to: &T::AccountId,
1550		value: U256,
1551		storage_meter: &mut storage::meter::GenericMeter<T, S>,
1552	) -> ExecResult {
1553		// If the from address is root there is no account to transfer from, and therefore we can't
1554		// take any `value` other than 0.
1555		let from = match from {
1556			Origin::Signed(caller) => caller,
1557			Origin::Root if value.is_zero() => return Ok(Default::default()),
1558			Origin::Root => return Err(DispatchError::RootNotAllowed.into()),
1559		};
1560		Self::transfer(origin, from, to, value, storage_meter)
1561			.map(|_| Default::default())
1562			.map_err(Into::into)
1563	}
1564
1565	/// Reference to the current (top) frame.
1566	fn top_frame(&self) -> &Frame<T> {
1567		top_frame!(self)
1568	}
1569
1570	/// Mutable reference to the current (top) frame.
1571	fn top_frame_mut(&mut self) -> &mut Frame<T> {
1572		top_frame_mut!(self)
1573	}
1574
1575	/// Iterator over all frames.
1576	///
1577	/// The iterator starts with the top frame and ends with the root frame.
1578	fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1579		core::iter::once(&self.first_frame).chain(&self.frames).rev()
1580	}
1581
1582	/// Same as `frames` but with a mutable reference as iterator item.
1583	fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1584		core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1585	}
1586
1587	/// Returns whether the current contract is on the stack multiple times.
1588	fn is_recursive(&self) -> bool {
1589		let account_id = &self.top_frame().account_id;
1590		self.frames().skip(1).any(|f| &f.account_id == account_id)
1591	}
1592
1593	/// Returns whether the specified contract allows to be reentered right now.
1594	fn allows_reentry(&self, id: &T::AccountId) -> bool {
1595		!self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1596	}
1597
1598	/// Returns the *free* balance of the supplied AccountId.
1599	fn account_balance(&self, who: &T::AccountId) -> U256 {
1600		let balance = AccountInfo::<T>::balance(AccountIdOrAddress::AccountId(who.clone()));
1601		crate::Pallet::<T>::convert_native_to_evm(balance)
1602	}
1603
1604	/// Certain APIs, e.g. `{set,get}_immutable_data` behave differently depending
1605	/// on the configured entry point. Thus, we allow setting the export manually.
1606	#[cfg(feature = "runtime-benchmarks")]
1607	pub(crate) fn override_export(&mut self, export: ExportedFunction) {
1608		self.top_frame_mut().entry_point = export;
1609	}
1610
1611	#[cfg(feature = "runtime-benchmarks")]
1612	pub(crate) fn set_block_number(&mut self, block_number: BlockNumberFor<T>) {
1613		self.block_number = block_number;
1614	}
1615
1616	fn block_hash(&self, block_number: U256) -> Option<H256> {
1617		let Ok(block_number) = BlockNumberFor::<T>::try_from(block_number) else {
1618			return None;
1619		};
1620		if block_number >= self.block_number {
1621			return None;
1622		}
1623		if block_number < self.block_number.saturating_sub(256u32.into()) {
1624			return None;
1625		}
1626		Some(System::<T>::block_hash(&block_number).into())
1627	}
1628}
1629
1630impl<'a, T, E> Ext for Stack<'a, T, E>
1631where
1632	T: Config,
1633	E: Executable<T>,
1634	BalanceOf<T>: Into<U256> + TryFrom<U256>,
1635	MomentOf<T>: Into<U256>,
1636	T::Hash: frame_support::traits::IsType<H256>,
1637{
1638	fn delegate_call(
1639		&mut self,
1640		gas_limit: Weight,
1641		deposit_limit: U256,
1642		address: H160,
1643		input_data: Vec<u8>,
1644	) -> Result<(), ExecError> {
1645		// We reset the return data now, so it is cleared out even if no new frame was executed.
1646		// This is for example the case for unknown code hashes or creating the frame fails.
1647		*self.last_frame_output_mut() = Default::default();
1648
1649		let top_frame = self.top_frame_mut();
1650		let contract_info = top_frame.contract_info().clone();
1651		let account_id = top_frame.account_id.clone();
1652		let value = top_frame.value_transferred;
1653		if let Some(executable) = self.push_frame(
1654			FrameArgs::Call {
1655				dest: account_id,
1656				cached_info: Some(contract_info),
1657				delegated_call: Some(DelegateInfo {
1658					caller: self.caller().clone(),
1659					callee: address,
1660				}),
1661			},
1662			value,
1663			gas_limit,
1664			deposit_limit.saturated_into::<BalanceOf<T>>(),
1665			self.is_read_only(),
1666		)? {
1667			self.run(executable, input_data, BumpNonce::Yes)
1668		} else {
1669			// Delegate-calls to non-contract accounts are considered success.
1670			Ok(())
1671		}
1672	}
1673
1674	fn terminate(&mut self, beneficiary: &H160) -> Result<CodeRemoved, DispatchError> {
1675		if self.is_recursive() {
1676			return Err(Error::<T>::TerminatedWhileReentrant.into());
1677		}
1678		let frame = self.top_frame_mut();
1679		if frame.entry_point == ExportedFunction::Constructor {
1680			return Err(Error::<T>::TerminatedInConstructor.into());
1681		}
1682		let info = frame.terminate();
1683		let beneficiary_account = T::AddressMapper::to_account_id(beneficiary);
1684		frame.nested_storage.terminate(&info, beneficiary_account);
1685
1686		info.queue_trie_for_deletion();
1687		let account_address = T::AddressMapper::to_address(&frame.account_id);
1688		AccountInfoOf::<T>::remove(&account_address);
1689		ImmutableDataOf::<T>::remove(&account_address);
1690		let removed = <CodeInfo<T>>::decrement_refcount(info.code_hash)?;
1691
1692		Ok(removed)
1693	}
1694
1695	fn own_code_hash(&mut self) -> &H256 {
1696		&self.top_frame_mut().contract_info().code_hash
1697	}
1698
1699	/// TODO: This should be changed to run the constructor of the supplied `hash`.
1700	///
1701	/// Because the immutable data is attached to a contract and not a code,
1702	/// we need to update the immutable data too.
1703	///
1704	/// Otherwise we open a massive footgun:
1705	/// If the immutables changed in the new code, the contract will brick.
1706	///
1707	/// A possible implementation strategy is to add a flag to `FrameArgs::Instantiate`,
1708	/// so that `fn run()` will roll back any changes if this flag is set.
1709	///
1710	/// After running the constructor, the new immutable data is already stored in
1711	/// `self.immutable_data` at the address of the (reverted) contract instantiation.
1712	///
1713	/// The `set_code_hash` contract API stays disabled until this change is implemented.
1714	fn set_code_hash(&mut self, hash: H256) -> Result<CodeRemoved, DispatchError> {
1715		let frame = top_frame_mut!(self);
1716
1717		let info = frame.contract_info();
1718
1719		let prev_hash = info.code_hash;
1720		info.code_hash = hash;
1721
1722		let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?;
1723
1724		let old_base_deposit = info.storage_base_deposit();
1725		let new_base_deposit = info.update_base_deposit(code_info.deposit());
1726		let deposit = StorageDeposit::Charge(new_base_deposit)
1727			.saturating_sub(&StorageDeposit::Charge(old_base_deposit));
1728
1729		frame.nested_storage.charge_deposit(frame.account_id.clone(), deposit);
1730
1731		<CodeInfo<T>>::increment_refcount(hash)?;
1732		let removed = <CodeInfo<T>>::decrement_refcount(prev_hash)?;
1733		Ok(removed)
1734	}
1735
1736	fn immutable_data_len(&mut self) -> u32 {
1737		self.top_frame_mut().contract_info().immutable_data_len()
1738	}
1739
1740	fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> {
1741		if self.top_frame().entry_point == ExportedFunction::Constructor {
1742			return Err(Error::<T>::InvalidImmutableAccess.into());
1743		}
1744
1745		// Immutable is read from contract code being executed
1746		let address = self
1747			.top_frame()
1748			.delegate
1749			.as_ref()
1750			.map(|d| d.callee)
1751			.unwrap_or(T::AddressMapper::to_address(self.account_id()));
1752		Ok(<ImmutableDataOf<T>>::get(address).ok_or_else(|| Error::<T>::InvalidImmutableAccess)?)
1753	}
1754
1755	fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> {
1756		let frame = self.top_frame_mut();
1757		if frame.entry_point == ExportedFunction::Call || data.is_empty() {
1758			return Err(Error::<T>::InvalidImmutableAccess.into());
1759		}
1760		frame.contract_info().set_immutable_data_len(data.len() as u32);
1761		<ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data);
1762		Ok(())
1763	}
1764}
1765
1766impl<'a, T, E> PrecompileWithInfoExt for Stack<'a, T, E>
1767where
1768	T: Config,
1769	E: Executable<T>,
1770	BalanceOf<T>: Into<U256> + TryFrom<U256>,
1771	MomentOf<T>: Into<U256>,
1772	T::Hash: frame_support::traits::IsType<H256>,
1773{
1774	fn get_storage(&mut self, key: &Key) -> Option<Vec<u8>> {
1775		self.top_frame_mut().contract_info().read(key)
1776	}
1777
1778	fn get_storage_size(&mut self, key: &Key) -> Option<u32> {
1779		self.top_frame_mut().contract_info().size(key.into())
1780	}
1781
1782	fn set_storage(
1783		&mut self,
1784		key: &Key,
1785		value: Option<Vec<u8>>,
1786		take_old: bool,
1787	) -> Result<WriteOutcome, DispatchError> {
1788		let frame = self.top_frame_mut();
1789		frame.contract_info.get(&frame.account_id).write(
1790			key.into(),
1791			value,
1792			Some(&mut frame.nested_storage),
1793			take_old,
1794		)
1795	}
1796
1797	fn charge_storage(&mut self, diff: &Diff) {
1798		self.top_frame_mut().nested_storage.charge(diff)
1799	}
1800
1801	fn instantiate(
1802		&mut self,
1803		gas_limit: Weight,
1804		deposit_limit: U256,
1805		code: Code,
1806		value: U256,
1807		input_data: Vec<u8>,
1808		salt: Option<&[u8; 32]>,
1809	) -> Result<H160, ExecError> {
1810		// We reset the return data now, so it is cleared out even if no new frame was executed.
1811		// This is for example the case when creating the frame fails.
1812		*self.last_frame_output_mut() = Default::default();
1813		let sender = self.top_frame().account_id.clone();
1814		let executable = match &code {
1815			Code::Upload(bytecode) => {
1816				if !T::AllowEVMBytecode::get() {
1817					return Err(<Error<T>>::CodeRejected.into());
1818				}
1819				E::from_evm_init_code(bytecode.clone(), sender.clone())?
1820			},
1821			Code::Existing(hash) => E::from_storage(*hash, self.gas_meter_mut())?,
1822		};
1823		let executable = self.push_frame(
1824			FrameArgs::Instantiate {
1825				sender: sender.clone(),
1826				executable,
1827				salt,
1828				input_data: input_data.as_ref(),
1829			},
1830			value,
1831			gas_limit,
1832			deposit_limit.saturated_into::<BalanceOf<T>>(),
1833			self.is_read_only(),
1834		)?;
1835		let address = T::AddressMapper::to_address(&self.top_frame().account_id);
1836		if_tracing(|t| t.instantiate_code(&code, salt));
1837		self.run(executable.expect(FRAME_ALWAYS_EXISTS_ON_INSTANTIATE), input_data, BumpNonce::Yes)
1838			.map(|_| address)
1839	}
1840}
1841
1842impl<'a, T, E> PrecompileExt for Stack<'a, T, E>
1843where
1844	T: Config,
1845	E: Executable<T>,
1846	BalanceOf<T>: Into<U256> + TryFrom<U256>,
1847	MomentOf<T>: Into<U256>,
1848	T::Hash: frame_support::traits::IsType<H256>,
1849{
1850	type T = T;
1851
1852	fn call(
1853		&mut self,
1854		gas_limit: Weight,
1855		deposit_limit: U256,
1856		dest_addr: &H160,
1857		value: U256,
1858		input_data: Vec<u8>,
1859		allows_reentry: bool,
1860		read_only: bool,
1861	) -> Result<(), ExecError> {
1862		// Before pushing the new frame: Protect the caller contract against reentrancy attacks.
1863		// It is important to do this before calling `allows_reentry` so that a direct recursion
1864		// is caught by it.
1865		self.top_frame_mut().allows_reentry = allows_reentry;
1866
1867		// We reset the return data now, so it is cleared out even if no new frame was executed.
1868		// This is for example the case for balance transfers or when creating the frame fails.
1869		*self.last_frame_output_mut() = Default::default();
1870
1871		let try_call = || {
1872			// Enable read-only access if requested; cannot disable it if already set.
1873			let is_read_only = read_only || self.is_read_only();
1874
1875			// We can skip the stateful lookup for pre-compiles.
1876			let dest = if <AllPrecompiles<T>>::get::<Self>(dest_addr.as_fixed_bytes()).is_some() {
1877				T::AddressMapper::to_fallback_account_id(dest_addr)
1878			} else {
1879				T::AddressMapper::to_account_id(dest_addr)
1880			};
1881
1882			if !self.allows_reentry(&dest) {
1883				return Err(<Error<T>>::ReentranceDenied.into());
1884			}
1885
1886			// We ignore instantiate frames in our search for a cached contract.
1887			// Otherwise it would be possible to recursively call a contract from its own
1888			// constructor: We disallow calling not fully constructed contracts.
1889			let cached_info = self
1890				.frames()
1891				.find(|f| f.entry_point == ExportedFunction::Call && f.account_id == dest)
1892				.and_then(|f| match &f.contract_info {
1893					CachedContract::Cached(contract) => Some(contract.clone()),
1894					_ => None,
1895				});
1896
1897			if let Some(executable) = self.push_frame(
1898				FrameArgs::Call { dest: dest.clone(), cached_info, delegated_call: None },
1899				value,
1900				gas_limit,
1901				deposit_limit.saturated_into::<BalanceOf<T>>(),
1902				is_read_only,
1903			)? {
1904				self.run(executable, input_data, BumpNonce::Yes)
1905			} else {
1906				if_tracing(|t| {
1907					t.enter_child_span(
1908						T::AddressMapper::to_address(self.account_id()),
1909						T::AddressMapper::to_address(&dest),
1910						false,
1911						is_read_only,
1912						value,
1913						&input_data,
1914						Weight::zero(),
1915					);
1916				});
1917
1918				let result = if is_read_only && value.is_zero() {
1919					Ok(Default::default())
1920				} else if is_read_only {
1921					Err(Error::<T>::StateChangeDenied.into())
1922				} else {
1923					let account_id = self.account_id().clone();
1924					let frame = top_frame_mut!(self);
1925					Self::transfer_from_origin(
1926						&self.origin,
1927						&Origin::from_account_id(account_id),
1928						&dest,
1929						value,
1930						&mut frame.nested_storage,
1931					)
1932				};
1933
1934				if_tracing(|t| match result {
1935					Ok(ref output) => t.exit_child_span(&output, Weight::zero()),
1936					Err(e) => t.exit_child_span_with_error(e.error.into(), Weight::zero()),
1937				});
1938
1939				result.map(|_| ())
1940			}
1941		};
1942
1943		// We need to make sure to reset `allows_reentry` even on failure.
1944		let result = try_call();
1945
1946		// Protection is on a per call basis.
1947		self.top_frame_mut().allows_reentry = true;
1948
1949		result
1950	}
1951
1952	fn get_transient_storage(&self, key: &Key) -> Option<Vec<u8>> {
1953		self.transient_storage.read(self.account_id(), key)
1954	}
1955
1956	fn get_transient_storage_size(&self, key: &Key) -> Option<u32> {
1957		self.transient_storage
1958			.read(self.account_id(), key)
1959			.map(|value| value.len() as _)
1960	}
1961
1962	fn set_transient_storage(
1963		&mut self,
1964		key: &Key,
1965		value: Option<Vec<u8>>,
1966		take_old: bool,
1967	) -> Result<WriteOutcome, DispatchError> {
1968		let account_id = self.account_id().clone();
1969		self.transient_storage.write(&account_id, key, value, take_old)
1970	}
1971
1972	fn account_id(&self) -> &T::AccountId {
1973		&self.top_frame().account_id
1974	}
1975
1976	fn caller(&self) -> Origin<T> {
1977		if let Some(DelegateInfo { caller, .. }) = &self.top_frame().delegate {
1978			caller.clone()
1979		} else {
1980			self.frames()
1981				.nth(1)
1982				.map(|f| Origin::from_account_id(f.account_id.clone()))
1983				.unwrap_or(self.origin.clone())
1984		}
1985	}
1986
1987	fn origin(&self) -> &Origin<T> {
1988		&self.origin
1989	}
1990
1991	fn code_hash(&self, address: &H160) -> H256 {
1992		if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
1993			return sp_io::hashing::keccak_256(code).into()
1994		}
1995
1996		<AccountInfo<T>>::load_contract(&address)
1997			.map(|contract| contract.code_hash)
1998			.unwrap_or_else(|| {
1999				if System::<T>::account_exists(&T::AddressMapper::to_account_id(address)) {
2000					return EMPTY_CODE_HASH;
2001				}
2002				H256::zero()
2003			})
2004	}
2005
2006	fn code_size(&self, address: &H160) -> u64 {
2007		if let Some(code) = <AllPrecompiles<T>>::code(address.as_fixed_bytes()) {
2008			return code.len() as u64
2009		}
2010
2011		<AccountInfo<T>>::load_contract(&address)
2012			.and_then(|contract| CodeInfoOf::<T>::get(contract.code_hash))
2013			.map(|info| info.code_len())
2014			.unwrap_or_default()
2015	}
2016
2017	fn caller_is_origin(&self) -> bool {
2018		self.origin == self.caller()
2019	}
2020
2021	fn caller_is_root(&self) -> bool {
2022		// if the caller isn't origin, then it can't be root.
2023		self.caller_is_origin() && self.origin == Origin::Root
2024	}
2025
2026	fn balance(&self) -> U256 {
2027		self.account_balance(&self.top_frame().account_id)
2028	}
2029
2030	fn balance_of(&self, address: &H160) -> U256 {
2031		let balance =
2032			self.account_balance(&<Self::T as Config>::AddressMapper::to_account_id(address));
2033		if_tracing(|tracer| {
2034			tracer.balance_read(address, balance);
2035		});
2036		balance
2037	}
2038
2039	fn value_transferred(&self) -> U256 {
2040		self.top_frame().value_transferred.into()
2041	}
2042
2043	fn now(&self) -> U256 {
2044		(self.timestamp / 1000u32.into()).into()
2045	}
2046
2047	fn minimum_balance(&self) -> U256 {
2048		T::Currency::minimum_balance().into()
2049	}
2050
2051	fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
2052		let contract = T::AddressMapper::to_address(self.account_id());
2053		if_tracing(|tracer| {
2054			tracer.log_event(contract, &topics, &data);
2055		});
2056		Contracts::<Self::T>::deposit_event(Event::ContractEmitted { contract, data, topics });
2057	}
2058
2059	fn block_number(&self) -> U256 {
2060		self.block_number.into()
2061	}
2062
2063	fn block_hash(&self, block_number: U256) -> Option<H256> {
2064		self.block_hash(block_number)
2065	}
2066
2067	fn block_author(&self) -> Option<H160> {
2068		Contracts::<Self::T>::block_author()
2069	}
2070
2071	fn gas_limit(&self) -> u64 {
2072		<T as frame_system::Config>::BlockWeights::get().max_block.ref_time()
2073	}
2074
2075	fn chain_id(&self) -> u64 {
2076		<T as Config>::ChainId::get()
2077	}
2078
2079	fn max_value_size(&self) -> u32 {
2080		limits::PAYLOAD_BYTES
2081	}
2082
2083	fn get_weight_price(&self, weight: Weight) -> U256 {
2084		T::WeightPrice::convert(weight).into()
2085	}
2086
2087	fn gas_meter(&self) -> &GasMeter<Self::T> {
2088		&self.top_frame().nested_gas
2089	}
2090
2091	fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T> {
2092		&mut self.top_frame_mut().nested_gas
2093	}
2094
2095	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
2096		secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
2097	}
2098
2099	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
2100		sp_io::crypto::sr25519_verify(
2101			&SR25519Signature::from(*signature),
2102			message,
2103			&SR25519Public::from(*pub_key),
2104		)
2105	}
2106
2107	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> {
2108		ECDSAPublic::from(*pk).to_eth_address()
2109	}
2110
2111	#[cfg(any(test, feature = "runtime-benchmarks"))]
2112	fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
2113		self.top_frame_mut().contract_info()
2114	}
2115
2116	#[cfg(any(feature = "runtime-benchmarks", test))]
2117	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
2118		&mut self.transient_storage
2119	}
2120
2121	fn is_read_only(&self) -> bool {
2122		self.top_frame().read_only
2123	}
2124
2125	fn last_frame_output(&self) -> &ExecReturnValue {
2126		&self.top_frame().last_frame_output
2127	}
2128
2129	fn last_frame_output_mut(&mut self) -> &mut ExecReturnValue {
2130		&mut self.top_frame_mut().last_frame_output
2131	}
2132}
2133
2134mod sealing {
2135	use super::*;
2136
2137	pub trait Sealed {}
2138	impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
2139
2140	#[cfg(test)]
2141	impl<T: Config> sealing::Sealed for mock_ext::MockExt<T> {}
2142}