referrerpolicy=no-referrer-when-downgrade

pallet_contracts/
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	debug::{CallInterceptor, CallSpan, Tracing},
20	gas::GasMeter,
21	primitives::{ExecReturnValue, StorageDeposit},
22	storage::{self, meter::Diff, WriteOutcome},
23	transient_storage::TransientStorage,
24	BalanceOf, CodeHash, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf,
25	DebugBufferVec, Determinism, Error, Event, Nonce, Origin, Pallet as Contracts, Schedule,
26	LOG_TARGET,
27};
28use alloc::vec::Vec;
29use core::{fmt::Debug, marker::PhantomData, mem};
30use frame_support::{
31	crypto::ecdsa::ECDSAExt,
32	dispatch::{DispatchResult, DispatchResultWithPostInfo},
33	ensure,
34	storage::{with_transaction, TransactionOutcome},
35	traits::{
36		fungible::{Inspect, Mutate},
37		tokens::{Fortitude, Preservation},
38		Contains, OriginTrait, Randomness, Time,
39	},
40	weights::Weight,
41	Blake2_128Concat, BoundedVec, StorageHasher,
42};
43use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
44use smallvec::{Array, SmallVec};
45use sp_core::{
46	ecdsa::Public as ECDSAPublic,
47	sr25519::{Public as SR25519Public, Signature as SR25519Signature},
48	Get,
49};
50use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
51use sp_runtime::{
52	traits::{Convert, Dispatchable, Zero},
53	DispatchError,
54};
55
56pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
57pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
58pub type SeedOf<T> = <T as frame_system::Config>::Hash;
59pub type ExecResult = Result<ExecReturnValue, ExecError>;
60
61/// A type that represents a topic of an event. At the moment a hash is used.
62pub type TopicOf<T> = <T as frame_system::Config>::Hash;
63
64/// Type for variable sized storage key. Used for transparent hashing.
65type VarSizedKey<T> = BoundedVec<u8, <T as Config>::MaxStorageKeyLen>;
66
67/// Combined key type for both fixed and variable sized storage keys.
68pub enum Key<T: Config> {
69	/// Variant for fixed sized keys.
70	Fix([u8; 32]),
71	/// Variant for variable sized keys.
72	Var(VarSizedKey<T>),
73}
74
75impl<T: Config> Key<T> {
76	/// Copies self into a new vec.
77	pub fn to_vec(&self) -> Vec<u8> {
78		match self {
79			Key::Fix(v) => v.to_vec(),
80			Key::Var(v) => v.to_vec(),
81		}
82	}
83
84	pub fn hash(&self) -> Vec<u8> {
85		match self {
86			Key::Fix(v) => blake2_256(v.as_slice()).to_vec(),
87			Key::Var(v) => Blake2_128Concat::hash(v.as_slice()),
88		}
89	}
90
91	pub fn try_from_fix(v: Vec<u8>) -> Result<Self, Vec<u8>> {
92		<[u8; 32]>::try_from(v).map(Self::Fix)
93	}
94
95	pub fn try_from_var(v: Vec<u8>) -> Result<Self, Vec<u8>> {
96		VarSizedKey::<T>::try_from(v).map(Self::Var)
97	}
98}
99
100/// Origin of the error.
101///
102/// Call or instantiate both called into other contracts and pass through errors happening
103/// in those to the caller. This enum is for the caller to distinguish whether the error
104/// happened during the execution of the callee or in the current execution context.
105#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
106pub enum ErrorOrigin {
107	/// Caller error origin.
108	///
109	/// The error happened in the current execution context rather than in the one
110	/// of the contract that is called into.
111	Caller,
112	/// The error happened during execution of the called contract.
113	Callee,
114}
115
116/// Error returned by contract execution.
117#[derive(Copy, Clone, PartialEq, Eq, Debug, codec::Decode, codec::Encode)]
118pub struct ExecError {
119	/// The reason why the execution failed.
120	pub error: DispatchError,
121	/// Origin of the error.
122	pub origin: ErrorOrigin,
123}
124
125impl<T: Into<DispatchError>> From<T> for ExecError {
126	fn from(error: T) -> Self {
127		Self { error: error.into(), origin: ErrorOrigin::Caller }
128	}
129}
130
131/// An interface that provides access to the external environment in which the
132/// smart-contract is executed.
133///
134/// This interface is specialized to an account of the executing code, so all
135/// operations are implicitly performed on that account.
136///
137/// # Note
138///
139/// This trait is sealed and cannot be implemented by downstream crates.
140pub trait Ext: sealing::Sealed {
141	type T: Config;
142
143	/// Call (possibly transferring some amount of funds) into the specified account.
144	///
145	/// Returns the code size of the called contract.
146	fn call(
147		&mut self,
148		gas_limit: Weight,
149		deposit_limit: BalanceOf<Self::T>,
150		to: AccountIdOf<Self::T>,
151		value: BalanceOf<Self::T>,
152		input_data: Vec<u8>,
153		allows_reentry: bool,
154		read_only: bool,
155	) -> Result<ExecReturnValue, ExecError>;
156
157	/// Execute code in the current frame.
158	///
159	/// Returns the code size of the called contract.
160	fn delegate_call(
161		&mut self,
162		code: CodeHash<Self::T>,
163		input_data: Vec<u8>,
164	) -> Result<ExecReturnValue, ExecError>;
165
166	/// Instantiate a contract from the given code.
167	///
168	/// Returns the original code size of the called contract.
169	/// The newly created account will be associated with `code`. `value` specifies the amount of
170	/// value transferred from the caller to the newly created account.
171	fn instantiate(
172		&mut self,
173		gas_limit: Weight,
174		deposit_limit: BalanceOf<Self::T>,
175		code: CodeHash<Self::T>,
176		value: BalanceOf<Self::T>,
177		input_data: Vec<u8>,
178		salt: &[u8],
179	) -> Result<(AccountIdOf<Self::T>, ExecReturnValue), ExecError>;
180
181	/// Transfer all funds to `beneficiary` and delete the contract.
182	///
183	/// Since this function removes the self contract eagerly, if succeeded, no further actions
184	/// should be performed on this `Ext` instance.
185	///
186	/// This function will fail if the same contract is present on the contract
187	/// call stack.
188	fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> DispatchResult;
189
190	/// Transfer some amount of funds into the specified account.
191	fn transfer(&mut self, to: &AccountIdOf<Self::T>, value: BalanceOf<Self::T>) -> DispatchResult;
192
193	/// Returns the storage entry of the executing account by the given `key`.
194	///
195	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
196	/// was deleted.
197	fn get_storage(&mut self, key: &Key<Self::T>) -> Option<Vec<u8>>;
198
199	/// Returns `Some(len)` (in bytes) if a storage item exists at `key`.
200	///
201	/// Returns `None` if the `key` wasn't previously set by `set_storage` or
202	/// was deleted.
203	fn get_storage_size(&mut self, key: &Key<Self::T>) -> Option<u32>;
204
205	/// Sets the storage entry by the given key to the specified value. If `value` is `None` then
206	/// the storage entry is deleted.
207	fn set_storage(
208		&mut self,
209		key: &Key<Self::T>,
210		value: Option<Vec<u8>>,
211		take_old: bool,
212	) -> Result<WriteOutcome, DispatchError>;
213
214	/// Returns the transient storage entry of the executing account for the given `key`.
215	///
216	/// Returns `None` if the `key` wasn't previously set by `set_transient_storage` or
217	/// was deleted.
218	fn get_transient_storage(&self, key: &Key<Self::T>) -> Option<Vec<u8>>;
219
220	/// Returns `Some(len)` (in bytes) if a transient storage item exists at `key`.
221	///
222	/// Returns `None` if the `key` wasn't previously set by `set_transient_storage` or
223	/// was deleted.
224	fn get_transient_storage_size(&self, key: &Key<Self::T>) -> Option<u32>;
225
226	/// Sets the transient storage entry for the given key to the specified value. If `value` is
227	/// `None` then the storage entry is deleted.
228	fn set_transient_storage(
229		&mut self,
230		key: &Key<Self::T>,
231		value: Option<Vec<u8>>,
232		take_old: bool,
233	) -> Result<WriteOutcome, DispatchError>;
234
235	/// Returns the caller.
236	fn caller(&self) -> Origin<Self::T>;
237
238	/// Check if a contract lives at the specified `address`.
239	fn is_contract(&self, address: &AccountIdOf<Self::T>) -> bool;
240
241	/// Returns the code hash of the contract for the given `address`.
242	///
243	/// Returns `None` if the `address` does not belong to a contract.
244	fn code_hash(&self, address: &AccountIdOf<Self::T>) -> Option<CodeHash<Self::T>>;
245
246	/// Returns the code hash of the contract being executed.
247	fn own_code_hash(&mut self) -> &CodeHash<Self::T>;
248
249	/// Check if the caller of the current contract is the origin of the whole call stack.
250	///
251	/// This can be checked with `is_contract(self.caller())` as well.
252	/// However, this function does not require any storage lookup and therefore uses less weight.
253	fn caller_is_origin(&self) -> bool;
254
255	/// Check if the caller is origin, and this origin is root.
256	fn caller_is_root(&self) -> bool;
257
258	/// Returns a reference to the account id of the current contract.
259	fn address(&self) -> &AccountIdOf<Self::T>;
260
261	/// Returns the balance of the current contract.
262	///
263	/// The `value_transferred` is already added.
264	fn balance(&self) -> BalanceOf<Self::T>;
265
266	/// Returns the value transferred along with this call.
267	fn value_transferred(&self) -> BalanceOf<Self::T>;
268
269	/// Returns a reference to the timestamp of the current block
270	fn now(&self) -> &MomentOf<Self::T>;
271
272	/// Returns the minimum balance that is required for creating an account.
273	fn minimum_balance(&self) -> BalanceOf<Self::T>;
274
275	/// Returns a random number for the current block with the given subject.
276	fn random(&self, subject: &[u8]) -> (SeedOf<Self::T>, BlockNumberFor<Self::T>);
277
278	/// Deposit an event with the given topics.
279	///
280	/// There should not be any duplicates in `topics`.
281	fn deposit_event(&mut self, topics: Vec<TopicOf<Self::T>>, data: Vec<u8>);
282
283	/// Returns the current block number.
284	fn block_number(&self) -> BlockNumberFor<Self::T>;
285
286	/// Returns the maximum allowed size of a storage item.
287	fn max_value_size(&self) -> u32;
288
289	/// Returns the price for the specified amount of weight.
290	fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T>;
291
292	/// Get a reference to the schedule used by the current call.
293	fn schedule(&self) -> &Schedule<Self::T>;
294
295	/// Get an immutable reference to the nested gas meter.
296	fn gas_meter(&self) -> &GasMeter<Self::T>;
297
298	/// Get a mutable reference to the nested gas meter.
299	fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T>;
300
301	/// Charges `diff` from the meter.
302	fn charge_storage(&mut self, diff: &Diff);
303
304	/// Append a string to the debug buffer.
305	///
306	/// It is added as-is without any additional new line.
307	///
308	/// This is a no-op if debug message recording is disabled which is always the case
309	/// when the code is executing on-chain.
310	///
311	/// Returns `true` if debug message recording is enabled. Otherwise `false` is returned.
312	fn append_debug_buffer(&mut self, msg: &str) -> bool;
313
314	/// Returns `true` if debug message recording is enabled. Otherwise `false` is returned.
315	fn debug_buffer_enabled(&self) -> bool;
316
317	/// Call some dispatchable and return the result.
318	fn call_runtime(&self, call: <Self::T as Config>::RuntimeCall) -> DispatchResultWithPostInfo;
319
320	/// Recovers ECDSA compressed public key based on signature and message hash.
321	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()>;
322
323	/// Verify a sr25519 signature.
324	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool;
325
326	/// Returns Ethereum address from the ECDSA compressed public key.
327	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()>;
328
329	/// Tests sometimes need to modify and inspect the contract info directly.
330	#[cfg(any(test, feature = "runtime-benchmarks"))]
331	fn contract_info(&mut self) -> &mut ContractInfo<Self::T>;
332
333	/// Get a mutable reference to the transient storage.
334	/// Useful in benchmarks when it is sometimes necessary to modify and inspect the transient
335	/// storage directly.
336	#[cfg(feature = "runtime-benchmarks")]
337	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T>;
338
339	/// Sets new code hash for existing contract.
340	fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> DispatchResult;
341
342	/// Returns the number of times the currently executing contract exists on the call stack in
343	/// addition to the calling instance. A value of 0 means no reentrancy.
344	fn reentrance_count(&self) -> u32;
345
346	/// Returns the number of times the specified contract exists on the call stack. Delegated calls
347	/// are not calculated as separate entrance.
348	/// A value of 0 means it does not exist on the call stack.
349	fn account_reentrance_count(&self, account_id: &AccountIdOf<Self::T>) -> u32;
350
351	/// Returns a nonce that is incremented for every instantiated contract.
352	fn nonce(&mut self) -> u64;
353
354	/// Increment the reference count of a of a stored code by one.
355	///
356	/// # Errors
357	///
358	/// [`Error::CodeNotFound`] is returned if no stored code found having the specified
359	/// `code_hash`.
360	fn increment_refcount(code_hash: CodeHash<Self::T>) -> DispatchResult;
361
362	/// Decrement the reference count of a stored code by one.
363	///
364	/// # Note
365	///
366	/// A contract whose reference count dropped to zero isn't automatically removed. A
367	/// `remove_code` transaction must be submitted by the original uploader to do so.
368	fn decrement_refcount(code_hash: CodeHash<Self::T>);
369
370	/// Adds a delegate dependency to [`ContractInfo`]'s `delegate_dependencies` field.
371	///
372	/// This ensures that the delegated contract is not removed while it is still in use. It
373	/// increases the reference count of the code hash and charges a fraction (see
374	/// [`Config::CodeHashLockupDepositPercent`]) of the code deposit.
375	///
376	/// # Errors
377	///
378	/// - [`Error::MaxDelegateDependenciesReached`]
379	/// - [`Error::CannotAddSelfAsDelegateDependency`]
380	/// - [`Error::DelegateDependencyAlreadyExists`]
381	fn lock_delegate_dependency(&mut self, code_hash: CodeHash<Self::T>) -> DispatchResult;
382
383	/// Removes a delegate dependency from [`ContractInfo`]'s `delegate_dependencies` field.
384	///
385	/// This is the counterpart of [`Self::lock_delegate_dependency`]. It decreases the reference
386	/// count and refunds the deposit that was charged by [`Self::lock_delegate_dependency`].
387	///
388	/// # Errors
389	///
390	/// - [`Error::DelegateDependencyNotFound`]
391	fn unlock_delegate_dependency(&mut self, code_hash: &CodeHash<Self::T>) -> DispatchResult;
392
393	/// Returns the number of locked delegate dependencies.
394	///
395	/// Note: Requires &mut self to access the contract info.
396	fn locked_delegate_dependencies_count(&mut self) -> usize;
397
398	/// Check if running in read-only context.
399	fn is_read_only(&self) -> bool;
400}
401
402/// Describes the different functions that can be exported by an [`Executable`].
403#[derive(
404	Copy,
405	Clone,
406	PartialEq,
407	Eq,
408	sp_core::RuntimeDebug,
409	codec::Decode,
410	codec::Encode,
411	codec::MaxEncodedLen,
412	scale_info::TypeInfo,
413)]
414pub enum ExportedFunction {
415	/// The constructor function which is executed on deployment of a contract.
416	Constructor,
417	/// The function which is executed when a contract is called.
418	Call,
419}
420
421/// A trait that represents something that can be executed.
422///
423/// In the on-chain environment this would be represented by a wasm module. This trait exists in
424/// order to be able to mock the wasm logic for testing.
425pub trait Executable<T: Config>: Sized {
426	/// Load the executable from storage.
427	///
428	/// # Note
429	/// Charges size base load weight from the gas meter.
430	fn from_storage(
431		code_hash: CodeHash<T>,
432		gas_meter: &mut GasMeter<T>,
433	) -> Result<Self, DispatchError>;
434
435	/// Execute the specified exported function and return the result.
436	///
437	/// When the specified function is `Constructor` the executable is stored and its
438	/// refcount incremented.
439	///
440	/// # Note
441	///
442	/// This functions expects to be executed in a storage transaction that rolls back
443	/// all of its emitted storage changes.
444	fn execute<E: Ext<T = T>>(
445		self,
446		ext: &mut E,
447		function: &ExportedFunction,
448		input_data: Vec<u8>,
449	) -> ExecResult;
450
451	/// The code info of the executable.
452	fn code_info(&self) -> &CodeInfo<T>;
453
454	/// The code hash of the executable.
455	fn code_hash(&self) -> &CodeHash<T>;
456
457	/// The code does not contain any instructions which could lead to indeterminism.
458	fn is_deterministic(&self) -> bool;
459}
460
461/// The complete call stack of a contract execution.
462///
463/// The call stack is initiated by either a signed origin or one of the contract RPC calls.
464/// This type implements `Ext` and by that exposes the business logic of contract execution to
465/// the runtime module which interfaces with the contract (the wasm blob) itself.
466pub struct Stack<'a, T: Config, E> {
467	/// The origin that initiated the call stack. It could either be a Signed plain account that
468	/// holds an account id or Root.
469	///
470	/// # Note
471	///
472	/// Please note that it is possible that the id of a Signed origin belongs to a contract rather
473	/// than a plain account when being called through one of the contract RPCs where the
474	/// client can freely choose the origin. This usually makes no sense but is still possible.
475	origin: Origin<T>,
476	/// The cost schedule used when charging from the gas meter.
477	schedule: &'a Schedule<T>,
478	/// The gas meter where costs are charged to.
479	gas_meter: &'a mut GasMeter<T>,
480	/// The storage meter makes sure that the storage deposit limit is obeyed.
481	storage_meter: &'a mut storage::meter::Meter<T>,
482	/// The timestamp at the point of call stack instantiation.
483	timestamp: MomentOf<T>,
484	/// The block number at the time of call stack instantiation.
485	block_number: BlockNumberFor<T>,
486	/// The nonce is cached here when accessed. It is written back when the call stack
487	/// finishes executing. Please refer to [`Nonce`] to a description of
488	/// the nonce itself.
489	nonce: Option<u64>,
490	/// The actual call stack. One entry per nested contract called/instantiated.
491	/// This does **not** include the [`Self::first_frame`].
492	frames: SmallVec<T::CallStack>,
493	/// Statically guarantee that each call stack has at least one frame.
494	first_frame: Frame<T>,
495	/// A text buffer used to output human readable information.
496	///
497	/// All the bytes added to this field should be valid UTF-8. The buffer has no defined
498	/// structure and is intended to be shown to users as-is for debugging purposes.
499	debug_message: Option<&'a mut DebugBufferVec<T>>,
500	/// The determinism requirement of this call stack.
501	determinism: Determinism,
502	/// Transient storage used to store data, which is kept for the duration of a transaction.
503	transient_storage: TransientStorage<T>,
504	/// No executable is held by the struct but influences its behaviour.
505	_phantom: PhantomData<E>,
506}
507
508/// Represents one entry in the call stack.
509///
510/// For each nested contract call or instantiate one frame is created. It holds specific
511/// information for the said call and caches the in-storage `ContractInfo` data structure.
512///
513/// # Note
514///
515/// This is an internal data structure. It is exposed to the public for the sole reason
516/// of specifying [`Config::CallStack`].
517pub struct Frame<T: Config> {
518	/// The account id of the executing contract.
519	account_id: T::AccountId,
520	/// The cached in-storage data of the contract.
521	contract_info: CachedContract<T>,
522	/// The amount of balance transferred by the caller as part of the call.
523	value_transferred: BalanceOf<T>,
524	/// Determines whether this is a call or instantiate frame.
525	entry_point: ExportedFunction,
526	/// The gas meter capped to the supplied gas limit.
527	nested_gas: GasMeter<T>,
528	/// The storage meter for the individual call.
529	nested_storage: storage::meter::NestedMeter<T>,
530	/// If `false` the contract enabled its defense against reentrance attacks.
531	allows_reentry: bool,
532	/// If `true` subsequent calls cannot modify storage.
533	read_only: bool,
534	/// The caller of the currently executing frame which was spawned by `delegate_call`.
535	delegate_caller: Option<Origin<T>>,
536}
537
538/// Used in a delegate call frame arguments in order to override the executable and caller.
539struct DelegatedCall<T: Config, E> {
540	/// The executable which is run instead of the contracts own `executable`.
541	executable: E,
542	/// The caller of the contract.
543	caller: Origin<T>,
544}
545
546/// Parameter passed in when creating a new `Frame`.
547///
548/// It determines whether the new frame is for a call or an instantiate.
549enum FrameArgs<'a, T: Config, E> {
550	Call {
551		/// The account id of the contract that is to be called.
552		dest: T::AccountId,
553		/// If `None` the contract info needs to be reloaded from storage.
554		cached_info: Option<ContractInfo<T>>,
555		/// This frame was created by `seal_delegate_call` and hence uses different code than
556		/// what is stored at [`Self::Call::dest`]. Its caller ([`DelegatedCall::caller`]) is the
557		/// account which called the caller contract
558		delegated_call: Option<DelegatedCall<T, E>>,
559	},
560	Instantiate {
561		/// The contract or signed origin which instantiates the new contract.
562		sender: T::AccountId,
563		/// The nonce that should be used to derive a new trie id for the contract.
564		nonce: u64,
565		/// The executable whose `deploy` function is run.
566		executable: E,
567		/// A salt used in the contract address derivation of the new contract.
568		salt: &'a [u8],
569		/// The input data is used in the contract address derivation of the new contract.
570		input_data: &'a [u8],
571	},
572}
573
574/// Describes the different states of a contract as contained in a `Frame`.
575enum CachedContract<T: Config> {
576	/// The cached contract is up to date with the in-storage value.
577	Cached(ContractInfo<T>),
578	/// A recursive call into the same contract did write to the contract info.
579	///
580	/// In this case the cached contract is stale and needs to be reloaded from storage.
581	Invalidated,
582	/// The current contract executed `terminate` and removed the contract.
583	///
584	/// In this case a reload is neither allowed nor possible. Please note that recursive
585	/// calls cannot remove a contract as this is checked and denied.
586	Terminated,
587}
588
589impl<T: Config> CachedContract<T> {
590	/// Return `Some(ContractInfo)` if the contract is in cached state. `None` otherwise.
591	fn into_contract(self) -> Option<ContractInfo<T>> {
592		if let CachedContract::Cached(contract) = self {
593			Some(contract)
594		} else {
595			None
596		}
597	}
598
599	/// Return `Some(&mut ContractInfo)` if the contract is in cached state. `None` otherwise.
600	fn as_contract(&mut self) -> Option<&mut ContractInfo<T>> {
601		if let CachedContract::Cached(contract) = self {
602			Some(contract)
603		} else {
604			None
605		}
606	}
607}
608
609impl<T: Config> Frame<T> {
610	/// Return the `contract_info` of the current contract.
611	fn contract_info(&mut self) -> &mut ContractInfo<T> {
612		self.contract_info.get(&self.account_id)
613	}
614
615	/// Terminate and return the `contract_info` of the current contract.
616	///
617	/// # Note
618	///
619	/// Under no circumstances the contract is allowed to access the `contract_info` after
620	/// a call to this function. This would constitute a programming error in the exec module.
621	fn terminate(&mut self) -> ContractInfo<T> {
622		self.contract_info.terminate(&self.account_id)
623	}
624}
625
626/// Extract the contract info after loading it from storage.
627///
628/// This assumes that `load` was executed before calling this macro.
629macro_rules! get_cached_or_panic_after_load {
630	($c:expr) => {{
631		if let CachedContract::Cached(contract) = $c {
632			contract
633		} else {
634			panic!(
635				"It is impossible to remove a contract that is on the call stack;\
636				See implementations of terminate;\
637				Therefore fetching a contract will never fail while using an account id
638				that is currently active on the call stack;\
639				qed"
640			);
641		}
642	}};
643}
644
645/// Same as [`Stack::top_frame`].
646///
647/// We need this access as a macro because sometimes hiding the lifetimes behind
648/// a function won't work out.
649macro_rules! top_frame {
650	($stack:expr) => {
651		$stack.frames.last().unwrap_or(&$stack.first_frame)
652	};
653}
654
655/// Same as [`Stack::top_frame_mut`].
656///
657/// We need this access as a macro because sometimes hiding the lifetimes behind
658/// a function won't work out.
659macro_rules! top_frame_mut {
660	($stack:expr) => {
661		$stack.frames.last_mut().unwrap_or(&mut $stack.first_frame)
662	};
663}
664
665impl<T: Config> CachedContract<T> {
666	/// Load the `contract_info` from storage if necessary.
667	fn load(&mut self, account_id: &T::AccountId) {
668		if let CachedContract::Invalidated = self {
669			let contract = <ContractInfoOf<T>>::get(&account_id);
670			if let Some(contract) = contract {
671				*self = CachedContract::Cached(contract);
672			}
673		}
674	}
675
676	/// Return the cached contract_info.
677	fn get(&mut self, account_id: &T::AccountId) -> &mut ContractInfo<T> {
678		self.load(account_id);
679		get_cached_or_panic_after_load!(self)
680	}
681
682	/// Terminate and return the contract info.
683	fn terminate(&mut self, account_id: &T::AccountId) -> ContractInfo<T> {
684		self.load(account_id);
685		get_cached_or_panic_after_load!(mem::replace(self, Self::Terminated))
686	}
687}
688
689impl<'a, T, E> Stack<'a, T, E>
690where
691	T: Config,
692	E: Executable<T>,
693{
694	/// Create and run a new call stack by calling into `dest`.
695	///
696	/// # Note
697	///
698	/// `debug_message` should only ever be set to `Some` when executing as an RPC because
699	/// it adds allocations and could be abused to drive the runtime into an OOM panic.
700	///
701	/// # Return Value
702	///
703	/// Result<(ExecReturnValue, CodeSize), (ExecError, CodeSize)>
704	pub fn run_call(
705		origin: Origin<T>,
706		dest: T::AccountId,
707		gas_meter: &'a mut GasMeter<T>,
708		storage_meter: &'a mut storage::meter::Meter<T>,
709		schedule: &'a Schedule<T>,
710		value: BalanceOf<T>,
711		input_data: Vec<u8>,
712		debug_message: Option<&'a mut DebugBufferVec<T>>,
713		determinism: Determinism,
714	) -> Result<ExecReturnValue, ExecError> {
715		let (mut stack, executable) = Self::new(
716			FrameArgs::Call { dest, cached_info: None, delegated_call: None },
717			origin,
718			gas_meter,
719			storage_meter,
720			schedule,
721			value,
722			debug_message,
723			determinism,
724		)?;
725		stack.run(executable, input_data)
726	}
727
728	/// Create and run a new call stack by instantiating a new contract.
729	///
730	/// # Note
731	///
732	/// `debug_message` should only ever be set to `Some` when executing as an RPC because
733	/// it adds allocations and could be abused to drive the runtime into an OOM panic.
734	///
735	/// # Return Value
736	///
737	/// Result<(NewContractAccountId, ExecReturnValue), ExecError)>
738	pub fn run_instantiate(
739		origin: T::AccountId,
740		executable: E,
741		gas_meter: &'a mut GasMeter<T>,
742		storage_meter: &'a mut storage::meter::Meter<T>,
743		schedule: &'a Schedule<T>,
744		value: BalanceOf<T>,
745		input_data: Vec<u8>,
746		salt: &[u8],
747		debug_message: Option<&'a mut DebugBufferVec<T>>,
748	) -> Result<(T::AccountId, ExecReturnValue), ExecError> {
749		let (mut stack, executable) = Self::new(
750			FrameArgs::Instantiate {
751				sender: origin.clone(),
752				nonce: <Nonce<T>>::get().wrapping_add(1),
753				executable,
754				salt,
755				input_data: input_data.as_ref(),
756			},
757			Origin::from_account_id(origin),
758			gas_meter,
759			storage_meter,
760			schedule,
761			value,
762			debug_message,
763			Determinism::Enforced,
764		)?;
765		let account_id = stack.top_frame().account_id.clone();
766		stack.run(executable, input_data).map(|ret| (account_id, ret))
767	}
768
769	#[cfg(feature = "runtime-benchmarks")]
770	pub fn bench_new_call(
771		dest: T::AccountId,
772		origin: Origin<T>,
773		gas_meter: &'a mut GasMeter<T>,
774		storage_meter: &'a mut storage::meter::Meter<T>,
775		schedule: &'a Schedule<T>,
776		value: BalanceOf<T>,
777		debug_message: Option<&'a mut DebugBufferVec<T>>,
778		determinism: Determinism,
779	) -> (Self, E) {
780		Self::new(
781			FrameArgs::Call { dest, cached_info: None, delegated_call: None },
782			origin,
783			gas_meter,
784			storage_meter,
785			schedule,
786			value,
787			debug_message,
788			determinism,
789		)
790		.unwrap()
791	}
792
793	/// Create a new call stack.
794	fn new(
795		args: FrameArgs<T, E>,
796		origin: Origin<T>,
797		gas_meter: &'a mut GasMeter<T>,
798		storage_meter: &'a mut storage::meter::Meter<T>,
799		schedule: &'a Schedule<T>,
800		value: BalanceOf<T>,
801		debug_message: Option<&'a mut DebugBufferVec<T>>,
802		determinism: Determinism,
803	) -> Result<(Self, E), ExecError> {
804		let (first_frame, executable, nonce) = Self::new_frame(
805			args,
806			value,
807			gas_meter,
808			Weight::zero(),
809			storage_meter,
810			BalanceOf::<T>::zero(),
811			determinism,
812			false,
813		)?;
814
815		let stack = Self {
816			origin,
817			schedule,
818			gas_meter,
819			storage_meter,
820			timestamp: T::Time::now(),
821			block_number: <frame_system::Pallet<T>>::block_number(),
822			nonce,
823			first_frame,
824			frames: Default::default(),
825			debug_message,
826			determinism,
827			transient_storage: TransientStorage::new(T::MaxTransientStorageSize::get()),
828			_phantom: Default::default(),
829		};
830
831		Ok((stack, executable))
832	}
833
834	/// Construct a new frame.
835	///
836	/// This does not take `self` because when constructing the first frame `self` is
837	/// not initialized, yet.
838	fn new_frame<S: storage::meter::State + Default + Debug>(
839		frame_args: FrameArgs<T, E>,
840		value_transferred: BalanceOf<T>,
841		gas_meter: &mut GasMeter<T>,
842		gas_limit: Weight,
843		storage_meter: &mut storage::meter::GenericMeter<T, S>,
844		deposit_limit: BalanceOf<T>,
845		determinism: Determinism,
846		read_only: bool,
847	) -> Result<(Frame<T>, E, Option<u64>), ExecError> {
848		let (account_id, contract_info, executable, delegate_caller, entry_point, nonce) =
849			match frame_args {
850				FrameArgs::Call { dest, cached_info, delegated_call } => {
851					let contract = if let Some(contract) = cached_info {
852						contract
853					} else {
854						<ContractInfoOf<T>>::get(&dest).ok_or(<Error<T>>::ContractNotFound)?
855					};
856
857					let (executable, delegate_caller) =
858						if let Some(DelegatedCall { executable, caller }) = delegated_call {
859							(executable, Some(caller))
860						} else {
861							(E::from_storage(contract.code_hash, gas_meter)?, None)
862						};
863
864					(dest, contract, executable, delegate_caller, ExportedFunction::Call, None)
865				},
866				FrameArgs::Instantiate { sender, nonce, executable, salt, input_data } => {
867					let account_id = Contracts::<T>::contract_address(
868						&sender,
869						&executable.code_hash(),
870						input_data,
871						salt,
872					);
873					let contract = ContractInfo::new(&account_id, nonce, *executable.code_hash())?;
874					(
875						account_id,
876						contract,
877						executable,
878						None,
879						ExportedFunction::Constructor,
880						Some(nonce),
881					)
882				},
883			};
884
885		// `Relaxed` will only be ever set in case of off-chain execution.
886		// Instantiations are never allowed even when executing off-chain.
887		if !(executable.is_deterministic() ||
888			(matches!(determinism, Determinism::Relaxed) &&
889				matches!(entry_point, ExportedFunction::Call)))
890		{
891			return Err(Error::<T>::Indeterministic.into())
892		}
893
894		let frame = Frame {
895			delegate_caller,
896			value_transferred,
897			contract_info: CachedContract::Cached(contract_info),
898			account_id,
899			entry_point,
900			nested_gas: gas_meter.nested(gas_limit),
901			nested_storage: storage_meter.nested(deposit_limit),
902			allows_reentry: true,
903			read_only,
904		};
905
906		Ok((frame, executable, nonce))
907	}
908
909	/// Create a subsequent nested frame.
910	fn push_frame(
911		&mut self,
912		frame_args: FrameArgs<T, E>,
913		value_transferred: BalanceOf<T>,
914		gas_limit: Weight,
915		deposit_limit: BalanceOf<T>,
916		read_only: bool,
917	) -> Result<E, ExecError> {
918		if self.frames.len() == T::CallStack::size() {
919			return Err(Error::<T>::MaxCallDepthReached.into())
920		}
921
922		// We need to make sure that changes made to the contract info are not discarded.
923		// See the `in_memory_changes_not_discarded` test for more information.
924		// We do not store on instantiate because we do not allow to call into a contract
925		// from its own constructor.
926		let frame = self.top_frame();
927		if let (CachedContract::Cached(contract), ExportedFunction::Call) =
928			(&frame.contract_info, frame.entry_point)
929		{
930			<ContractInfoOf<T>>::insert(frame.account_id.clone(), contract.clone());
931		}
932
933		let frame = top_frame_mut!(self);
934		let nested_gas = &mut frame.nested_gas;
935		let nested_storage = &mut frame.nested_storage;
936		let (frame, executable, _) = Self::new_frame(
937			frame_args,
938			value_transferred,
939			nested_gas,
940			gas_limit,
941			nested_storage,
942			deposit_limit,
943			self.determinism,
944			read_only,
945		)?;
946		self.frames.push(frame);
947		Ok(executable)
948	}
949
950	/// Run the current (top) frame.
951	///
952	/// This can be either a call or an instantiate.
953	fn run(&mut self, executable: E, input_data: Vec<u8>) -> Result<ExecReturnValue, ExecError> {
954		let frame = self.top_frame();
955		let entry_point = frame.entry_point;
956		let delegated_code_hash =
957			if frame.delegate_caller.is_some() { Some(*executable.code_hash()) } else { None };
958
959		self.transient_storage.start_transaction();
960
961		let do_transaction = || {
962			// We need to charge the storage deposit before the initial transfer so that
963			// it can create the account in case the initial transfer is < ed.
964			if entry_point == ExportedFunction::Constructor {
965				// Root origin can't be used to instantiate a contract, so it is safe to assume that
966				// if we reached this point the origin has an associated account.
967				let origin = &self.origin.account_id()?;
968				let frame = top_frame_mut!(self);
969				frame.nested_storage.charge_instantiate(
970					origin,
971					&frame.account_id,
972					frame.contract_info.get(&frame.account_id),
973					executable.code_info(),
974				)?;
975			}
976
977			// Every non delegate call or instantiate also optionally transfers the balance.
978			self.initial_transfer()?;
979
980			let contract_address = &top_frame!(self).account_id;
981
982			let call_span = T::Debug::new_call_span(contract_address, entry_point, &input_data);
983
984			let output = T::Debug::intercept_call(contract_address, &entry_point, &input_data)
985				.unwrap_or_else(|| {
986					executable
987						.execute(self, &entry_point, input_data)
988						.map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })
989				})?;
990
991			call_span.after_call(&output);
992
993			// Avoid useless work that would be reverted anyways.
994			if output.did_revert() {
995				return Ok(output)
996			}
997
998			// Storage limit is normally enforced as late as possible (when the last frame returns)
999			// so that the ordering of storage accesses does not matter.
1000			// (However, if a special limit was set for a sub-call, it should be enforced right
1001			// after the sub-call returned. See below for this case of enforcement).
1002			if self.frames.is_empty() {
1003				let frame = &mut self.first_frame;
1004				frame.contract_info.load(&frame.account_id);
1005				let contract = frame.contract_info.as_contract();
1006				frame.nested_storage.enforce_limit(contract)?;
1007			}
1008
1009			let frame = self.top_frame();
1010			let account_id = &frame.account_id.clone();
1011			match (entry_point, delegated_code_hash) {
1012				(ExportedFunction::Constructor, _) => {
1013					// It is not allowed to terminate a contract inside its constructor.
1014					if matches!(frame.contract_info, CachedContract::Terminated) {
1015						return Err(Error::<T>::TerminatedInConstructor.into())
1016					}
1017
1018					// If a special limit was set for the sub-call, we enforce it here.
1019					// This is needed because contract constructor might write to storage.
1020					// The sub-call will be rolled back in case the limit is exhausted.
1021					let frame = self.top_frame_mut();
1022					let contract = frame.contract_info.as_contract();
1023					frame.nested_storage.enforce_subcall_limit(contract)?;
1024
1025					let caller = self.caller().account_id()?.clone();
1026
1027					// Deposit an instantiation event.
1028					Contracts::<T>::deposit_event(Event::Instantiated {
1029						deployer: caller,
1030						contract: account_id.clone(),
1031					});
1032				},
1033				(ExportedFunction::Call, Some(code_hash)) => {
1034					Contracts::<T>::deposit_event(Event::DelegateCalled {
1035						contract: account_id.clone(),
1036						code_hash,
1037					});
1038				},
1039				(ExportedFunction::Call, None) => {
1040					// If a special limit was set for the sub-call, we enforce it here.
1041					// The sub-call will be rolled back in case the limit is exhausted.
1042					let frame = self.top_frame_mut();
1043					let contract = frame.contract_info.as_contract();
1044					frame.nested_storage.enforce_subcall_limit(contract)?;
1045
1046					let caller = self.caller();
1047					Contracts::<T>::deposit_event(Event::Called {
1048						caller: caller.clone(),
1049						contract: account_id.clone(),
1050					});
1051				},
1052			}
1053
1054			Ok(output)
1055		};
1056
1057		// All changes performed by the contract are executed under a storage transaction.
1058		// This allows for roll back on error. Changes to the cached contract_info are
1059		// committed or rolled back when popping the frame.
1060		//
1061		// `with_transactional` may return an error caused by a limit in the
1062		// transactional storage depth.
1063		let transaction_outcome =
1064			with_transaction(|| -> TransactionOutcome<Result<_, DispatchError>> {
1065				let output = do_transaction();
1066				match &output {
1067					Ok(result) if !result.did_revert() =>
1068						TransactionOutcome::Commit(Ok((true, output))),
1069					_ => TransactionOutcome::Rollback(Ok((false, output))),
1070				}
1071			});
1072
1073		let (success, output) = match transaction_outcome {
1074			// `with_transactional` executed successfully, and we have the expected output.
1075			Ok((success, output)) => (success, output),
1076			// `with_transactional` returned an error, and we propagate that error and note no state
1077			// has changed.
1078			Err(error) => (false, Err(error.into())),
1079		};
1080
1081		if success {
1082			self.transient_storage.commit_transaction();
1083		} else {
1084			self.transient_storage.rollback_transaction();
1085		}
1086
1087		self.pop_frame(success);
1088		output
1089	}
1090
1091	/// Remove the current (top) frame from the stack.
1092	///
1093	/// This is called after running the current frame. It commits cached values to storage
1094	/// and invalidates all stale references to it that might exist further down the call stack.
1095	fn pop_frame(&mut self, persist: bool) {
1096		// Revert changes to the nonce in case of a failed instantiation.
1097		if !persist && self.top_frame().entry_point == ExportedFunction::Constructor {
1098			self.nonce.as_mut().map(|c| *c = c.wrapping_sub(1));
1099		}
1100
1101		// Pop the current frame from the stack and return it in case it needs to interact
1102		// with duplicates that might exist on the stack.
1103		// A `None` means that we are returning from the `first_frame`.
1104		let frame = self.frames.pop();
1105
1106		// Both branches do essentially the same with the exception. The difference is that
1107		// the else branch does consume the hardcoded `first_frame`.
1108		if let Some(mut frame) = frame {
1109			let account_id = &frame.account_id;
1110			let prev = top_frame_mut!(self);
1111
1112			prev.nested_gas.absorb_nested(frame.nested_gas);
1113
1114			// Only gas counter changes are persisted in case of a failure.
1115			if !persist {
1116				return
1117			}
1118
1119			// Record the storage meter changes of the nested call into the parent meter.
1120			// If the dropped frame's contract wasn't terminated we update the deposit counter
1121			// in its contract info. The load is necessary to pull it from storage in case
1122			// it was invalidated.
1123			frame.contract_info.load(account_id);
1124			let mut contract = frame.contract_info.into_contract();
1125			prev.nested_storage.absorb(frame.nested_storage, account_id, contract.as_mut());
1126
1127			// In case the contract wasn't terminated we need to persist changes made to it.
1128			if let Some(contract) = contract {
1129				// optimization: Predecessor is the same contract.
1130				// We can just copy the contract into the predecessor without a storage write.
1131				// This is possible when there is no other contract in-between that could
1132				// trigger a rollback.
1133				if prev.account_id == *account_id {
1134					prev.contract_info = CachedContract::Cached(contract);
1135					return
1136				}
1137
1138				// Predecessor is a different contract: We persist the info and invalidate the first
1139				// stale cache we find. This triggers a reload from storage on next use. We skip(1)
1140				// because that case is already handled by the optimization above. Only the first
1141				// cache needs to be invalidated because that one will invalidate the next cache
1142				// when it is popped from the stack.
1143				<ContractInfoOf<T>>::insert(account_id, contract);
1144				if let Some(c) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) {
1145					c.contract_info = CachedContract::Invalidated;
1146				}
1147			}
1148		} else {
1149			if let Some((msg, false)) = self.debug_message.as_ref().map(|m| (m, m.is_empty())) {
1150				log::debug!(
1151					target: LOG_TARGET,
1152					"Execution finished with debug buffer: {}",
1153					core::str::from_utf8(msg).unwrap_or("<Invalid UTF8>"),
1154				);
1155			}
1156			self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas));
1157			if !persist {
1158				return
1159			}
1160			let mut contract = self.first_frame.contract_info.as_contract();
1161			self.storage_meter.absorb(
1162				mem::take(&mut self.first_frame.nested_storage),
1163				&self.first_frame.account_id,
1164				contract.as_deref_mut(),
1165			);
1166			if let Some(contract) = contract {
1167				<ContractInfoOf<T>>::insert(&self.first_frame.account_id, contract);
1168			}
1169			if let Some(nonce) = self.nonce {
1170				<Nonce<T>>::set(nonce);
1171			}
1172		}
1173	}
1174
1175	/// Transfer some funds from `from` to `to`.
1176	fn transfer(
1177		preservation: Preservation,
1178		from: &T::AccountId,
1179		to: &T::AccountId,
1180		value: BalanceOf<T>,
1181	) -> DispatchResult {
1182		if !value.is_zero() && from != to {
1183			T::Currency::transfer(from, to, value, preservation)
1184				.map_err(|_| Error::<T>::TransferFailed)?;
1185		}
1186		Ok(())
1187	}
1188
1189	// The transfer as performed by a call or instantiate.
1190	fn initial_transfer(&self) -> DispatchResult {
1191		let frame = self.top_frame();
1192
1193		// If it is a delegate call, then we've already transferred tokens in the
1194		// last non-delegate frame.
1195		if frame.delegate_caller.is_some() {
1196			return Ok(())
1197		}
1198
1199		let value = frame.value_transferred;
1200
1201		// Get the account id from the caller.
1202		// If the caller is root there is no account to transfer from, and therefore we can't take
1203		// any `value` other than 0.
1204		let caller = match self.caller() {
1205			Origin::Signed(caller) => caller,
1206			Origin::Root if value.is_zero() => return Ok(()),
1207			Origin::Root => return DispatchError::RootNotAllowed.into(),
1208		};
1209		Self::transfer(Preservation::Preserve, &caller, &frame.account_id, value)
1210	}
1211
1212	/// Reference to the current (top) frame.
1213	fn top_frame(&self) -> &Frame<T> {
1214		top_frame!(self)
1215	}
1216
1217	/// Mutable reference to the current (top) frame.
1218	fn top_frame_mut(&mut self) -> &mut Frame<T> {
1219		top_frame_mut!(self)
1220	}
1221
1222	/// Iterator over all frames.
1223	///
1224	/// The iterator starts with the top frame and ends with the root frame.
1225	fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1226		core::iter::once(&self.first_frame).chain(&self.frames).rev()
1227	}
1228
1229	/// Same as `frames` but with a mutable reference as iterator item.
1230	fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1231		core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1232	}
1233
1234	/// Returns whether the current contract is on the stack multiple times.
1235	fn is_recursive(&self) -> bool {
1236		let account_id = &self.top_frame().account_id;
1237		self.frames().skip(1).any(|f| &f.account_id == account_id)
1238	}
1239
1240	/// Returns whether the specified contract allows to be reentered right now.
1241	fn allows_reentry(&self, id: &AccountIdOf<T>) -> bool {
1242		!self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1243	}
1244
1245	/// Increments and returns the next nonce. Pulls it from storage if it isn't in cache.
1246	fn next_nonce(&mut self) -> u64 {
1247		let next = self.nonce().wrapping_add(1);
1248		self.nonce = Some(next);
1249		next
1250	}
1251}
1252
1253impl<'a, T, E> Ext for Stack<'a, T, E>
1254where
1255	T: Config,
1256	E: Executable<T>,
1257{
1258	type T = T;
1259
1260	fn call(
1261		&mut self,
1262		gas_limit: Weight,
1263		deposit_limit: BalanceOf<T>,
1264		to: T::AccountId,
1265		value: BalanceOf<T>,
1266		input_data: Vec<u8>,
1267		allows_reentry: bool,
1268		read_only: bool,
1269	) -> Result<ExecReturnValue, ExecError> {
1270		// Before pushing the new frame: Protect the caller contract against reentrancy attacks.
1271		// It is important to do this before calling `allows_reentry` so that a direct recursion
1272		// is caught by it.
1273		self.top_frame_mut().allows_reentry = allows_reentry;
1274
1275		let try_call = || {
1276			if !self.allows_reentry(&to) {
1277				return Err(<Error<T>>::ReentranceDenied.into())
1278			}
1279
1280			// We ignore instantiate frames in our search for a cached contract.
1281			// Otherwise it would be possible to recursively call a contract from its own
1282			// constructor: We disallow calling not fully constructed contracts.
1283			let cached_info = self
1284				.frames()
1285				.find(|f| f.entry_point == ExportedFunction::Call && f.account_id == to)
1286				.and_then(|f| match &f.contract_info {
1287					CachedContract::Cached(contract) => Some(contract.clone()),
1288					_ => None,
1289				});
1290			let executable = self.push_frame(
1291				FrameArgs::Call { dest: to, cached_info, delegated_call: None },
1292				value,
1293				gas_limit,
1294				deposit_limit,
1295				// Enable read-only access if requested; cannot disable it if already set.
1296				read_only || self.is_read_only(),
1297			)?;
1298			self.run(executable, input_data)
1299		};
1300
1301		// We need to make sure to reset `allows_reentry` even on failure.
1302		let result = try_call();
1303
1304		// Protection is on a per call basis.
1305		self.top_frame_mut().allows_reentry = true;
1306
1307		result
1308	}
1309
1310	fn delegate_call(
1311		&mut self,
1312		code_hash: CodeHash<Self::T>,
1313		input_data: Vec<u8>,
1314	) -> Result<ExecReturnValue, ExecError> {
1315		let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
1316		let top_frame = self.top_frame_mut();
1317		let contract_info = top_frame.contract_info().clone();
1318		let account_id = top_frame.account_id.clone();
1319		let value = top_frame.value_transferred;
1320		let executable = self.push_frame(
1321			FrameArgs::Call {
1322				dest: account_id,
1323				cached_info: Some(contract_info),
1324				delegated_call: Some(DelegatedCall { executable, caller: self.caller().clone() }),
1325			},
1326			value,
1327			Weight::zero(),
1328			BalanceOf::<T>::zero(),
1329			self.is_read_only(),
1330		)?;
1331		self.run(executable, input_data)
1332	}
1333
1334	fn instantiate(
1335		&mut self,
1336		gas_limit: Weight,
1337		deposit_limit: BalanceOf<Self::T>,
1338		code_hash: CodeHash<T>,
1339		value: BalanceOf<T>,
1340		input_data: Vec<u8>,
1341		salt: &[u8],
1342	) -> Result<(AccountIdOf<T>, ExecReturnValue), ExecError> {
1343		let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
1344		let nonce = self.next_nonce();
1345		let executable = self.push_frame(
1346			FrameArgs::Instantiate {
1347				sender: self.top_frame().account_id.clone(),
1348				nonce,
1349				executable,
1350				salt,
1351				input_data: input_data.as_ref(),
1352			},
1353			value,
1354			gas_limit,
1355			deposit_limit,
1356			self.is_read_only(),
1357		)?;
1358		let account_id = self.top_frame().account_id.clone();
1359		self.run(executable, input_data).map(|ret| (account_id, ret))
1360	}
1361
1362	fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> DispatchResult {
1363		if self.is_recursive() {
1364			return Err(Error::<T>::TerminatedWhileReentrant.into())
1365		}
1366		let frame = self.top_frame_mut();
1367		let info = frame.terminate();
1368		frame.nested_storage.terminate(&info, beneficiary.clone());
1369
1370		info.queue_trie_for_deletion();
1371		ContractInfoOf::<T>::remove(&frame.account_id);
1372		Self::decrement_refcount(info.code_hash);
1373
1374		for (code_hash, deposit) in info.delegate_dependencies() {
1375			Self::decrement_refcount(*code_hash);
1376			frame
1377				.nested_storage
1378				.charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(*deposit));
1379		}
1380
1381		Contracts::<T>::deposit_event(Event::Terminated {
1382			contract: frame.account_id.clone(),
1383			beneficiary: beneficiary.clone(),
1384		});
1385		Ok(())
1386	}
1387
1388	fn transfer(&mut self, to: &T::AccountId, value: BalanceOf<T>) -> DispatchResult {
1389		Self::transfer(Preservation::Preserve, &self.top_frame().account_id, to, value)
1390	}
1391
1392	fn get_storage(&mut self, key: &Key<T>) -> Option<Vec<u8>> {
1393		self.top_frame_mut().contract_info().read(key)
1394	}
1395
1396	fn get_storage_size(&mut self, key: &Key<T>) -> Option<u32> {
1397		self.top_frame_mut().contract_info().size(key.into())
1398	}
1399
1400	fn set_storage(
1401		&mut self,
1402		key: &Key<T>,
1403		value: Option<Vec<u8>>,
1404		take_old: bool,
1405	) -> Result<WriteOutcome, DispatchError> {
1406		let frame = self.top_frame_mut();
1407		frame.contract_info.get(&frame.account_id).write(
1408			key.into(),
1409			value,
1410			Some(&mut frame.nested_storage),
1411			take_old,
1412		)
1413	}
1414
1415	fn get_transient_storage(&self, key: &Key<T>) -> Option<Vec<u8>> {
1416		self.transient_storage.read(self.address(), key)
1417	}
1418
1419	fn get_transient_storage_size(&self, key: &Key<T>) -> Option<u32> {
1420		self.transient_storage.read(self.address(), key).map(|value| value.len() as _)
1421	}
1422
1423	fn set_transient_storage(
1424		&mut self,
1425		key: &Key<T>,
1426		value: Option<Vec<u8>>,
1427		take_old: bool,
1428	) -> Result<WriteOutcome, DispatchError> {
1429		let account_id = self.address().clone();
1430		self.transient_storage.write(&account_id, key, value, take_old)
1431	}
1432
1433	fn address(&self) -> &T::AccountId {
1434		&self.top_frame().account_id
1435	}
1436
1437	fn caller(&self) -> Origin<T> {
1438		if let Some(caller) = &self.top_frame().delegate_caller {
1439			caller.clone()
1440		} else {
1441			self.frames()
1442				.nth(1)
1443				.map(|f| Origin::from_account_id(f.account_id.clone()))
1444				.unwrap_or(self.origin.clone())
1445		}
1446	}
1447
1448	fn is_contract(&self, address: &T::AccountId) -> bool {
1449		ContractInfoOf::<T>::contains_key(&address)
1450	}
1451
1452	fn code_hash(&self, address: &T::AccountId) -> Option<CodeHash<Self::T>> {
1453		<ContractInfoOf<T>>::get(&address).map(|contract| contract.code_hash)
1454	}
1455
1456	fn own_code_hash(&mut self) -> &CodeHash<Self::T> {
1457		&self.top_frame_mut().contract_info().code_hash
1458	}
1459
1460	fn caller_is_origin(&self) -> bool {
1461		self.origin == self.caller()
1462	}
1463
1464	fn caller_is_root(&self) -> bool {
1465		// if the caller isn't origin, then it can't be root.
1466		self.caller_is_origin() && self.origin == Origin::Root
1467	}
1468
1469	fn balance(&self) -> BalanceOf<T> {
1470		T::Currency::reducible_balance(
1471			&self.top_frame().account_id,
1472			Preservation::Preserve,
1473			Fortitude::Polite,
1474		)
1475	}
1476
1477	fn value_transferred(&self) -> BalanceOf<T> {
1478		self.top_frame().value_transferred
1479	}
1480
1481	fn random(&self, subject: &[u8]) -> (SeedOf<T>, BlockNumberFor<T>) {
1482		T::Randomness::random(subject)
1483	}
1484
1485	fn now(&self) -> &MomentOf<T> {
1486		&self.timestamp
1487	}
1488
1489	fn minimum_balance(&self) -> BalanceOf<T> {
1490		T::Currency::minimum_balance()
1491	}
1492
1493	fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) {
1494		Contracts::<Self::T>::deposit_indexed_event(
1495			topics,
1496			Event::ContractEmitted { contract: self.top_frame().account_id.clone(), data },
1497		);
1498	}
1499
1500	fn block_number(&self) -> BlockNumberFor<T> {
1501		self.block_number
1502	}
1503
1504	fn max_value_size(&self) -> u32 {
1505		self.schedule.limits.payload_len
1506	}
1507
1508	fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T> {
1509		T::WeightPrice::convert(weight)
1510	}
1511
1512	fn schedule(&self) -> &Schedule<Self::T> {
1513		self.schedule
1514	}
1515
1516	fn gas_meter(&self) -> &GasMeter<Self::T> {
1517		&self.top_frame().nested_gas
1518	}
1519
1520	fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T> {
1521		&mut self.top_frame_mut().nested_gas
1522	}
1523
1524	fn charge_storage(&mut self, diff: &Diff) {
1525		self.top_frame_mut().nested_storage.charge(diff)
1526	}
1527
1528	fn debug_buffer_enabled(&self) -> bool {
1529		self.debug_message.is_some()
1530	}
1531
1532	fn append_debug_buffer(&mut self, msg: &str) -> bool {
1533		if let Some(buffer) = &mut self.debug_message {
1534			buffer
1535				.try_extend(&mut msg.bytes())
1536				.map_err(|_| {
1537					log::debug!(
1538						target: LOG_TARGET,
1539						"Debug buffer (of {} bytes) exhausted!",
1540						DebugBufferVec::<T>::bound(),
1541					)
1542				})
1543				.ok();
1544			true
1545		} else {
1546			false
1547		}
1548	}
1549
1550	fn call_runtime(&self, call: <Self::T as Config>::RuntimeCall) -> DispatchResultWithPostInfo {
1551		let mut origin: T::RuntimeOrigin = RawOrigin::Signed(self.address().clone()).into();
1552		origin.add_filter(T::CallFilter::contains);
1553		call.dispatch(origin)
1554	}
1555
1556	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
1557		secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
1558	}
1559
1560	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
1561		sp_io::crypto::sr25519_verify(
1562			&SR25519Signature::from(*signature),
1563			message,
1564			&SR25519Public::from(*pub_key),
1565		)
1566	}
1567
1568	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> {
1569		ECDSAPublic::from(*pk).to_eth_address()
1570	}
1571
1572	#[cfg(any(test, feature = "runtime-benchmarks"))]
1573	fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
1574		self.top_frame_mut().contract_info()
1575	}
1576
1577	#[cfg(feature = "runtime-benchmarks")]
1578	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
1579		&mut self.transient_storage
1580	}
1581
1582	fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> DispatchResult {
1583		let frame = top_frame_mut!(self);
1584		if !E::from_storage(hash, &mut frame.nested_gas)?.is_deterministic() {
1585			return Err(<Error<T>>::Indeterministic.into())
1586		}
1587
1588		let info = frame.contract_info();
1589
1590		let prev_hash = info.code_hash;
1591		info.code_hash = hash;
1592
1593		let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?;
1594
1595		let old_base_deposit = info.storage_base_deposit();
1596		let new_base_deposit = info.update_base_deposit(&code_info);
1597		let deposit = StorageDeposit::Charge(new_base_deposit)
1598			.saturating_sub(&StorageDeposit::Charge(old_base_deposit));
1599
1600		frame.nested_storage.charge_deposit(frame.account_id.clone(), deposit);
1601
1602		Self::increment_refcount(hash)?;
1603		Self::decrement_refcount(prev_hash);
1604		Contracts::<Self::T>::deposit_event(Event::ContractCodeUpdated {
1605			contract: frame.account_id.clone(),
1606			new_code_hash: hash,
1607			old_code_hash: prev_hash,
1608		});
1609		Ok(())
1610	}
1611
1612	fn reentrance_count(&self) -> u32 {
1613		let id: &AccountIdOf<Self::T> = &self.top_frame().account_id;
1614		self.account_reentrance_count(id).saturating_sub(1)
1615	}
1616
1617	fn account_reentrance_count(&self, account_id: &AccountIdOf<Self::T>) -> u32 {
1618		self.frames()
1619			.filter(|f| f.delegate_caller.is_none() && &f.account_id == account_id)
1620			.count() as u32
1621	}
1622
1623	fn nonce(&mut self) -> u64 {
1624		if let Some(current) = self.nonce {
1625			current
1626		} else {
1627			let current = <Nonce<T>>::get();
1628			self.nonce = Some(current);
1629			current
1630		}
1631	}
1632
1633	fn increment_refcount(code_hash: CodeHash<Self::T>) -> DispatchResult {
1634		<CodeInfoOf<Self::T>>::mutate(code_hash, |existing| -> Result<(), DispatchError> {
1635			if let Some(info) = existing {
1636				*info.refcount_mut() = info.refcount().saturating_add(1);
1637				Ok(())
1638			} else {
1639				Err(Error::<T>::CodeNotFound.into())
1640			}
1641		})
1642	}
1643
1644	fn decrement_refcount(code_hash: CodeHash<T>) {
1645		<CodeInfoOf<T>>::mutate(code_hash, |existing| {
1646			if let Some(info) = existing {
1647				*info.refcount_mut() = info.refcount().saturating_sub(1);
1648			}
1649		});
1650	}
1651
1652	fn lock_delegate_dependency(&mut self, code_hash: CodeHash<Self::T>) -> DispatchResult {
1653		let frame = self.top_frame_mut();
1654		let info = frame.contract_info.get(&frame.account_id);
1655		ensure!(code_hash != info.code_hash, Error::<T>::CannotAddSelfAsDelegateDependency);
1656
1657		let code_info = CodeInfoOf::<T>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
1658		let deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_info.deposit());
1659
1660		info.lock_delegate_dependency(code_hash, deposit)?;
1661		Self::increment_refcount(code_hash)?;
1662		frame
1663			.nested_storage
1664			.charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit));
1665		Ok(())
1666	}
1667
1668	fn unlock_delegate_dependency(&mut self, code_hash: &CodeHash<Self::T>) -> DispatchResult {
1669		let frame = self.top_frame_mut();
1670		let info = frame.contract_info.get(&frame.account_id);
1671
1672		let deposit = info.unlock_delegate_dependency(code_hash)?;
1673		Self::decrement_refcount(*code_hash);
1674		frame
1675			.nested_storage
1676			.charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(deposit));
1677		Ok(())
1678	}
1679
1680	fn locked_delegate_dependencies_count(&mut self) -> usize {
1681		self.top_frame_mut().contract_info().delegate_dependencies_count()
1682	}
1683
1684	fn is_read_only(&self) -> bool {
1685		self.top_frame().read_only
1686	}
1687}
1688
1689mod sealing {
1690	use super::*;
1691
1692	pub trait Sealed {}
1693
1694	impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
1695
1696	#[cfg(test)]
1697	impl Sealed for crate::wasm::MockExt {}
1698
1699	#[cfg(test)]
1700	impl Sealed for &mut crate::wasm::MockExt {}
1701}
1702
1703/// These tests exercise the executive layer.
1704///
1705/// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use simple
1706/// closures. This allows you to tackle executive logic more thoroughly without writing a
1707/// wasm VM code.
1708#[cfg(test)]
1709mod tests {
1710	use super::*;
1711	use crate::{
1712		exec::ExportedFunction::*,
1713		gas::GasMeter,
1714		tests::{
1715			test_utils::{get_balance, place_contract, set_balance},
1716			ExtBuilder, RuntimeCall, RuntimeEvent as MetaEvent, Test, TestFilter, ALICE, BOB,
1717			CHARLIE, GAS_LIMIT,
1718		},
1719		Error,
1720	};
1721	use assert_matches::assert_matches;
1722	use codec::{Decode, Encode};
1723	use frame_support::{assert_err, assert_ok, parameter_types};
1724	use frame_system::{EventRecord, Phase};
1725	use pallet_contracts_uapi::ReturnFlags;
1726	use pretty_assertions::assert_eq;
1727	use sp_runtime::{traits::Hash, DispatchError};
1728	use std::{cell::RefCell, collections::hash_map::HashMap, rc::Rc};
1729
1730	type System = frame_system::Pallet<Test>;
1731
1732	type MockStack<'a> = Stack<'a, Test, MockExecutable>;
1733
1734	parameter_types! {
1735		static Loader: MockLoader = MockLoader::default();
1736	}
1737
1738	fn events() -> Vec<Event<Test>> {
1739		System::events()
1740			.into_iter()
1741			.filter_map(|meta| match meta.event {
1742				MetaEvent::Contracts(contract_event) => Some(contract_event),
1743				_ => None,
1744			})
1745			.collect()
1746	}
1747
1748	struct MockCtx<'a> {
1749		ext: &'a mut MockStack<'a>,
1750		input_data: Vec<u8>,
1751	}
1752
1753	#[derive(Clone)]
1754	struct MockExecutable {
1755		func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
1756		func_type: ExportedFunction,
1757		code_hash: CodeHash<Test>,
1758		code_info: CodeInfo<Test>,
1759	}
1760
1761	#[derive(Default, Clone)]
1762	pub struct MockLoader {
1763		map: HashMap<CodeHash<Test>, MockExecutable>,
1764		counter: u64,
1765	}
1766
1767	impl MockLoader {
1768		fn code_hashes() -> Vec<CodeHash<Test>> {
1769			Loader::get().map.keys().copied().collect()
1770		}
1771
1772		fn insert(
1773			func_type: ExportedFunction,
1774			f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
1775		) -> CodeHash<Test> {
1776			Loader::mutate(|loader| {
1777				// Generate code hashes as monotonically increasing values.
1778				let hash = <Test as frame_system::Config>::Hash::from_low_u64_be(loader.counter);
1779				loader.counter += 1;
1780				loader.map.insert(
1781					hash,
1782					MockExecutable {
1783						func: Rc::new(f),
1784						func_type,
1785						code_hash: hash,
1786						code_info: CodeInfo::<Test>::new(ALICE),
1787					},
1788				);
1789				hash
1790			})
1791		}
1792	}
1793
1794	impl Executable<Test> for MockExecutable {
1795		fn from_storage(
1796			code_hash: CodeHash<Test>,
1797			_gas_meter: &mut GasMeter<Test>,
1798		) -> Result<Self, DispatchError> {
1799			Loader::mutate(|loader| {
1800				loader.map.get(&code_hash).cloned().ok_or(Error::<Test>::CodeNotFound.into())
1801			})
1802		}
1803
1804		fn execute<E: Ext<T = Test>>(
1805			self,
1806			ext: &mut E,
1807			function: &ExportedFunction,
1808			input_data: Vec<u8>,
1809		) -> ExecResult {
1810			if let &Constructor = function {
1811				E::increment_refcount(self.code_hash).unwrap();
1812			}
1813			// # Safety
1814			//
1815			// We know that we **always** call execute with a `MockStack` in this test.
1816			//
1817			// # Note
1818			//
1819			// The transmute is necessary because `execute` has to be generic over all
1820			// `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would
1821			// constitute a cycle.
1822			let ext = unsafe { mem::transmute(ext) };
1823			if function == &self.func_type {
1824				(self.func)(MockCtx { ext, input_data }, &self)
1825			} else {
1826				exec_success()
1827			}
1828		}
1829
1830		fn code_hash(&self) -> &CodeHash<Test> {
1831			&self.code_hash
1832		}
1833
1834		fn code_info(&self) -> &CodeInfo<Test> {
1835			&self.code_info
1836		}
1837
1838		fn is_deterministic(&self) -> bool {
1839			true
1840		}
1841	}
1842
1843	fn exec_success() -> ExecResult {
1844		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1845	}
1846
1847	fn exec_trapped() -> ExecResult {
1848		Err(ExecError { error: <Error<Test>>::ContractTrapped.into(), origin: ErrorOrigin::Callee })
1849	}
1850
1851	#[test]
1852	fn it_works() {
1853		parameter_types! {
1854			static TestData: Vec<usize> = vec![0];
1855		}
1856
1857		let value = Default::default();
1858		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
1859		let exec_ch = MockLoader::insert(Call, |_ctx, _executable| {
1860			TestData::mutate(|data| data.push(1));
1861			exec_success()
1862		});
1863
1864		ExtBuilder::default().build().execute_with(|| {
1865			let schedule = <Test as Config>::Schedule::get();
1866			place_contract(&BOB, exec_ch);
1867			let mut storage_meter =
1868				storage::meter::Meter::new(&Origin::from_account_id(ALICE), Some(0), value)
1869					.unwrap();
1870
1871			assert_matches!(
1872				MockStack::run_call(
1873					Origin::from_account_id(ALICE),
1874					BOB,
1875					&mut gas_meter,
1876					&mut storage_meter,
1877					&schedule,
1878					value,
1879					vec![],
1880					None,
1881					Determinism::Enforced,
1882				),
1883				Ok(_)
1884			);
1885		});
1886
1887		assert_eq!(TestData::get(), vec![0, 1]);
1888	}
1889
1890	#[test]
1891	fn transfer_works() {
1892		// This test verifies that a contract is able to transfer
1893		// some funds to another account.
1894		let origin = ALICE;
1895		let dest = BOB;
1896
1897		ExtBuilder::default().build().execute_with(|| {
1898			set_balance(&origin, 100);
1899			set_balance(&dest, 0);
1900
1901			MockStack::transfer(Preservation::Preserve, &origin, &dest, 55).unwrap();
1902
1903			assert_eq!(get_balance(&origin), 45);
1904			assert_eq!(get_balance(&dest), 55);
1905		});
1906	}
1907
1908	#[test]
1909	fn correct_transfer_on_call() {
1910		let origin = ALICE;
1911		let dest = BOB;
1912		let value = 55;
1913
1914		let success_ch = MockLoader::insert(Call, move |ctx, _| {
1915			assert_eq!(ctx.ext.value_transferred(), value);
1916			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1917		});
1918
1919		ExtBuilder::default().build().execute_with(|| {
1920			let schedule = <Test as Config>::Schedule::get();
1921			place_contract(&dest, success_ch);
1922			set_balance(&origin, 100);
1923			let balance = get_balance(&dest);
1924			let contract_origin = Origin::from_account_id(origin.clone());
1925			let mut storage_meter =
1926				storage::meter::Meter::new(&contract_origin, Some(0), value).unwrap();
1927
1928			let _ = MockStack::run_call(
1929				contract_origin.clone(),
1930				dest.clone(),
1931				&mut GasMeter::<Test>::new(GAS_LIMIT),
1932				&mut storage_meter,
1933				&schedule,
1934				value,
1935				vec![],
1936				None,
1937				Determinism::Enforced,
1938			)
1939			.unwrap();
1940
1941			assert_eq!(get_balance(&origin), 100 - value);
1942			assert_eq!(get_balance(&dest), balance + value);
1943		});
1944	}
1945
1946	#[test]
1947	fn correct_transfer_on_delegate_call() {
1948		let origin = ALICE;
1949		let dest = BOB;
1950		let value = 35;
1951
1952		let success_ch = MockLoader::insert(Call, move |ctx, _| {
1953			assert_eq!(ctx.ext.value_transferred(), value);
1954			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1955		});
1956
1957		let delegate_ch = MockLoader::insert(Call, move |ctx, _| {
1958			assert_eq!(ctx.ext.value_transferred(), value);
1959			ctx.ext.delegate_call(success_ch, Vec::new())?;
1960			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1961		});
1962
1963		ExtBuilder::default().build().execute_with(|| {
1964			let schedule = <Test as Config>::Schedule::get();
1965			place_contract(&dest, delegate_ch);
1966			set_balance(&origin, 100);
1967			let balance = get_balance(&dest);
1968			let contract_origin = Origin::from_account_id(origin.clone());
1969			let mut storage_meter =
1970				storage::meter::Meter::new(&contract_origin, Some(0), 55).unwrap();
1971
1972			let _ = MockStack::run_call(
1973				contract_origin.clone(),
1974				dest.clone(),
1975				&mut GasMeter::<Test>::new(GAS_LIMIT),
1976				&mut storage_meter,
1977				&schedule,
1978				value,
1979				vec![],
1980				None,
1981				Determinism::Enforced,
1982			)
1983			.unwrap();
1984
1985			assert_eq!(get_balance(&origin), 100 - value);
1986			assert_eq!(get_balance(&dest), balance + value);
1987		});
1988	}
1989
1990	#[test]
1991	fn changes_are_reverted_on_failing_call() {
1992		// This test verifies that changes are reverted on a call which fails (or equally, returns
1993		// a non-zero status code).
1994		let origin = ALICE;
1995		let dest = BOB;
1996
1997		let return_ch = MockLoader::insert(Call, |_, _| {
1998			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() })
1999		});
2000
2001		ExtBuilder::default().build().execute_with(|| {
2002			let schedule = <Test as Config>::Schedule::get();
2003			place_contract(&dest, return_ch);
2004			set_balance(&origin, 100);
2005			let balance = get_balance(&dest);
2006			let contract_origin = Origin::from_account_id(origin.clone());
2007			let mut storage_meter =
2008				storage::meter::Meter::new(&contract_origin, Some(0), 55).unwrap();
2009
2010			let output = MockStack::run_call(
2011				contract_origin.clone(),
2012				dest.clone(),
2013				&mut GasMeter::<Test>::new(GAS_LIMIT),
2014				&mut storage_meter,
2015				&schedule,
2016				55,
2017				vec![],
2018				None,
2019				Determinism::Enforced,
2020			)
2021			.unwrap();
2022
2023			assert!(output.did_revert());
2024			assert_eq!(get_balance(&origin), 100);
2025			assert_eq!(get_balance(&dest), balance);
2026		});
2027	}
2028
2029	#[test]
2030	fn balance_too_low() {
2031		// This test verifies that a contract can't send value if it's
2032		// balance is too low.
2033		let origin = ALICE;
2034		let dest = BOB;
2035
2036		ExtBuilder::default().build().execute_with(|| {
2037			set_balance(&origin, 0);
2038
2039			let result = MockStack::transfer(Preservation::Preserve, &origin, &dest, 100);
2040
2041			assert_eq!(result, Err(Error::<Test>::TransferFailed.into()));
2042			assert_eq!(get_balance(&origin), 0);
2043			assert_eq!(get_balance(&dest), 0);
2044		});
2045	}
2046
2047	#[test]
2048	fn output_is_returned_on_success() {
2049		// Verifies that if a contract returns data with a successful exit status, this data
2050		// is returned from the execution context.
2051		let origin = ALICE;
2052		let dest = BOB;
2053		let return_ch = MockLoader::insert(Call, |_, _| {
2054			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] })
2055		});
2056
2057		ExtBuilder::default().build().execute_with(|| {
2058			let schedule = <Test as Config>::Schedule::get();
2059			let contract_origin = Origin::from_account_id(origin);
2060			let mut storage_meter =
2061				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2062			place_contract(&BOB, return_ch);
2063
2064			let result = MockStack::run_call(
2065				contract_origin,
2066				dest,
2067				&mut GasMeter::<Test>::new(GAS_LIMIT),
2068				&mut storage_meter,
2069				&schedule,
2070				0,
2071				vec![],
2072				None,
2073				Determinism::Enforced,
2074			);
2075
2076			let output = result.unwrap();
2077			assert!(!output.did_revert());
2078			assert_eq!(output.data, vec![1, 2, 3, 4]);
2079		});
2080	}
2081
2082	#[test]
2083	fn output_is_returned_on_failure() {
2084		// Verifies that if a contract returns data with a failing exit status, this data
2085		// is returned from the execution context.
2086		let origin = ALICE;
2087		let dest = BOB;
2088		let return_ch = MockLoader::insert(Call, |_, _| {
2089			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] })
2090		});
2091
2092		ExtBuilder::default().build().execute_with(|| {
2093			let schedule = <Test as Config>::Schedule::get();
2094			place_contract(&BOB, return_ch);
2095			let contract_origin = Origin::from_account_id(origin);
2096			let mut storage_meter =
2097				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2098
2099			let result = MockStack::run_call(
2100				contract_origin,
2101				dest,
2102				&mut GasMeter::<Test>::new(GAS_LIMIT),
2103				&mut storage_meter,
2104				&schedule,
2105				0,
2106				vec![],
2107				None,
2108				Determinism::Enforced,
2109			);
2110
2111			let output = result.unwrap();
2112			assert!(output.did_revert());
2113			assert_eq!(output.data, vec![1, 2, 3, 4]);
2114		});
2115	}
2116
2117	#[test]
2118	fn input_data_to_call() {
2119		let input_data_ch = MockLoader::insert(Call, |ctx, _| {
2120			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
2121			exec_success()
2122		});
2123
2124		// This one tests passing the input data into a contract via call.
2125		ExtBuilder::default().build().execute_with(|| {
2126			let schedule = <Test as Config>::Schedule::get();
2127			place_contract(&BOB, input_data_ch);
2128			let contract_origin = Origin::from_account_id(ALICE);
2129			let mut storage_meter =
2130				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2131
2132			let result = MockStack::run_call(
2133				contract_origin,
2134				BOB,
2135				&mut GasMeter::<Test>::new(GAS_LIMIT),
2136				&mut storage_meter,
2137				&schedule,
2138				0,
2139				vec![1, 2, 3, 4],
2140				None,
2141				Determinism::Enforced,
2142			);
2143			assert_matches!(result, Ok(_));
2144		});
2145	}
2146
2147	#[test]
2148	fn input_data_to_instantiate() {
2149		let input_data_ch = MockLoader::insert(Constructor, |ctx, _| {
2150			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
2151			exec_success()
2152		});
2153
2154		// This one tests passing the input data into a contract via instantiate.
2155		ExtBuilder::default()
2156			.with_code_hashes(MockLoader::code_hashes())
2157			.build()
2158			.execute_with(|| {
2159				let schedule = <Test as Config>::Schedule::get();
2160				let min_balance = <Test as Config>::Currency::minimum_balance();
2161				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2162				let executable =
2163					MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
2164				set_balance(&ALICE, min_balance * 10_000);
2165				let contract_origin = Origin::from_account_id(ALICE);
2166				let mut storage_meter =
2167					storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
2168
2169				let result = MockStack::run_instantiate(
2170					ALICE,
2171					executable,
2172					&mut gas_meter,
2173					&mut storage_meter,
2174					&schedule,
2175					min_balance,
2176					vec![1, 2, 3, 4],
2177					&[],
2178					None,
2179				);
2180				assert_matches!(result, Ok(_));
2181			});
2182	}
2183
2184	#[test]
2185	fn max_depth() {
2186		// This test verifies that when we reach the maximal depth creation of an
2187		// yet another context fails.
2188		parameter_types! {
2189			static ReachedBottom: bool = false;
2190		}
2191		let value = Default::default();
2192		let recurse_ch = MockLoader::insert(Call, |ctx, _| {
2193			// Try to call into yourself.
2194			let r = ctx.ext.call(
2195				Weight::zero(),
2196				BalanceOf::<Test>::zero(),
2197				BOB,
2198				0,
2199				vec![],
2200				true,
2201				false,
2202			);
2203
2204			ReachedBottom::mutate(|reached_bottom| {
2205				if !*reached_bottom {
2206					// We are first time here, it means we just reached bottom.
2207					// Verify that we've got proper error and set `reached_bottom`.
2208					assert_eq!(r, Err(Error::<Test>::MaxCallDepthReached.into()));
2209					*reached_bottom = true;
2210				} else {
2211					// We just unwinding stack here.
2212					assert_matches!(r, Ok(_));
2213				}
2214			});
2215
2216			exec_success()
2217		});
2218
2219		ExtBuilder::default().build().execute_with(|| {
2220			let schedule = <Test as Config>::Schedule::get();
2221			set_balance(&BOB, 1);
2222			place_contract(&BOB, recurse_ch);
2223			let contract_origin = Origin::from_account_id(ALICE);
2224			let mut storage_meter =
2225				storage::meter::Meter::new(&contract_origin, Some(0), value).unwrap();
2226
2227			let result = MockStack::run_call(
2228				contract_origin,
2229				BOB,
2230				&mut GasMeter::<Test>::new(GAS_LIMIT),
2231				&mut storage_meter,
2232				&schedule,
2233				value,
2234				vec![],
2235				None,
2236				Determinism::Enforced,
2237			);
2238
2239			assert_matches!(result, Ok(_));
2240		});
2241	}
2242
2243	#[test]
2244	fn caller_returns_proper_values() {
2245		let origin = ALICE;
2246		let dest = BOB;
2247
2248		parameter_types! {
2249			static WitnessedCallerBob: Option<AccountIdOf<Test>> = None;
2250			static WitnessedCallerCharlie: Option<AccountIdOf<Test>> = None;
2251		}
2252
2253		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2254			// Record the caller for bob.
2255			WitnessedCallerBob::mutate(|caller| {
2256				*caller = Some(ctx.ext.caller().account_id().unwrap().clone())
2257			});
2258
2259			// Call into CHARLIE contract.
2260			assert_matches!(
2261				ctx.ext.call(
2262					Weight::zero(),
2263					BalanceOf::<Test>::zero(),
2264					CHARLIE,
2265					0,
2266					vec![],
2267					true,
2268					false
2269				),
2270				Ok(_)
2271			);
2272			exec_success()
2273		});
2274		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
2275			// Record the caller for charlie.
2276			WitnessedCallerCharlie::mutate(|caller| {
2277				*caller = Some(ctx.ext.caller().account_id().unwrap().clone())
2278			});
2279			exec_success()
2280		});
2281
2282		ExtBuilder::default().build().execute_with(|| {
2283			let schedule = <Test as Config>::Schedule::get();
2284			place_contract(&dest, bob_ch);
2285			place_contract(&CHARLIE, charlie_ch);
2286			let contract_origin = Origin::from_account_id(origin.clone());
2287			let mut storage_meter =
2288				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2289
2290			let result = MockStack::run_call(
2291				contract_origin.clone(),
2292				dest.clone(),
2293				&mut GasMeter::<Test>::new(GAS_LIMIT),
2294				&mut storage_meter,
2295				&schedule,
2296				0,
2297				vec![],
2298				None,
2299				Determinism::Enforced,
2300			);
2301
2302			assert_matches!(result, Ok(_));
2303		});
2304
2305		assert_eq!(WitnessedCallerBob::get(), Some(origin));
2306		assert_eq!(WitnessedCallerCharlie::get(), Some(dest));
2307	}
2308
2309	#[test]
2310	fn is_contract_returns_proper_values() {
2311		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2312			// Verify that BOB is a contract
2313			assert!(ctx.ext.is_contract(&BOB));
2314			// Verify that ALICE is not a contract
2315			assert!(!ctx.ext.is_contract(&ALICE));
2316			exec_success()
2317		});
2318
2319		ExtBuilder::default().build().execute_with(|| {
2320			let schedule = <Test as Config>::Schedule::get();
2321			place_contract(&BOB, bob_ch);
2322
2323			let contract_origin = Origin::from_account_id(ALICE);
2324			let mut storage_meter =
2325				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2326			let result = MockStack::run_call(
2327				contract_origin,
2328				BOB,
2329				&mut GasMeter::<Test>::new(GAS_LIMIT),
2330				&mut storage_meter,
2331				&schedule,
2332				0,
2333				vec![],
2334				None,
2335				Determinism::Enforced,
2336			);
2337			assert_matches!(result, Ok(_));
2338		});
2339	}
2340
2341	#[test]
2342	fn code_hash_returns_proper_values() {
2343		let code_bob = MockLoader::insert(Call, |ctx, _| {
2344			// ALICE is not a contract and hence they do not have a code_hash
2345			assert!(ctx.ext.code_hash(&ALICE).is_none());
2346			// BOB is a contract and hence it has a code_hash
2347			assert!(ctx.ext.code_hash(&BOB).is_some());
2348			exec_success()
2349		});
2350
2351		ExtBuilder::default().build().execute_with(|| {
2352			let schedule = <Test as Config>::Schedule::get();
2353			place_contract(&BOB, code_bob);
2354			let contract_origin = Origin::from_account_id(ALICE);
2355			let mut storage_meter =
2356				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2357			// ALICE (not contract) -> BOB (contract)
2358			let result = MockStack::run_call(
2359				contract_origin,
2360				BOB,
2361				&mut GasMeter::<Test>::new(GAS_LIMIT),
2362				&mut storage_meter,
2363				&schedule,
2364				0,
2365				vec![0],
2366				None,
2367				Determinism::Enforced,
2368			);
2369			assert_matches!(result, Ok(_));
2370		});
2371	}
2372
2373	#[test]
2374	fn own_code_hash_returns_proper_values() {
2375		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2376			let code_hash = ctx.ext.code_hash(&BOB).unwrap();
2377			assert_eq!(*ctx.ext.own_code_hash(), code_hash);
2378			exec_success()
2379		});
2380
2381		ExtBuilder::default().build().execute_with(|| {
2382			let schedule = <Test as Config>::Schedule::get();
2383			place_contract(&BOB, bob_ch);
2384			let contract_origin = Origin::from_account_id(ALICE);
2385			let mut storage_meter =
2386				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2387			// ALICE (not contract) -> BOB (contract)
2388			let result = MockStack::run_call(
2389				contract_origin,
2390				BOB,
2391				&mut GasMeter::<Test>::new(GAS_LIMIT),
2392				&mut storage_meter,
2393				&schedule,
2394				0,
2395				vec![0],
2396				None,
2397				Determinism::Enforced,
2398			);
2399			assert_matches!(result, Ok(_));
2400		});
2401	}
2402
2403	#[test]
2404	fn caller_is_origin_returns_proper_values() {
2405		let code_charlie = MockLoader::insert(Call, |ctx, _| {
2406			// BOB is not the origin of the stack call
2407			assert!(!ctx.ext.caller_is_origin());
2408			exec_success()
2409		});
2410
2411		let code_bob = MockLoader::insert(Call, |ctx, _| {
2412			// ALICE is the origin of the call stack
2413			assert!(ctx.ext.caller_is_origin());
2414			// BOB calls CHARLIE
2415			ctx.ext
2416				.call(Weight::zero(), BalanceOf::<Test>::zero(), CHARLIE, 0, vec![], true, false)
2417		});
2418
2419		ExtBuilder::default().build().execute_with(|| {
2420			let schedule = <Test as Config>::Schedule::get();
2421			place_contract(&BOB, code_bob);
2422			place_contract(&CHARLIE, code_charlie);
2423			let contract_origin = Origin::from_account_id(ALICE);
2424			let mut storage_meter =
2425				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2426			// ALICE -> BOB (caller is origin) -> CHARLIE (caller is not origin)
2427			let result = MockStack::run_call(
2428				contract_origin,
2429				BOB,
2430				&mut GasMeter::<Test>::new(GAS_LIMIT),
2431				&mut storage_meter,
2432				&schedule,
2433				0,
2434				vec![0],
2435				None,
2436				Determinism::Enforced,
2437			);
2438			assert_matches!(result, Ok(_));
2439		});
2440	}
2441
2442	#[test]
2443	fn root_caller_succeeds() {
2444		let code_bob = MockLoader::insert(Call, |ctx, _| {
2445			// root is the origin of the call stack.
2446			assert!(ctx.ext.caller_is_root());
2447			exec_success()
2448		});
2449
2450		ExtBuilder::default().build().execute_with(|| {
2451			let schedule = <Test as Config>::Schedule::get();
2452			place_contract(&BOB, code_bob);
2453			let contract_origin = Origin::Root;
2454			let mut storage_meter =
2455				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2456			// root -> BOB (caller is root)
2457			let result = MockStack::run_call(
2458				contract_origin,
2459				BOB,
2460				&mut GasMeter::<Test>::new(GAS_LIMIT),
2461				&mut storage_meter,
2462				&schedule,
2463				0,
2464				vec![0],
2465				None,
2466				Determinism::Enforced,
2467			);
2468			assert_matches!(result, Ok(_));
2469		});
2470	}
2471
2472	#[test]
2473	fn root_caller_does_not_succeed_when_value_not_zero() {
2474		let code_bob = MockLoader::insert(Call, |ctx, _| {
2475			// root is the origin of the call stack.
2476			assert!(ctx.ext.caller_is_root());
2477			exec_success()
2478		});
2479
2480		ExtBuilder::default().build().execute_with(|| {
2481			let schedule = <Test as Config>::Schedule::get();
2482			place_contract(&BOB, code_bob);
2483			let contract_origin = Origin::Root;
2484			let mut storage_meter =
2485				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2486			// root -> BOB (caller is root)
2487			let result = MockStack::run_call(
2488				contract_origin,
2489				BOB,
2490				&mut GasMeter::<Test>::new(GAS_LIMIT),
2491				&mut storage_meter,
2492				&schedule,
2493				1,
2494				vec![0],
2495				None,
2496				Determinism::Enforced,
2497			);
2498			assert_matches!(result, Err(_));
2499		});
2500	}
2501
2502	#[test]
2503	fn root_caller_succeeds_with_consecutive_calls() {
2504		let code_charlie = MockLoader::insert(Call, |ctx, _| {
2505			// BOB is not root, even though the origin is root.
2506			assert!(!ctx.ext.caller_is_root());
2507			exec_success()
2508		});
2509
2510		let code_bob = MockLoader::insert(Call, |ctx, _| {
2511			// root is the origin of the call stack.
2512			assert!(ctx.ext.caller_is_root());
2513			// BOB calls CHARLIE.
2514			ctx.ext
2515				.call(Weight::zero(), BalanceOf::<Test>::zero(), CHARLIE, 0, vec![], true, false)
2516		});
2517
2518		ExtBuilder::default().build().execute_with(|| {
2519			let schedule = <Test as Config>::Schedule::get();
2520			place_contract(&BOB, code_bob);
2521			place_contract(&CHARLIE, code_charlie);
2522			let contract_origin = Origin::Root;
2523			let mut storage_meter =
2524				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2525			// root -> BOB (caller is root) -> CHARLIE (caller is not root)
2526			let result = MockStack::run_call(
2527				contract_origin,
2528				BOB,
2529				&mut GasMeter::<Test>::new(GAS_LIMIT),
2530				&mut storage_meter,
2531				&schedule,
2532				0,
2533				vec![0],
2534				None,
2535				Determinism::Enforced,
2536			);
2537			assert_matches!(result, Ok(_));
2538		});
2539	}
2540
2541	#[test]
2542	fn address_returns_proper_values() {
2543		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2544			// Verify that address matches BOB.
2545			assert_eq!(*ctx.ext.address(), BOB);
2546
2547			// Call into charlie contract.
2548			assert_matches!(
2549				ctx.ext.call(
2550					Weight::zero(),
2551					BalanceOf::<Test>::zero(),
2552					CHARLIE,
2553					0,
2554					vec![],
2555					true,
2556					false
2557				),
2558				Ok(_)
2559			);
2560			exec_success()
2561		});
2562		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
2563			assert_eq!(*ctx.ext.address(), CHARLIE);
2564			exec_success()
2565		});
2566
2567		ExtBuilder::default().build().execute_with(|| {
2568			let schedule = <Test as Config>::Schedule::get();
2569			place_contract(&BOB, bob_ch);
2570			place_contract(&CHARLIE, charlie_ch);
2571			let contract_origin = Origin::from_account_id(ALICE);
2572			let mut storage_meter =
2573				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2574
2575			let result = MockStack::run_call(
2576				contract_origin,
2577				BOB,
2578				&mut GasMeter::<Test>::new(GAS_LIMIT),
2579				&mut storage_meter,
2580				&schedule,
2581				0,
2582				vec![],
2583				None,
2584				Determinism::Enforced,
2585			);
2586
2587			assert_matches!(result, Ok(_));
2588		});
2589	}
2590
2591	#[test]
2592	fn refuse_instantiate_with_value_below_existential_deposit() {
2593		let dummy_ch = MockLoader::insert(Constructor, |_, _| exec_success());
2594
2595		ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
2596			let schedule = <Test as Config>::Schedule::get();
2597			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2598			let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
2599			let contract_origin = Origin::from_account_id(ALICE);
2600			let mut storage_meter =
2601				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2602
2603			assert_matches!(
2604				MockStack::run_instantiate(
2605					ALICE,
2606					executable,
2607					&mut gas_meter,
2608					&mut storage_meter,
2609					&schedule,
2610					0, // <- zero value
2611					vec![],
2612					&[],
2613					None,
2614				),
2615				Err(_)
2616			);
2617		});
2618	}
2619
2620	#[test]
2621	fn instantiation_work_with_success_output() {
2622		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
2623			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] })
2624		});
2625
2626		ExtBuilder::default()
2627			.with_code_hashes(MockLoader::code_hashes())
2628			.existential_deposit(15)
2629			.build()
2630			.execute_with(|| {
2631				let schedule = <Test as Config>::Schedule::get();
2632				let min_balance = <Test as Config>::Currency::minimum_balance();
2633				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2634				let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
2635				set_balance(&ALICE, min_balance * 1000);
2636				let contract_origin = Origin::from_account_id(ALICE);
2637				let mut storage_meter = storage::meter::Meter::new(
2638					&contract_origin,
2639					Some(min_balance * 100),
2640					min_balance,
2641				)
2642				.unwrap();
2643
2644				let instantiated_contract_address = assert_matches!(
2645					MockStack::run_instantiate(
2646						ALICE,
2647						executable,
2648						&mut gas_meter,
2649						&mut storage_meter,
2650						&schedule,
2651						min_balance,
2652						vec![],
2653						&[],
2654						None,
2655					),
2656					Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
2657				);
2658
2659				// Check that the newly created account has the expected code hash and
2660				// there are instantiation event.
2661				assert_eq!(
2662					ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
2663					dummy_ch
2664				);
2665				assert_eq!(
2666					&events(),
2667					&[Event::Instantiated {
2668						deployer: ALICE,
2669						contract: instantiated_contract_address
2670					}]
2671				);
2672			});
2673	}
2674
2675	#[test]
2676	fn instantiation_fails_with_failing_output() {
2677		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
2678			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] })
2679		});
2680
2681		ExtBuilder::default()
2682			.with_code_hashes(MockLoader::code_hashes())
2683			.existential_deposit(15)
2684			.build()
2685			.execute_with(|| {
2686				let schedule = <Test as Config>::Schedule::get();
2687				let min_balance = <Test as Config>::Currency::minimum_balance();
2688				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2689				let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
2690				set_balance(&ALICE, min_balance * 1000);
2691				let contract_origin = Origin::from_account_id(ALICE);
2692				let mut storage_meter = storage::meter::Meter::new(
2693					&contract_origin,
2694					Some(min_balance * 100),
2695					min_balance,
2696				)
2697				.unwrap();
2698
2699				let instantiated_contract_address = assert_matches!(
2700					MockStack::run_instantiate(
2701						ALICE,
2702						executable,
2703						&mut gas_meter,
2704						&mut storage_meter,
2705						&schedule,
2706						min_balance,
2707						vec![],
2708						&[],
2709						None,
2710					),
2711					Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
2712				);
2713
2714				// Check that the account has not been created.
2715				assert!(
2716					ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).is_none()
2717				);
2718				assert!(events().is_empty());
2719			});
2720	}
2721
2722	#[test]
2723	fn instantiation_from_contract() {
2724		let dummy_ch = MockLoader::insert(Call, |_, _| exec_success());
2725		let instantiated_contract_address = Rc::new(RefCell::new(None::<AccountIdOf<Test>>));
2726		let instantiator_ch = MockLoader::insert(Call, {
2727			let instantiated_contract_address = Rc::clone(&instantiated_contract_address);
2728			move |ctx, _| {
2729				// Instantiate a contract and save it's address in `instantiated_contract_address`.
2730				let (address, output) = ctx
2731					.ext
2732					.instantiate(
2733						Weight::zero(),
2734						BalanceOf::<Test>::zero(),
2735						dummy_ch,
2736						<Test as Config>::Currency::minimum_balance(),
2737						vec![],
2738						&[48, 49, 50],
2739					)
2740					.unwrap();
2741
2742				*instantiated_contract_address.borrow_mut() = address.into();
2743				Ok(output)
2744			}
2745		});
2746
2747		ExtBuilder::default()
2748			.with_code_hashes(MockLoader::code_hashes())
2749			.existential_deposit(15)
2750			.build()
2751			.execute_with(|| {
2752				let schedule = <Test as Config>::Schedule::get();
2753				let min_balance = <Test as Config>::Currency::minimum_balance();
2754				set_balance(&ALICE, min_balance * 100);
2755				place_contract(&BOB, instantiator_ch);
2756				let contract_origin = Origin::from_account_id(ALICE);
2757				let mut storage_meter = storage::meter::Meter::new(
2758					&contract_origin,
2759					Some(min_balance * 10),
2760					min_balance * 10,
2761				)
2762				.unwrap();
2763
2764				assert_matches!(
2765					MockStack::run_call(
2766						contract_origin,
2767						BOB,
2768						&mut GasMeter::<Test>::new(GAS_LIMIT),
2769						&mut storage_meter,
2770						&schedule,
2771						min_balance * 10,
2772						vec![],
2773						None,
2774						Determinism::Enforced,
2775					),
2776					Ok(_)
2777				);
2778
2779				let instantiated_contract_address =
2780					instantiated_contract_address.borrow().as_ref().unwrap().clone();
2781
2782				// Check that the newly created account has the expected code hash and
2783				// there are instantiation event.
2784				assert_eq!(
2785					ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
2786					dummy_ch
2787				);
2788				assert_eq!(
2789					&events(),
2790					&[
2791						Event::Instantiated {
2792							deployer: BOB,
2793							contract: instantiated_contract_address
2794						},
2795						Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },
2796					]
2797				);
2798			});
2799	}
2800
2801	#[test]
2802	fn instantiation_traps() {
2803		let dummy_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
2804		let instantiator_ch = MockLoader::insert(Call, {
2805			move |ctx, _| {
2806				// Instantiate a contract and save it's address in `instantiated_contract_address`.
2807				assert_matches!(
2808					ctx.ext.instantiate(
2809						Weight::zero(),
2810						BalanceOf::<Test>::zero(),
2811						dummy_ch,
2812						<Test as Config>::Currency::minimum_balance(),
2813						vec![],
2814						&[],
2815					),
2816					Err(ExecError {
2817						error: DispatchError::Other("It's a trap!"),
2818						origin: ErrorOrigin::Callee,
2819					})
2820				);
2821
2822				exec_success()
2823			}
2824		});
2825
2826		ExtBuilder::default()
2827			.with_code_hashes(MockLoader::code_hashes())
2828			.existential_deposit(15)
2829			.build()
2830			.execute_with(|| {
2831				let schedule = <Test as Config>::Schedule::get();
2832				set_balance(&ALICE, 1000);
2833				set_balance(&BOB, 100);
2834				place_contract(&BOB, instantiator_ch);
2835				let contract_origin = Origin::from_account_id(ALICE);
2836				let mut storage_meter =
2837					storage::meter::Meter::new(&contract_origin, Some(200), 0).unwrap();
2838
2839				assert_matches!(
2840					MockStack::run_call(
2841						contract_origin,
2842						BOB,
2843						&mut GasMeter::<Test>::new(GAS_LIMIT),
2844						&mut storage_meter,
2845						&schedule,
2846						0,
2847						vec![],
2848						None,
2849						Determinism::Enforced,
2850					),
2851					Ok(_)
2852				);
2853
2854				// The contract wasn't instantiated so we don't expect to see an instantiation
2855				// event here.
2856				assert_eq!(
2857					&events(),
2858					&[Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },]
2859				);
2860			});
2861	}
2862
2863	#[test]
2864	fn termination_from_instantiate_fails() {
2865		let terminate_ch = MockLoader::insert(Constructor, |ctx, _| {
2866			ctx.ext.terminate(&ALICE).unwrap();
2867			exec_success()
2868		});
2869
2870		ExtBuilder::default()
2871			.with_code_hashes(MockLoader::code_hashes())
2872			.existential_deposit(15)
2873			.build()
2874			.execute_with(|| {
2875				let schedule = <Test as Config>::Schedule::get();
2876				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2877				let executable =
2878					MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
2879				set_balance(&ALICE, 10_000);
2880				let contract_origin = Origin::from_account_id(ALICE);
2881				let mut storage_meter =
2882					storage::meter::Meter::new(&contract_origin, None, 100).unwrap();
2883
2884				assert_eq!(
2885					MockStack::run_instantiate(
2886						ALICE,
2887						executable,
2888						&mut gas_meter,
2889						&mut storage_meter,
2890						&schedule,
2891						100,
2892						vec![],
2893						&[],
2894						None,
2895					),
2896					Err(Error::<Test>::TerminatedInConstructor.into())
2897				);
2898
2899				assert_eq!(&events(), &[]);
2900			});
2901	}
2902
2903	#[test]
2904	fn in_memory_changes_not_discarded() {
2905		// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
2906		// This tests verifies some edge case of the contract info cache:
2907		// We change some value in our contract info before calling into a contract
2908		// that calls into ourself. This triggers a case where BOBs contract info
2909		// is written to storage and invalidated by the successful execution of BOB'.
2910		// The trap of CHARLIE reverts the storage changes to BOB. When the root BOB regains
2911		// control it reloads its contract info from storage. We check that changes that
2912		// are made before calling into CHARLIE are not discarded.
2913		let code_bob = MockLoader::insert(Call, |ctx, _| {
2914			if ctx.input_data[0] == 0 {
2915				let info = ctx.ext.contract_info();
2916				assert_eq!(info.storage_byte_deposit, 0);
2917				info.storage_byte_deposit = 42;
2918				assert_eq!(
2919					ctx.ext.call(
2920						Weight::zero(),
2921						BalanceOf::<Test>::zero(),
2922						CHARLIE,
2923						0,
2924						vec![],
2925						true,
2926						false
2927					),
2928					exec_trapped()
2929				);
2930				assert_eq!(ctx.ext.contract_info().storage_byte_deposit, 42);
2931			}
2932			exec_success()
2933		});
2934		let code_charlie = MockLoader::insert(Call, |ctx, _| {
2935			assert!(ctx
2936				.ext
2937				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false)
2938				.is_ok());
2939			exec_trapped()
2940		});
2941
2942		// This one tests passing the input data into a contract via call.
2943		ExtBuilder::default().build().execute_with(|| {
2944			let schedule = <Test as Config>::Schedule::get();
2945			place_contract(&BOB, code_bob);
2946			place_contract(&CHARLIE, code_charlie);
2947			let contract_origin = Origin::from_account_id(ALICE);
2948			let mut storage_meter =
2949				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2950
2951			let result = MockStack::run_call(
2952				contract_origin,
2953				BOB,
2954				&mut GasMeter::<Test>::new(GAS_LIMIT),
2955				&mut storage_meter,
2956				&schedule,
2957				0,
2958				vec![0],
2959				None,
2960				Determinism::Enforced,
2961			);
2962			assert_matches!(result, Ok(_));
2963		});
2964	}
2965
2966	#[test]
2967	fn recursive_call_during_constructor_fails() {
2968		let code = MockLoader::insert(Constructor, |ctx, _| {
2969			assert_matches!(
2970				ctx.ext.call(Weight::zero(), BalanceOf::<Test>::zero(), ctx.ext.address().clone(), 0, vec![], true, false),
2971				Err(ExecError{error, ..}) if error == <Error<Test>>::ContractNotFound.into()
2972			);
2973			exec_success()
2974		});
2975
2976		// This one tests passing the input data into a contract via instantiate.
2977		ExtBuilder::default()
2978			.with_code_hashes(MockLoader::code_hashes())
2979			.build()
2980			.execute_with(|| {
2981				let schedule = <Test as Config>::Schedule::get();
2982				let min_balance = <Test as Config>::Currency::minimum_balance();
2983				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2984				let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
2985				set_balance(&ALICE, min_balance * 10_000);
2986				let contract_origin = Origin::from_account_id(ALICE);
2987				let mut storage_meter =
2988					storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
2989
2990				let result = MockStack::run_instantiate(
2991					ALICE,
2992					executable,
2993					&mut gas_meter,
2994					&mut storage_meter,
2995					&schedule,
2996					min_balance,
2997					vec![],
2998					&[],
2999					None,
3000				);
3001				assert_matches!(result, Ok(_));
3002			});
3003	}
3004
3005	#[test]
3006	fn printing_works() {
3007		let code_hash = MockLoader::insert(Call, |ctx, _| {
3008			ctx.ext.append_debug_buffer("This is a test");
3009			ctx.ext.append_debug_buffer("More text");
3010			exec_success()
3011		});
3012
3013		let mut debug_buffer = DebugBufferVec::<Test>::try_from(Vec::new()).unwrap();
3014
3015		ExtBuilder::default().build().execute_with(|| {
3016			let min_balance = <Test as Config>::Currency::minimum_balance();
3017			let schedule = <Test as Config>::Schedule::get();
3018			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3019			set_balance(&ALICE, min_balance * 10);
3020			place_contract(&BOB, code_hash);
3021			let contract_origin = Origin::from_account_id(ALICE);
3022			let mut storage_meter =
3023				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3024			MockStack::run_call(
3025				contract_origin,
3026				BOB,
3027				&mut gas_meter,
3028				&mut storage_meter,
3029				&schedule,
3030				0,
3031				vec![],
3032				Some(&mut debug_buffer),
3033				Determinism::Enforced,
3034			)
3035			.unwrap();
3036		});
3037
3038		assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text");
3039	}
3040
3041	#[test]
3042	fn printing_works_on_fail() {
3043		let code_hash = MockLoader::insert(Call, |ctx, _| {
3044			ctx.ext.append_debug_buffer("This is a test");
3045			ctx.ext.append_debug_buffer("More text");
3046			exec_trapped()
3047		});
3048
3049		let mut debug_buffer = DebugBufferVec::<Test>::try_from(Vec::new()).unwrap();
3050
3051		ExtBuilder::default().build().execute_with(|| {
3052			let min_balance = <Test as Config>::Currency::minimum_balance();
3053			let schedule = <Test as Config>::Schedule::get();
3054			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3055			set_balance(&ALICE, min_balance * 10);
3056			place_contract(&BOB, code_hash);
3057			let contract_origin = Origin::from_account_id(ALICE);
3058			let mut storage_meter =
3059				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3060			let result = MockStack::run_call(
3061				contract_origin,
3062				BOB,
3063				&mut gas_meter,
3064				&mut storage_meter,
3065				&schedule,
3066				0,
3067				vec![],
3068				Some(&mut debug_buffer),
3069				Determinism::Enforced,
3070			);
3071			assert!(result.is_err());
3072		});
3073
3074		assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text");
3075	}
3076
3077	#[test]
3078	fn debug_buffer_is_limited() {
3079		let code_hash = MockLoader::insert(Call, move |ctx, _| {
3080			ctx.ext.append_debug_buffer("overflowing bytes");
3081			exec_success()
3082		});
3083
3084		// Pre-fill the buffer almost up to its limit, leaving not enough space to the message
3085		let debug_buf_before =
3086			DebugBufferVec::<Test>::try_from(vec![0u8; DebugBufferVec::<Test>::bound() - 5])
3087				.unwrap();
3088		let mut debug_buf_after = debug_buf_before.clone();
3089
3090		ExtBuilder::default().build().execute_with(|| {
3091			let schedule: Schedule<Test> = <Test as Config>::Schedule::get();
3092			let min_balance = <Test as Config>::Currency::minimum_balance();
3093			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3094			set_balance(&ALICE, min_balance * 10);
3095			place_contract(&BOB, code_hash);
3096			let contract_origin = Origin::from_account_id(ALICE);
3097			let mut storage_meter =
3098				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3099			MockStack::run_call(
3100				contract_origin,
3101				BOB,
3102				&mut gas_meter,
3103				&mut storage_meter,
3104				&schedule,
3105				0,
3106				vec![],
3107				Some(&mut debug_buf_after),
3108				Determinism::Enforced,
3109			)
3110			.unwrap();
3111			assert_eq!(debug_buf_before, debug_buf_after);
3112		});
3113	}
3114
3115	#[test]
3116	fn call_reentry_direct_recursion() {
3117		// call the contract passed as input with disabled reentry
3118		let code_bob = MockLoader::insert(Call, |ctx, _| {
3119			let dest = Decode::decode(&mut ctx.input_data.as_ref()).unwrap();
3120			ctx.ext
3121				.call(Weight::zero(), BalanceOf::<Test>::zero(), dest, 0, vec![], false, false)
3122		});
3123
3124		let code_charlie = MockLoader::insert(Call, |_, _| exec_success());
3125
3126		ExtBuilder::default().build().execute_with(|| {
3127			let schedule = <Test as Config>::Schedule::get();
3128			place_contract(&BOB, code_bob);
3129			place_contract(&CHARLIE, code_charlie);
3130			let contract_origin = Origin::from_account_id(ALICE);
3131			let mut storage_meter =
3132				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3133
3134			// Calling another contract should succeed
3135			assert_ok!(MockStack::run_call(
3136				contract_origin.clone(),
3137				BOB,
3138				&mut GasMeter::<Test>::new(GAS_LIMIT),
3139				&mut storage_meter,
3140				&schedule,
3141				0,
3142				CHARLIE.encode(),
3143				None,
3144				Determinism::Enforced
3145			));
3146
3147			// Calling into oneself fails
3148			assert_err!(
3149				MockStack::run_call(
3150					contract_origin,
3151					BOB,
3152					&mut GasMeter::<Test>::new(GAS_LIMIT),
3153					&mut storage_meter,
3154					&schedule,
3155					0,
3156					BOB.encode(),
3157					None,
3158					Determinism::Enforced
3159				)
3160				.map_err(|e| e.error),
3161				<Error<Test>>::ReentranceDenied,
3162			);
3163		});
3164	}
3165
3166	#[test]
3167	fn call_deny_reentry() {
3168		let code_bob = MockLoader::insert(Call, |ctx, _| {
3169			if ctx.input_data[0] == 0 {
3170				ctx.ext.call(
3171					Weight::zero(),
3172					BalanceOf::<Test>::zero(),
3173					CHARLIE,
3174					0,
3175					vec![],
3176					false,
3177					false,
3178				)
3179			} else {
3180				exec_success()
3181			}
3182		});
3183
3184		// call BOB with input set to '1'
3185		let code_charlie = MockLoader::insert(Call, |ctx, _| {
3186			ctx.ext
3187				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![1], true, false)
3188		});
3189
3190		ExtBuilder::default().build().execute_with(|| {
3191			let schedule = <Test as Config>::Schedule::get();
3192			place_contract(&BOB, code_bob);
3193			place_contract(&CHARLIE, code_charlie);
3194			let contract_origin = Origin::from_account_id(ALICE);
3195			let mut storage_meter =
3196				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3197
3198			// BOB -> CHARLIE -> BOB fails as BOB denies reentry.
3199			assert_err!(
3200				MockStack::run_call(
3201					contract_origin,
3202					BOB,
3203					&mut GasMeter::<Test>::new(GAS_LIMIT),
3204					&mut storage_meter,
3205					&schedule,
3206					0,
3207					vec![0],
3208					None,
3209					Determinism::Enforced
3210				)
3211				.map_err(|e| e.error),
3212				<Error<Test>>::ReentranceDenied,
3213			);
3214		});
3215	}
3216
3217	#[test]
3218	fn call_runtime_works() {
3219		let code_hash = MockLoader::insert(Call, |ctx, _| {
3220			let call = RuntimeCall::System(frame_system::Call::remark_with_event {
3221				remark: b"Hello World".to_vec(),
3222			});
3223			ctx.ext.call_runtime(call).unwrap();
3224			exec_success()
3225		});
3226
3227		ExtBuilder::default().build().execute_with(|| {
3228			let min_balance = <Test as Config>::Currency::minimum_balance();
3229			let schedule = <Test as Config>::Schedule::get();
3230			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3231			set_balance(&ALICE, min_balance * 10);
3232			place_contract(&BOB, code_hash);
3233			let contract_origin = Origin::from_account_id(ALICE);
3234			let mut storage_meter =
3235				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3236			System::reset_events();
3237			MockStack::run_call(
3238				contract_origin,
3239				BOB,
3240				&mut gas_meter,
3241				&mut storage_meter,
3242				&schedule,
3243				0,
3244				vec![],
3245				None,
3246				Determinism::Enforced,
3247			)
3248			.unwrap();
3249
3250			let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello World");
3251			assert_eq!(
3252				System::events(),
3253				vec![
3254					EventRecord {
3255						phase: Phase::Initialization,
3256						event: MetaEvent::System(frame_system::Event::Remarked {
3257							sender: BOB,
3258							hash: remark_hash
3259						}),
3260						topics: vec![],
3261					},
3262					EventRecord {
3263						phase: Phase::Initialization,
3264						event: MetaEvent::Contracts(crate::Event::Called {
3265							caller: Origin::from_account_id(ALICE),
3266							contract: BOB,
3267						}),
3268						topics: vec![],
3269					},
3270				]
3271			);
3272		});
3273	}
3274
3275	#[test]
3276	fn call_runtime_filter() {
3277		let code_hash = MockLoader::insert(Call, |ctx, _| {
3278			use frame_system::Call as SysCall;
3279			use pallet_balances::Call as BalanceCall;
3280			use pallet_utility::Call as UtilCall;
3281
3282			// remark should still be allowed
3283			let allowed_call =
3284				RuntimeCall::System(SysCall::remark_with_event { remark: b"Hello".to_vec() });
3285
3286			// transfers are disallowed by the `TestFiler` (see below)
3287			let forbidden_call = RuntimeCall::Balances(BalanceCall::transfer_allow_death {
3288				dest: CHARLIE,
3289				value: 22,
3290			});
3291
3292			// simple cases: direct call
3293			assert_err!(
3294				ctx.ext.call_runtime(forbidden_call.clone()),
3295				frame_system::Error::<Test>::CallFiltered
3296			);
3297
3298			// as part of a patch: return is OK (but it interrupted the batch)
3299			assert_ok!(ctx.ext.call_runtime(RuntimeCall::Utility(UtilCall::batch {
3300				calls: vec![allowed_call.clone(), forbidden_call, allowed_call]
3301			})),);
3302
3303			// the transfer wasn't performed
3304			assert_eq!(get_balance(&CHARLIE), 0);
3305
3306			exec_success()
3307		});
3308
3309		TestFilter::set_filter(|call| match call {
3310			RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) => false,
3311			_ => true,
3312		});
3313
3314		ExtBuilder::default().build().execute_with(|| {
3315			let min_balance = <Test as Config>::Currency::minimum_balance();
3316			let schedule = <Test as Config>::Schedule::get();
3317			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3318			set_balance(&ALICE, min_balance * 10);
3319			place_contract(&BOB, code_hash);
3320			let contract_origin = Origin::from_account_id(ALICE);
3321			let mut storage_meter =
3322				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3323			System::reset_events();
3324			MockStack::run_call(
3325				contract_origin,
3326				BOB,
3327				&mut gas_meter,
3328				&mut storage_meter,
3329				&schedule,
3330				0,
3331				vec![],
3332				None,
3333				Determinism::Enforced,
3334			)
3335			.unwrap();
3336
3337			let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello");
3338			assert_eq!(
3339				System::events(),
3340				vec![
3341					EventRecord {
3342						phase: Phase::Initialization,
3343						event: MetaEvent::System(frame_system::Event::Remarked {
3344							sender: BOB,
3345							hash: remark_hash
3346						}),
3347						topics: vec![],
3348					},
3349					EventRecord {
3350						phase: Phase::Initialization,
3351						event: MetaEvent::Utility(pallet_utility::Event::ItemCompleted),
3352						topics: vec![],
3353					},
3354					EventRecord {
3355						phase: Phase::Initialization,
3356						event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted {
3357							index: 1,
3358							error: frame_system::Error::<Test>::CallFiltered.into()
3359						},),
3360						topics: vec![],
3361					},
3362					EventRecord {
3363						phase: Phase::Initialization,
3364						event: MetaEvent::Contracts(crate::Event::Called {
3365							caller: Origin::from_account_id(ALICE),
3366							contract: BOB,
3367						}),
3368						topics: vec![],
3369					},
3370				]
3371			);
3372		});
3373	}
3374
3375	#[test]
3376	fn nonce() {
3377		let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped());
3378		let success_code = MockLoader::insert(Constructor, |_, _| exec_success());
3379		let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| {
3380			ctx.ext
3381				.instantiate(
3382					Weight::zero(),
3383					BalanceOf::<Test>::zero(),
3384					fail_code,
3385					ctx.ext.minimum_balance() * 100,
3386					vec![],
3387					&[],
3388				)
3389				.ok();
3390			exec_success()
3391		});
3392		let succ_succ_code = MockLoader::insert(Constructor, move |ctx, _| {
3393			let (account_id, _) = ctx
3394				.ext
3395				.instantiate(
3396					Weight::zero(),
3397					BalanceOf::<Test>::zero(),
3398					success_code,
3399					ctx.ext.minimum_balance() * 100,
3400					vec![],
3401					&[],
3402				)
3403				.unwrap();
3404
3405			// a plain call should not influence the account counter
3406			ctx.ext
3407				.call(
3408					Weight::zero(),
3409					BalanceOf::<Test>::zero(),
3410					account_id,
3411					0,
3412					vec![],
3413					false,
3414					false,
3415				)
3416				.unwrap();
3417
3418			exec_success()
3419		});
3420
3421		ExtBuilder::default()
3422			.with_code_hashes(MockLoader::code_hashes())
3423			.build()
3424			.execute_with(|| {
3425				let schedule = <Test as Config>::Schedule::get();
3426				let min_balance = <Test as Config>::Currency::minimum_balance();
3427				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3428				let fail_executable =
3429					MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
3430				let success_executable =
3431					MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
3432				let succ_fail_executable =
3433					MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
3434				let succ_succ_executable =
3435					MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
3436				set_balance(&ALICE, min_balance * 10_000);
3437				let contract_origin = Origin::from_account_id(ALICE);
3438				let mut storage_meter =
3439					storage::meter::Meter::new(&contract_origin, None, min_balance * 100).unwrap();
3440
3441				MockStack::run_instantiate(
3442					ALICE,
3443					fail_executable,
3444					&mut gas_meter,
3445					&mut storage_meter,
3446					&schedule,
3447					min_balance * 100,
3448					vec![],
3449					&[],
3450					None,
3451				)
3452				.ok();
3453				assert_eq!(<Nonce<Test>>::get(), 0);
3454
3455				assert_ok!(MockStack::run_instantiate(
3456					ALICE,
3457					success_executable,
3458					&mut gas_meter,
3459					&mut storage_meter,
3460					&schedule,
3461					min_balance * 100,
3462					vec![],
3463					&[],
3464					None,
3465				));
3466				assert_eq!(<Nonce<Test>>::get(), 1);
3467
3468				assert_ok!(MockStack::run_instantiate(
3469					ALICE,
3470					succ_fail_executable,
3471					&mut gas_meter,
3472					&mut storage_meter,
3473					&schedule,
3474					min_balance * 200,
3475					vec![],
3476					&[],
3477					None,
3478				));
3479				assert_eq!(<Nonce<Test>>::get(), 2);
3480
3481				assert_ok!(MockStack::run_instantiate(
3482					ALICE,
3483					succ_succ_executable,
3484					&mut gas_meter,
3485					&mut storage_meter,
3486					&schedule,
3487					min_balance * 200,
3488					vec![],
3489					&[],
3490					None,
3491				));
3492				assert_eq!(<Nonce<Test>>::get(), 4);
3493			});
3494	}
3495
3496	#[test]
3497	fn set_storage_works() {
3498		let code_hash = MockLoader::insert(Call, |ctx, _| {
3499			// Write
3500			assert_eq!(
3501				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3502				Ok(WriteOutcome::New)
3503			);
3504			assert_eq!(
3505				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
3506				Ok(WriteOutcome::New)
3507			);
3508			assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
3509			assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
3510			assert_eq!(
3511				ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3512				Ok(WriteOutcome::New)
3513			);
3514			assert_eq!(
3515				ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3516				Ok(WriteOutcome::New)
3517			);
3518
3519			// Overwrite
3520			assert_eq!(
3521				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
3522				Ok(WriteOutcome::Overwritten(3))
3523			);
3524			assert_eq!(
3525				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
3526				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
3527			);
3528			assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
3529			assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
3530			assert_eq!(
3531				ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3532				Ok(WriteOutcome::Overwritten(0))
3533			);
3534			assert_eq!(
3535				ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3536				Ok(WriteOutcome::Taken(vec![]))
3537			);
3538
3539			exec_success()
3540		});
3541
3542		ExtBuilder::default().build().execute_with(|| {
3543			let min_balance = <Test as Config>::Currency::minimum_balance();
3544			let schedule = <Test as Config>::Schedule::get();
3545			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3546			set_balance(&ALICE, min_balance * 1000);
3547			place_contract(&BOB, code_hash);
3548			let contract_origin = Origin::from_account_id(ALICE);
3549			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3550			assert_ok!(MockStack::run_call(
3551				contract_origin,
3552				BOB,
3553				&mut gas_meter,
3554				&mut storage_meter,
3555				&schedule,
3556				0,
3557				vec![],
3558				None,
3559				Determinism::Enforced
3560			));
3561		});
3562	}
3563
3564	#[test]
3565	fn set_storage_varsized_key_works() {
3566		let code_hash = MockLoader::insert(Call, |ctx, _| {
3567			// Write
3568			assert_eq!(
3569				ctx.ext.set_storage(
3570					&Key::<Test>::try_from_var([1; 64].to_vec()).unwrap(),
3571					Some(vec![1, 2, 3]),
3572					false
3573				),
3574				Ok(WriteOutcome::New)
3575			);
3576			assert_eq!(
3577				ctx.ext.set_storage(
3578					&Key::<Test>::try_from_var([2; 19].to_vec()).unwrap(),
3579					Some(vec![4, 5, 6]),
3580					true
3581				),
3582				Ok(WriteOutcome::New)
3583			);
3584			assert_eq!(
3585				ctx.ext.set_storage(
3586					&Key::<Test>::try_from_var([3; 19].to_vec()).unwrap(),
3587					None,
3588					false
3589				),
3590				Ok(WriteOutcome::New)
3591			);
3592			assert_eq!(
3593				ctx.ext.set_storage(
3594					&Key::<Test>::try_from_var([4; 64].to_vec()).unwrap(),
3595					None,
3596					true
3597				),
3598				Ok(WriteOutcome::New)
3599			);
3600			assert_eq!(
3601				ctx.ext.set_storage(
3602					&Key::<Test>::try_from_var([5; 30].to_vec()).unwrap(),
3603					Some(vec![]),
3604					false
3605				),
3606				Ok(WriteOutcome::New)
3607			);
3608			assert_eq!(
3609				ctx.ext.set_storage(
3610					&Key::<Test>::try_from_var([6; 128].to_vec()).unwrap(),
3611					Some(vec![]),
3612					true
3613				),
3614				Ok(WriteOutcome::New)
3615			);
3616
3617			// Overwrite
3618			assert_eq!(
3619				ctx.ext.set_storage(
3620					&Key::<Test>::try_from_var([1; 64].to_vec()).unwrap(),
3621					Some(vec![42, 43, 44]),
3622					false
3623				),
3624				Ok(WriteOutcome::Overwritten(3))
3625			);
3626			assert_eq!(
3627				ctx.ext.set_storage(
3628					&Key::<Test>::try_from_var([2; 19].to_vec()).unwrap(),
3629					Some(vec![48]),
3630					true
3631				),
3632				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
3633			);
3634			assert_eq!(
3635				ctx.ext.set_storage(
3636					&Key::<Test>::try_from_var([3; 19].to_vec()).unwrap(),
3637					None,
3638					false
3639				),
3640				Ok(WriteOutcome::New)
3641			);
3642			assert_eq!(
3643				ctx.ext.set_storage(
3644					&Key::<Test>::try_from_var([4; 64].to_vec()).unwrap(),
3645					None,
3646					true
3647				),
3648				Ok(WriteOutcome::New)
3649			);
3650			assert_eq!(
3651				ctx.ext.set_storage(
3652					&Key::<Test>::try_from_var([5; 30].to_vec()).unwrap(),
3653					Some(vec![]),
3654					false
3655				),
3656				Ok(WriteOutcome::Overwritten(0))
3657			);
3658			assert_eq!(
3659				ctx.ext.set_storage(
3660					&Key::<Test>::try_from_var([6; 128].to_vec()).unwrap(),
3661					Some(vec![]),
3662					true
3663				),
3664				Ok(WriteOutcome::Taken(vec![]))
3665			);
3666
3667			exec_success()
3668		});
3669
3670		ExtBuilder::default().build().execute_with(|| {
3671			let min_balance = <Test as Config>::Currency::minimum_balance();
3672			let schedule = <Test as Config>::Schedule::get();
3673			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3674			set_balance(&ALICE, min_balance * 1000);
3675			place_contract(&BOB, code_hash);
3676			let contract_origin = Origin::from_account_id(ALICE);
3677			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3678			assert_ok!(MockStack::run_call(
3679				contract_origin,
3680				BOB,
3681				&mut gas_meter,
3682				&mut storage_meter,
3683				&schedule,
3684				0,
3685				vec![],
3686				None,
3687				Determinism::Enforced
3688			));
3689		});
3690	}
3691
3692	#[test]
3693	fn get_storage_works() {
3694		let code_hash = MockLoader::insert(Call, |ctx, _| {
3695			assert_eq!(
3696				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3697				Ok(WriteOutcome::New)
3698			);
3699			assert_eq!(
3700				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
3701				Ok(WriteOutcome::New)
3702			);
3703			assert_eq!(ctx.ext.get_storage(&Key::Fix([1; 32])), Some(vec![1, 2, 3]));
3704			assert_eq!(ctx.ext.get_storage(&Key::Fix([2; 32])), Some(vec![]));
3705			assert_eq!(ctx.ext.get_storage(&Key::Fix([3; 32])), None);
3706
3707			exec_success()
3708		});
3709
3710		ExtBuilder::default().build().execute_with(|| {
3711			let min_balance = <Test as Config>::Currency::minimum_balance();
3712			let schedule = <Test as Config>::Schedule::get();
3713			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3714			set_balance(&ALICE, min_balance * 1000);
3715			place_contract(&BOB, code_hash);
3716			let contract_origin = Origin::from_account_id(ALICE);
3717			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3718			assert_ok!(MockStack::run_call(
3719				contract_origin,
3720				BOB,
3721				&mut gas_meter,
3722				&mut storage_meter,
3723				&schedule,
3724				0,
3725				vec![],
3726				None,
3727				Determinism::Enforced
3728			));
3729		});
3730	}
3731
3732	#[test]
3733	fn get_storage_size_works() {
3734		let code_hash = MockLoader::insert(Call, |ctx, _| {
3735			assert_eq!(
3736				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3737				Ok(WriteOutcome::New)
3738			);
3739			assert_eq!(
3740				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
3741				Ok(WriteOutcome::New)
3742			);
3743			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([1; 32])), Some(3));
3744			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([2; 32])), Some(0));
3745			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([3; 32])), None);
3746
3747			exec_success()
3748		});
3749
3750		ExtBuilder::default().build().execute_with(|| {
3751			let min_balance = <Test as Config>::Currency::minimum_balance();
3752			let schedule = <Test as Config>::Schedule::get();
3753			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3754			set_balance(&ALICE, min_balance * 1000);
3755			place_contract(&BOB, code_hash);
3756			let contract_origin = Origin::from_account_id(ALICE);
3757			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3758			assert_ok!(MockStack::run_call(
3759				contract_origin,
3760				BOB,
3761				&mut gas_meter,
3762				&mut storage_meter,
3763				&schedule,
3764				0,
3765				vec![],
3766				None,
3767				Determinism::Enforced
3768			));
3769		});
3770	}
3771
3772	#[test]
3773	fn get_storage_varsized_key_works() {
3774		let code_hash = MockLoader::insert(Call, |ctx, _| {
3775			assert_eq!(
3776				ctx.ext.set_storage(
3777					&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap(),
3778					Some(vec![1, 2, 3]),
3779					false
3780				),
3781				Ok(WriteOutcome::New)
3782			);
3783			assert_eq!(
3784				ctx.ext.set_storage(
3785					&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap(),
3786					Some(vec![]),
3787					false
3788				),
3789				Ok(WriteOutcome::New)
3790			);
3791			assert_eq!(
3792				ctx.ext.get_storage(&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap()),
3793				Some(vec![1, 2, 3])
3794			);
3795			assert_eq!(
3796				ctx.ext.get_storage(&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap()),
3797				Some(vec![])
3798			);
3799			assert_eq!(
3800				ctx.ext.get_storage(&Key::<Test>::try_from_var([3; 8].to_vec()).unwrap()),
3801				None
3802			);
3803
3804			exec_success()
3805		});
3806
3807		ExtBuilder::default().build().execute_with(|| {
3808			let min_balance = <Test as Config>::Currency::minimum_balance();
3809			let schedule = <Test as Config>::Schedule::get();
3810			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3811			set_balance(&ALICE, min_balance * 1000);
3812			place_contract(&BOB, code_hash);
3813			let contract_origin = Origin::from_account_id(ALICE);
3814			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3815			assert_ok!(MockStack::run_call(
3816				contract_origin,
3817				BOB,
3818				&mut gas_meter,
3819				&mut storage_meter,
3820				&schedule,
3821				0,
3822				vec![],
3823				None,
3824				Determinism::Enforced
3825			));
3826		});
3827	}
3828
3829	#[test]
3830	fn get_storage_size_varsized_key_works() {
3831		let code_hash = MockLoader::insert(Call, |ctx, _| {
3832			assert_eq!(
3833				ctx.ext.set_storage(
3834					&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap(),
3835					Some(vec![1, 2, 3]),
3836					false
3837				),
3838				Ok(WriteOutcome::New)
3839			);
3840			assert_eq!(
3841				ctx.ext.set_storage(
3842					&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap(),
3843					Some(vec![]),
3844					false
3845				),
3846				Ok(WriteOutcome::New)
3847			);
3848			assert_eq!(
3849				ctx.ext.get_storage_size(&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap()),
3850				Some(3)
3851			);
3852			assert_eq!(
3853				ctx.ext.get_storage_size(&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap()),
3854				Some(0)
3855			);
3856			assert_eq!(
3857				ctx.ext.get_storage_size(&Key::<Test>::try_from_var([3; 8].to_vec()).unwrap()),
3858				None
3859			);
3860
3861			exec_success()
3862		});
3863
3864		ExtBuilder::default().build().execute_with(|| {
3865			let min_balance = <Test as Config>::Currency::minimum_balance();
3866			let schedule = <Test as Config>::Schedule::get();
3867			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3868			set_balance(&ALICE, min_balance * 1000);
3869			place_contract(&BOB, code_hash);
3870			let contract_origin = Origin::from_account_id(ALICE);
3871			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3872			assert_ok!(MockStack::run_call(
3873				contract_origin,
3874				BOB,
3875				&mut gas_meter,
3876				&mut storage_meter,
3877				&schedule,
3878				0,
3879				vec![],
3880				None,
3881				Determinism::Enforced
3882			));
3883		});
3884	}
3885
3886	#[test]
3887	fn set_transient_storage_works() {
3888		let code_hash = MockLoader::insert(Call, |ctx, _| {
3889			// Write
3890			assert_eq!(
3891				ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3892				Ok(WriteOutcome::New)
3893			);
3894			assert_eq!(
3895				ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
3896				Ok(WriteOutcome::New)
3897			);
3898			assert_eq!(
3899				ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
3900				Ok(WriteOutcome::New)
3901			);
3902			assert_eq!(
3903				ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
3904				Ok(WriteOutcome::New)
3905			);
3906			assert_eq!(
3907				ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3908				Ok(WriteOutcome::New)
3909			);
3910			assert_eq!(
3911				ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3912				Ok(WriteOutcome::New)
3913			);
3914
3915			// Overwrite
3916			assert_eq!(
3917				ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
3918				Ok(WriteOutcome::Overwritten(3))
3919			);
3920			assert_eq!(
3921				ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
3922				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
3923			);
3924			assert_eq!(
3925				ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
3926				Ok(WriteOutcome::New)
3927			);
3928			assert_eq!(
3929				ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
3930				Ok(WriteOutcome::New)
3931			);
3932			assert_eq!(
3933				ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3934				Ok(WriteOutcome::Overwritten(0))
3935			);
3936			assert_eq!(
3937				ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3938				Ok(WriteOutcome::Taken(vec![]))
3939			);
3940
3941			exec_success()
3942		});
3943
3944		ExtBuilder::default().build().execute_with(|| {
3945			let schedule = <Test as Config>::Schedule::get();
3946			place_contract(&BOB, code_hash);
3947			let contract_origin = Origin::from_account_id(ALICE);
3948			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3949			assert_ok!(MockStack::run_call(
3950				contract_origin,
3951				BOB,
3952				&mut GasMeter::<Test>::new(GAS_LIMIT),
3953				&mut storage_meter,
3954				&schedule,
3955				0,
3956				vec![],
3957				None,
3958				Determinism::Enforced
3959			));
3960		});
3961	}
3962
3963	#[test]
3964	fn get_transient_storage_works() {
3965		// Call stack: BOB -> CHARLIE(success) -> BOB' (success)
3966		let storage_key_1 = &Key::Fix([1; 32]);
3967		let storage_key_2 = &Key::Fix([2; 32]);
3968		let storage_key_3 = &Key::Fix([3; 32]);
3969		let code_bob = MockLoader::insert(Call, |ctx, _| {
3970			if ctx.input_data[0] == 0 {
3971				assert_eq!(
3972					ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2]), false),
3973					Ok(WriteOutcome::New)
3974				);
3975				assert_eq!(
3976					ctx.ext.call(
3977						Weight::zero(),
3978						BalanceOf::<Test>::zero(),
3979						CHARLIE,
3980						0,
3981						vec![],
3982						true,
3983						false,
3984					),
3985					exec_success()
3986				);
3987				assert_eq!(ctx.ext.get_transient_storage(storage_key_1), Some(vec![3]));
3988				assert_eq!(ctx.ext.get_transient_storage(storage_key_2), Some(vec![]));
3989				assert_eq!(ctx.ext.get_transient_storage(storage_key_3), None);
3990			} else {
3991				assert_eq!(
3992					ctx.ext.set_transient_storage(storage_key_1, Some(vec![3]), true),
3993					Ok(WriteOutcome::Taken(vec![1, 2]))
3994				);
3995				assert_eq!(
3996					ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
3997					Ok(WriteOutcome::New)
3998				);
3999			}
4000			exec_success()
4001		});
4002		let code_charlie = MockLoader::insert(Call, |ctx, _| {
4003			assert!(ctx
4004				.ext
4005				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false)
4006				.is_ok());
4007			// CHARLIE can not read BOB`s storage.
4008			assert_eq!(ctx.ext.get_transient_storage(storage_key_1), None);
4009			exec_success()
4010		});
4011
4012		// This one tests passing the input data into a contract via call.
4013		ExtBuilder::default().build().execute_with(|| {
4014			let schedule = <Test as Config>::Schedule::get();
4015			place_contract(&BOB, code_bob);
4016			place_contract(&CHARLIE, code_charlie);
4017			let contract_origin = Origin::from_account_id(ALICE);
4018			let mut storage_meter =
4019				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4020
4021			let result = MockStack::run_call(
4022				contract_origin,
4023				BOB,
4024				&mut GasMeter::<Test>::new(GAS_LIMIT),
4025				&mut storage_meter,
4026				&schedule,
4027				0,
4028				vec![0],
4029				None,
4030				Determinism::Enforced,
4031			);
4032			assert_matches!(result, Ok(_));
4033		});
4034	}
4035
4036	#[test]
4037	fn get_transient_storage_size_works() {
4038		let storage_key_1 = &Key::Fix([1; 32]);
4039		let storage_key_2 = &Key::Fix([2; 32]);
4040		let storage_key_3 = &Key::Fix([3; 32]);
4041		let code_hash = MockLoader::insert(Call, |ctx, _| {
4042			assert_eq!(
4043				ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2, 3]), false),
4044				Ok(WriteOutcome::New)
4045			);
4046			assert_eq!(
4047				ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
4048				Ok(WriteOutcome::New)
4049			);
4050			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_1), Some(3));
4051			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_2), Some(0));
4052			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_3), None);
4053
4054			exec_success()
4055		});
4056
4057		ExtBuilder::default().build().execute_with(|| {
4058			let schedule = <Test as Config>::Schedule::get();
4059			place_contract(&BOB, code_hash);
4060			let contract_origin = Origin::from_account_id(ALICE);
4061			let mut storage_meter =
4062				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4063			assert_ok!(MockStack::run_call(
4064				contract_origin,
4065				BOB,
4066				&mut GasMeter::<Test>::new(GAS_LIMIT),
4067				&mut storage_meter,
4068				&schedule,
4069				0,
4070				vec![],
4071				None,
4072				Determinism::Enforced
4073			));
4074		});
4075	}
4076
4077	#[test]
4078	fn rollback_transient_storage_works() {
4079		// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
4080		let storage_key = &Key::Fix([1; 32]);
4081		let code_bob = MockLoader::insert(Call, |ctx, _| {
4082			if ctx.input_data[0] == 0 {
4083				assert_eq!(
4084					ctx.ext.set_transient_storage(storage_key, Some(vec![1, 2]), false),
4085					Ok(WriteOutcome::New)
4086				);
4087				assert_eq!(
4088					ctx.ext.call(
4089						Weight::zero(),
4090						BalanceOf::<Test>::zero(),
4091						CHARLIE,
4092						0,
4093						vec![],
4094						true,
4095						false
4096					),
4097					exec_trapped()
4098				);
4099				assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![1, 2]));
4100			} else {
4101				let overwritten_length = ctx.ext.get_transient_storage_size(storage_key).unwrap();
4102				assert_eq!(
4103					ctx.ext.set_transient_storage(storage_key, Some(vec![3]), false),
4104					Ok(WriteOutcome::Overwritten(overwritten_length))
4105				);
4106				assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![3]));
4107			}
4108			exec_success()
4109		});
4110		let code_charlie = MockLoader::insert(Call, |ctx, _| {
4111			assert!(ctx
4112				.ext
4113				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false)
4114				.is_ok());
4115			exec_trapped()
4116		});
4117
4118		// This one tests passing the input data into a contract via call.
4119		ExtBuilder::default().build().execute_with(|| {
4120			let schedule = <Test as Config>::Schedule::get();
4121			place_contract(&BOB, code_bob);
4122			place_contract(&CHARLIE, code_charlie);
4123			let contract_origin = Origin::from_account_id(ALICE);
4124			let mut storage_meter =
4125				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4126
4127			let result = MockStack::run_call(
4128				contract_origin,
4129				BOB,
4130				&mut GasMeter::<Test>::new(GAS_LIMIT),
4131				&mut storage_meter,
4132				&schedule,
4133				0,
4134				vec![0],
4135				None,
4136				Determinism::Enforced,
4137			);
4138			assert_matches!(result, Ok(_));
4139		});
4140	}
4141
4142	#[test]
4143	fn ecdsa_to_eth_address_returns_proper_value() {
4144		let bob_ch = MockLoader::insert(Call, |ctx, _| {
4145			let pubkey_compressed = array_bytes::hex2array_unchecked(
4146				"028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91",
4147			);
4148			assert_eq!(
4149				ctx.ext.ecdsa_to_eth_address(&pubkey_compressed).unwrap(),
4150				array_bytes::hex2array_unchecked::<_, 20>(
4151					"09231da7b19A016f9e576d23B16277062F4d46A8"
4152				)
4153			);
4154			exec_success()
4155		});
4156
4157		ExtBuilder::default().build().execute_with(|| {
4158			let schedule = <Test as Config>::Schedule::get();
4159			place_contract(&BOB, bob_ch);
4160
4161			let contract_origin = Origin::from_account_id(ALICE);
4162			let mut storage_meter =
4163				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4164			let result = MockStack::run_call(
4165				contract_origin,
4166				BOB,
4167				&mut GasMeter::<Test>::new(GAS_LIMIT),
4168				&mut storage_meter,
4169				&schedule,
4170				0,
4171				vec![],
4172				None,
4173				Determinism::Enforced,
4174			);
4175			assert_matches!(result, Ok(_));
4176		});
4177	}
4178
4179	#[test]
4180	fn nonce_api_works() {
4181		let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped());
4182		let success_code = MockLoader::insert(Constructor, |_, _| exec_success());
4183		let code_hash = MockLoader::insert(Call, move |ctx, _| {
4184			// It is set to one when this contract was instantiated by `place_contract`
4185			assert_eq!(ctx.ext.nonce(), 1);
4186			// Should not change without any instantiation in-between
4187			assert_eq!(ctx.ext.nonce(), 1);
4188			// Should not change with a failed instantiation
4189			assert_err!(
4190				ctx.ext.instantiate(
4191					Weight::zero(),
4192					BalanceOf::<Test>::zero(),
4193					fail_code,
4194					0,
4195					vec![],
4196					&[],
4197				),
4198				ExecError {
4199					error: <Error<Test>>::ContractTrapped.into(),
4200					origin: ErrorOrigin::Callee
4201				}
4202			);
4203			assert_eq!(ctx.ext.nonce(), 1);
4204			// Successful instantiation increments
4205			ctx.ext
4206				.instantiate(
4207					Weight::zero(),
4208					BalanceOf::<Test>::zero(),
4209					success_code,
4210					0,
4211					vec![],
4212					&[],
4213				)
4214				.unwrap();
4215			assert_eq!(ctx.ext.nonce(), 2);
4216			exec_success()
4217		});
4218
4219		ExtBuilder::default()
4220			.with_code_hashes(MockLoader::code_hashes())
4221			.build()
4222			.execute_with(|| {
4223				let min_balance = <Test as Config>::Currency::minimum_balance();
4224				let schedule = <Test as Config>::Schedule::get();
4225				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
4226				set_balance(&ALICE, min_balance * 1000);
4227				place_contract(&BOB, code_hash);
4228				let contract_origin = Origin::from_account_id(ALICE);
4229				let mut storage_meter =
4230					storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
4231				assert_ok!(MockStack::run_call(
4232					contract_origin,
4233					BOB,
4234					&mut gas_meter,
4235					&mut storage_meter,
4236					&schedule,
4237					0,
4238					vec![],
4239					None,
4240					Determinism::Enforced
4241				));
4242			});
4243	}
4244
4245	/// This works even though random interface is deprecated, as the check to ban deprecated
4246	/// functions happens in the wasm stack which is mocked for exec tests.
4247	#[test]
4248	fn randomness_works() {
4249		let subject = b"nice subject".as_ref();
4250		let code_hash = MockLoader::insert(Call, move |ctx, _| {
4251			let rand = <Test as Config>::Randomness::random(subject);
4252			assert_eq!(rand, ctx.ext.random(subject));
4253			exec_success()
4254		});
4255
4256		ExtBuilder::default().build().execute_with(|| {
4257			let schedule = <Test as Config>::Schedule::get();
4258			place_contract(&BOB, code_hash);
4259
4260			let contract_origin = Origin::from_account_id(ALICE);
4261			let mut storage_meter =
4262				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4263			let result = MockStack::run_call(
4264				contract_origin,
4265				BOB,
4266				&mut GasMeter::<Test>::new(GAS_LIMIT),
4267				&mut storage_meter,
4268				&schedule,
4269				0,
4270				vec![],
4271				None,
4272				Determinism::Enforced,
4273			);
4274			assert_matches!(result, Ok(_));
4275		});
4276	}
4277}