pezpallet_revive/
exec.rs

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