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	Debug,
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					},
1070					_ => TransactionOutcome::Rollback(Ok((false, output))),
1071				}
1072			});
1073
1074		let (success, output) = match transaction_outcome {
1075			// `with_transactional` executed successfully, and we have the expected output.
1076			Ok((success, output)) => (success, output),
1077			// `with_transactional` returned an error, and we propagate that error and note no state
1078			// has changed.
1079			Err(error) => (false, Err(error.into())),
1080		};
1081
1082		if success {
1083			self.transient_storage.commit_transaction();
1084		} else {
1085			self.transient_storage.rollback_transaction();
1086		}
1087
1088		self.pop_frame(success);
1089		output
1090	}
1091
1092	/// Remove the current (top) frame from the stack.
1093	///
1094	/// This is called after running the current frame. It commits cached values to storage
1095	/// and invalidates all stale references to it that might exist further down the call stack.
1096	fn pop_frame(&mut self, persist: bool) {
1097		// Revert changes to the nonce in case of a failed instantiation.
1098		if !persist && self.top_frame().entry_point == ExportedFunction::Constructor {
1099			self.nonce.as_mut().map(|c| *c = c.wrapping_sub(1));
1100		}
1101
1102		// Pop the current frame from the stack and return it in case it needs to interact
1103		// with duplicates that might exist on the stack.
1104		// A `None` means that we are returning from the `first_frame`.
1105		let frame = self.frames.pop();
1106
1107		// Both branches do essentially the same with the exception. The difference is that
1108		// the else branch does consume the hardcoded `first_frame`.
1109		if let Some(mut frame) = frame {
1110			let account_id = &frame.account_id;
1111			let prev = top_frame_mut!(self);
1112
1113			prev.nested_gas.absorb_nested(frame.nested_gas);
1114
1115			// Only gas counter changes are persisted in case of a failure.
1116			if !persist {
1117				return;
1118			}
1119
1120			// Record the storage meter changes of the nested call into the parent meter.
1121			// If the dropped frame's contract wasn't terminated we update the deposit counter
1122			// in its contract info. The load is necessary to pull it from storage in case
1123			// it was invalidated.
1124			frame.contract_info.load(account_id);
1125			let mut contract = frame.contract_info.into_contract();
1126			prev.nested_storage.absorb(frame.nested_storage, account_id, contract.as_mut());
1127
1128			// In case the contract wasn't terminated we need to persist changes made to it.
1129			if let Some(contract) = contract {
1130				// optimization: Predecessor is the same contract.
1131				// We can just copy the contract into the predecessor without a storage write.
1132				// This is possible when there is no other contract in-between that could
1133				// trigger a rollback.
1134				if prev.account_id == *account_id {
1135					prev.contract_info = CachedContract::Cached(contract);
1136					return;
1137				}
1138
1139				// Predecessor is a different contract: We persist the info and invalidate the first
1140				// stale cache we find. This triggers a reload from storage on next use. We skip(1)
1141				// because that case is already handled by the optimization above. Only the first
1142				// cache needs to be invalidated because that one will invalidate the next cache
1143				// when it is popped from the stack.
1144				<ContractInfoOf<T>>::insert(account_id, contract);
1145				if let Some(c) = self.frames_mut().skip(1).find(|f| f.account_id == *account_id) {
1146					c.contract_info = CachedContract::Invalidated;
1147				}
1148			}
1149		} else {
1150			if let Some((msg, false)) = self.debug_message.as_ref().map(|m| (m, m.is_empty())) {
1151				log::debug!(
1152					target: LOG_TARGET,
1153					"Execution finished with debug buffer: {}",
1154					core::str::from_utf8(msg).unwrap_or("<Invalid UTF8>"),
1155				);
1156			}
1157			self.gas_meter.absorb_nested(mem::take(&mut self.first_frame.nested_gas));
1158			if !persist {
1159				return;
1160			}
1161			let mut contract = self.first_frame.contract_info.as_contract();
1162			self.storage_meter.absorb(
1163				mem::take(&mut self.first_frame.nested_storage),
1164				&self.first_frame.account_id,
1165				contract.as_deref_mut(),
1166			);
1167			if let Some(contract) = contract {
1168				<ContractInfoOf<T>>::insert(&self.first_frame.account_id, contract);
1169			}
1170			if let Some(nonce) = self.nonce {
1171				<Nonce<T>>::set(nonce);
1172			}
1173		}
1174	}
1175
1176	/// Transfer some funds from `from` to `to`.
1177	fn transfer(
1178		preservation: Preservation,
1179		from: &T::AccountId,
1180		to: &T::AccountId,
1181		value: BalanceOf<T>,
1182	) -> DispatchResult {
1183		if !value.is_zero() && from != to {
1184			T::Currency::transfer(from, to, value, preservation)
1185				.map_err(|_| Error::<T>::TransferFailed)?;
1186		}
1187		Ok(())
1188	}
1189
1190	// The transfer as performed by a call or instantiate.
1191	fn initial_transfer(&self) -> DispatchResult {
1192		let frame = self.top_frame();
1193
1194		// If it is a delegate call, then we've already transferred tokens in the
1195		// last non-delegate frame.
1196		if frame.delegate_caller.is_some() {
1197			return Ok(());
1198		}
1199
1200		let value = frame.value_transferred;
1201
1202		// Get the account id from the caller.
1203		// If the caller is root there is no account to transfer from, and therefore we can't take
1204		// any `value` other than 0.
1205		let caller = match self.caller() {
1206			Origin::Signed(caller) => caller,
1207			Origin::Root if value.is_zero() => return Ok(()),
1208			Origin::Root => return DispatchError::RootNotAllowed.into(),
1209		};
1210		Self::transfer(Preservation::Preserve, &caller, &frame.account_id, value)
1211	}
1212
1213	/// Reference to the current (top) frame.
1214	fn top_frame(&self) -> &Frame<T> {
1215		top_frame!(self)
1216	}
1217
1218	/// Mutable reference to the current (top) frame.
1219	fn top_frame_mut(&mut self) -> &mut Frame<T> {
1220		top_frame_mut!(self)
1221	}
1222
1223	/// Iterator over all frames.
1224	///
1225	/// The iterator starts with the top frame and ends with the root frame.
1226	fn frames(&self) -> impl Iterator<Item = &Frame<T>> {
1227		core::iter::once(&self.first_frame).chain(&self.frames).rev()
1228	}
1229
1230	/// Same as `frames` but with a mutable reference as iterator item.
1231	fn frames_mut(&mut self) -> impl Iterator<Item = &mut Frame<T>> {
1232		core::iter::once(&mut self.first_frame).chain(&mut self.frames).rev()
1233	}
1234
1235	/// Returns whether the current contract is on the stack multiple times.
1236	fn is_recursive(&self) -> bool {
1237		let account_id = &self.top_frame().account_id;
1238		self.frames().skip(1).any(|f| &f.account_id == account_id)
1239	}
1240
1241	/// Returns whether the specified contract allows to be reentered right now.
1242	fn allows_reentry(&self, id: &AccountIdOf<T>) -> bool {
1243		!self.frames().any(|f| &f.account_id == id && !f.allows_reentry)
1244	}
1245
1246	/// Increments and returns the next nonce. Pulls it from storage if it isn't in cache.
1247	fn next_nonce(&mut self) -> u64 {
1248		let next = self.nonce().wrapping_add(1);
1249		self.nonce = Some(next);
1250		next
1251	}
1252}
1253
1254impl<'a, T, E> Ext for Stack<'a, T, E>
1255where
1256	T: Config,
1257	E: Executable<T>,
1258{
1259	type T = T;
1260
1261	fn call(
1262		&mut self,
1263		gas_limit: Weight,
1264		deposit_limit: BalanceOf<T>,
1265		to: T::AccountId,
1266		value: BalanceOf<T>,
1267		input_data: Vec<u8>,
1268		allows_reentry: bool,
1269		read_only: bool,
1270	) -> Result<ExecReturnValue, ExecError> {
1271		// Before pushing the new frame: Protect the caller contract against reentrancy attacks.
1272		// It is important to do this before calling `allows_reentry` so that a direct recursion
1273		// is caught by it.
1274		self.top_frame_mut().allows_reentry = allows_reentry;
1275
1276		let try_call = || {
1277			if !self.allows_reentry(&to) {
1278				return Err(<Error<T>>::ReentranceDenied.into());
1279			}
1280
1281			// We ignore instantiate frames in our search for a cached contract.
1282			// Otherwise it would be possible to recursively call a contract from its own
1283			// constructor: We disallow calling not fully constructed contracts.
1284			let cached_info = self
1285				.frames()
1286				.find(|f| f.entry_point == ExportedFunction::Call && f.account_id == to)
1287				.and_then(|f| match &f.contract_info {
1288					CachedContract::Cached(contract) => Some(contract.clone()),
1289					_ => None,
1290				});
1291			let executable = self.push_frame(
1292				FrameArgs::Call { dest: to, cached_info, delegated_call: None },
1293				value,
1294				gas_limit,
1295				deposit_limit,
1296				// Enable read-only access if requested; cannot disable it if already set.
1297				read_only || self.is_read_only(),
1298			)?;
1299			self.run(executable, input_data)
1300		};
1301
1302		// We need to make sure to reset `allows_reentry` even on failure.
1303		let result = try_call();
1304
1305		// Protection is on a per call basis.
1306		self.top_frame_mut().allows_reentry = true;
1307
1308		result
1309	}
1310
1311	fn delegate_call(
1312		&mut self,
1313		code_hash: CodeHash<Self::T>,
1314		input_data: Vec<u8>,
1315	) -> Result<ExecReturnValue, ExecError> {
1316		let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
1317		let top_frame = self.top_frame_mut();
1318		let contract_info = top_frame.contract_info().clone();
1319		let account_id = top_frame.account_id.clone();
1320		let value = top_frame.value_transferred;
1321		let executable = self.push_frame(
1322			FrameArgs::Call {
1323				dest: account_id,
1324				cached_info: Some(contract_info),
1325				delegated_call: Some(DelegatedCall { executable, caller: self.caller().clone() }),
1326			},
1327			value,
1328			Weight::zero(),
1329			BalanceOf::<T>::zero(),
1330			self.is_read_only(),
1331		)?;
1332		self.run(executable, input_data)
1333	}
1334
1335	fn instantiate(
1336		&mut self,
1337		gas_limit: Weight,
1338		deposit_limit: BalanceOf<Self::T>,
1339		code_hash: CodeHash<T>,
1340		value: BalanceOf<T>,
1341		input_data: Vec<u8>,
1342		salt: &[u8],
1343	) -> Result<(AccountIdOf<T>, ExecReturnValue), ExecError> {
1344		let executable = E::from_storage(code_hash, self.gas_meter_mut())?;
1345		let nonce = self.next_nonce();
1346		let executable = self.push_frame(
1347			FrameArgs::Instantiate {
1348				sender: self.top_frame().account_id.clone(),
1349				nonce,
1350				executable,
1351				salt,
1352				input_data: input_data.as_ref(),
1353			},
1354			value,
1355			gas_limit,
1356			deposit_limit,
1357			self.is_read_only(),
1358		)?;
1359		let account_id = self.top_frame().account_id.clone();
1360		self.run(executable, input_data).map(|ret| (account_id, ret))
1361	}
1362
1363	fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> DispatchResult {
1364		if self.is_recursive() {
1365			return Err(Error::<T>::TerminatedWhileReentrant.into());
1366		}
1367		let frame = self.top_frame_mut();
1368		let info = frame.terminate();
1369		frame.nested_storage.terminate(&info, beneficiary.clone());
1370
1371		info.queue_trie_for_deletion();
1372		ContractInfoOf::<T>::remove(&frame.account_id);
1373		Self::decrement_refcount(info.code_hash);
1374
1375		for (code_hash, deposit) in info.delegate_dependencies() {
1376			Self::decrement_refcount(*code_hash);
1377			frame
1378				.nested_storage
1379				.charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(*deposit));
1380		}
1381
1382		Contracts::<T>::deposit_event(Event::Terminated {
1383			contract: frame.account_id.clone(),
1384			beneficiary: beneficiary.clone(),
1385		});
1386		Ok(())
1387	}
1388
1389	fn transfer(&mut self, to: &T::AccountId, value: BalanceOf<T>) -> DispatchResult {
1390		Self::transfer(Preservation::Preserve, &self.top_frame().account_id, to, value)
1391	}
1392
1393	fn get_storage(&mut self, key: &Key<T>) -> Option<Vec<u8>> {
1394		self.top_frame_mut().contract_info().read(key)
1395	}
1396
1397	fn get_storage_size(&mut self, key: &Key<T>) -> Option<u32> {
1398		self.top_frame_mut().contract_info().size(key.into())
1399	}
1400
1401	fn set_storage(
1402		&mut self,
1403		key: &Key<T>,
1404		value: Option<Vec<u8>>,
1405		take_old: bool,
1406	) -> Result<WriteOutcome, DispatchError> {
1407		let frame = self.top_frame_mut();
1408		frame.contract_info.get(&frame.account_id).write(
1409			key.into(),
1410			value,
1411			Some(&mut frame.nested_storage),
1412			take_old,
1413		)
1414	}
1415
1416	fn get_transient_storage(&self, key: &Key<T>) -> Option<Vec<u8>> {
1417		self.transient_storage.read(self.address(), key)
1418	}
1419
1420	fn get_transient_storage_size(&self, key: &Key<T>) -> Option<u32> {
1421		self.transient_storage.read(self.address(), key).map(|value| value.len() as _)
1422	}
1423
1424	fn set_transient_storage(
1425		&mut self,
1426		key: &Key<T>,
1427		value: Option<Vec<u8>>,
1428		take_old: bool,
1429	) -> Result<WriteOutcome, DispatchError> {
1430		let account_id = self.address().clone();
1431		self.transient_storage.write(&account_id, key, value, take_old)
1432	}
1433
1434	fn address(&self) -> &T::AccountId {
1435		&self.top_frame().account_id
1436	}
1437
1438	fn caller(&self) -> Origin<T> {
1439		if let Some(caller) = &self.top_frame().delegate_caller {
1440			caller.clone()
1441		} else {
1442			self.frames()
1443				.nth(1)
1444				.map(|f| Origin::from_account_id(f.account_id.clone()))
1445				.unwrap_or(self.origin.clone())
1446		}
1447	}
1448
1449	fn is_contract(&self, address: &T::AccountId) -> bool {
1450		ContractInfoOf::<T>::contains_key(&address)
1451	}
1452
1453	fn code_hash(&self, address: &T::AccountId) -> Option<CodeHash<Self::T>> {
1454		<ContractInfoOf<T>>::get(&address).map(|contract| contract.code_hash)
1455	}
1456
1457	fn own_code_hash(&mut self) -> &CodeHash<Self::T> {
1458		&self.top_frame_mut().contract_info().code_hash
1459	}
1460
1461	fn caller_is_origin(&self) -> bool {
1462		self.origin == self.caller()
1463	}
1464
1465	fn caller_is_root(&self) -> bool {
1466		// if the caller isn't origin, then it can't be root.
1467		self.caller_is_origin() && self.origin == Origin::Root
1468	}
1469
1470	fn balance(&self) -> BalanceOf<T> {
1471		T::Currency::reducible_balance(
1472			&self.top_frame().account_id,
1473			Preservation::Preserve,
1474			Fortitude::Polite,
1475		)
1476	}
1477
1478	fn value_transferred(&self) -> BalanceOf<T> {
1479		self.top_frame().value_transferred
1480	}
1481
1482	fn random(&self, subject: &[u8]) -> (SeedOf<T>, BlockNumberFor<T>) {
1483		T::Randomness::random(subject)
1484	}
1485
1486	fn now(&self) -> &MomentOf<T> {
1487		&self.timestamp
1488	}
1489
1490	fn minimum_balance(&self) -> BalanceOf<T> {
1491		T::Currency::minimum_balance()
1492	}
1493
1494	fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) {
1495		Contracts::<Self::T>::deposit_indexed_event(
1496			topics,
1497			Event::ContractEmitted { contract: self.top_frame().account_id.clone(), data },
1498		);
1499	}
1500
1501	fn block_number(&self) -> BlockNumberFor<T> {
1502		self.block_number
1503	}
1504
1505	fn max_value_size(&self) -> u32 {
1506		self.schedule.limits.payload_len
1507	}
1508
1509	fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T> {
1510		T::WeightPrice::convert(weight)
1511	}
1512
1513	fn schedule(&self) -> &Schedule<Self::T> {
1514		self.schedule
1515	}
1516
1517	fn gas_meter(&self) -> &GasMeter<Self::T> {
1518		&self.top_frame().nested_gas
1519	}
1520
1521	fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T> {
1522		&mut self.top_frame_mut().nested_gas
1523	}
1524
1525	fn charge_storage(&mut self, diff: &Diff) {
1526		self.top_frame_mut().nested_storage.charge(diff)
1527	}
1528
1529	fn debug_buffer_enabled(&self) -> bool {
1530		self.debug_message.is_some()
1531	}
1532
1533	fn append_debug_buffer(&mut self, msg: &str) -> bool {
1534		if let Some(buffer) = &mut self.debug_message {
1535			buffer
1536				.try_extend(&mut msg.bytes())
1537				.map_err(|_| {
1538					log::debug!(
1539						target: LOG_TARGET,
1540						"Debug buffer (of {} bytes) exhausted!",
1541						DebugBufferVec::<T>::bound(),
1542					)
1543				})
1544				.ok();
1545			true
1546		} else {
1547			false
1548		}
1549	}
1550
1551	fn call_runtime(&self, call: <Self::T as Config>::RuntimeCall) -> DispatchResultWithPostInfo {
1552		let mut origin: T::RuntimeOrigin = RawOrigin::Signed(self.address().clone()).into();
1553		origin.add_filter(T::CallFilter::contains);
1554		call.dispatch(origin)
1555	}
1556
1557	fn ecdsa_recover(&self, signature: &[u8; 65], message_hash: &[u8; 32]) -> Result<[u8; 33], ()> {
1558		secp256k1_ecdsa_recover_compressed(signature, message_hash).map_err(|_| ())
1559	}
1560
1561	fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
1562		sp_io::crypto::sr25519_verify(
1563			&SR25519Signature::from(*signature),
1564			message,
1565			&SR25519Public::from(*pub_key),
1566		)
1567	}
1568
1569	fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> {
1570		ECDSAPublic::from(*pk).to_eth_address()
1571	}
1572
1573	#[cfg(any(test, feature = "runtime-benchmarks"))]
1574	fn contract_info(&mut self) -> &mut ContractInfo<Self::T> {
1575		self.top_frame_mut().contract_info()
1576	}
1577
1578	#[cfg(feature = "runtime-benchmarks")]
1579	fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
1580		&mut self.transient_storage
1581	}
1582
1583	fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> DispatchResult {
1584		let frame = top_frame_mut!(self);
1585		if !E::from_storage(hash, &mut frame.nested_gas)?.is_deterministic() {
1586			return Err(<Error<T>>::Indeterministic.into());
1587		}
1588
1589		let info = frame.contract_info();
1590
1591		let prev_hash = info.code_hash;
1592		info.code_hash = hash;
1593
1594		let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?;
1595
1596		let old_base_deposit = info.storage_base_deposit();
1597		let new_base_deposit = info.update_base_deposit(&code_info);
1598		let deposit = StorageDeposit::Charge(new_base_deposit)
1599			.saturating_sub(&StorageDeposit::Charge(old_base_deposit));
1600
1601		frame.nested_storage.charge_deposit(frame.account_id.clone(), deposit);
1602
1603		Self::increment_refcount(hash)?;
1604		Self::decrement_refcount(prev_hash);
1605		Contracts::<Self::T>::deposit_event(Event::ContractCodeUpdated {
1606			contract: frame.account_id.clone(),
1607			new_code_hash: hash,
1608			old_code_hash: prev_hash,
1609		});
1610		Ok(())
1611	}
1612
1613	fn reentrance_count(&self) -> u32 {
1614		let id: &AccountIdOf<Self::T> = &self.top_frame().account_id;
1615		self.account_reentrance_count(id).saturating_sub(1)
1616	}
1617
1618	fn account_reentrance_count(&self, account_id: &AccountIdOf<Self::T>) -> u32 {
1619		self.frames()
1620			.filter(|f| f.delegate_caller.is_none() && &f.account_id == account_id)
1621			.count() as u32
1622	}
1623
1624	fn nonce(&mut self) -> u64 {
1625		if let Some(current) = self.nonce {
1626			current
1627		} else {
1628			let current = <Nonce<T>>::get();
1629			self.nonce = Some(current);
1630			current
1631		}
1632	}
1633
1634	fn increment_refcount(code_hash: CodeHash<Self::T>) -> DispatchResult {
1635		<CodeInfoOf<Self::T>>::mutate(code_hash, |existing| -> Result<(), DispatchError> {
1636			if let Some(info) = existing {
1637				*info.refcount_mut() = info.refcount().saturating_add(1);
1638				Ok(())
1639			} else {
1640				Err(Error::<T>::CodeNotFound.into())
1641			}
1642		})
1643	}
1644
1645	fn decrement_refcount(code_hash: CodeHash<T>) {
1646		<CodeInfoOf<T>>::mutate(code_hash, |existing| {
1647			if let Some(info) = existing {
1648				*info.refcount_mut() = info.refcount().saturating_sub(1);
1649			}
1650		});
1651	}
1652
1653	fn lock_delegate_dependency(&mut self, code_hash: CodeHash<Self::T>) -> DispatchResult {
1654		let frame = self.top_frame_mut();
1655		let info = frame.contract_info.get(&frame.account_id);
1656		ensure!(code_hash != info.code_hash, Error::<T>::CannotAddSelfAsDelegateDependency);
1657
1658		let code_info = CodeInfoOf::<T>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
1659		let deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_info.deposit());
1660
1661		info.lock_delegate_dependency(code_hash, deposit)?;
1662		Self::increment_refcount(code_hash)?;
1663		frame
1664			.nested_storage
1665			.charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit));
1666		Ok(())
1667	}
1668
1669	fn unlock_delegate_dependency(&mut self, code_hash: &CodeHash<Self::T>) -> DispatchResult {
1670		let frame = self.top_frame_mut();
1671		let info = frame.contract_info.get(&frame.account_id);
1672
1673		let deposit = info.unlock_delegate_dependency(code_hash)?;
1674		Self::decrement_refcount(*code_hash);
1675		frame
1676			.nested_storage
1677			.charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(deposit));
1678		Ok(())
1679	}
1680
1681	fn locked_delegate_dependencies_count(&mut self) -> usize {
1682		self.top_frame_mut().contract_info().delegate_dependencies_count()
1683	}
1684
1685	fn is_read_only(&self) -> bool {
1686		self.top_frame().read_only
1687	}
1688}
1689
1690mod sealing {
1691	use super::*;
1692
1693	pub trait Sealed {}
1694
1695	impl<'a, T: Config, E> Sealed for Stack<'a, T, E> {}
1696
1697	#[cfg(test)]
1698	impl Sealed for crate::wasm::MockExt {}
1699
1700	#[cfg(test)]
1701	impl Sealed for &mut crate::wasm::MockExt {}
1702}
1703
1704/// These tests exercise the executive layer.
1705///
1706/// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use simple
1707/// closures. This allows you to tackle executive logic more thoroughly without writing a
1708/// wasm VM code.
1709#[cfg(test)]
1710mod tests {
1711	use super::*;
1712	use crate::{
1713		exec::ExportedFunction::*,
1714		gas::GasMeter,
1715		tests::{
1716			test_utils::{get_balance, place_contract, set_balance},
1717			ExtBuilder, RuntimeCall, RuntimeEvent as MetaEvent, Test, TestFilter, ALICE, BOB,
1718			CHARLIE, GAS_LIMIT,
1719		},
1720		Error,
1721	};
1722	use assert_matches::assert_matches;
1723	use codec::{Decode, Encode};
1724	use frame_support::{assert_err, assert_ok, parameter_types};
1725	use frame_system::{EventRecord, Phase};
1726	use pallet_contracts_uapi::ReturnFlags;
1727	use pretty_assertions::assert_eq;
1728	use sp_runtime::{traits::Hash, DispatchError};
1729	use std::{cell::RefCell, collections::hash_map::HashMap, rc::Rc};
1730
1731	type System = frame_system::Pallet<Test>;
1732
1733	type MockStack<'a> = Stack<'a, Test, MockExecutable>;
1734
1735	parameter_types! {
1736		static Loader: MockLoader = MockLoader::default();
1737	}
1738
1739	fn events() -> Vec<Event<Test>> {
1740		System::events()
1741			.into_iter()
1742			.filter_map(|meta| match meta.event {
1743				MetaEvent::Contracts(contract_event) => Some(contract_event),
1744				_ => None,
1745			})
1746			.collect()
1747	}
1748
1749	struct MockCtx<'a> {
1750		ext: &'a mut MockStack<'a>,
1751		input_data: Vec<u8>,
1752	}
1753
1754	#[derive(Clone)]
1755	struct MockExecutable {
1756		func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
1757		func_type: ExportedFunction,
1758		code_hash: CodeHash<Test>,
1759		code_info: CodeInfo<Test>,
1760	}
1761
1762	#[derive(Default, Clone)]
1763	pub struct MockLoader {
1764		map: HashMap<CodeHash<Test>, MockExecutable>,
1765		counter: u64,
1766	}
1767
1768	impl MockLoader {
1769		fn code_hashes() -> Vec<CodeHash<Test>> {
1770			Loader::get().map.keys().copied().collect()
1771		}
1772
1773		fn insert(
1774			func_type: ExportedFunction,
1775			f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
1776		) -> CodeHash<Test> {
1777			Loader::mutate(|loader| {
1778				// Generate code hashes as monotonically increasing values.
1779				let hash = <Test as frame_system::Config>::Hash::from_low_u64_be(loader.counter);
1780				loader.counter += 1;
1781				loader.map.insert(
1782					hash,
1783					MockExecutable {
1784						func: Rc::new(f),
1785						func_type,
1786						code_hash: hash,
1787						code_info: CodeInfo::<Test>::new(ALICE),
1788					},
1789				);
1790				hash
1791			})
1792		}
1793	}
1794
1795	impl Executable<Test> for MockExecutable {
1796		fn from_storage(
1797			code_hash: CodeHash<Test>,
1798			_gas_meter: &mut GasMeter<Test>,
1799		) -> Result<Self, DispatchError> {
1800			Loader::mutate(|loader| {
1801				loader.map.get(&code_hash).cloned().ok_or(Error::<Test>::CodeNotFound.into())
1802			})
1803		}
1804
1805		fn execute<E: Ext<T = Test>>(
1806			self,
1807			ext: &mut E,
1808			function: &ExportedFunction,
1809			input_data: Vec<u8>,
1810		) -> ExecResult {
1811			if let &Constructor = function {
1812				E::increment_refcount(self.code_hash).unwrap();
1813			}
1814			// # Safety
1815			//
1816			// We know that we **always** call execute with a `MockStack` in this test.
1817			//
1818			// # Note
1819			//
1820			// The transmute is necessary because `execute` has to be generic over all
1821			// `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would
1822			// constitute a cycle.
1823			let ext = unsafe { mem::transmute(ext) };
1824			if function == &self.func_type {
1825				(self.func)(MockCtx { ext, input_data }, &self)
1826			} else {
1827				exec_success()
1828			}
1829		}
1830
1831		fn code_hash(&self) -> &CodeHash<Test> {
1832			&self.code_hash
1833		}
1834
1835		fn code_info(&self) -> &CodeInfo<Test> {
1836			&self.code_info
1837		}
1838
1839		fn is_deterministic(&self) -> bool {
1840			true
1841		}
1842	}
1843
1844	fn exec_success() -> ExecResult {
1845		Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1846	}
1847
1848	fn exec_trapped() -> ExecResult {
1849		Err(ExecError { error: <Error<Test>>::ContractTrapped.into(), origin: ErrorOrigin::Callee })
1850	}
1851
1852	#[test]
1853	fn it_works() {
1854		parameter_types! {
1855			static TestData: Vec<usize> = vec![0];
1856		}
1857
1858		let value = Default::default();
1859		let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
1860		let exec_ch = MockLoader::insert(Call, |_ctx, _executable| {
1861			TestData::mutate(|data| data.push(1));
1862			exec_success()
1863		});
1864
1865		ExtBuilder::default().build().execute_with(|| {
1866			let schedule = <Test as Config>::Schedule::get();
1867			place_contract(&BOB, exec_ch);
1868			let mut storage_meter =
1869				storage::meter::Meter::new(&Origin::from_account_id(ALICE), Some(0), value)
1870					.unwrap();
1871
1872			assert_matches!(
1873				MockStack::run_call(
1874					Origin::from_account_id(ALICE),
1875					BOB,
1876					&mut gas_meter,
1877					&mut storage_meter,
1878					&schedule,
1879					value,
1880					vec![],
1881					None,
1882					Determinism::Enforced,
1883				),
1884				Ok(_)
1885			);
1886		});
1887
1888		assert_eq!(TestData::get(), vec![0, 1]);
1889	}
1890
1891	#[test]
1892	fn transfer_works() {
1893		// This test verifies that a contract is able to transfer
1894		// some funds to another account.
1895		let origin = ALICE;
1896		let dest = BOB;
1897
1898		ExtBuilder::default().build().execute_with(|| {
1899			set_balance(&origin, 100);
1900			set_balance(&dest, 0);
1901
1902			MockStack::transfer(Preservation::Preserve, &origin, &dest, 55).unwrap();
1903
1904			assert_eq!(get_balance(&origin), 45);
1905			assert_eq!(get_balance(&dest), 55);
1906		});
1907	}
1908
1909	#[test]
1910	fn correct_transfer_on_call() {
1911		let origin = ALICE;
1912		let dest = BOB;
1913		let value = 55;
1914
1915		let success_ch = MockLoader::insert(Call, move |ctx, _| {
1916			assert_eq!(ctx.ext.value_transferred(), value);
1917			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1918		});
1919
1920		ExtBuilder::default().build().execute_with(|| {
1921			let schedule = <Test as Config>::Schedule::get();
1922			place_contract(&dest, success_ch);
1923			set_balance(&origin, 100);
1924			let balance = get_balance(&dest);
1925			let contract_origin = Origin::from_account_id(origin.clone());
1926			let mut storage_meter =
1927				storage::meter::Meter::new(&contract_origin, Some(0), value).unwrap();
1928
1929			let _ = MockStack::run_call(
1930				contract_origin.clone(),
1931				dest.clone(),
1932				&mut GasMeter::<Test>::new(GAS_LIMIT),
1933				&mut storage_meter,
1934				&schedule,
1935				value,
1936				vec![],
1937				None,
1938				Determinism::Enforced,
1939			)
1940			.unwrap();
1941
1942			assert_eq!(get_balance(&origin), 100 - value);
1943			assert_eq!(get_balance(&dest), balance + value);
1944		});
1945	}
1946
1947	#[test]
1948	fn correct_transfer_on_delegate_call() {
1949		let origin = ALICE;
1950		let dest = BOB;
1951		let value = 35;
1952
1953		let success_ch = MockLoader::insert(Call, move |ctx, _| {
1954			assert_eq!(ctx.ext.value_transferred(), value);
1955			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1956		});
1957
1958		let delegate_ch = MockLoader::insert(Call, move |ctx, _| {
1959			assert_eq!(ctx.ext.value_transferred(), value);
1960			ctx.ext.delegate_call(success_ch, Vec::new())?;
1961			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
1962		});
1963
1964		ExtBuilder::default().build().execute_with(|| {
1965			let schedule = <Test as Config>::Schedule::get();
1966			place_contract(&dest, delegate_ch);
1967			set_balance(&origin, 100);
1968			let balance = get_balance(&dest);
1969			let contract_origin = Origin::from_account_id(origin.clone());
1970			let mut storage_meter =
1971				storage::meter::Meter::new(&contract_origin, Some(0), 55).unwrap();
1972
1973			let _ = MockStack::run_call(
1974				contract_origin.clone(),
1975				dest.clone(),
1976				&mut GasMeter::<Test>::new(GAS_LIMIT),
1977				&mut storage_meter,
1978				&schedule,
1979				value,
1980				vec![],
1981				None,
1982				Determinism::Enforced,
1983			)
1984			.unwrap();
1985
1986			assert_eq!(get_balance(&origin), 100 - value);
1987			assert_eq!(get_balance(&dest), balance + value);
1988		});
1989	}
1990
1991	#[test]
1992	fn changes_are_reverted_on_failing_call() {
1993		// This test verifies that changes are reverted on a call which fails (or equally, returns
1994		// a non-zero status code).
1995		let origin = ALICE;
1996		let dest = BOB;
1997
1998		let return_ch = MockLoader::insert(Call, |_, _| {
1999			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() })
2000		});
2001
2002		ExtBuilder::default().build().execute_with(|| {
2003			let schedule = <Test as Config>::Schedule::get();
2004			place_contract(&dest, return_ch);
2005			set_balance(&origin, 100);
2006			let balance = get_balance(&dest);
2007			let contract_origin = Origin::from_account_id(origin.clone());
2008			let mut storage_meter =
2009				storage::meter::Meter::new(&contract_origin, Some(0), 55).unwrap();
2010
2011			let output = MockStack::run_call(
2012				contract_origin.clone(),
2013				dest.clone(),
2014				&mut GasMeter::<Test>::new(GAS_LIMIT),
2015				&mut storage_meter,
2016				&schedule,
2017				55,
2018				vec![],
2019				None,
2020				Determinism::Enforced,
2021			)
2022			.unwrap();
2023
2024			assert!(output.did_revert());
2025			assert_eq!(get_balance(&origin), 100);
2026			assert_eq!(get_balance(&dest), balance);
2027		});
2028	}
2029
2030	#[test]
2031	fn balance_too_low() {
2032		// This test verifies that a contract can't send value if it's
2033		// balance is too low.
2034		let origin = ALICE;
2035		let dest = BOB;
2036
2037		ExtBuilder::default().build().execute_with(|| {
2038			set_balance(&origin, 0);
2039
2040			let result = MockStack::transfer(Preservation::Preserve, &origin, &dest, 100);
2041
2042			assert_eq!(result, Err(Error::<Test>::TransferFailed.into()));
2043			assert_eq!(get_balance(&origin), 0);
2044			assert_eq!(get_balance(&dest), 0);
2045		});
2046	}
2047
2048	#[test]
2049	fn output_is_returned_on_success() {
2050		// Verifies that if a contract returns data with a successful exit status, this data
2051		// is returned from the execution context.
2052		let origin = ALICE;
2053		let dest = BOB;
2054		let return_ch = MockLoader::insert(Call, |_, _| {
2055			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] })
2056		});
2057
2058		ExtBuilder::default().build().execute_with(|| {
2059			let schedule = <Test as Config>::Schedule::get();
2060			let contract_origin = Origin::from_account_id(origin);
2061			let mut storage_meter =
2062				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2063			place_contract(&BOB, return_ch);
2064
2065			let result = MockStack::run_call(
2066				contract_origin,
2067				dest,
2068				&mut GasMeter::<Test>::new(GAS_LIMIT),
2069				&mut storage_meter,
2070				&schedule,
2071				0,
2072				vec![],
2073				None,
2074				Determinism::Enforced,
2075			);
2076
2077			let output = result.unwrap();
2078			assert!(!output.did_revert());
2079			assert_eq!(output.data, vec![1, 2, 3, 4]);
2080		});
2081	}
2082
2083	#[test]
2084	fn output_is_returned_on_failure() {
2085		// Verifies that if a contract returns data with a failing exit status, this data
2086		// is returned from the execution context.
2087		let origin = ALICE;
2088		let dest = BOB;
2089		let return_ch = MockLoader::insert(Call, |_, _| {
2090			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] })
2091		});
2092
2093		ExtBuilder::default().build().execute_with(|| {
2094			let schedule = <Test as Config>::Schedule::get();
2095			place_contract(&BOB, return_ch);
2096			let contract_origin = Origin::from_account_id(origin);
2097			let mut storage_meter =
2098				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2099
2100			let result = MockStack::run_call(
2101				contract_origin,
2102				dest,
2103				&mut GasMeter::<Test>::new(GAS_LIMIT),
2104				&mut storage_meter,
2105				&schedule,
2106				0,
2107				vec![],
2108				None,
2109				Determinism::Enforced,
2110			);
2111
2112			let output = result.unwrap();
2113			assert!(output.did_revert());
2114			assert_eq!(output.data, vec![1, 2, 3, 4]);
2115		});
2116	}
2117
2118	#[test]
2119	fn input_data_to_call() {
2120		let input_data_ch = MockLoader::insert(Call, |ctx, _| {
2121			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
2122			exec_success()
2123		});
2124
2125		// This one tests passing the input data into a contract via call.
2126		ExtBuilder::default().build().execute_with(|| {
2127			let schedule = <Test as Config>::Schedule::get();
2128			place_contract(&BOB, input_data_ch);
2129			let contract_origin = Origin::from_account_id(ALICE);
2130			let mut storage_meter =
2131				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2132
2133			let result = MockStack::run_call(
2134				contract_origin,
2135				BOB,
2136				&mut GasMeter::<Test>::new(GAS_LIMIT),
2137				&mut storage_meter,
2138				&schedule,
2139				0,
2140				vec![1, 2, 3, 4],
2141				None,
2142				Determinism::Enforced,
2143			);
2144			assert_matches!(result, Ok(_));
2145		});
2146	}
2147
2148	#[test]
2149	fn input_data_to_instantiate() {
2150		let input_data_ch = MockLoader::insert(Constructor, |ctx, _| {
2151			assert_eq!(ctx.input_data, &[1, 2, 3, 4]);
2152			exec_success()
2153		});
2154
2155		// This one tests passing the input data into a contract via instantiate.
2156		ExtBuilder::default()
2157			.with_code_hashes(MockLoader::code_hashes())
2158			.build()
2159			.execute_with(|| {
2160				let schedule = <Test as Config>::Schedule::get();
2161				let min_balance = <Test as Config>::Currency::minimum_balance();
2162				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2163				let executable =
2164					MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
2165				set_balance(&ALICE, min_balance * 10_000);
2166				let contract_origin = Origin::from_account_id(ALICE);
2167				let mut storage_meter =
2168					storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
2169
2170				let result = MockStack::run_instantiate(
2171					ALICE,
2172					executable,
2173					&mut gas_meter,
2174					&mut storage_meter,
2175					&schedule,
2176					min_balance,
2177					vec![1, 2, 3, 4],
2178					&[],
2179					None,
2180				);
2181				assert_matches!(result, Ok(_));
2182			});
2183	}
2184
2185	#[test]
2186	fn max_depth() {
2187		// This test verifies that when we reach the maximal depth creation of an
2188		// yet another context fails.
2189		parameter_types! {
2190			static ReachedBottom: bool = false;
2191		}
2192		let value = Default::default();
2193		let recurse_ch = MockLoader::insert(Call, |ctx, _| {
2194			// Try to call into yourself.
2195			let r = ctx.ext.call(
2196				Weight::zero(),
2197				BalanceOf::<Test>::zero(),
2198				BOB,
2199				0,
2200				vec![],
2201				true,
2202				false,
2203			);
2204
2205			ReachedBottom::mutate(|reached_bottom| {
2206				if !*reached_bottom {
2207					// We are first time here, it means we just reached bottom.
2208					// Verify that we've got proper error and set `reached_bottom`.
2209					assert_eq!(r, Err(Error::<Test>::MaxCallDepthReached.into()));
2210					*reached_bottom = true;
2211				} else {
2212					// We just unwinding stack here.
2213					assert_matches!(r, Ok(_));
2214				}
2215			});
2216
2217			exec_success()
2218		});
2219
2220		ExtBuilder::default().build().execute_with(|| {
2221			let schedule = <Test as Config>::Schedule::get();
2222			set_balance(&BOB, 1);
2223			place_contract(&BOB, recurse_ch);
2224			let contract_origin = Origin::from_account_id(ALICE);
2225			let mut storage_meter =
2226				storage::meter::Meter::new(&contract_origin, Some(0), value).unwrap();
2227
2228			let result = MockStack::run_call(
2229				contract_origin,
2230				BOB,
2231				&mut GasMeter::<Test>::new(GAS_LIMIT),
2232				&mut storage_meter,
2233				&schedule,
2234				value,
2235				vec![],
2236				None,
2237				Determinism::Enforced,
2238			);
2239
2240			assert_matches!(result, Ok(_));
2241		});
2242	}
2243
2244	#[test]
2245	fn caller_returns_proper_values() {
2246		let origin = ALICE;
2247		let dest = BOB;
2248
2249		parameter_types! {
2250			static WitnessedCallerBob: Option<AccountIdOf<Test>> = None;
2251			static WitnessedCallerCharlie: Option<AccountIdOf<Test>> = None;
2252		}
2253
2254		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2255			// Record the caller for bob.
2256			WitnessedCallerBob::mutate(|caller| {
2257				*caller = Some(ctx.ext.caller().account_id().unwrap().clone())
2258			});
2259
2260			// Call into CHARLIE contract.
2261			assert_matches!(
2262				ctx.ext.call(
2263					Weight::zero(),
2264					BalanceOf::<Test>::zero(),
2265					CHARLIE,
2266					0,
2267					vec![],
2268					true,
2269					false
2270				),
2271				Ok(_)
2272			);
2273			exec_success()
2274		});
2275		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
2276			// Record the caller for charlie.
2277			WitnessedCallerCharlie::mutate(|caller| {
2278				*caller = Some(ctx.ext.caller().account_id().unwrap().clone())
2279			});
2280			exec_success()
2281		});
2282
2283		ExtBuilder::default().build().execute_with(|| {
2284			let schedule = <Test as Config>::Schedule::get();
2285			place_contract(&dest, bob_ch);
2286			place_contract(&CHARLIE, charlie_ch);
2287			let contract_origin = Origin::from_account_id(origin.clone());
2288			let mut storage_meter =
2289				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2290
2291			let result = MockStack::run_call(
2292				contract_origin.clone(),
2293				dest.clone(),
2294				&mut GasMeter::<Test>::new(GAS_LIMIT),
2295				&mut storage_meter,
2296				&schedule,
2297				0,
2298				vec![],
2299				None,
2300				Determinism::Enforced,
2301			);
2302
2303			assert_matches!(result, Ok(_));
2304		});
2305
2306		assert_eq!(WitnessedCallerBob::get(), Some(origin));
2307		assert_eq!(WitnessedCallerCharlie::get(), Some(dest));
2308	}
2309
2310	#[test]
2311	fn is_contract_returns_proper_values() {
2312		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2313			// Verify that BOB is a contract
2314			assert!(ctx.ext.is_contract(&BOB));
2315			// Verify that ALICE is not a contract
2316			assert!(!ctx.ext.is_contract(&ALICE));
2317			exec_success()
2318		});
2319
2320		ExtBuilder::default().build().execute_with(|| {
2321			let schedule = <Test as Config>::Schedule::get();
2322			place_contract(&BOB, bob_ch);
2323
2324			let contract_origin = Origin::from_account_id(ALICE);
2325			let mut storage_meter =
2326				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2327			let result = MockStack::run_call(
2328				contract_origin,
2329				BOB,
2330				&mut GasMeter::<Test>::new(GAS_LIMIT),
2331				&mut storage_meter,
2332				&schedule,
2333				0,
2334				vec![],
2335				None,
2336				Determinism::Enforced,
2337			);
2338			assert_matches!(result, Ok(_));
2339		});
2340	}
2341
2342	#[test]
2343	fn code_hash_returns_proper_values() {
2344		let code_bob = MockLoader::insert(Call, |ctx, _| {
2345			// ALICE is not a contract and hence they do not have a code_hash
2346			assert!(ctx.ext.code_hash(&ALICE).is_none());
2347			// BOB is a contract and hence it has a code_hash
2348			assert!(ctx.ext.code_hash(&BOB).is_some());
2349			exec_success()
2350		});
2351
2352		ExtBuilder::default().build().execute_with(|| {
2353			let schedule = <Test as Config>::Schedule::get();
2354			place_contract(&BOB, code_bob);
2355			let contract_origin = Origin::from_account_id(ALICE);
2356			let mut storage_meter =
2357				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2358			// ALICE (not contract) -> BOB (contract)
2359			let result = MockStack::run_call(
2360				contract_origin,
2361				BOB,
2362				&mut GasMeter::<Test>::new(GAS_LIMIT),
2363				&mut storage_meter,
2364				&schedule,
2365				0,
2366				vec![0],
2367				None,
2368				Determinism::Enforced,
2369			);
2370			assert_matches!(result, Ok(_));
2371		});
2372	}
2373
2374	#[test]
2375	fn own_code_hash_returns_proper_values() {
2376		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2377			let code_hash = ctx.ext.code_hash(&BOB).unwrap();
2378			assert_eq!(*ctx.ext.own_code_hash(), code_hash);
2379			exec_success()
2380		});
2381
2382		ExtBuilder::default().build().execute_with(|| {
2383			let schedule = <Test as Config>::Schedule::get();
2384			place_contract(&BOB, bob_ch);
2385			let contract_origin = Origin::from_account_id(ALICE);
2386			let mut storage_meter =
2387				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2388			// ALICE (not contract) -> BOB (contract)
2389			let result = MockStack::run_call(
2390				contract_origin,
2391				BOB,
2392				&mut GasMeter::<Test>::new(GAS_LIMIT),
2393				&mut storage_meter,
2394				&schedule,
2395				0,
2396				vec![0],
2397				None,
2398				Determinism::Enforced,
2399			);
2400			assert_matches!(result, Ok(_));
2401		});
2402	}
2403
2404	#[test]
2405	fn caller_is_origin_returns_proper_values() {
2406		let code_charlie = MockLoader::insert(Call, |ctx, _| {
2407			// BOB is not the origin of the stack call
2408			assert!(!ctx.ext.caller_is_origin());
2409			exec_success()
2410		});
2411
2412		let code_bob = MockLoader::insert(Call, |ctx, _| {
2413			// ALICE is the origin of the call stack
2414			assert!(ctx.ext.caller_is_origin());
2415			// BOB calls CHARLIE
2416			ctx.ext
2417				.call(Weight::zero(), BalanceOf::<Test>::zero(), CHARLIE, 0, vec![], true, false)
2418		});
2419
2420		ExtBuilder::default().build().execute_with(|| {
2421			let schedule = <Test as Config>::Schedule::get();
2422			place_contract(&BOB, code_bob);
2423			place_contract(&CHARLIE, code_charlie);
2424			let contract_origin = Origin::from_account_id(ALICE);
2425			let mut storage_meter =
2426				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2427			// ALICE -> BOB (caller is origin) -> CHARLIE (caller is not origin)
2428			let result = MockStack::run_call(
2429				contract_origin,
2430				BOB,
2431				&mut GasMeter::<Test>::new(GAS_LIMIT),
2432				&mut storage_meter,
2433				&schedule,
2434				0,
2435				vec![0],
2436				None,
2437				Determinism::Enforced,
2438			);
2439			assert_matches!(result, Ok(_));
2440		});
2441	}
2442
2443	#[test]
2444	fn root_caller_succeeds() {
2445		let code_bob = MockLoader::insert(Call, |ctx, _| {
2446			// root is the origin of the call stack.
2447			assert!(ctx.ext.caller_is_root());
2448			exec_success()
2449		});
2450
2451		ExtBuilder::default().build().execute_with(|| {
2452			let schedule = <Test as Config>::Schedule::get();
2453			place_contract(&BOB, code_bob);
2454			let contract_origin = Origin::Root;
2455			let mut storage_meter =
2456				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2457			// root -> BOB (caller is root)
2458			let result = MockStack::run_call(
2459				contract_origin,
2460				BOB,
2461				&mut GasMeter::<Test>::new(GAS_LIMIT),
2462				&mut storage_meter,
2463				&schedule,
2464				0,
2465				vec![0],
2466				None,
2467				Determinism::Enforced,
2468			);
2469			assert_matches!(result, Ok(_));
2470		});
2471	}
2472
2473	#[test]
2474	fn root_caller_does_not_succeed_when_value_not_zero() {
2475		let code_bob = MockLoader::insert(Call, |ctx, _| {
2476			// root is the origin of the call stack.
2477			assert!(ctx.ext.caller_is_root());
2478			exec_success()
2479		});
2480
2481		ExtBuilder::default().build().execute_with(|| {
2482			let schedule = <Test as Config>::Schedule::get();
2483			place_contract(&BOB, code_bob);
2484			let contract_origin = Origin::Root;
2485			let mut storage_meter =
2486				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2487			// root -> BOB (caller is root)
2488			let result = MockStack::run_call(
2489				contract_origin,
2490				BOB,
2491				&mut GasMeter::<Test>::new(GAS_LIMIT),
2492				&mut storage_meter,
2493				&schedule,
2494				1,
2495				vec![0],
2496				None,
2497				Determinism::Enforced,
2498			);
2499			assert_matches!(result, Err(_));
2500		});
2501	}
2502
2503	#[test]
2504	fn root_caller_succeeds_with_consecutive_calls() {
2505		let code_charlie = MockLoader::insert(Call, |ctx, _| {
2506			// BOB is not root, even though the origin is root.
2507			assert!(!ctx.ext.caller_is_root());
2508			exec_success()
2509		});
2510
2511		let code_bob = MockLoader::insert(Call, |ctx, _| {
2512			// root is the origin of the call stack.
2513			assert!(ctx.ext.caller_is_root());
2514			// BOB calls CHARLIE.
2515			ctx.ext
2516				.call(Weight::zero(), BalanceOf::<Test>::zero(), CHARLIE, 0, vec![], true, false)
2517		});
2518
2519		ExtBuilder::default().build().execute_with(|| {
2520			let schedule = <Test as Config>::Schedule::get();
2521			place_contract(&BOB, code_bob);
2522			place_contract(&CHARLIE, code_charlie);
2523			let contract_origin = Origin::Root;
2524			let mut storage_meter =
2525				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2526			// root -> BOB (caller is root) -> CHARLIE (caller is not root)
2527			let result = MockStack::run_call(
2528				contract_origin,
2529				BOB,
2530				&mut GasMeter::<Test>::new(GAS_LIMIT),
2531				&mut storage_meter,
2532				&schedule,
2533				0,
2534				vec![0],
2535				None,
2536				Determinism::Enforced,
2537			);
2538			assert_matches!(result, Ok(_));
2539		});
2540	}
2541
2542	#[test]
2543	fn address_returns_proper_values() {
2544		let bob_ch = MockLoader::insert(Call, |ctx, _| {
2545			// Verify that address matches BOB.
2546			assert_eq!(*ctx.ext.address(), BOB);
2547
2548			// Call into charlie contract.
2549			assert_matches!(
2550				ctx.ext.call(
2551					Weight::zero(),
2552					BalanceOf::<Test>::zero(),
2553					CHARLIE,
2554					0,
2555					vec![],
2556					true,
2557					false
2558				),
2559				Ok(_)
2560			);
2561			exec_success()
2562		});
2563		let charlie_ch = MockLoader::insert(Call, |ctx, _| {
2564			assert_eq!(*ctx.ext.address(), CHARLIE);
2565			exec_success()
2566		});
2567
2568		ExtBuilder::default().build().execute_with(|| {
2569			let schedule = <Test as Config>::Schedule::get();
2570			place_contract(&BOB, bob_ch);
2571			place_contract(&CHARLIE, charlie_ch);
2572			let contract_origin = Origin::from_account_id(ALICE);
2573			let mut storage_meter =
2574				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2575
2576			let result = MockStack::run_call(
2577				contract_origin,
2578				BOB,
2579				&mut GasMeter::<Test>::new(GAS_LIMIT),
2580				&mut storage_meter,
2581				&schedule,
2582				0,
2583				vec![],
2584				None,
2585				Determinism::Enforced,
2586			);
2587
2588			assert_matches!(result, Ok(_));
2589		});
2590	}
2591
2592	#[test]
2593	fn refuse_instantiate_with_value_below_existential_deposit() {
2594		let dummy_ch = MockLoader::insert(Constructor, |_, _| exec_success());
2595
2596		ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
2597			let schedule = <Test as Config>::Schedule::get();
2598			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2599			let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
2600			let contract_origin = Origin::from_account_id(ALICE);
2601			let mut storage_meter =
2602				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2603
2604			assert_matches!(
2605				MockStack::run_instantiate(
2606					ALICE,
2607					executable,
2608					&mut gas_meter,
2609					&mut storage_meter,
2610					&schedule,
2611					0, // <- zero value
2612					vec![],
2613					&[],
2614					None,
2615				),
2616				Err(_)
2617			);
2618		});
2619	}
2620
2621	#[test]
2622	fn instantiation_work_with_success_output() {
2623		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
2624			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] })
2625		});
2626
2627		ExtBuilder::default()
2628			.with_code_hashes(MockLoader::code_hashes())
2629			.existential_deposit(15)
2630			.build()
2631			.execute_with(|| {
2632				let schedule = <Test as Config>::Schedule::get();
2633				let min_balance = <Test as Config>::Currency::minimum_balance();
2634				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2635				let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
2636				set_balance(&ALICE, min_balance * 1000);
2637				let contract_origin = Origin::from_account_id(ALICE);
2638				let mut storage_meter = storage::meter::Meter::new(
2639					&contract_origin,
2640					Some(min_balance * 100),
2641					min_balance,
2642				)
2643				.unwrap();
2644
2645				let instantiated_contract_address = assert_matches!(
2646					MockStack::run_instantiate(
2647						ALICE,
2648						executable,
2649						&mut gas_meter,
2650						&mut storage_meter,
2651						&schedule,
2652						min_balance,
2653						vec![],
2654						&[],
2655						None,
2656					),
2657					Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
2658				);
2659
2660				// Check that the newly created account has the expected code hash and
2661				// there are instantiation event.
2662				assert_eq!(
2663					ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
2664					dummy_ch
2665				);
2666				assert_eq!(
2667					&events(),
2668					&[Event::Instantiated {
2669						deployer: ALICE,
2670						contract: instantiated_contract_address
2671					}]
2672				);
2673			});
2674	}
2675
2676	#[test]
2677	fn instantiation_fails_with_failing_output() {
2678		let dummy_ch = MockLoader::insert(Constructor, |_, _| {
2679			Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] })
2680		});
2681
2682		ExtBuilder::default()
2683			.with_code_hashes(MockLoader::code_hashes())
2684			.existential_deposit(15)
2685			.build()
2686			.execute_with(|| {
2687				let schedule = <Test as Config>::Schedule::get();
2688				let min_balance = <Test as Config>::Currency::minimum_balance();
2689				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2690				let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
2691				set_balance(&ALICE, min_balance * 1000);
2692				let contract_origin = Origin::from_account_id(ALICE);
2693				let mut storage_meter = storage::meter::Meter::new(
2694					&contract_origin,
2695					Some(min_balance * 100),
2696					min_balance,
2697				)
2698				.unwrap();
2699
2700				let instantiated_contract_address = assert_matches!(
2701					MockStack::run_instantiate(
2702						ALICE,
2703						executable,
2704						&mut gas_meter,
2705						&mut storage_meter,
2706						&schedule,
2707						min_balance,
2708						vec![],
2709						&[],
2710						None,
2711					),
2712					Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
2713				);
2714
2715				// Check that the account has not been created.
2716				assert!(
2717					ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).is_none()
2718				);
2719				assert!(events().is_empty());
2720			});
2721	}
2722
2723	#[test]
2724	fn instantiation_from_contract() {
2725		let dummy_ch = MockLoader::insert(Call, |_, _| exec_success());
2726		let instantiated_contract_address = Rc::new(RefCell::new(None::<AccountIdOf<Test>>));
2727		let instantiator_ch = MockLoader::insert(Call, {
2728			let instantiated_contract_address = Rc::clone(&instantiated_contract_address);
2729			move |ctx, _| {
2730				// Instantiate a contract and save it's address in `instantiated_contract_address`.
2731				let (address, output) = ctx
2732					.ext
2733					.instantiate(
2734						Weight::zero(),
2735						BalanceOf::<Test>::zero(),
2736						dummy_ch,
2737						<Test as Config>::Currency::minimum_balance(),
2738						vec![],
2739						&[48, 49, 50],
2740					)
2741					.unwrap();
2742
2743				*instantiated_contract_address.borrow_mut() = address.into();
2744				Ok(output)
2745			}
2746		});
2747
2748		ExtBuilder::default()
2749			.with_code_hashes(MockLoader::code_hashes())
2750			.existential_deposit(15)
2751			.build()
2752			.execute_with(|| {
2753				let schedule = <Test as Config>::Schedule::get();
2754				let min_balance = <Test as Config>::Currency::minimum_balance();
2755				set_balance(&ALICE, min_balance * 100);
2756				place_contract(&BOB, instantiator_ch);
2757				let contract_origin = Origin::from_account_id(ALICE);
2758				let mut storage_meter = storage::meter::Meter::new(
2759					&contract_origin,
2760					Some(min_balance * 10),
2761					min_balance * 10,
2762				)
2763				.unwrap();
2764
2765				assert_matches!(
2766					MockStack::run_call(
2767						contract_origin,
2768						BOB,
2769						&mut GasMeter::<Test>::new(GAS_LIMIT),
2770						&mut storage_meter,
2771						&schedule,
2772						min_balance * 10,
2773						vec![],
2774						None,
2775						Determinism::Enforced,
2776					),
2777					Ok(_)
2778				);
2779
2780				let instantiated_contract_address =
2781					instantiated_contract_address.borrow().as_ref().unwrap().clone();
2782
2783				// Check that the newly created account has the expected code hash and
2784				// there are instantiation event.
2785				assert_eq!(
2786					ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
2787					dummy_ch
2788				);
2789				assert_eq!(
2790					&events(),
2791					&[
2792						Event::Instantiated {
2793							deployer: BOB,
2794							contract: instantiated_contract_address
2795						},
2796						Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },
2797					]
2798				);
2799			});
2800	}
2801
2802	#[test]
2803	fn instantiation_traps() {
2804		let dummy_ch = MockLoader::insert(Constructor, |_, _| Err("It's a trap!".into()));
2805		let instantiator_ch = MockLoader::insert(Call, {
2806			move |ctx, _| {
2807				// Instantiate a contract and save it's address in `instantiated_contract_address`.
2808				assert_matches!(
2809					ctx.ext.instantiate(
2810						Weight::zero(),
2811						BalanceOf::<Test>::zero(),
2812						dummy_ch,
2813						<Test as Config>::Currency::minimum_balance(),
2814						vec![],
2815						&[],
2816					),
2817					Err(ExecError {
2818						error: DispatchError::Other("It's a trap!"),
2819						origin: ErrorOrigin::Callee,
2820					})
2821				);
2822
2823				exec_success()
2824			}
2825		});
2826
2827		ExtBuilder::default()
2828			.with_code_hashes(MockLoader::code_hashes())
2829			.existential_deposit(15)
2830			.build()
2831			.execute_with(|| {
2832				let schedule = <Test as Config>::Schedule::get();
2833				set_balance(&ALICE, 1000);
2834				set_balance(&BOB, 100);
2835				place_contract(&BOB, instantiator_ch);
2836				let contract_origin = Origin::from_account_id(ALICE);
2837				let mut storage_meter =
2838					storage::meter::Meter::new(&contract_origin, Some(200), 0).unwrap();
2839
2840				assert_matches!(
2841					MockStack::run_call(
2842						contract_origin,
2843						BOB,
2844						&mut GasMeter::<Test>::new(GAS_LIMIT),
2845						&mut storage_meter,
2846						&schedule,
2847						0,
2848						vec![],
2849						None,
2850						Determinism::Enforced,
2851					),
2852					Ok(_)
2853				);
2854
2855				// The contract wasn't instantiated so we don't expect to see an instantiation
2856				// event here.
2857				assert_eq!(
2858					&events(),
2859					&[Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },]
2860				);
2861			});
2862	}
2863
2864	#[test]
2865	fn termination_from_instantiate_fails() {
2866		let terminate_ch = MockLoader::insert(Constructor, |ctx, _| {
2867			ctx.ext.terminate(&ALICE).unwrap();
2868			exec_success()
2869		});
2870
2871		ExtBuilder::default()
2872			.with_code_hashes(MockLoader::code_hashes())
2873			.existential_deposit(15)
2874			.build()
2875			.execute_with(|| {
2876				let schedule = <Test as Config>::Schedule::get();
2877				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2878				let executable =
2879					MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
2880				set_balance(&ALICE, 10_000);
2881				let contract_origin = Origin::from_account_id(ALICE);
2882				let mut storage_meter =
2883					storage::meter::Meter::new(&contract_origin, None, 100).unwrap();
2884
2885				assert_eq!(
2886					MockStack::run_instantiate(
2887						ALICE,
2888						executable,
2889						&mut gas_meter,
2890						&mut storage_meter,
2891						&schedule,
2892						100,
2893						vec![],
2894						&[],
2895						None,
2896					),
2897					Err(Error::<Test>::TerminatedInConstructor.into())
2898				);
2899
2900				assert_eq!(&events(), &[]);
2901			});
2902	}
2903
2904	#[test]
2905	fn in_memory_changes_not_discarded() {
2906		// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
2907		// This tests verifies some edge case of the contract info cache:
2908		// We change some value in our contract info before calling into a contract
2909		// that calls into ourself. This triggers a case where BOBs contract info
2910		// is written to storage and invalidated by the successful execution of BOB'.
2911		// The trap of CHARLIE reverts the storage changes to BOB. When the root BOB regains
2912		// control it reloads its contract info from storage. We check that changes that
2913		// are made before calling into CHARLIE are not discarded.
2914		let code_bob = MockLoader::insert(Call, |ctx, _| {
2915			if ctx.input_data[0] == 0 {
2916				let info = ctx.ext.contract_info();
2917				assert_eq!(info.storage_byte_deposit, 0);
2918				info.storage_byte_deposit = 42;
2919				assert_eq!(
2920					ctx.ext.call(
2921						Weight::zero(),
2922						BalanceOf::<Test>::zero(),
2923						CHARLIE,
2924						0,
2925						vec![],
2926						true,
2927						false
2928					),
2929					exec_trapped()
2930				);
2931				assert_eq!(ctx.ext.contract_info().storage_byte_deposit, 42);
2932			}
2933			exec_success()
2934		});
2935		let code_charlie = MockLoader::insert(Call, |ctx, _| {
2936			assert!(ctx
2937				.ext
2938				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false)
2939				.is_ok());
2940			exec_trapped()
2941		});
2942
2943		// This one tests passing the input data into a contract via call.
2944		ExtBuilder::default().build().execute_with(|| {
2945			let schedule = <Test as Config>::Schedule::get();
2946			place_contract(&BOB, code_bob);
2947			place_contract(&CHARLIE, code_charlie);
2948			let contract_origin = Origin::from_account_id(ALICE);
2949			let mut storage_meter =
2950				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
2951
2952			let result = MockStack::run_call(
2953				contract_origin,
2954				BOB,
2955				&mut GasMeter::<Test>::new(GAS_LIMIT),
2956				&mut storage_meter,
2957				&schedule,
2958				0,
2959				vec![0],
2960				None,
2961				Determinism::Enforced,
2962			);
2963			assert_matches!(result, Ok(_));
2964		});
2965	}
2966
2967	#[test]
2968	fn recursive_call_during_constructor_fails() {
2969		let code = MockLoader::insert(Constructor, |ctx, _| {
2970			assert_matches!(
2971				ctx.ext.call(Weight::zero(), BalanceOf::<Test>::zero(), ctx.ext.address().clone(), 0, vec![], true, false),
2972				Err(ExecError{error, ..}) if error == <Error<Test>>::ContractNotFound.into()
2973			);
2974			exec_success()
2975		});
2976
2977		// This one tests passing the input data into a contract via instantiate.
2978		ExtBuilder::default()
2979			.with_code_hashes(MockLoader::code_hashes())
2980			.build()
2981			.execute_with(|| {
2982				let schedule = <Test as Config>::Schedule::get();
2983				let min_balance = <Test as Config>::Currency::minimum_balance();
2984				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
2985				let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
2986				set_balance(&ALICE, min_balance * 10_000);
2987				let contract_origin = Origin::from_account_id(ALICE);
2988				let mut storage_meter =
2989					storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
2990
2991				let result = MockStack::run_instantiate(
2992					ALICE,
2993					executable,
2994					&mut gas_meter,
2995					&mut storage_meter,
2996					&schedule,
2997					min_balance,
2998					vec![],
2999					&[],
3000					None,
3001				);
3002				assert_matches!(result, Ok(_));
3003			});
3004	}
3005
3006	#[test]
3007	fn printing_works() {
3008		let code_hash = MockLoader::insert(Call, |ctx, _| {
3009			ctx.ext.append_debug_buffer("This is a test");
3010			ctx.ext.append_debug_buffer("More text");
3011			exec_success()
3012		});
3013
3014		let mut debug_buffer = DebugBufferVec::<Test>::try_from(Vec::new()).unwrap();
3015
3016		ExtBuilder::default().build().execute_with(|| {
3017			let min_balance = <Test as Config>::Currency::minimum_balance();
3018			let schedule = <Test as Config>::Schedule::get();
3019			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3020			set_balance(&ALICE, min_balance * 10);
3021			place_contract(&BOB, code_hash);
3022			let contract_origin = Origin::from_account_id(ALICE);
3023			let mut storage_meter =
3024				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3025			MockStack::run_call(
3026				contract_origin,
3027				BOB,
3028				&mut gas_meter,
3029				&mut storage_meter,
3030				&schedule,
3031				0,
3032				vec![],
3033				Some(&mut debug_buffer),
3034				Determinism::Enforced,
3035			)
3036			.unwrap();
3037		});
3038
3039		assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text");
3040	}
3041
3042	#[test]
3043	fn printing_works_on_fail() {
3044		let code_hash = MockLoader::insert(Call, |ctx, _| {
3045			ctx.ext.append_debug_buffer("This is a test");
3046			ctx.ext.append_debug_buffer("More text");
3047			exec_trapped()
3048		});
3049
3050		let mut debug_buffer = DebugBufferVec::<Test>::try_from(Vec::new()).unwrap();
3051
3052		ExtBuilder::default().build().execute_with(|| {
3053			let min_balance = <Test as Config>::Currency::minimum_balance();
3054			let schedule = <Test as Config>::Schedule::get();
3055			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3056			set_balance(&ALICE, min_balance * 10);
3057			place_contract(&BOB, code_hash);
3058			let contract_origin = Origin::from_account_id(ALICE);
3059			let mut storage_meter =
3060				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3061			let result = MockStack::run_call(
3062				contract_origin,
3063				BOB,
3064				&mut gas_meter,
3065				&mut storage_meter,
3066				&schedule,
3067				0,
3068				vec![],
3069				Some(&mut debug_buffer),
3070				Determinism::Enforced,
3071			);
3072			assert!(result.is_err());
3073		});
3074
3075		assert_eq!(&String::from_utf8(debug_buffer.to_vec()).unwrap(), "This is a testMore text");
3076	}
3077
3078	#[test]
3079	fn debug_buffer_is_limited() {
3080		let code_hash = MockLoader::insert(Call, move |ctx, _| {
3081			ctx.ext.append_debug_buffer("overflowing bytes");
3082			exec_success()
3083		});
3084
3085		// Pre-fill the buffer almost up to its limit, leaving not enough space to the message
3086		let debug_buf_before =
3087			DebugBufferVec::<Test>::try_from(vec![0u8; DebugBufferVec::<Test>::bound() - 5])
3088				.unwrap();
3089		let mut debug_buf_after = debug_buf_before.clone();
3090
3091		ExtBuilder::default().build().execute_with(|| {
3092			let schedule: Schedule<Test> = <Test as Config>::Schedule::get();
3093			let min_balance = <Test as Config>::Currency::minimum_balance();
3094			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3095			set_balance(&ALICE, min_balance * 10);
3096			place_contract(&BOB, code_hash);
3097			let contract_origin = Origin::from_account_id(ALICE);
3098			let mut storage_meter =
3099				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3100			MockStack::run_call(
3101				contract_origin,
3102				BOB,
3103				&mut gas_meter,
3104				&mut storage_meter,
3105				&schedule,
3106				0,
3107				vec![],
3108				Some(&mut debug_buf_after),
3109				Determinism::Enforced,
3110			)
3111			.unwrap();
3112			assert_eq!(debug_buf_before, debug_buf_after);
3113		});
3114	}
3115
3116	#[test]
3117	fn call_reentry_direct_recursion() {
3118		// call the contract passed as input with disabled reentry
3119		let code_bob = MockLoader::insert(Call, |ctx, _| {
3120			let dest = Decode::decode(&mut ctx.input_data.as_ref()).unwrap();
3121			ctx.ext
3122				.call(Weight::zero(), BalanceOf::<Test>::zero(), dest, 0, vec![], false, false)
3123		});
3124
3125		let code_charlie = MockLoader::insert(Call, |_, _| exec_success());
3126
3127		ExtBuilder::default().build().execute_with(|| {
3128			let schedule = <Test as Config>::Schedule::get();
3129			place_contract(&BOB, code_bob);
3130			place_contract(&CHARLIE, code_charlie);
3131			let contract_origin = Origin::from_account_id(ALICE);
3132			let mut storage_meter =
3133				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3134
3135			// Calling another contract should succeed
3136			assert_ok!(MockStack::run_call(
3137				contract_origin.clone(),
3138				BOB,
3139				&mut GasMeter::<Test>::new(GAS_LIMIT),
3140				&mut storage_meter,
3141				&schedule,
3142				0,
3143				CHARLIE.encode(),
3144				None,
3145				Determinism::Enforced
3146			));
3147
3148			// Calling into oneself fails
3149			assert_err!(
3150				MockStack::run_call(
3151					contract_origin,
3152					BOB,
3153					&mut GasMeter::<Test>::new(GAS_LIMIT),
3154					&mut storage_meter,
3155					&schedule,
3156					0,
3157					BOB.encode(),
3158					None,
3159					Determinism::Enforced
3160				)
3161				.map_err(|e| e.error),
3162				<Error<Test>>::ReentranceDenied,
3163			);
3164		});
3165	}
3166
3167	#[test]
3168	fn call_deny_reentry() {
3169		let code_bob = MockLoader::insert(Call, |ctx, _| {
3170			if ctx.input_data[0] == 0 {
3171				ctx.ext.call(
3172					Weight::zero(),
3173					BalanceOf::<Test>::zero(),
3174					CHARLIE,
3175					0,
3176					vec![],
3177					false,
3178					false,
3179				)
3180			} else {
3181				exec_success()
3182			}
3183		});
3184
3185		// call BOB with input set to '1'
3186		let code_charlie = MockLoader::insert(Call, |ctx, _| {
3187			ctx.ext
3188				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![1], true, false)
3189		});
3190
3191		ExtBuilder::default().build().execute_with(|| {
3192			let schedule = <Test as Config>::Schedule::get();
3193			place_contract(&BOB, code_bob);
3194			place_contract(&CHARLIE, code_charlie);
3195			let contract_origin = Origin::from_account_id(ALICE);
3196			let mut storage_meter =
3197				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3198
3199			// BOB -> CHARLIE -> BOB fails as BOB denies reentry.
3200			assert_err!(
3201				MockStack::run_call(
3202					contract_origin,
3203					BOB,
3204					&mut GasMeter::<Test>::new(GAS_LIMIT),
3205					&mut storage_meter,
3206					&schedule,
3207					0,
3208					vec![0],
3209					None,
3210					Determinism::Enforced
3211				)
3212				.map_err(|e| e.error),
3213				<Error<Test>>::ReentranceDenied,
3214			);
3215		});
3216	}
3217
3218	#[test]
3219	fn call_runtime_works() {
3220		let code_hash = MockLoader::insert(Call, |ctx, _| {
3221			let call = RuntimeCall::System(frame_system::Call::remark_with_event {
3222				remark: b"Hello World".to_vec(),
3223			});
3224			ctx.ext.call_runtime(call).unwrap();
3225			exec_success()
3226		});
3227
3228		ExtBuilder::default().build().execute_with(|| {
3229			let min_balance = <Test as Config>::Currency::minimum_balance();
3230			let schedule = <Test as Config>::Schedule::get();
3231			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3232			set_balance(&ALICE, min_balance * 10);
3233			place_contract(&BOB, code_hash);
3234			let contract_origin = Origin::from_account_id(ALICE);
3235			let mut storage_meter =
3236				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3237			System::reset_events();
3238			MockStack::run_call(
3239				contract_origin,
3240				BOB,
3241				&mut gas_meter,
3242				&mut storage_meter,
3243				&schedule,
3244				0,
3245				vec![],
3246				None,
3247				Determinism::Enforced,
3248			)
3249			.unwrap();
3250
3251			let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello World");
3252			assert_eq!(
3253				System::events(),
3254				vec![
3255					EventRecord {
3256						phase: Phase::Initialization,
3257						event: MetaEvent::System(frame_system::Event::Remarked {
3258							sender: BOB,
3259							hash: remark_hash
3260						}),
3261						topics: vec![],
3262					},
3263					EventRecord {
3264						phase: Phase::Initialization,
3265						event: MetaEvent::Contracts(crate::Event::Called {
3266							caller: Origin::from_account_id(ALICE),
3267							contract: BOB,
3268						}),
3269						topics: vec![],
3270					},
3271				]
3272			);
3273		});
3274	}
3275
3276	#[test]
3277	fn call_runtime_filter() {
3278		let code_hash = MockLoader::insert(Call, |ctx, _| {
3279			use frame_system::Call as SysCall;
3280			use pallet_balances::Call as BalanceCall;
3281			use pallet_utility::Call as UtilCall;
3282
3283			// remark should still be allowed
3284			let allowed_call =
3285				RuntimeCall::System(SysCall::remark_with_event { remark: b"Hello".to_vec() });
3286
3287			// transfers are disallowed by the `TestFiler` (see below)
3288			let forbidden_call = RuntimeCall::Balances(BalanceCall::transfer_allow_death {
3289				dest: CHARLIE,
3290				value: 22,
3291			});
3292
3293			// simple cases: direct call
3294			assert_err!(
3295				ctx.ext.call_runtime(forbidden_call.clone()),
3296				frame_system::Error::<Test>::CallFiltered
3297			);
3298
3299			// as part of a patch: return is OK (but it interrupted the batch)
3300			assert_ok!(ctx.ext.call_runtime(RuntimeCall::Utility(UtilCall::batch {
3301				calls: vec![allowed_call.clone(), forbidden_call, allowed_call]
3302			})),);
3303
3304			// the transfer wasn't performed
3305			assert_eq!(get_balance(&CHARLIE), 0);
3306
3307			exec_success()
3308		});
3309
3310		TestFilter::set_filter(|call| match call {
3311			RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) => false,
3312			_ => true,
3313		});
3314
3315		ExtBuilder::default().build().execute_with(|| {
3316			let min_balance = <Test as Config>::Currency::minimum_balance();
3317			let schedule = <Test as Config>::Schedule::get();
3318			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3319			set_balance(&ALICE, min_balance * 10);
3320			place_contract(&BOB, code_hash);
3321			let contract_origin = Origin::from_account_id(ALICE);
3322			let mut storage_meter =
3323				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
3324			System::reset_events();
3325			MockStack::run_call(
3326				contract_origin,
3327				BOB,
3328				&mut gas_meter,
3329				&mut storage_meter,
3330				&schedule,
3331				0,
3332				vec![],
3333				None,
3334				Determinism::Enforced,
3335			)
3336			.unwrap();
3337
3338			let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello");
3339			assert_eq!(
3340				System::events(),
3341				vec![
3342					EventRecord {
3343						phase: Phase::Initialization,
3344						event: MetaEvent::System(frame_system::Event::Remarked {
3345							sender: BOB,
3346							hash: remark_hash
3347						}),
3348						topics: vec![],
3349					},
3350					EventRecord {
3351						phase: Phase::Initialization,
3352						event: MetaEvent::Utility(pallet_utility::Event::ItemCompleted),
3353						topics: vec![],
3354					},
3355					EventRecord {
3356						phase: Phase::Initialization,
3357						event: MetaEvent::Utility(pallet_utility::Event::BatchInterrupted {
3358							index: 1,
3359							error: frame_system::Error::<Test>::CallFiltered.into()
3360						},),
3361						topics: vec![],
3362					},
3363					EventRecord {
3364						phase: Phase::Initialization,
3365						event: MetaEvent::Contracts(crate::Event::Called {
3366							caller: Origin::from_account_id(ALICE),
3367							contract: BOB,
3368						}),
3369						topics: vec![],
3370					},
3371				]
3372			);
3373		});
3374	}
3375
3376	#[test]
3377	fn nonce() {
3378		let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped());
3379		let success_code = MockLoader::insert(Constructor, |_, _| exec_success());
3380		let succ_fail_code = MockLoader::insert(Constructor, move |ctx, _| {
3381			ctx.ext
3382				.instantiate(
3383					Weight::zero(),
3384					BalanceOf::<Test>::zero(),
3385					fail_code,
3386					ctx.ext.minimum_balance() * 100,
3387					vec![],
3388					&[],
3389				)
3390				.ok();
3391			exec_success()
3392		});
3393		let succ_succ_code = MockLoader::insert(Constructor, move |ctx, _| {
3394			let (account_id, _) = ctx
3395				.ext
3396				.instantiate(
3397					Weight::zero(),
3398					BalanceOf::<Test>::zero(),
3399					success_code,
3400					ctx.ext.minimum_balance() * 100,
3401					vec![],
3402					&[],
3403				)
3404				.unwrap();
3405
3406			// a plain call should not influence the account counter
3407			ctx.ext
3408				.call(
3409					Weight::zero(),
3410					BalanceOf::<Test>::zero(),
3411					account_id,
3412					0,
3413					vec![],
3414					false,
3415					false,
3416				)
3417				.unwrap();
3418
3419			exec_success()
3420		});
3421
3422		ExtBuilder::default()
3423			.with_code_hashes(MockLoader::code_hashes())
3424			.build()
3425			.execute_with(|| {
3426				let schedule = <Test as Config>::Schedule::get();
3427				let min_balance = <Test as Config>::Currency::minimum_balance();
3428				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3429				let fail_executable =
3430					MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
3431				let success_executable =
3432					MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
3433				let succ_fail_executable =
3434					MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
3435				let succ_succ_executable =
3436					MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
3437				set_balance(&ALICE, min_balance * 10_000);
3438				let contract_origin = Origin::from_account_id(ALICE);
3439				let mut storage_meter =
3440					storage::meter::Meter::new(&contract_origin, None, min_balance * 100).unwrap();
3441
3442				MockStack::run_instantiate(
3443					ALICE,
3444					fail_executable,
3445					&mut gas_meter,
3446					&mut storage_meter,
3447					&schedule,
3448					min_balance * 100,
3449					vec![],
3450					&[],
3451					None,
3452				)
3453				.ok();
3454				assert_eq!(<Nonce<Test>>::get(), 0);
3455
3456				assert_ok!(MockStack::run_instantiate(
3457					ALICE,
3458					success_executable,
3459					&mut gas_meter,
3460					&mut storage_meter,
3461					&schedule,
3462					min_balance * 100,
3463					vec![],
3464					&[],
3465					None,
3466				));
3467				assert_eq!(<Nonce<Test>>::get(), 1);
3468
3469				assert_ok!(MockStack::run_instantiate(
3470					ALICE,
3471					succ_fail_executable,
3472					&mut gas_meter,
3473					&mut storage_meter,
3474					&schedule,
3475					min_balance * 200,
3476					vec![],
3477					&[],
3478					None,
3479				));
3480				assert_eq!(<Nonce<Test>>::get(), 2);
3481
3482				assert_ok!(MockStack::run_instantiate(
3483					ALICE,
3484					succ_succ_executable,
3485					&mut gas_meter,
3486					&mut storage_meter,
3487					&schedule,
3488					min_balance * 200,
3489					vec![],
3490					&[],
3491					None,
3492				));
3493				assert_eq!(<Nonce<Test>>::get(), 4);
3494			});
3495	}
3496
3497	#[test]
3498	fn set_storage_works() {
3499		let code_hash = MockLoader::insert(Call, |ctx, _| {
3500			// Write
3501			assert_eq!(
3502				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3503				Ok(WriteOutcome::New)
3504			);
3505			assert_eq!(
3506				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
3507				Ok(WriteOutcome::New)
3508			);
3509			assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
3510			assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
3511			assert_eq!(
3512				ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3513				Ok(WriteOutcome::New)
3514			);
3515			assert_eq!(
3516				ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3517				Ok(WriteOutcome::New)
3518			);
3519
3520			// Overwrite
3521			assert_eq!(
3522				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
3523				Ok(WriteOutcome::Overwritten(3))
3524			);
3525			assert_eq!(
3526				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
3527				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
3528			);
3529			assert_eq!(ctx.ext.set_storage(&Key::Fix([3; 32]), None, false), Ok(WriteOutcome::New));
3530			assert_eq!(ctx.ext.set_storage(&Key::Fix([4; 32]), None, true), Ok(WriteOutcome::New));
3531			assert_eq!(
3532				ctx.ext.set_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3533				Ok(WriteOutcome::Overwritten(0))
3534			);
3535			assert_eq!(
3536				ctx.ext.set_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3537				Ok(WriteOutcome::Taken(vec![]))
3538			);
3539
3540			exec_success()
3541		});
3542
3543		ExtBuilder::default().build().execute_with(|| {
3544			let min_balance = <Test as Config>::Currency::minimum_balance();
3545			let schedule = <Test as Config>::Schedule::get();
3546			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3547			set_balance(&ALICE, min_balance * 1000);
3548			place_contract(&BOB, code_hash);
3549			let contract_origin = Origin::from_account_id(ALICE);
3550			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3551			assert_ok!(MockStack::run_call(
3552				contract_origin,
3553				BOB,
3554				&mut gas_meter,
3555				&mut storage_meter,
3556				&schedule,
3557				0,
3558				vec![],
3559				None,
3560				Determinism::Enforced
3561			));
3562		});
3563	}
3564
3565	#[test]
3566	fn set_storage_varsized_key_works() {
3567		let code_hash = MockLoader::insert(Call, |ctx, _| {
3568			// Write
3569			assert_eq!(
3570				ctx.ext.set_storage(
3571					&Key::<Test>::try_from_var([1; 64].to_vec()).unwrap(),
3572					Some(vec![1, 2, 3]),
3573					false
3574				),
3575				Ok(WriteOutcome::New)
3576			);
3577			assert_eq!(
3578				ctx.ext.set_storage(
3579					&Key::<Test>::try_from_var([2; 19].to_vec()).unwrap(),
3580					Some(vec![4, 5, 6]),
3581					true
3582				),
3583				Ok(WriteOutcome::New)
3584			);
3585			assert_eq!(
3586				ctx.ext.set_storage(
3587					&Key::<Test>::try_from_var([3; 19].to_vec()).unwrap(),
3588					None,
3589					false
3590				),
3591				Ok(WriteOutcome::New)
3592			);
3593			assert_eq!(
3594				ctx.ext.set_storage(
3595					&Key::<Test>::try_from_var([4; 64].to_vec()).unwrap(),
3596					None,
3597					true
3598				),
3599				Ok(WriteOutcome::New)
3600			);
3601			assert_eq!(
3602				ctx.ext.set_storage(
3603					&Key::<Test>::try_from_var([5; 30].to_vec()).unwrap(),
3604					Some(vec![]),
3605					false
3606				),
3607				Ok(WriteOutcome::New)
3608			);
3609			assert_eq!(
3610				ctx.ext.set_storage(
3611					&Key::<Test>::try_from_var([6; 128].to_vec()).unwrap(),
3612					Some(vec![]),
3613					true
3614				),
3615				Ok(WriteOutcome::New)
3616			);
3617
3618			// Overwrite
3619			assert_eq!(
3620				ctx.ext.set_storage(
3621					&Key::<Test>::try_from_var([1; 64].to_vec()).unwrap(),
3622					Some(vec![42, 43, 44]),
3623					false
3624				),
3625				Ok(WriteOutcome::Overwritten(3))
3626			);
3627			assert_eq!(
3628				ctx.ext.set_storage(
3629					&Key::<Test>::try_from_var([2; 19].to_vec()).unwrap(),
3630					Some(vec![48]),
3631					true
3632				),
3633				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
3634			);
3635			assert_eq!(
3636				ctx.ext.set_storage(
3637					&Key::<Test>::try_from_var([3; 19].to_vec()).unwrap(),
3638					None,
3639					false
3640				),
3641				Ok(WriteOutcome::New)
3642			);
3643			assert_eq!(
3644				ctx.ext.set_storage(
3645					&Key::<Test>::try_from_var([4; 64].to_vec()).unwrap(),
3646					None,
3647					true
3648				),
3649				Ok(WriteOutcome::New)
3650			);
3651			assert_eq!(
3652				ctx.ext.set_storage(
3653					&Key::<Test>::try_from_var([5; 30].to_vec()).unwrap(),
3654					Some(vec![]),
3655					false
3656				),
3657				Ok(WriteOutcome::Overwritten(0))
3658			);
3659			assert_eq!(
3660				ctx.ext.set_storage(
3661					&Key::<Test>::try_from_var([6; 128].to_vec()).unwrap(),
3662					Some(vec![]),
3663					true
3664				),
3665				Ok(WriteOutcome::Taken(vec![]))
3666			);
3667
3668			exec_success()
3669		});
3670
3671		ExtBuilder::default().build().execute_with(|| {
3672			let min_balance = <Test as Config>::Currency::minimum_balance();
3673			let schedule = <Test as Config>::Schedule::get();
3674			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3675			set_balance(&ALICE, min_balance * 1000);
3676			place_contract(&BOB, code_hash);
3677			let contract_origin = Origin::from_account_id(ALICE);
3678			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3679			assert_ok!(MockStack::run_call(
3680				contract_origin,
3681				BOB,
3682				&mut gas_meter,
3683				&mut storage_meter,
3684				&schedule,
3685				0,
3686				vec![],
3687				None,
3688				Determinism::Enforced
3689			));
3690		});
3691	}
3692
3693	#[test]
3694	fn get_storage_works() {
3695		let code_hash = MockLoader::insert(Call, |ctx, _| {
3696			assert_eq!(
3697				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3698				Ok(WriteOutcome::New)
3699			);
3700			assert_eq!(
3701				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
3702				Ok(WriteOutcome::New)
3703			);
3704			assert_eq!(ctx.ext.get_storage(&Key::Fix([1; 32])), Some(vec![1, 2, 3]));
3705			assert_eq!(ctx.ext.get_storage(&Key::Fix([2; 32])), Some(vec![]));
3706			assert_eq!(ctx.ext.get_storage(&Key::Fix([3; 32])), None);
3707
3708			exec_success()
3709		});
3710
3711		ExtBuilder::default().build().execute_with(|| {
3712			let min_balance = <Test as Config>::Currency::minimum_balance();
3713			let schedule = <Test as Config>::Schedule::get();
3714			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3715			set_balance(&ALICE, min_balance * 1000);
3716			place_contract(&BOB, code_hash);
3717			let contract_origin = Origin::from_account_id(ALICE);
3718			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3719			assert_ok!(MockStack::run_call(
3720				contract_origin,
3721				BOB,
3722				&mut gas_meter,
3723				&mut storage_meter,
3724				&schedule,
3725				0,
3726				vec![],
3727				None,
3728				Determinism::Enforced
3729			));
3730		});
3731	}
3732
3733	#[test]
3734	fn get_storage_size_works() {
3735		let code_hash = MockLoader::insert(Call, |ctx, _| {
3736			assert_eq!(
3737				ctx.ext.set_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3738				Ok(WriteOutcome::New)
3739			);
3740			assert_eq!(
3741				ctx.ext.set_storage(&Key::Fix([2; 32]), Some(vec![]), false),
3742				Ok(WriteOutcome::New)
3743			);
3744			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([1; 32])), Some(3));
3745			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([2; 32])), Some(0));
3746			assert_eq!(ctx.ext.get_storage_size(&Key::Fix([3; 32])), None);
3747
3748			exec_success()
3749		});
3750
3751		ExtBuilder::default().build().execute_with(|| {
3752			let min_balance = <Test as Config>::Currency::minimum_balance();
3753			let schedule = <Test as Config>::Schedule::get();
3754			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3755			set_balance(&ALICE, min_balance * 1000);
3756			place_contract(&BOB, code_hash);
3757			let contract_origin = Origin::from_account_id(ALICE);
3758			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3759			assert_ok!(MockStack::run_call(
3760				contract_origin,
3761				BOB,
3762				&mut gas_meter,
3763				&mut storage_meter,
3764				&schedule,
3765				0,
3766				vec![],
3767				None,
3768				Determinism::Enforced
3769			));
3770		});
3771	}
3772
3773	#[test]
3774	fn get_storage_varsized_key_works() {
3775		let code_hash = MockLoader::insert(Call, |ctx, _| {
3776			assert_eq!(
3777				ctx.ext.set_storage(
3778					&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap(),
3779					Some(vec![1, 2, 3]),
3780					false
3781				),
3782				Ok(WriteOutcome::New)
3783			);
3784			assert_eq!(
3785				ctx.ext.set_storage(
3786					&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap(),
3787					Some(vec![]),
3788					false
3789				),
3790				Ok(WriteOutcome::New)
3791			);
3792			assert_eq!(
3793				ctx.ext.get_storage(&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap()),
3794				Some(vec![1, 2, 3])
3795			);
3796			assert_eq!(
3797				ctx.ext.get_storage(&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap()),
3798				Some(vec![])
3799			);
3800			assert_eq!(
3801				ctx.ext.get_storage(&Key::<Test>::try_from_var([3; 8].to_vec()).unwrap()),
3802				None
3803			);
3804
3805			exec_success()
3806		});
3807
3808		ExtBuilder::default().build().execute_with(|| {
3809			let min_balance = <Test as Config>::Currency::minimum_balance();
3810			let schedule = <Test as Config>::Schedule::get();
3811			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3812			set_balance(&ALICE, min_balance * 1000);
3813			place_contract(&BOB, code_hash);
3814			let contract_origin = Origin::from_account_id(ALICE);
3815			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3816			assert_ok!(MockStack::run_call(
3817				contract_origin,
3818				BOB,
3819				&mut gas_meter,
3820				&mut storage_meter,
3821				&schedule,
3822				0,
3823				vec![],
3824				None,
3825				Determinism::Enforced
3826			));
3827		});
3828	}
3829
3830	#[test]
3831	fn get_storage_size_varsized_key_works() {
3832		let code_hash = MockLoader::insert(Call, |ctx, _| {
3833			assert_eq!(
3834				ctx.ext.set_storage(
3835					&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap(),
3836					Some(vec![1, 2, 3]),
3837					false
3838				),
3839				Ok(WriteOutcome::New)
3840			);
3841			assert_eq!(
3842				ctx.ext.set_storage(
3843					&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap(),
3844					Some(vec![]),
3845					false
3846				),
3847				Ok(WriteOutcome::New)
3848			);
3849			assert_eq!(
3850				ctx.ext.get_storage_size(&Key::<Test>::try_from_var([1; 19].to_vec()).unwrap()),
3851				Some(3)
3852			);
3853			assert_eq!(
3854				ctx.ext.get_storage_size(&Key::<Test>::try_from_var([2; 16].to_vec()).unwrap()),
3855				Some(0)
3856			);
3857			assert_eq!(
3858				ctx.ext.get_storage_size(&Key::<Test>::try_from_var([3; 8].to_vec()).unwrap()),
3859				None
3860			);
3861
3862			exec_success()
3863		});
3864
3865		ExtBuilder::default().build().execute_with(|| {
3866			let min_balance = <Test as Config>::Currency::minimum_balance();
3867			let schedule = <Test as Config>::Schedule::get();
3868			let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
3869			set_balance(&ALICE, min_balance * 1000);
3870			place_contract(&BOB, code_hash);
3871			let contract_origin = Origin::from_account_id(ALICE);
3872			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3873			assert_ok!(MockStack::run_call(
3874				contract_origin,
3875				BOB,
3876				&mut gas_meter,
3877				&mut storage_meter,
3878				&schedule,
3879				0,
3880				vec![],
3881				None,
3882				Determinism::Enforced
3883			));
3884		});
3885	}
3886
3887	#[test]
3888	fn set_transient_storage_works() {
3889		let code_hash = MockLoader::insert(Call, |ctx, _| {
3890			// Write
3891			assert_eq!(
3892				ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![1, 2, 3]), false),
3893				Ok(WriteOutcome::New)
3894			);
3895			assert_eq!(
3896				ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![4, 5, 6]), true),
3897				Ok(WriteOutcome::New)
3898			);
3899			assert_eq!(
3900				ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
3901				Ok(WriteOutcome::New)
3902			);
3903			assert_eq!(
3904				ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
3905				Ok(WriteOutcome::New)
3906			);
3907			assert_eq!(
3908				ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3909				Ok(WriteOutcome::New)
3910			);
3911			assert_eq!(
3912				ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3913				Ok(WriteOutcome::New)
3914			);
3915
3916			// Overwrite
3917			assert_eq!(
3918				ctx.ext.set_transient_storage(&Key::Fix([1; 32]), Some(vec![42]), false),
3919				Ok(WriteOutcome::Overwritten(3))
3920			);
3921			assert_eq!(
3922				ctx.ext.set_transient_storage(&Key::Fix([2; 32]), Some(vec![48]), true),
3923				Ok(WriteOutcome::Taken(vec![4, 5, 6]))
3924			);
3925			assert_eq!(
3926				ctx.ext.set_transient_storage(&Key::Fix([3; 32]), None, false),
3927				Ok(WriteOutcome::New)
3928			);
3929			assert_eq!(
3930				ctx.ext.set_transient_storage(&Key::Fix([4; 32]), None, true),
3931				Ok(WriteOutcome::New)
3932			);
3933			assert_eq!(
3934				ctx.ext.set_transient_storage(&Key::Fix([5; 32]), Some(vec![]), false),
3935				Ok(WriteOutcome::Overwritten(0))
3936			);
3937			assert_eq!(
3938				ctx.ext.set_transient_storage(&Key::Fix([6; 32]), Some(vec![]), true),
3939				Ok(WriteOutcome::Taken(vec![]))
3940			);
3941
3942			exec_success()
3943		});
3944
3945		ExtBuilder::default().build().execute_with(|| {
3946			let schedule = <Test as Config>::Schedule::get();
3947			place_contract(&BOB, code_hash);
3948			let contract_origin = Origin::from_account_id(ALICE);
3949			let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
3950			assert_ok!(MockStack::run_call(
3951				contract_origin,
3952				BOB,
3953				&mut GasMeter::<Test>::new(GAS_LIMIT),
3954				&mut storage_meter,
3955				&schedule,
3956				0,
3957				vec![],
3958				None,
3959				Determinism::Enforced
3960			));
3961		});
3962	}
3963
3964	#[test]
3965	fn get_transient_storage_works() {
3966		// Call stack: BOB -> CHARLIE(success) -> BOB' (success)
3967		let storage_key_1 = &Key::Fix([1; 32]);
3968		let storage_key_2 = &Key::Fix([2; 32]);
3969		let storage_key_3 = &Key::Fix([3; 32]);
3970		let code_bob = MockLoader::insert(Call, |ctx, _| {
3971			if ctx.input_data[0] == 0 {
3972				assert_eq!(
3973					ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2]), false),
3974					Ok(WriteOutcome::New)
3975				);
3976				assert_eq!(
3977					ctx.ext.call(
3978						Weight::zero(),
3979						BalanceOf::<Test>::zero(),
3980						CHARLIE,
3981						0,
3982						vec![],
3983						true,
3984						false,
3985					),
3986					exec_success()
3987				);
3988				assert_eq!(ctx.ext.get_transient_storage(storage_key_1), Some(vec![3]));
3989				assert_eq!(ctx.ext.get_transient_storage(storage_key_2), Some(vec![]));
3990				assert_eq!(ctx.ext.get_transient_storage(storage_key_3), None);
3991			} else {
3992				assert_eq!(
3993					ctx.ext.set_transient_storage(storage_key_1, Some(vec![3]), true),
3994					Ok(WriteOutcome::Taken(vec![1, 2]))
3995				);
3996				assert_eq!(
3997					ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
3998					Ok(WriteOutcome::New)
3999				);
4000			}
4001			exec_success()
4002		});
4003		let code_charlie = MockLoader::insert(Call, |ctx, _| {
4004			assert!(ctx
4005				.ext
4006				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false)
4007				.is_ok());
4008			// CHARLIE can not read BOB`s storage.
4009			assert_eq!(ctx.ext.get_transient_storage(storage_key_1), None);
4010			exec_success()
4011		});
4012
4013		// This one tests passing the input data into a contract via call.
4014		ExtBuilder::default().build().execute_with(|| {
4015			let schedule = <Test as Config>::Schedule::get();
4016			place_contract(&BOB, code_bob);
4017			place_contract(&CHARLIE, code_charlie);
4018			let contract_origin = Origin::from_account_id(ALICE);
4019			let mut storage_meter =
4020				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4021
4022			let result = MockStack::run_call(
4023				contract_origin,
4024				BOB,
4025				&mut GasMeter::<Test>::new(GAS_LIMIT),
4026				&mut storage_meter,
4027				&schedule,
4028				0,
4029				vec![0],
4030				None,
4031				Determinism::Enforced,
4032			);
4033			assert_matches!(result, Ok(_));
4034		});
4035	}
4036
4037	#[test]
4038	fn get_transient_storage_size_works() {
4039		let storage_key_1 = &Key::Fix([1; 32]);
4040		let storage_key_2 = &Key::Fix([2; 32]);
4041		let storage_key_3 = &Key::Fix([3; 32]);
4042		let code_hash = MockLoader::insert(Call, |ctx, _| {
4043			assert_eq!(
4044				ctx.ext.set_transient_storage(storage_key_1, Some(vec![1, 2, 3]), false),
4045				Ok(WriteOutcome::New)
4046			);
4047			assert_eq!(
4048				ctx.ext.set_transient_storage(storage_key_2, Some(vec![]), false),
4049				Ok(WriteOutcome::New)
4050			);
4051			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_1), Some(3));
4052			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_2), Some(0));
4053			assert_eq!(ctx.ext.get_transient_storage_size(storage_key_3), None);
4054
4055			exec_success()
4056		});
4057
4058		ExtBuilder::default().build().execute_with(|| {
4059			let schedule = <Test as Config>::Schedule::get();
4060			place_contract(&BOB, code_hash);
4061			let contract_origin = Origin::from_account_id(ALICE);
4062			let mut storage_meter =
4063				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4064			assert_ok!(MockStack::run_call(
4065				contract_origin,
4066				BOB,
4067				&mut GasMeter::<Test>::new(GAS_LIMIT),
4068				&mut storage_meter,
4069				&schedule,
4070				0,
4071				vec![],
4072				None,
4073				Determinism::Enforced
4074			));
4075		});
4076	}
4077
4078	#[test]
4079	fn rollback_transient_storage_works() {
4080		// Call stack: BOB -> CHARLIE (trap) -> BOB' (success)
4081		let storage_key = &Key::Fix([1; 32]);
4082		let code_bob = MockLoader::insert(Call, |ctx, _| {
4083			if ctx.input_data[0] == 0 {
4084				assert_eq!(
4085					ctx.ext.set_transient_storage(storage_key, Some(vec![1, 2]), false),
4086					Ok(WriteOutcome::New)
4087				);
4088				assert_eq!(
4089					ctx.ext.call(
4090						Weight::zero(),
4091						BalanceOf::<Test>::zero(),
4092						CHARLIE,
4093						0,
4094						vec![],
4095						true,
4096						false
4097					),
4098					exec_trapped()
4099				);
4100				assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![1, 2]));
4101			} else {
4102				let overwritten_length = ctx.ext.get_transient_storage_size(storage_key).unwrap();
4103				assert_eq!(
4104					ctx.ext.set_transient_storage(storage_key, Some(vec![3]), false),
4105					Ok(WriteOutcome::Overwritten(overwritten_length))
4106				);
4107				assert_eq!(ctx.ext.get_transient_storage(storage_key), Some(vec![3]));
4108			}
4109			exec_success()
4110		});
4111		let code_charlie = MockLoader::insert(Call, |ctx, _| {
4112			assert!(ctx
4113				.ext
4114				.call(Weight::zero(), BalanceOf::<Test>::zero(), BOB, 0, vec![99], true, false)
4115				.is_ok());
4116			exec_trapped()
4117		});
4118
4119		// This one tests passing the input data into a contract via call.
4120		ExtBuilder::default().build().execute_with(|| {
4121			let schedule = <Test as Config>::Schedule::get();
4122			place_contract(&BOB, code_bob);
4123			place_contract(&CHARLIE, code_charlie);
4124			let contract_origin = Origin::from_account_id(ALICE);
4125			let mut storage_meter =
4126				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4127
4128			let result = MockStack::run_call(
4129				contract_origin,
4130				BOB,
4131				&mut GasMeter::<Test>::new(GAS_LIMIT),
4132				&mut storage_meter,
4133				&schedule,
4134				0,
4135				vec![0],
4136				None,
4137				Determinism::Enforced,
4138			);
4139			assert_matches!(result, Ok(_));
4140		});
4141	}
4142
4143	#[test]
4144	fn ecdsa_to_eth_address_returns_proper_value() {
4145		let bob_ch = MockLoader::insert(Call, |ctx, _| {
4146			let pubkey_compressed = array_bytes::hex2array_unchecked(
4147				"028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91",
4148			);
4149			assert_eq!(
4150				ctx.ext.ecdsa_to_eth_address(&pubkey_compressed).unwrap(),
4151				array_bytes::hex2array_unchecked::<_, 20>(
4152					"09231da7b19A016f9e576d23B16277062F4d46A8"
4153				)
4154			);
4155			exec_success()
4156		});
4157
4158		ExtBuilder::default().build().execute_with(|| {
4159			let schedule = <Test as Config>::Schedule::get();
4160			place_contract(&BOB, bob_ch);
4161
4162			let contract_origin = Origin::from_account_id(ALICE);
4163			let mut storage_meter =
4164				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4165			let result = MockStack::run_call(
4166				contract_origin,
4167				BOB,
4168				&mut GasMeter::<Test>::new(GAS_LIMIT),
4169				&mut storage_meter,
4170				&schedule,
4171				0,
4172				vec![],
4173				None,
4174				Determinism::Enforced,
4175			);
4176			assert_matches!(result, Ok(_));
4177		});
4178	}
4179
4180	#[test]
4181	fn nonce_api_works() {
4182		let fail_code = MockLoader::insert(Constructor, |_, _| exec_trapped());
4183		let success_code = MockLoader::insert(Constructor, |_, _| exec_success());
4184		let code_hash = MockLoader::insert(Call, move |ctx, _| {
4185			// It is set to one when this contract was instantiated by `place_contract`
4186			assert_eq!(ctx.ext.nonce(), 1);
4187			// Should not change without any instantiation in-between
4188			assert_eq!(ctx.ext.nonce(), 1);
4189			// Should not change with a failed instantiation
4190			assert_err!(
4191				ctx.ext.instantiate(
4192					Weight::zero(),
4193					BalanceOf::<Test>::zero(),
4194					fail_code,
4195					0,
4196					vec![],
4197					&[],
4198				),
4199				ExecError {
4200					error: <Error<Test>>::ContractTrapped.into(),
4201					origin: ErrorOrigin::Callee
4202				}
4203			);
4204			assert_eq!(ctx.ext.nonce(), 1);
4205			// Successful instantiation increments
4206			ctx.ext
4207				.instantiate(
4208					Weight::zero(),
4209					BalanceOf::<Test>::zero(),
4210					success_code,
4211					0,
4212					vec![],
4213					&[],
4214				)
4215				.unwrap();
4216			assert_eq!(ctx.ext.nonce(), 2);
4217			exec_success()
4218		});
4219
4220		ExtBuilder::default()
4221			.with_code_hashes(MockLoader::code_hashes())
4222			.build()
4223			.execute_with(|| {
4224				let min_balance = <Test as Config>::Currency::minimum_balance();
4225				let schedule = <Test as Config>::Schedule::get();
4226				let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
4227				set_balance(&ALICE, min_balance * 1000);
4228				place_contract(&BOB, code_hash);
4229				let contract_origin = Origin::from_account_id(ALICE);
4230				let mut storage_meter =
4231					storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
4232				assert_ok!(MockStack::run_call(
4233					contract_origin,
4234					BOB,
4235					&mut gas_meter,
4236					&mut storage_meter,
4237					&schedule,
4238					0,
4239					vec![],
4240					None,
4241					Determinism::Enforced
4242				));
4243			});
4244	}
4245
4246	/// This works even though random interface is deprecated, as the check to ban deprecated
4247	/// functions happens in the wasm stack which is mocked for exec tests.
4248	#[test]
4249	fn randomness_works() {
4250		let subject = b"nice subject".as_ref();
4251		let code_hash = MockLoader::insert(Call, move |ctx, _| {
4252			let rand = <Test as Config>::Randomness::random(subject);
4253			assert_eq!(rand, ctx.ext.random(subject));
4254			exec_success()
4255		});
4256
4257		ExtBuilder::default().build().execute_with(|| {
4258			let schedule = <Test as Config>::Schedule::get();
4259			place_contract(&BOB, code_hash);
4260
4261			let contract_origin = Origin::from_account_id(ALICE);
4262			let mut storage_meter =
4263				storage::meter::Meter::new(&contract_origin, Some(0), 0).unwrap();
4264			let result = MockStack::run_call(
4265				contract_origin,
4266				BOB,
4267				&mut GasMeter::<Test>::new(GAS_LIMIT),
4268				&mut storage_meter,
4269				&schedule,
4270				0,
4271				vec![],
4272				None,
4273				Determinism::Enforced,
4274			);
4275			assert_matches!(result, Ok(_));
4276		});
4277	}
4278}