referrerpolicy=no-referrer-when-downgrade

pallet_contracts/wasm/
mod.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
18//! This module provides a means for executing contracts
19//! represented in wasm.
20
21mod prepare;
22mod runtime;
23
24#[cfg(doc)]
25pub use crate::wasm::runtime::api_doc;
26
27#[cfg(test)]
28pub use {
29	crate::wasm::{prepare::tracker, runtime::ReturnErrorCode},
30	runtime::STABLE_API_COUNT,
31	tests::MockExt,
32};
33
34#[cfg(feature = "runtime-benchmarks")]
35pub use crate::wasm::runtime::{BenchEnv, ReturnData, TrapReason};
36
37pub use crate::wasm::{
38	prepare::{LoadedModule, LoadingMode},
39	runtime::{
40		AllowDeprecatedInterface, AllowUnstableInterface, Environment, Runtime, RuntimeCosts,
41	},
42};
43
44use crate::{
45	exec::{ExecResult, Executable, ExportedFunction, Ext},
46	gas::{GasMeter, Token},
47	weights::WeightInfo,
48	AccountIdOf, BadOrigin, BalanceOf, CodeHash, CodeInfoOf, CodeVec, Config, Error, Event,
49	HoldReason, Pallet, PristineCode, Schedule, Weight, LOG_TARGET,
50};
51use alloc::vec::Vec;
52use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
53use frame_support::{
54	dispatch::DispatchResult,
55	ensure,
56	traits::{fungible::MutateHold, tokens::Precision::BestEffort},
57};
58use sp_core::Get;
59use sp_runtime::DispatchError;
60use wasmi::{CompilationMode, InstancePre, Linker, Memory, MemoryType, StackLimits, Store};
61
62const BYTES_PER_PAGE: usize = 64 * 1024;
63
64/// Validated Wasm module ready for execution.
65/// This data structure is immutable once created and stored.
66#[derive(Encode, Decode, scale_info::TypeInfo)]
67#[codec(mel_bound())]
68#[scale_info(skip_type_params(T))]
69pub struct WasmBlob<T: Config> {
70	code: CodeVec<T>,
71	// This isn't needed for contract execution and is not stored alongside it.
72	#[codec(skip)]
73	code_info: CodeInfo<T>,
74	// This is for not calculating the hash every time we need it.
75	#[codec(skip)]
76	code_hash: CodeHash<T>,
77}
78
79/// Contract code related data, such as:
80///
81/// - owner of the contract, i.e. account uploaded its code,
82/// - storage deposit amount,
83/// - reference count,
84/// - determinism marker.
85///
86/// It is stored in a separate storage entry to avoid loading the code when not necessary.
87#[derive(Clone, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)]
88#[codec(mel_bound())]
89#[scale_info(skip_type_params(T))]
90pub struct CodeInfo<T: Config> {
91	/// The account that has uploaded the contract code and hence is allowed to remove it.
92	owner: AccountIdOf<T>,
93	/// The amount of balance that was deposited by the owner in order to store it on-chain.
94	#[codec(compact)]
95	deposit: BalanceOf<T>,
96	/// The number of instantiated contracts that use this as their code.
97	#[codec(compact)]
98	refcount: u64,
99	/// Marks if the code might contain non-deterministic features and is therefore never allowed
100	/// to be run on-chain. Specifically, such a code can never be instantiated into a contract
101	/// and can just be used through a delegate call.
102	determinism: Determinism,
103	/// length of the code in bytes.
104	code_len: u32,
105}
106
107/// Defines the required determinism level of a wasm blob when either running or uploading code.
108#[derive(
109	Clone,
110	Copy,
111	Encode,
112	Decode,
113	DecodeWithMemTracking,
114	scale_info::TypeInfo,
115	MaxEncodedLen,
116	Debug,
117	PartialEq,
118	Eq,
119)]
120pub enum Determinism {
121	/// The execution should be deterministic and hence no indeterministic instructions are
122	/// allowed.
123	///
124	/// Dispatchables always use this mode in order to make on-chain execution deterministic.
125	Enforced,
126	/// Allow calling or uploading an indeterministic code.
127	///
128	/// This is only possible when calling into `pallet-contracts` directly via
129	/// [`crate::Pallet::bare_call`].
130	///
131	/// # Note
132	///
133	/// **Never** use this mode for on-chain execution.
134	Relaxed,
135}
136
137impl ExportedFunction {
138	/// The wasm export name for the function.
139	fn identifier(&self) -> &str {
140		match self {
141			Self::Constructor => "deploy",
142			Self::Call => "call",
143		}
144	}
145}
146
147/// Cost of code loading from storage.
148#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
149#[derive(Clone, Copy)]
150struct CodeLoadToken(u32);
151
152impl<T: Config> Token<T> for CodeLoadToken {
153	fn weight(&self) -> Weight {
154		T::WeightInfo::call_with_code_per_byte(self.0)
155			.saturating_sub(T::WeightInfo::call_with_code_per_byte(0))
156	}
157}
158
159impl<T: Config> WasmBlob<T> {
160	/// Create the module by checking the `code`.
161	pub fn from_code(
162		code: Vec<u8>,
163		schedule: &Schedule<T>,
164		owner: AccountIdOf<T>,
165		determinism: Determinism,
166	) -> Result<Self, (DispatchError, &'static str)> {
167		prepare::prepare::<runtime::Env, T>(
168			code.try_into().map_err(|_| (<Error<T>>::CodeTooLarge.into(), ""))?,
169			schedule,
170			owner,
171			determinism,
172		)
173	}
174
175	/// Remove the code from storage and refund the deposit to its owner.
176	///
177	/// Applies all necessary checks before removing the code.
178	pub fn remove(origin: &T::AccountId, code_hash: CodeHash<T>) -> DispatchResult {
179		<CodeInfoOf<T>>::try_mutate_exists(&code_hash, |existing| {
180			if let Some(code_info) = existing {
181				ensure!(code_info.refcount == 0, <Error<T>>::CodeInUse);
182				ensure!(&code_info.owner == origin, BadOrigin);
183				let _ = T::Currency::release(
184					&HoldReason::CodeUploadDepositReserve.into(),
185					&code_info.owner,
186					code_info.deposit,
187					BestEffort,
188				);
189				let deposit_released = code_info.deposit;
190				let remover = code_info.owner.clone();
191
192				*existing = None;
193				<PristineCode<T>>::remove(&code_hash);
194				<Pallet<T>>::deposit_event(Event::CodeRemoved {
195					code_hash,
196					deposit_released,
197					remover,
198				});
199				Ok(())
200			} else {
201				Err(<Error<T>>::CodeNotFound.into())
202			}
203		})
204	}
205
206	/// Creates and returns an instance of the supplied code.
207	///
208	/// This is either used for later executing a contract or for validation of a contract.
209	/// When validating we pass `()` as `host_state`. Please note that such a dummy instance must
210	/// **never** be called/executed, since it will panic the executor.
211	pub fn instantiate<E, H>(
212		contract: LoadedModule,
213		host_state: H,
214		schedule: &Schedule<T>,
215		allow_deprecated: AllowDeprecatedInterface,
216	) -> Result<(Store<H>, Memory, InstancePre), &'static str>
217	where
218		E: Environment<H>,
219	{
220		let mut store = Store::new(&contract.engine, host_state);
221		let mut linker = Linker::new(&contract.engine);
222		E::define(
223			&mut store,
224			&mut linker,
225			if T::UnsafeUnstableInterface::get() {
226				AllowUnstableInterface::Yes
227			} else {
228				AllowUnstableInterface::No
229			},
230			allow_deprecated,
231		)
232		.map_err(|_| "can't define host functions to Linker")?;
233
234		// Query wasmi for memory limits specified in the module's import entry.
235		let memory_limits = contract.scan_imports::<T>(schedule)?;
236		// Here we allocate this memory in the _store_. It allocates _inital_ value, but allows it
237		// to grow up to maximum number of memory pages, if necessary.
238		let qed = "We checked the limits versus our Schedule,
239					 which specifies the max amount of memory pages
240					 well below u16::MAX; qed";
241		let memory = Memory::new(
242			&mut store,
243			MemoryType::new(memory_limits.0, Some(memory_limits.1)).expect(qed),
244		)
245		.expect(qed);
246
247		linker
248			.define("env", "memory", memory)
249			.expect("We just created the Linker. It has no definitions with this name; qed");
250
251		let instance = linker.instantiate(&mut store, &contract.module).map_err(|err| {
252			log::debug!(target: LOG_TARGET, "failed to instantiate module: {:?}", err);
253			"can't instantiate module with provided definitions"
254		})?;
255
256		Ok((store, memory, instance))
257	}
258
259	/// Puts the module blob into storage, and returns the deposit collected for the storage.
260	pub fn store_code(&mut self) -> Result<BalanceOf<T>, Error<T>> {
261		let code_hash = *self.code_hash();
262		<CodeInfoOf<T>>::mutate(code_hash, |stored_code_info| {
263			match stored_code_info {
264				// Contract code is already stored in storage. Nothing to be done here.
265				Some(_) => Ok(Default::default()),
266				// Upload a new contract code.
267				// We need to store the code and its code_info, and collect the deposit.
268				// This `None` case happens only with freshly uploaded modules. This means that
269				// the `owner` is always the origin of the current transaction.
270				None => {
271					let deposit = self.code_info.deposit;
272					T::Currency::hold(
273						&HoldReason::CodeUploadDepositReserve.into(),
274						&self.code_info.owner,
275						deposit,
276					)
277					.map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
278
279					self.code_info.refcount = 0;
280					<PristineCode<T>>::insert(code_hash, &self.code);
281					*stored_code_info = Some(self.code_info.clone());
282					<Pallet<T>>::deposit_event(Event::CodeStored {
283						code_hash,
284						deposit_held: deposit,
285						uploader: self.code_info.owner.clone(),
286					});
287					Ok(deposit)
288				},
289			}
290		})
291	}
292
293	/// Create the module without checking the passed code.
294	///
295	/// # Note
296	///
297	/// This is useful for benchmarking where we don't want validation of the module to skew
298	/// our results. This also does not collect any deposit from the `owner`. Also useful
299	/// during testing when we want to deploy codes that do not pass the instantiation checks.
300	#[cfg(any(test, feature = "runtime-benchmarks"))]
301	pub fn from_code_unchecked(
302		code: Vec<u8>,
303		schedule: &Schedule<T>,
304		owner: T::AccountId,
305	) -> Result<Self, DispatchError> {
306		prepare::benchmarking::prepare(code, schedule, owner)
307	}
308}
309
310impl<T: Config> CodeInfo<T> {
311	#[cfg(test)]
312	pub fn new(owner: T::AccountId) -> Self {
313		CodeInfo {
314			owner,
315			deposit: Default::default(),
316			refcount: 0,
317			code_len: 0,
318			determinism: Determinism::Enforced,
319		}
320	}
321
322	/// Returns the determinism of the module.
323	pub fn determinism(&self) -> Determinism {
324		self.determinism
325	}
326
327	/// Returns reference count of the module.
328	pub fn refcount(&self) -> u64 {
329		self.refcount
330	}
331
332	/// Return mutable reference to the refcount of the module.
333	pub fn refcount_mut(&mut self) -> &mut u64 {
334		&mut self.refcount
335	}
336
337	/// Returns the deposit of the module.
338	pub fn deposit(&self) -> BalanceOf<T> {
339		self.deposit
340	}
341}
342
343use crate::{ExecError, ExecReturnValue};
344use wasmi::Func;
345enum InstanceOrExecReturn<'a, E: Ext> {
346	Instance((Func, Store<Runtime<'a, E>>)),
347	ExecReturn(ExecReturnValue),
348}
349
350type PreExecResult<'a, E> = Result<InstanceOrExecReturn<'a, E>, ExecError>;
351
352impl<T: Config> WasmBlob<T> {
353	/// Sync the frame's gas meter with the engine's one.
354	pub fn process_result<E: Ext<T = T>>(
355		mut store: Store<Runtime<E>>,
356		result: Result<(), wasmi::Error>,
357	) -> ExecResult {
358		let engine_fuel = store.get_fuel().expect("Fuel metering is enabled; qed");
359		let gas_meter = store.data_mut().ext().gas_meter_mut();
360		let _ = gas_meter.sync_from_executor(engine_fuel)?;
361		store.into_data().to_execution_result(result)
362	}
363
364	#[cfg(feature = "runtime-benchmarks")]
365	pub fn bench_prepare_call<'a, E: Ext<T = T>>(
366		self,
367		ext: &'a mut E,
368		input_data: Vec<u8>,
369	) -> (Func, Store<Runtime<'a, E>>) {
370		use InstanceOrExecReturn::*;
371		match Self::prepare_execute(
372			self,
373			Runtime::new(ext, input_data),
374			&ExportedFunction::Call,
375			CompilationMode::Eager,
376		)
377		.expect("Benchmark should provide valid module")
378		{
379			Instance((func, store)) => (func, store),
380			ExecReturn(_) => panic!("Expected Instance"),
381		}
382	}
383
384	fn prepare_execute<'a, E: Ext<T = T>>(
385		self,
386		runtime: Runtime<'a, E>,
387		function: &'a ExportedFunction,
388		compilation_mode: CompilationMode,
389	) -> PreExecResult<'a, E> {
390		let code = self.code.as_slice();
391		// Instantiate the Wasm module to the engine.
392		let schedule = <T>::Schedule::get();
393
394		let contract = LoadedModule::new::<T>(
395			&code,
396			self.code_info.determinism,
397			Some(StackLimits::default()),
398			LoadingMode::Unchecked,
399			compilation_mode,
400		)
401		.map_err(|err| {
402			log::debug!(target: LOG_TARGET, "failed to create wasmi module: {err:?}");
403			Error::<T>::CodeRejected
404		})?;
405
406		let (mut store, memory, instance) = Self::instantiate::<crate::wasm::runtime::Env, _>(
407			contract,
408			runtime,
409			&schedule,
410			match function {
411				ExportedFunction::Call => AllowDeprecatedInterface::Yes,
412				ExportedFunction::Constructor => AllowDeprecatedInterface::No,
413			},
414		)
415		.map_err(|msg| {
416			log::debug!(target: LOG_TARGET, "failed to instantiate code to wasmi: {}", msg);
417			Error::<T>::CodeRejected
418		})?;
419		store.data_mut().set_memory(memory);
420
421		// Set fuel limit for the wasmi execution.
422		// We normalize it by the base instruction weight, as its cost in wasmi engine is `1`.
423		let fuel_limit = store
424			.data_mut()
425			.ext()
426			.gas_meter_mut()
427			.gas_left()
428			.ref_time()
429			.checked_div(T::Schedule::get().ref_time_by_fuel())
430			.ok_or(Error::<T>::InvalidSchedule)?;
431		store
432			.set_fuel(fuel_limit)
433			.expect("We've set up engine to fuel consuming mode; qed");
434
435		// Start function should already see the correct refcount in case it will be ever inspected.
436		if let &ExportedFunction::Constructor = function {
437			E::increment_refcount(self.code_hash)?;
438		}
439
440		// Any abort in start function (includes `return` + `terminate`) will make us skip the
441		// call into the subsequent exported function. This means that calling `return` returns data
442		// from the whole contract execution.
443		match instance.start(&mut store) {
444			Ok(instance) => {
445				let exported_func = instance
446					.get_export(&store, function.identifier())
447					.and_then(|export| export.into_func())
448					.ok_or_else(|| {
449						log::error!(target: LOG_TARGET, "failed to find entry point");
450						Error::<T>::CodeRejected
451					})?;
452
453				Ok(InstanceOrExecReturn::Instance((exported_func, store)))
454			},
455			Err(err) => Self::process_result(store, Err(err)).map(InstanceOrExecReturn::ExecReturn),
456		}
457	}
458}
459
460impl<T: Config> Executable<T> for WasmBlob<T> {
461	fn from_storage(
462		code_hash: CodeHash<T>,
463		gas_meter: &mut GasMeter<T>,
464	) -> Result<Self, DispatchError> {
465		let code_info = <CodeInfoOf<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
466		gas_meter.charge(CodeLoadToken(code_info.code_len))?;
467		let code = <PristineCode<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
468		Ok(Self { code, code_info, code_hash })
469	}
470
471	fn execute<E: Ext<T = T>>(
472		self,
473		ext: &mut E,
474		function: &ExportedFunction,
475		input_data: Vec<u8>,
476	) -> ExecResult {
477		use InstanceOrExecReturn::*;
478		match Self::prepare_execute(
479			self,
480			Runtime::new(ext, input_data),
481			function,
482			CompilationMode::Lazy,
483		)? {
484			Instance((func, mut store)) => {
485				let result = func.call(&mut store, &[], &mut []);
486				Self::process_result(store, result)
487			},
488			ExecReturn(exec_return) => Ok(exec_return),
489		}
490	}
491
492	fn code_hash(&self) -> &CodeHash<T> {
493		&self.code_hash
494	}
495
496	fn code_info(&self) -> &CodeInfo<T> {
497		&self.code_info
498	}
499
500	fn is_deterministic(&self) -> bool {
501		matches!(self.code_info.determinism, Determinism::Enforced)
502	}
503}
504
505#[cfg(test)]
506mod tests {
507	use super::*;
508	use crate::{
509		exec::{AccountIdOf, ErrorOrigin, ExecError, Executable, Ext, Key, SeedOf},
510		gas::GasMeter,
511		primitives::ExecReturnValue,
512		storage::WriteOutcome,
513		tests::{RuntimeCall, Test, ALICE, BOB},
514		transient_storage::TransientStorage,
515		BalanceOf, CodeHash, Error, Origin, Pallet as Contracts,
516	};
517	use assert_matches::assert_matches;
518	use frame_support::{
519		assert_err, assert_ok, dispatch::DispatchResultWithPostInfo, weights::Weight,
520	};
521	use frame_system::pallet_prelude::BlockNumberFor;
522	use pallet_contracts_uapi::ReturnFlags;
523	use pretty_assertions::assert_eq;
524	use sp_core::H256;
525	use sp_runtime::DispatchError;
526	use std::{
527		borrow::BorrowMut,
528		cell::RefCell,
529		collections::{
530			hash_map::{Entry, HashMap},
531			HashSet,
532		},
533	};
534
535	#[derive(Debug, PartialEq, Eq)]
536	struct InstantiateEntry {
537		code_hash: H256,
538		value: u64,
539		data: Vec<u8>,
540		gas_left: u64,
541		salt: Vec<u8>,
542	}
543
544	#[derive(Debug, PartialEq, Eq)]
545	struct TerminationEntry {
546		beneficiary: AccountIdOf<Test>,
547	}
548
549	#[derive(Debug, PartialEq, Eq)]
550	struct TransferEntry {
551		to: AccountIdOf<Test>,
552		value: u64,
553	}
554
555	#[derive(Debug, PartialEq, Eq)]
556	struct CallEntry {
557		to: AccountIdOf<Test>,
558		value: u64,
559		data: Vec<u8>,
560		allows_reentry: bool,
561		read_only: bool,
562	}
563
564	#[derive(Debug, PartialEq, Eq)]
565	struct CallCodeEntry {
566		code_hash: H256,
567		data: Vec<u8>,
568	}
569
570	pub struct MockExt {
571		storage: HashMap<Vec<u8>, Vec<u8>>,
572		transient_storage: TransientStorage<Test>,
573		instantiates: Vec<InstantiateEntry>,
574		terminations: Vec<TerminationEntry>,
575		calls: Vec<CallEntry>,
576		code_calls: Vec<CallCodeEntry>,
577		transfers: Vec<TransferEntry>,
578		// (topics, data)
579		events: Vec<(Vec<H256>, Vec<u8>)>,
580		runtime_calls: RefCell<Vec<RuntimeCall>>,
581		schedule: Schedule<Test>,
582		gas_meter: GasMeter<Test>,
583		debug_buffer: Vec<u8>,
584		ecdsa_recover: RefCell<Vec<([u8; 65], [u8; 32])>>,
585		sr25519_verify: RefCell<Vec<([u8; 64], Vec<u8>, [u8; 32])>>,
586		code_hashes: Vec<CodeHash<Test>>,
587		caller: Origin<Test>,
588		delegate_dependencies: RefCell<HashSet<CodeHash<Test>>>,
589	}
590
591	/// The call is mocked and just returns this hardcoded value.
592	fn call_return_data() -> Vec<u8> {
593		vec![0xDE, 0xAD, 0xBE, 0xEF]
594	}
595
596	impl Default for MockExt {
597		fn default() -> Self {
598			Self {
599				code_hashes: Default::default(),
600				storage: Default::default(),
601				transient_storage: TransientStorage::new(1024 * 1024),
602				instantiates: Default::default(),
603				terminations: Default::default(),
604				calls: Default::default(),
605				code_calls: Default::default(),
606				transfers: Default::default(),
607				events: Default::default(),
608				runtime_calls: Default::default(),
609				schedule: Default::default(),
610				gas_meter: GasMeter::new(Weight::from_parts(10_000_000_000, 10 * 1024 * 1024)),
611				debug_buffer: Default::default(),
612				ecdsa_recover: Default::default(),
613				caller: Default::default(),
614				sr25519_verify: Default::default(),
615				delegate_dependencies: Default::default(),
616			}
617		}
618	}
619
620	impl Ext for MockExt {
621		type T = Test;
622
623		fn call(
624			&mut self,
625			_gas_limit: Weight,
626			_deposit_limit: BalanceOf<Self::T>,
627			to: AccountIdOf<Self::T>,
628			value: u64,
629			data: Vec<u8>,
630			allows_reentry: bool,
631			read_only: bool,
632		) -> Result<ExecReturnValue, ExecError> {
633			self.calls.push(CallEntry { to, value, data, allows_reentry, read_only });
634			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: call_return_data() })
635		}
636		fn delegate_call(
637			&mut self,
638			code_hash: CodeHash<Self::T>,
639			data: Vec<u8>,
640		) -> Result<ExecReturnValue, ExecError> {
641			self.code_calls.push(CallCodeEntry { code_hash, data });
642			Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: call_return_data() })
643		}
644		fn instantiate(
645			&mut self,
646			gas_limit: Weight,
647			_deposit_limit: BalanceOf<Self::T>,
648			code_hash: CodeHash<Test>,
649			value: u64,
650			data: Vec<u8>,
651			salt: &[u8],
652		) -> Result<(AccountIdOf<Self::T>, ExecReturnValue), ExecError> {
653			self.instantiates.push(InstantiateEntry {
654				code_hash,
655				value,
656				data: data.to_vec(),
657				gas_left: gas_limit.ref_time(),
658				salt: salt.to_vec(),
659			});
660			Ok((
661				Contracts::<Test>::contract_address(&ALICE, &code_hash, &data, salt),
662				ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() },
663			))
664		}
665		fn set_code_hash(&mut self, hash: CodeHash<Self::T>) -> DispatchResult {
666			self.code_hashes.push(hash);
667			Ok(())
668		}
669		fn transfer(&mut self, to: &AccountIdOf<Self::T>, value: u64) -> DispatchResult {
670			self.transfers.push(TransferEntry { to: to.clone(), value });
671			Ok(())
672		}
673		fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> DispatchResult {
674			self.terminations.push(TerminationEntry { beneficiary: beneficiary.clone() });
675			Ok(())
676		}
677		fn get_storage(&mut self, key: &Key<Self::T>) -> Option<Vec<u8>> {
678			self.storage.get(&key.to_vec()).cloned()
679		}
680		fn get_storage_size(&mut self, key: &Key<Self::T>) -> Option<u32> {
681			self.storage.get(&key.to_vec()).map(|val| val.len() as u32)
682		}
683		fn set_storage(
684			&mut self,
685			key: &Key<Self::T>,
686			value: Option<Vec<u8>>,
687			take_old: bool,
688		) -> Result<WriteOutcome, DispatchError> {
689			let key = key.to_vec();
690			let entry = self.storage.entry(key.clone());
691			let result = match (entry, take_old) {
692				(Entry::Vacant(_), _) => WriteOutcome::New,
693				(Entry::Occupied(entry), false) => {
694					WriteOutcome::Overwritten(entry.remove().len() as u32)
695				},
696				(Entry::Occupied(entry), true) => WriteOutcome::Taken(entry.remove()),
697			};
698			if let Some(value) = value {
699				self.storage.insert(key, value);
700			}
701			Ok(result)
702		}
703		fn get_transient_storage(&self, key: &Key<Self::T>) -> Option<Vec<u8>> {
704			self.transient_storage.read(self.address(), key)
705		}
706		fn get_transient_storage_size(&self, key: &Key<Self::T>) -> Option<u32> {
707			self.transient_storage.read(self.address(), key).map(|value| value.len() as _)
708		}
709		fn set_transient_storage(
710			&mut self,
711			key: &Key<Self::T>,
712			value: Option<Vec<u8>>,
713			take_old: bool,
714		) -> Result<WriteOutcome, DispatchError> {
715			let account_id = self.address().clone();
716			self.transient_storage.write(&account_id, key, value, take_old)
717		}
718		fn caller(&self) -> Origin<Self::T> {
719			self.caller.clone()
720		}
721		fn is_contract(&self, _address: &AccountIdOf<Self::T>) -> bool {
722			true
723		}
724		fn code_hash(&self, _address: &AccountIdOf<Self::T>) -> Option<CodeHash<Self::T>> {
725			Some(H256::from_slice(&[0x11; 32]))
726		}
727		fn own_code_hash(&mut self) -> &CodeHash<Self::T> {
728			const HASH: H256 = H256::repeat_byte(0x10);
729			&HASH
730		}
731		fn caller_is_origin(&self) -> bool {
732			false
733		}
734		fn caller_is_root(&self) -> bool {
735			&self.caller == &Origin::Root
736		}
737		fn address(&self) -> &AccountIdOf<Self::T> {
738			&BOB
739		}
740		fn balance(&self) -> u64 {
741			228
742		}
743		fn value_transferred(&self) -> u64 {
744			1337
745		}
746		fn now(&self) -> &u64 {
747			&1111
748		}
749		fn minimum_balance(&self) -> u64 {
750			666
751		}
752		fn random(&self, subject: &[u8]) -> (SeedOf<Self::T>, BlockNumberFor<Self::T>) {
753			(H256::from_slice(subject), 42)
754		}
755		fn deposit_event(&mut self, topics: Vec<H256>, data: Vec<u8>) {
756			self.events.push((topics, data))
757		}
758		fn block_number(&self) -> u64 {
759			121
760		}
761		fn max_value_size(&self) -> u32 {
762			16_384
763		}
764		fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T> {
765			BalanceOf::<Self::T>::from(1312_u32)
766				.saturating_mul(weight.ref_time().into())
767				.saturating_add(
768					BalanceOf::<Self::T>::from(103_u32).saturating_mul(weight.proof_size()),
769				)
770		}
771		fn schedule(&self) -> &Schedule<Self::T> {
772			&self.schedule
773		}
774		fn gas_meter(&self) -> &GasMeter<Self::T> {
775			&self.gas_meter
776		}
777		fn gas_meter_mut(&mut self) -> &mut GasMeter<Self::T> {
778			&mut self.gas_meter
779		}
780		fn charge_storage(&mut self, _diff: &crate::storage::meter::Diff) {}
781
782		fn debug_buffer_enabled(&self) -> bool {
783			true
784		}
785		fn append_debug_buffer(&mut self, msg: &str) -> bool {
786			self.debug_buffer.extend(msg.as_bytes());
787			true
788		}
789		fn call_runtime(
790			&self,
791			call: <Self::T as Config>::RuntimeCall,
792		) -> DispatchResultWithPostInfo {
793			self.runtime_calls.borrow_mut().push(call);
794			Ok(Default::default())
795		}
796		fn ecdsa_recover(
797			&self,
798			signature: &[u8; 65],
799			message_hash: &[u8; 32],
800		) -> Result<[u8; 33], ()> {
801			self.ecdsa_recover.borrow_mut().push((*signature, *message_hash));
802			Ok([3; 33])
803		}
804		fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool {
805			self.sr25519_verify.borrow_mut().push((*signature, message.to_vec(), *pub_key));
806			true
807		}
808		fn contract_info(&mut self) -> &mut crate::ContractInfo<Self::T> {
809			unimplemented!()
810		}
811		#[cfg(feature = "runtime-benchmarks")]
812		fn transient_storage(&mut self) -> &mut TransientStorage<Self::T> {
813			unimplemented!()
814		}
815		fn ecdsa_to_eth_address(&self, _pk: &[u8; 33]) -> Result<[u8; 20], ()> {
816			Ok([2u8; 20])
817		}
818		fn reentrance_count(&self) -> u32 {
819			12
820		}
821		fn account_reentrance_count(&self, _account_id: &AccountIdOf<Self::T>) -> u32 {
822			12
823		}
824		fn nonce(&mut self) -> u64 {
825			995
826		}
827		fn increment_refcount(_code_hash: CodeHash<Self::T>) -> DispatchResult {
828			Ok(())
829		}
830		fn decrement_refcount(_code_hash: CodeHash<Self::T>) {}
831		fn lock_delegate_dependency(&mut self, code: CodeHash<Self::T>) -> DispatchResult {
832			self.delegate_dependencies.borrow_mut().insert(code);
833			Ok(())
834		}
835		fn unlock_delegate_dependency(&mut self, code: &CodeHash<Self::T>) -> DispatchResult {
836			self.delegate_dependencies.borrow_mut().remove(code);
837			Ok(())
838		}
839
840		fn locked_delegate_dependencies_count(&mut self) -> usize {
841			self.delegate_dependencies.borrow().len()
842		}
843
844		fn is_read_only(&self) -> bool {
845			false
846		}
847	}
848
849	/// Execute the supplied code.
850	///
851	/// Not used directly but through the wrapper functions defined below.
852	fn execute_internal<E: BorrowMut<MockExt>>(
853		wat: &str,
854		input_data: Vec<u8>,
855		mut ext: E,
856		entry_point: &ExportedFunction,
857		unstable_interface: bool,
858		skip_checks: bool,
859	) -> ExecResult {
860		type RuntimeConfig = <MockExt as Ext>::T;
861		RuntimeConfig::set_unstable_interface(unstable_interface);
862		let wasm = wat::parse_str(wat).unwrap();
863		let executable = if skip_checks {
864			WasmBlob::<RuntimeConfig>::from_code_unchecked(
865				wasm,
866				ext.borrow_mut().schedule(),
867				ALICE,
868			)?
869		} else {
870			WasmBlob::<RuntimeConfig>::from_code(
871				wasm,
872				ext.borrow_mut().schedule(),
873				ALICE,
874				Determinism::Enforced,
875			)
876			.map_err(|err| err.0)?
877		};
878		executable.execute(ext.borrow_mut(), entry_point, input_data)
879	}
880
881	/// Execute the `call` function within the supplied code.
882	fn execute<E: BorrowMut<MockExt>>(wat: &str, input_data: Vec<u8>, ext: E) -> ExecResult {
883		execute_internal(wat, input_data, ext, &ExportedFunction::Call, true, false)
884	}
885
886	/// Execute the `deploy` function within the supplied code.
887	fn execute_instantiate<E: BorrowMut<MockExt>>(
888		wat: &str,
889		input_data: Vec<u8>,
890		ext: E,
891	) -> ExecResult {
892		execute_internal(wat, input_data, ext, &ExportedFunction::Constructor, true, false)
893	}
894
895	/// Execute the supplied code with disabled unstable functions.
896	///
897	/// In our test config unstable functions are disabled so that we can test them.
898	/// In order to test that code using them is properly rejected we temporarily disable
899	/// them when this test is run.
900	#[cfg(not(feature = "runtime-benchmarks"))]
901	fn execute_no_unstable<E: BorrowMut<MockExt>>(
902		wat: &str,
903		input_data: Vec<u8>,
904		ext: E,
905	) -> ExecResult {
906		execute_internal(wat, input_data, ext, &ExportedFunction::Call, false, false)
907	}
908
909	/// Execute code without validating it first.
910	///
911	/// This is mainly useful in order to test code which uses deprecated functions. Those
912	/// would fail when validating the code.
913	fn execute_unvalidated<E: BorrowMut<MockExt>>(
914		wat: &str,
915		input_data: Vec<u8>,
916		ext: E,
917	) -> ExecResult {
918		execute_internal(wat, input_data, ext, &ExportedFunction::Call, false, true)
919	}
920
921	/// Execute instantiation entry point of code without validating it first.
922	///
923	/// Same as `execute_unvalidated` except that the `deploy` entry point is ran.
924	#[cfg(not(feature = "runtime-benchmarks"))]
925	fn execute_instantiate_unvalidated<E: BorrowMut<MockExt>>(
926		wat: &str,
927		input_data: Vec<u8>,
928		ext: E,
929	) -> ExecResult {
930		execute_internal(wat, input_data, ext, &ExportedFunction::Constructor, false, true)
931	}
932
933	const CODE_TRANSFER: &str = r#"
934(module
935	;; seal_transfer(
936	;;    account_ptr: u32,
937	;;    account_len: u32,
938	;;    value_ptr: u32,
939	;;    value_len: u32,
940	;;) -> u32
941	(import "seal0" "seal_transfer" (func $seal_transfer (param i32 i32 i32 i32) (result i32)))
942	(import "env" "memory" (memory 1 1))
943	(func (export "call")
944		(drop
945			(call $seal_transfer
946				(i32.const 4)  ;; Pointer to "account" address.
947				(i32.const 32)  ;; Length of "account" address.
948				(i32.const 36) ;; Pointer to the buffer with value to transfer
949				(i32.const 8)  ;; Length of the buffer with value to transfer.
950			)
951		)
952	)
953	(func (export "deploy"))
954
955	;; Destination AccountId (ALICE)
956	(data (i32.const 4)
957		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
958		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
959	)
960
961	;; Amount of value to transfer.
962	;; Represented by u64 (8 bytes long) in little endian.
963	(data (i32.const 36) "\99\00\00\00\00\00\00\00")
964)
965"#;
966
967	#[test]
968	fn contract_transfer() {
969		let mut mock_ext = MockExt::default();
970		assert_ok!(execute(CODE_TRANSFER, vec![], &mut mock_ext));
971
972		assert_eq!(&mock_ext.transfers, &[TransferEntry { to: ALICE, value: 153 }]);
973	}
974
975	const CODE_CALL: &str = r#"
976(module
977	;; seal_call(
978	;;    callee_ptr: u32,
979	;;    callee_len: u32,
980	;;    gas: u64,
981	;;    value_ptr: u32,
982	;;    value_len: u32,
983	;;    input_data_ptr: u32,
984	;;    input_data_len: u32,
985	;;    output_ptr: u32,
986	;;    output_len_ptr: u32
987	;;) -> u32
988	(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
989	(import "env" "memory" (memory 1 1))
990	(func (export "call")
991		(drop
992			(call $seal_call
993				(i32.const 4)  ;; Pointer to "callee" address.
994				(i32.const 32)  ;; Length of "callee" address.
995				(i64.const 0)  ;; How much gas to devote for the execution. 0 = all.
996				(i32.const 36) ;; Pointer to the buffer with value to transfer
997				(i32.const 8)  ;; Length of the buffer with value to transfer.
998				(i32.const 44) ;; Pointer to input data buffer address
999				(i32.const 4)  ;; Length of input data buffer
1000				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1001				(i32.const 0) ;; Length is ignored in this case
1002			)
1003		)
1004	)
1005	(func (export "deploy"))
1006
1007	;; Destination AccountId (ALICE)
1008	(data (i32.const 4)
1009		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1010		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1011	)
1012
1013	;; Amount of value to transfer.
1014	;; Represented by u64 (8 bytes long) in little endian.
1015	(data (i32.const 36) "\06\00\00\00\00\00\00\00")
1016
1017	(data (i32.const 44) "\01\02\03\04")
1018)
1019"#;
1020
1021	#[test]
1022	fn contract_call() {
1023		let mut mock_ext = MockExt::default();
1024		assert_ok!(execute(CODE_CALL, vec![], &mut mock_ext));
1025
1026		assert_eq!(
1027			&mock_ext.calls,
1028			&[CallEntry {
1029				to: ALICE,
1030				value: 6,
1031				data: vec![1, 2, 3, 4],
1032				allows_reentry: true,
1033				read_only: false
1034			}]
1035		);
1036	}
1037
1038	#[test]
1039	fn contract_delegate_call() {
1040		const CODE: &str = r#"
1041(module
1042	;; seal_delegate_call(
1043	;;    flags: u32,
1044	;;    code_hash_ptr: u32,
1045	;;    input_data_ptr: u32,
1046	;;    input_data_len: u32,
1047	;;    output_ptr: u32,
1048	;;    output_len_ptr: u32
1049	;;) -> u32
1050	(import "seal0" "seal_delegate_call" (func $seal_delegate_call (param i32 i32 i32 i32 i32 i32) (result i32)))
1051	(import "env" "memory" (memory 1 1))
1052	(func (export "call")
1053		(drop
1054			(call $seal_delegate_call
1055				(i32.const 0) ;; No flags are set
1056				(i32.const 4)  ;; Pointer to "callee" code_hash.
1057				(i32.const 36) ;; Pointer to input data buffer address
1058				(i32.const 4)  ;; Length of input data buffer
1059				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1060				(i32.const 0) ;; Length is ignored in this case
1061			)
1062		)
1063	)
1064	(func (export "deploy"))
1065
1066	;; Callee code_hash
1067	(data (i32.const 4)
1068		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
1069		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
1070	)
1071
1072	(data (i32.const 36) "\01\02\03\04")
1073)
1074"#;
1075		let mut mock_ext = MockExt::default();
1076		assert_ok!(execute(CODE, vec![], &mut mock_ext));
1077
1078		assert_eq!(
1079			&mock_ext.code_calls,
1080			&[CallCodeEntry { code_hash: [0x11; 32].into(), data: vec![1, 2, 3, 4] }]
1081		);
1082	}
1083
1084	#[test]
1085	fn contract_call_forward_input() {
1086		const CODE: &str = r#"
1087(module
1088	(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
1089	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
1090	(import "env" "memory" (memory 1 1))
1091	(func (export "call")
1092		(drop
1093			(call $seal_call
1094				(i32.const 1) ;; Set FORWARD_INPUT bit
1095				(i32.const 4)  ;; Pointer to "callee" address.
1096				(i64.const 0)  ;; How much gas to devote for the execution. 0 = all.
1097				(i32.const 36) ;; Pointer to the buffer with value to transfer
1098				(i32.const 44) ;; Pointer to input data buffer address
1099				(i32.const 4)  ;; Length of input data buffer
1100				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1101				(i32.const 0) ;; Length is ignored in this case
1102			)
1103		)
1104
1105		;; triggers a trap because we already forwarded the input
1106		(call $seal_input (i32.const 1) (i32.const 44))
1107	)
1108
1109	(func (export "deploy"))
1110
1111	;; Destination AccountId (ALICE)
1112	(data (i32.const 4)
1113		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1114		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1115	)
1116
1117	;; Amount of value to transfer.
1118	;; Represented by u64 (8 bytes long) in little endian.
1119	(data (i32.const 36) "\2A\00\00\00\00\00\00\00")
1120
1121	;; The input is ignored because we forward our own input
1122	(data (i32.const 44) "\01\02\03\04")
1123)
1124"#;
1125		let mut mock_ext = MockExt::default();
1126		let input = vec![0xff, 0x2a, 0x99, 0x88];
1127		assert_err!(execute(CODE, input.clone(), &mut mock_ext), <Error<Test>>::InputForwarded,);
1128
1129		assert_eq!(
1130			&mock_ext.calls,
1131			&[CallEntry {
1132				to: ALICE,
1133				value: 0x2a,
1134				data: input,
1135				allows_reentry: false,
1136				read_only: false
1137			}]
1138		);
1139	}
1140
1141	#[test]
1142	fn contract_call_clone_input() {
1143		const CODE: &str = r#"
1144(module
1145	(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
1146	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
1147	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
1148	(import "env" "memory" (memory 1 1))
1149	(func (export "call")
1150		(drop
1151			(call $seal_call
1152				(i32.const 11) ;; Set FORWARD_INPUT | CLONE_INPUT | ALLOW_REENTRY bits
1153				(i32.const 4)  ;; Pointer to "callee" address.
1154				(i64.const 0)  ;; How much gas to devote for the execution. 0 = all.
1155				(i32.const 36) ;; Pointer to the buffer with value to transfer
1156				(i32.const 44) ;; Pointer to input data buffer address
1157				(i32.const 4)  ;; Length of input data buffer
1158				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1159				(i32.const 0) ;; Length is ignored in this case
1160			)
1161		)
1162
1163		;; works because the input was cloned
1164		(call $seal_input (i32.const 0) (i32.const 44))
1165
1166		;; return the input to caller for inspection
1167		(call $seal_return (i32.const 0) (i32.const 0) (i32.load (i32.const 44)))
1168	)
1169
1170	(func (export "deploy"))
1171
1172	;; Destination AccountId (ALICE)
1173	(data (i32.const 4)
1174		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1175		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1176	)
1177
1178	;; Amount of value to transfer.
1179	;; Represented by u64 (8 bytes long) in little endian.
1180	(data (i32.const 36) "\2A\00\00\00\00\00\00\00")
1181
1182	;; The input is ignored because we forward our own input
1183	(data (i32.const 44) "\01\02\03\04")
1184)
1185"#;
1186		let mut mock_ext = MockExt::default();
1187		let input = vec![0xff, 0x2a, 0x99, 0x88];
1188		let result = execute(CODE, input.clone(), &mut mock_ext).unwrap();
1189		assert_eq!(result.data, input);
1190		assert_eq!(
1191			&mock_ext.calls,
1192			&[CallEntry {
1193				to: ALICE,
1194				value: 0x2a,
1195				data: input,
1196				allows_reentry: true,
1197				read_only: false
1198			}]
1199		);
1200	}
1201
1202	#[test]
1203	fn contract_call_tail_call() {
1204		const CODE: &str = r#"
1205(module
1206	(import "seal1" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32) (result i32)))
1207	(import "env" "memory" (memory 1 1))
1208	(func (export "call")
1209		(drop
1210			(call $seal_call
1211				(i32.const 5) ;; Set FORWARD_INPUT | TAIL_CALL bit
1212				(i32.const 4)  ;; Pointer to "callee" address.
1213				(i64.const 0)  ;; How much gas to devote for the execution. 0 = all.
1214				(i32.const 36) ;; Pointer to the buffer with value to transfer
1215				(i32.const 0) ;; Pointer to input data buffer address
1216				(i32.const 0)  ;; Length of input data buffer
1217				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1218				(i32.const 0) ;; Length is ignored in this case
1219			)
1220		)
1221
1222		;; a tail call never returns
1223		(unreachable)
1224	)
1225
1226	(func (export "deploy"))
1227
1228	;; Destination AccountId (ALICE)
1229	(data (i32.const 4)
1230		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1231		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1232	)
1233
1234	;; Amount of value to transfer.
1235	;; Represented by u64 (8 bytes long) in little endian.
1236	(data (i32.const 36) "\2A\00\00\00\00\00\00\00")
1237)
1238"#;
1239		let mut mock_ext = MockExt::default();
1240		let input = vec![0xff, 0x2a, 0x99, 0x88];
1241		let result = execute(CODE, input.clone(), &mut mock_ext).unwrap();
1242		assert_eq!(result.data, call_return_data());
1243		assert_eq!(
1244			&mock_ext.calls,
1245			&[CallEntry {
1246				to: ALICE,
1247				value: 0x2a,
1248				data: input,
1249				allows_reentry: false,
1250				read_only: false
1251			}]
1252		);
1253	}
1254
1255	#[test]
1256	fn contains_storage_works() {
1257		const CODE: &str = r#"
1258(module
1259	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
1260	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
1261	(import "seal1" "contains_storage" (func $contains_storage (param i32 i32) (result i32)))
1262	(import "env" "memory" (memory 1 1))
1263
1264
1265	;; size of input buffer
1266	;; [0, 4) size of input buffer (128+32 = 160 bytes = 0xA0)
1267	(data (i32.const 0) "\A0")
1268
1269	;; [4, 164) input buffer
1270
1271	(func (export "call")
1272		;; Receive key
1273		(call $seal_input
1274			(i32.const 4)	;; Where we take input and store it
1275			(i32.const 0)	;; Where we take and store the length of the data
1276		)
1277		;; Call seal_clear_storage and save what it returns at 0
1278		(i32.store (i32.const 0)
1279			(call $contains_storage
1280				(i32.const 8)			;; key_ptr
1281				(i32.load (i32.const 4))	;; key_len
1282			)
1283		)
1284		(call $seal_return
1285			(i32.const 0)	;; flags
1286			(i32.const 0)	;; returned value
1287			(i32.const 4)	;; length of returned value
1288		)
1289	)
1290
1291	(func (export "deploy"))
1292)
1293"#;
1294
1295		let mut ext = MockExt::default();
1296		ext.set_storage(
1297			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
1298			Some(vec![42u8]),
1299			false,
1300		)
1301		.unwrap();
1302		ext.set_storage(
1303			&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap(),
1304			Some(vec![]),
1305			false,
1306		)
1307		.unwrap();
1308
1309		// value does not exist (wrong key length)
1310		let input = (63, [1u8; 64]).encode();
1311		let result = execute(CODE, input, &mut ext).unwrap();
1312		// sentinel returned
1313		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
1314
1315		// value exists
1316		let input = (64, [1u8; 64]).encode();
1317		let result = execute(CODE, input, &mut ext).unwrap();
1318		// true as u32 returned
1319		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 1);
1320		// getter does not remove the value from storage
1321		assert_eq!(ext.storage.get(&[1u8; 64].to_vec()).unwrap(), &[42u8]);
1322
1323		// value exists (test for 0 sized)
1324		let input = (19, [2u8; 19]).encode();
1325		let result = execute(CODE, input, &mut ext).unwrap();
1326		// true as u32 returned
1327		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0);
1328		// getter does not remove the value from storage
1329		assert_eq!(ext.storage.get(&[2u8; 19].to_vec()).unwrap(), &([] as [u8; 0]));
1330	}
1331
1332	const CODE_INSTANTIATE: &str = r#"
1333(module
1334	;; seal_instantiate(
1335	;;     code_ptr: u32,
1336	;;     code_len: u32,
1337	;;     gas: u64,
1338	;;     value_ptr: u32,
1339	;;     value_len: u32,
1340	;;     input_data_ptr: u32,
1341	;;     input_data_len: u32,
1342	;;     input_data_len: u32,
1343	;;     address_ptr: u32,
1344	;;     address_len_ptr: u32,
1345	;;     output_ptr: u32,
1346	;;     output_len_ptr: u32
1347	;; ) -> u32
1348	(import "seal0" "seal_instantiate" (func $seal_instantiate
1349		(param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
1350	))
1351	(import "env" "memory" (memory 1 1))
1352	(func (export "call")
1353		(drop
1354			(call $seal_instantiate
1355				(i32.const 16)   ;; Pointer to `code_hash`
1356				(i32.const 32)   ;; Length of `code_hash`
1357				(i64.const 0)    ;; How much gas to devote for the execution. 0 = all.
1358				(i32.const 4)    ;; Pointer to the buffer with value to transfer
1359				(i32.const 8)    ;; Length of the buffer with value to transfer
1360				(i32.const 12)   ;; Pointer to input data buffer address
1361				(i32.const 4)    ;; Length of input data buffer
1362				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy address
1363				(i32.const 0) ;; Length is ignored in this case
1364				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1365				(i32.const 0) ;; Length is ignored in this case
1366				(i32.const 0) ;; salt_ptr
1367				(i32.const 4) ;; salt_len
1368			)
1369		)
1370	)
1371	(func (export "deploy"))
1372
1373	;; Salt
1374	(data (i32.const 0) "\42\43\44\45")
1375	;; Amount of value to transfer.
1376	;; Represented by u64 (8 bytes long) in little endian.
1377	(data (i32.const 4) "\03\00\00\00\00\00\00\00")
1378	;; Input data to pass to the contract being instantiated.
1379	(data (i32.const 12) "\01\02\03\04")
1380	;; Hash of code.
1381	(data (i32.const 16)
1382		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
1383		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
1384	)
1385)
1386"#;
1387
1388	#[test]
1389	fn contract_instantiate() {
1390		let mut mock_ext = MockExt::default();
1391		assert_ok!(execute(CODE_INSTANTIATE, vec![], &mut mock_ext));
1392
1393		assert_matches!(
1394			&mock_ext.instantiates[..],
1395			[InstantiateEntry {
1396				code_hash,
1397				value: 3,
1398				data,
1399				gas_left: _,
1400				salt,
1401			}] if
1402				code_hash == &[0x11; 32].into() &&
1403				data == &vec![1, 2, 3, 4] &&
1404				salt == &vec![0x42, 0x43, 0x44, 0x45]
1405		);
1406	}
1407
1408	const CODE_TERMINATE: &str = r#"
1409(module
1410	;; seal_terminate(
1411	;;     beneficiary_ptr: u32,
1412	;;     beneficiary_len: u32,
1413	;; )
1414	(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
1415	(import "env" "memory" (memory 1 1))
1416	(func (export "call")
1417		(call $seal_terminate
1418			(i32.const 4)  ;; Pointer to "beneficiary" address.
1419			(i32.const 32)  ;; Length of "beneficiary" address.
1420		)
1421	)
1422	(func (export "deploy"))
1423
1424	;; Beneficiary AccountId to transfer the funds.
1425	(data (i32.const 4)
1426		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1427		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1428	)
1429)
1430"#;
1431
1432	#[test]
1433	fn contract_terminate() {
1434		let mut mock_ext = MockExt::default();
1435		execute(CODE_TERMINATE, vec![], &mut mock_ext).unwrap();
1436
1437		assert_eq!(&mock_ext.terminations, &[TerminationEntry { beneficiary: ALICE }]);
1438	}
1439
1440	const CODE_TRANSFER_LIMITED_GAS: &str = r#"
1441(module
1442	;; seal_call(
1443	;;    callee_ptr: u32,
1444	;;    callee_len: u32,
1445	;;    gas: u64,
1446	;;    value_ptr: u32,
1447	;;    value_len: u32,
1448	;;    input_data_ptr: u32,
1449	;;    input_data_len: u32,
1450	;;    output_ptr: u32,
1451	;;    output_len_ptr: u32
1452	;;) -> u32
1453	(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
1454	(import "env" "memory" (memory 1 1))
1455	(func (export "call")
1456		(drop
1457			(call $seal_call
1458				(i32.const 4)  ;; Pointer to "callee" address.
1459				(i32.const 32)  ;; Length of "callee" address.
1460				(i64.const 228)  ;; How much gas to devote for the execution.
1461				(i32.const 36)  ;; Pointer to the buffer with value to transfer
1462				(i32.const 8)   ;; Length of the buffer with value to transfer.
1463				(i32.const 44)   ;; Pointer to input data buffer address
1464				(i32.const 4)   ;; Length of input data buffer
1465				(i32.const 4294967295) ;; u32 max value is the sentinel value: do not copy output
1466				(i32.const 0) ;; Length is ignored in this cas
1467			)
1468		)
1469	)
1470	(func (export "deploy"))
1471
1472	;; Destination AccountId to transfer the funds.
1473	(data (i32.const 4)
1474		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1475		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1476	)
1477	;; Amount of value to transfer.
1478	;; Represented by u64 (8 bytes long) in little endian.
1479	(data (i32.const 36) "\06\00\00\00\00\00\00\00")
1480
1481	(data (i32.const 44) "\01\02\03\04")
1482)
1483"#;
1484
1485	#[test]
1486	fn contract_call_limited_gas() {
1487		let mut mock_ext = MockExt::default();
1488		assert_ok!(execute(&CODE_TRANSFER_LIMITED_GAS, vec![], &mut mock_ext));
1489
1490		assert_eq!(
1491			&mock_ext.calls,
1492			&[CallEntry {
1493				to: ALICE,
1494				value: 6,
1495				data: vec![1, 2, 3, 4],
1496				allows_reentry: true,
1497				read_only: false
1498			}]
1499		);
1500	}
1501
1502	const CODE_ECDSA_RECOVER: &str = r#"
1503(module
1504	;; seal_ecdsa_recover(
1505	;;    signature_ptr: u32,
1506	;;    message_hash_ptr: u32,
1507	;;    output_ptr: u32
1508	;; ) -> u32
1509	(import "seal0" "seal_ecdsa_recover" (func $seal_ecdsa_recover (param i32 i32 i32) (result i32)))
1510	(import "env" "memory" (memory 1 1))
1511	(func (export "call")
1512		(drop
1513			(call $seal_ecdsa_recover
1514				(i32.const 36) ;; Pointer to signature.
1515				(i32.const 4)  ;; Pointer to message hash.
1516				(i32.const 36) ;; Pointer for output - public key.
1517			)
1518		)
1519	)
1520	(func (export "deploy"))
1521
1522	;; Hash of message.
1523	(data (i32.const 4)
1524		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1525		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1526	)
1527	;; Signature
1528	(data (i32.const 36)
1529		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1530		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1531		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1532		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1533		"\01"
1534	)
1535)
1536"#;
1537
1538	#[test]
1539	fn contract_ecdsa_recover() {
1540		let mut mock_ext = MockExt::default();
1541		assert_ok!(execute(&CODE_ECDSA_RECOVER, vec![], &mut mock_ext));
1542		assert_eq!(mock_ext.ecdsa_recover.into_inner(), [([1; 65], [1; 32])]);
1543	}
1544
1545	#[test]
1546	fn contract_ecdsa_to_eth_address() {
1547		/// calls `seal_ecdsa_to_eth_address` for the constant and ensures the result equals the
1548		/// expected one.
1549		const CODE_ECDSA_TO_ETH_ADDRESS: &str = r#"
1550(module
1551	(import "seal0" "seal_ecdsa_to_eth_address" (func $seal_ecdsa_to_eth_address (param i32 i32) (result i32)))
1552	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
1553	(import "env" "memory" (memory 1 1))
1554
1555	(func (export "call")
1556		;; fill the buffer with the eth address.
1557		(call $seal_ecdsa_to_eth_address (i32.const 0) (i32.const 0))
1558
1559		;; Return the contents of the buffer
1560		(call $seal_return
1561			(i32.const 0)
1562			(i32.const 0)
1563			(i32.const 20)
1564		)
1565
1566		;; seal_return doesn't return, so this is effectively unreachable.
1567		(unreachable)
1568	)
1569	(func (export "deploy"))
1570)
1571"#;
1572
1573		let output = execute(CODE_ECDSA_TO_ETH_ADDRESS, vec![], MockExt::default()).unwrap();
1574		assert_eq!(
1575			output,
1576			ExecReturnValue { flags: ReturnFlags::empty(), data: [0x02; 20].to_vec() }
1577		);
1578	}
1579
1580	#[test]
1581	fn contract_sr25519() {
1582		const CODE_SR25519: &str = r#"
1583(module
1584	(import "seal0" "sr25519_verify" (func $sr25519_verify (param i32 i32 i32 i32) (result i32)))
1585	(import "env" "memory" (memory 1 1))
1586	(func (export "call")
1587		(drop
1588			(call $sr25519_verify
1589				(i32.const 0) ;; Pointer to signature.
1590				(i32.const 64) ;; Pointer to public key.
1591				(i32.const 16) ;; message length.
1592				(i32.const 96) ;; Pointer to message.
1593			)
1594		)
1595	)
1596	(func (export "deploy"))
1597
1598	;; Signature (64 bytes)
1599	(data (i32.const 0)
1600		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1601		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1602		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1603		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1604	)
1605
1606	;;  public key (32 bytes)
1607	(data (i32.const 64)
1608		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1609		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1610	)
1611
1612	;;  message. (16 bytes)
1613	(data (i32.const 96)
1614		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
1615	)
1616)
1617"#;
1618		let mut mock_ext = MockExt::default();
1619		assert_ok!(execute(&CODE_SR25519, vec![], &mut mock_ext));
1620		assert_eq!(mock_ext.sr25519_verify.into_inner(), [([1; 64], [1; 16].to_vec(), [1; 32])]);
1621	}
1622
1623	const CODE_GET_STORAGE: &str = r#"
1624(module
1625	(import "seal0" "seal_get_storage" (func $seal_get_storage (param i32 i32 i32) (result i32)))
1626	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
1627	(import "env" "memory" (memory 1 1))
1628
1629	;; [0, 32) key for get storage
1630	(data (i32.const 0)
1631		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
1632		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
1633	)
1634
1635	;; [32, 36) buffer size = 4k in little endian
1636	(data (i32.const 32) "\00\10")
1637
1638	;; [36; inf) buffer where the result is copied
1639
1640	(func $assert (param i32)
1641		(block $ok
1642			(br_if $ok
1643				(local.get 0)
1644			)
1645			(unreachable)
1646		)
1647	)
1648
1649	(func (export "call")
1650		(local $buf_size i32)
1651
1652		;; Load a storage value into contract memory.
1653		(call $assert
1654			(i32.eq
1655				(call $seal_get_storage
1656					(i32.const 0)		;; The pointer to the storage key to fetch
1657					(i32.const 36)		;; Pointer to the output buffer
1658					(i32.const 32)		;; Pointer to the size of the buffer
1659				)
1660
1661				;; Return value 0 means that the value is found and there were
1662				;; no errors.
1663				(i32.const 0)
1664			)
1665		)
1666
1667		;; Find out the size of the buffer
1668		(local.set $buf_size
1669			(i32.load (i32.const 32))
1670		)
1671
1672		;; Return the contents of the buffer
1673		(call $seal_return
1674			(i32.const 0)
1675			(i32.const 36)
1676			(local.get $buf_size)
1677		)
1678
1679		;; env:seal_return doesn't return, so this is effectively unreachable.
1680		(unreachable)
1681	)
1682
1683	(func (export "deploy"))
1684)
1685"#;
1686
1687	#[test]
1688	fn get_storage_puts_data_into_buf() {
1689		let mut mock_ext = MockExt::default();
1690		mock_ext.storage.insert([0x11; 32].to_vec(), [0x22; 32].to_vec());
1691
1692		let output = execute(CODE_GET_STORAGE, vec![], mock_ext).unwrap();
1693
1694		assert_eq!(
1695			output,
1696			ExecReturnValue { flags: ReturnFlags::empty(), data: [0x22; 32].to_vec() }
1697		);
1698	}
1699
1700	/// calls `seal_caller` and compares the result with the constant (ALICE's address part).
1701	const CODE_CALLER: &str = r#"
1702(module
1703	(import "seal0" "seal_caller" (func $seal_caller (param i32 i32)))
1704	(import "env" "memory" (memory 1 1))
1705
1706	;; size of our buffer is 32 bytes
1707	(data (i32.const 32) "\20")
1708
1709	(func $assert (param i32)
1710		(block $ok
1711			(br_if $ok
1712				(local.get 0)
1713			)
1714			(unreachable)
1715		)
1716	)
1717
1718	(func (export "call")
1719		;; fill the buffer with the caller.
1720		(call $seal_caller (i32.const 0) (i32.const 32))
1721
1722		;; assert len == 32
1723		(call $assert
1724			(i32.eq
1725				(i32.load (i32.const 32))
1726				(i32.const 32)
1727			)
1728		)
1729
1730		;; assert that the first 8 bytes are the beginning of "ALICE"
1731		(call $assert
1732			(i64.eq
1733				(i64.load (i32.const 0))
1734				(i64.const 0x0101010101010101)
1735			)
1736		)
1737	)
1738
1739	(func (export "deploy"))
1740)
1741"#;
1742
1743	#[test]
1744	fn caller() {
1745		assert_ok!(execute(CODE_CALLER, vec![], MockExt::default()));
1746	}
1747
1748	#[test]
1749	fn caller_traps_when_no_account_id() {
1750		let mut ext = MockExt::default();
1751		ext.caller = Origin::Root;
1752		assert_eq!(
1753			execute(CODE_CALLER, vec![], ext),
1754			Err(ExecError { error: DispatchError::RootNotAllowed, origin: ErrorOrigin::Caller })
1755		);
1756	}
1757
1758	/// calls `seal_address` and compares the result with the constant (BOB's address part).
1759	const CODE_ADDRESS: &str = r#"
1760(module
1761	(import "seal0" "seal_address" (func $seal_address (param i32 i32)))
1762	(import "env" "memory" (memory 1 1))
1763
1764	;; size of our buffer is 32 bytes
1765	(data (i32.const 32) "\20")
1766
1767	(func $assert (param i32)
1768		(block $ok
1769			(br_if $ok
1770				(local.get 0)
1771			)
1772			(unreachable)
1773		)
1774	)
1775
1776	(func (export "call")
1777		;; fill the buffer with the self address.
1778		(call $seal_address (i32.const 0) (i32.const 32))
1779
1780		;; assert size == 32
1781		(call $assert
1782			(i32.eq
1783				(i32.load (i32.const 32))
1784				(i32.const 32)
1785			)
1786		)
1787
1788		;; assert that the first 8 bytes are the beginning of "BOB"
1789		(call $assert
1790			(i64.eq
1791				(i64.load (i32.const 0))
1792				(i64.const 0x0202020202020202)
1793			)
1794		)
1795	)
1796
1797	(func (export "deploy"))
1798)
1799"#;
1800
1801	#[test]
1802	fn address() {
1803		assert_ok!(execute(CODE_ADDRESS, vec![], MockExt::default()));
1804	}
1805
1806	const CODE_BALANCE: &str = r#"
1807(module
1808	(import "seal0" "seal_balance" (func $seal_balance (param i32 i32)))
1809	(import "env" "memory" (memory 1 1))
1810
1811	;; size of our buffer is 32 bytes
1812	(data (i32.const 32) "\20")
1813
1814	(func $assert (param i32)
1815		(block $ok
1816			(br_if $ok
1817				(local.get 0)
1818			)
1819			(unreachable)
1820		)
1821	)
1822
1823	(func (export "call")
1824		;; This stores the balance in the buffer
1825		(call $seal_balance (i32.const 0) (i32.const 32))
1826
1827		;; assert len == 8
1828		(call $assert
1829			(i32.eq
1830				(i32.load (i32.const 32))
1831				(i32.const 8)
1832			)
1833		)
1834
1835		;; assert that contents of the buffer is equal to the i64 value of 228.
1836		(call $assert
1837			(i64.eq
1838				(i64.load (i32.const 0))
1839				(i64.const 228)
1840			)
1841		)
1842	)
1843	(func (export "deploy"))
1844)
1845"#;
1846
1847	#[test]
1848	fn balance() {
1849		assert_ok!(execute(CODE_BALANCE, vec![], MockExt::default()));
1850	}
1851
1852	const CODE_GAS_PRICE: &str = r#"
1853(module
1854	(import "seal1" "weight_to_fee" (func $seal_weight_to_fee (param i64 i64 i32 i32)))
1855	(import "env" "memory" (memory 1 1))
1856
1857	;; size of our buffer is 32 bytes
1858	(data (i32.const 32) "\20")
1859
1860	(func $assert (param i32)
1861		(block $ok
1862			(br_if $ok
1863				(local.get 0)
1864			)
1865			(unreachable)
1866		)
1867	)
1868
1869	(func (export "call")
1870		;; This stores the gas price in the buffer
1871		(call $seal_weight_to_fee (i64.const 2) (i64.const 1) (i32.const 0) (i32.const 32))
1872
1873		;; assert len == 8
1874		(call $assert
1875			(i32.eq
1876				(i32.load (i32.const 32))
1877				(i32.const 8)
1878			)
1879		)
1880
1881		;; assert that contents of the buffer is equal to the i64 value of 2 * 1312 + 103 = 2727.
1882		(call $assert
1883			(i64.eq
1884				(i64.load (i32.const 0))
1885				(i64.const 2727)
1886			)
1887		)
1888	)
1889	(func (export "deploy"))
1890)
1891"#;
1892
1893	#[test]
1894	fn gas_price() {
1895		assert_ok!(execute(CODE_GAS_PRICE, vec![], MockExt::default()));
1896	}
1897
1898	const CODE_GAS_LEFT: &str = r#"
1899(module
1900	(import "seal1" "gas_left" (func $seal_gas_left (param i32 i32)))
1901	(import "seal0" "clear_storage" (func $clear_storage (param i32)))
1902	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
1903	(import "env" "memory" (memory 1 1))
1904
1905	;; Make output buffer size 20 bytes
1906	(data (i32.const 20) "\14")
1907
1908	(func $assert (param i32)
1909		(block $ok
1910			(br_if $ok
1911				(local.get 0)
1912			)
1913			(unreachable)
1914		)
1915	)
1916
1917	(func (export "call")
1918		;; Burn some PoV, clear_storage consumes some PoV as in order to clear the storage we need to we need to read its size first.
1919		(call $clear_storage (i32.const 0))
1920
1921		;; This stores the weight left to the buffer
1922		(call $seal_gas_left (i32.const 0) (i32.const 20))
1923
1924		;; Assert len <= 16 (max encoded Weight len)
1925		(call $assert
1926			(i32.le_u
1927				(i32.load (i32.const 20))
1928				(i32.const 16)
1929			)
1930		)
1931
1932		;; Burn some PoV, clear_storage consumes some PoV as in order to clear the storage we need to we need to read its size first.
1933		(call $clear_storage (i32.const 0))
1934
1935		;; Return weight left and its encoded value len
1936		(call $seal_return (i32.const 0) (i32.const 0) (i32.load (i32.const 20)))
1937
1938		(unreachable)
1939	)
1940	(func (export "deploy"))
1941)
1942"#;
1943
1944	#[test]
1945	fn gas_left() {
1946		let mut ext = MockExt::default();
1947		let gas_limit = ext.gas_meter.gas_left();
1948
1949		let output = execute(CODE_GAS_LEFT, vec![], &mut ext).unwrap();
1950
1951		let weight_left = Weight::decode(&mut &*output.data).unwrap();
1952		let actual_left = ext.gas_meter.gas_left();
1953
1954		assert!(weight_left.all_lt(gas_limit), "gas_left must be less than initial");
1955		assert!(weight_left.all_gt(actual_left), "gas_left must be greater than final");
1956	}
1957
1958	const CODE_VALUE_TRANSFERRED: &str = r#"
1959(module
1960	(import "seal0" "seal_value_transferred" (func $seal_value_transferred (param i32 i32)))
1961	(import "env" "memory" (memory 1 1))
1962
1963	;; size of our buffer is 32 bytes
1964	(data (i32.const 32) "\20")
1965
1966	(func $assert (param i32)
1967		(block $ok
1968			(br_if $ok
1969				(local.get 0)
1970			)
1971			(unreachable)
1972		)
1973	)
1974
1975	(func (export "call")
1976		;; This stores the value transferred in the buffer
1977		(call $seal_value_transferred (i32.const 0) (i32.const 32))
1978
1979		;; assert len == 8
1980		(call $assert
1981			(i32.eq
1982				(i32.load (i32.const 32))
1983				(i32.const 8)
1984			)
1985		)
1986
1987		;; assert that contents of the buffer is equal to the i64 value of 1337.
1988		(call $assert
1989			(i64.eq
1990				(i64.load (i32.const 0))
1991				(i64.const 1337)
1992			)
1993		)
1994	)
1995	(func (export "deploy"))
1996)
1997"#;
1998
1999	#[test]
2000	fn value_transferred() {
2001		assert_ok!(execute(CODE_VALUE_TRANSFERRED, vec![], MockExt::default()));
2002	}
2003
2004	const START_FN_DOES_RUN: &str = r#"
2005(module
2006	(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
2007	(import "env" "memory" (memory 1 1))
2008
2009	(start $start)
2010	(func $start
2011		(call $seal_deposit_event
2012			(i32.const 0) ;; Pointer to the start of topics buffer
2013			(i32.const 0) ;; The length of the topics buffer.
2014			(i32.const 0) ;; Pointer to the start of the data buffer
2015			(i32.const 13) ;; Length of the buffer
2016		)
2017	)
2018
2019	(func (export "call"))
2020
2021	(func (export "deploy"))
2022
2023	(data (i32.const 0) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
2024)
2025"#;
2026
2027	#[test]
2028	fn start_fn_does_run_on_call() {
2029		let mut ext = MockExt::default();
2030		execute(START_FN_DOES_RUN, vec![], &mut ext).unwrap();
2031		assert_eq!(
2032			ext.events[0].1,
2033			[0x00_u8, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
2034		);
2035	}
2036
2037	#[test]
2038	fn start_fn_does_run_on_deploy() {
2039		let mut ext = MockExt::default();
2040		execute_instantiate(START_FN_DOES_RUN, vec![], &mut ext).unwrap();
2041		assert_eq!(
2042			ext.events[0].1,
2043			[0x00_u8, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
2044		);
2045	}
2046
2047	const CODE_TIMESTAMP_NOW: &str = r#"
2048(module
2049	(import "seal0" "seal_now" (func $seal_now (param i32 i32)))
2050	(import "env" "memory" (memory 1 1))
2051
2052	;; size of our buffer is 32 bytes
2053	(data (i32.const 32) "\20")
2054
2055	(func $assert (param i32)
2056		(block $ok
2057			(br_if $ok
2058				(local.get 0)
2059			)
2060			(unreachable)
2061		)
2062	)
2063
2064	(func (export "call")
2065		;; This stores the block timestamp in the buffer
2066		(call $seal_now (i32.const 0) (i32.const 32))
2067
2068		;; assert len == 8
2069		(call $assert
2070			(i32.eq
2071				(i32.load (i32.const 32))
2072				(i32.const 8)
2073			)
2074		)
2075
2076		;; assert that contents of the buffer is equal to the i64 value of 1111.
2077		(call $assert
2078			(i64.eq
2079				(i64.load (i32.const 0))
2080				(i64.const 1111)
2081			)
2082		)
2083	)
2084	(func (export "deploy"))
2085)
2086"#;
2087
2088	const CODE_TIMESTAMP_NOW_UNPREFIXED: &str = r#"
2089(module
2090	(import "seal0" "now" (func $now (param i32 i32)))
2091	(import "env" "memory" (memory 1 1))
2092
2093	;; size of our buffer is 32 bytes
2094	(data (i32.const 32) "\20")
2095
2096	(func $assert (param i32)
2097		(block $ok
2098			(br_if $ok
2099				(local.get 0)
2100			)
2101			(unreachable)
2102		)
2103	)
2104
2105	(func (export "call")
2106		;; This stores the block timestamp in the buffer
2107		(call $now (i32.const 0) (i32.const 32))
2108
2109		;; assert len == 8
2110		(call $assert
2111			(i32.eq
2112				(i32.load (i32.const 32))
2113				(i32.const 8)
2114			)
2115		)
2116
2117		;; assert that contents of the buffer is equal to the i64 value of 1111.
2118		(call $assert
2119			(i64.eq
2120				(i64.load (i32.const 0))
2121				(i64.const 1111)
2122			)
2123		)
2124	)
2125	(func (export "deploy"))
2126)
2127"#;
2128
2129	#[test]
2130	fn now() {
2131		assert_ok!(execute(CODE_TIMESTAMP_NOW, vec![], MockExt::default()));
2132		assert_ok!(execute(CODE_TIMESTAMP_NOW_UNPREFIXED, vec![], MockExt::default()));
2133	}
2134
2135	const CODE_MINIMUM_BALANCE: &str = r#"
2136(module
2137	(import "seal0" "seal_minimum_balance" (func $seal_minimum_balance (param i32 i32)))
2138	(import "env" "memory" (memory 1 1))
2139
2140	;; size of our buffer is 32 bytes
2141	(data (i32.const 32) "\20")
2142
2143	(func $assert (param i32)
2144		(block $ok
2145			(br_if $ok
2146				(local.get 0)
2147			)
2148			(unreachable)
2149		)
2150	)
2151
2152	(func (export "call")
2153		(call $seal_minimum_balance (i32.const 0) (i32.const 32))
2154
2155		;; assert len == 8
2156		(call $assert
2157			(i32.eq
2158				(i32.load (i32.const 32))
2159				(i32.const 8)
2160			)
2161		)
2162
2163		;; assert that contents of the buffer is equal to the i64 value of 666.
2164		(call $assert
2165			(i64.eq
2166				(i64.load (i32.const 0))
2167				(i64.const 666)
2168			)
2169		)
2170	)
2171	(func (export "deploy"))
2172)
2173"#;
2174
2175	#[test]
2176	fn minimum_balance() {
2177		assert_ok!(execute(CODE_MINIMUM_BALANCE, vec![], MockExt::default()));
2178	}
2179
2180	const CODE_RANDOM: &str = r#"
2181(module
2182	(import "seal0" "seal_random" (func $seal_random (param i32 i32 i32 i32)))
2183	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2184	(import "env" "memory" (memory 1 1))
2185
2186	;; [0,128) is reserved for the result of PRNG.
2187
2188	;; the subject used for the PRNG. [128,160)
2189	(data (i32.const 128)
2190		"\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F"
2191		"\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F"
2192	)
2193
2194	;; size of our buffer is 128 bytes
2195	(data (i32.const 160) "\80")
2196
2197	(func $assert (param i32)
2198		(block $ok
2199			(br_if $ok
2200				(local.get 0)
2201			)
2202			(unreachable)
2203		)
2204	)
2205
2206	(func (export "call")
2207		;; This stores the block random seed in the buffer
2208		(call $seal_random
2209			(i32.const 128) ;; Pointer in memory to the start of the subject buffer
2210			(i32.const 32) ;; The subject buffer's length
2211			(i32.const 0) ;; Pointer to the output buffer
2212			(i32.const 160) ;; Pointer to the output buffer length
2213		)
2214
2215		;; assert len == 32
2216		(call $assert
2217			(i32.eq
2218				(i32.load (i32.const 160))
2219				(i32.const 32)
2220			)
2221		)
2222
2223		;; return the random data
2224		(call $seal_return
2225			(i32.const 0)
2226			(i32.const 0)
2227			(i32.const 32)
2228		)
2229	)
2230	(func (export "deploy"))
2231)
2232"#;
2233
2234	#[test]
2235	fn random() {
2236		let output = execute_unvalidated(CODE_RANDOM, vec![], MockExt::default()).unwrap();
2237
2238		// The mock ext just returns the same data that was passed as the subject.
2239		assert_eq!(
2240			output,
2241			ExecReturnValue {
2242				flags: ReturnFlags::empty(),
2243				data: array_bytes::hex_into_unchecked(
2244					"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
2245				)
2246			},
2247		);
2248	}
2249
2250	const CODE_RANDOM_V1: &str = r#"
2251(module
2252	(import "seal1" "seal_random" (func $seal_random (param i32 i32 i32 i32)))
2253	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2254	(import "env" "memory" (memory 1 1))
2255
2256	;; [0,128) is reserved for the result of PRNG.
2257
2258	;; the subject used for the PRNG. [128,160)
2259	(data (i32.const 128)
2260		"\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F"
2261		"\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F"
2262	)
2263
2264	;; size of our buffer is 128 bytes
2265	(data (i32.const 160) "\80")
2266
2267	(func $assert (param i32)
2268		(block $ok
2269			(br_if $ok
2270				(local.get 0)
2271			)
2272			(unreachable)
2273		)
2274	)
2275
2276	(func (export "call")
2277		;; This stores the block random seed in the buffer
2278		(call $seal_random
2279			(i32.const 128) ;; Pointer in memory to the start of the subject buffer
2280			(i32.const 32) ;; The subject buffer's length
2281			(i32.const 0) ;; Pointer to the output buffer
2282			(i32.const 160) ;; Pointer to the output buffer length
2283		)
2284
2285		;; assert len == 32
2286		(call $assert
2287			(i32.eq
2288				(i32.load (i32.const 160))
2289				(i32.const 40)
2290			)
2291		)
2292
2293		;; return the random data
2294		(call $seal_return
2295			(i32.const 0)
2296			(i32.const 0)
2297			(i32.const 40)
2298		)
2299	)
2300	(func (export "deploy"))
2301)
2302"#;
2303
2304	#[test]
2305	fn random_v1() {
2306		let output = execute_unvalidated(CODE_RANDOM_V1, vec![], MockExt::default()).unwrap();
2307
2308		// The mock ext just returns the same data that was passed as the subject.
2309		assert_eq!(
2310			output,
2311			ExecReturnValue {
2312				flags: ReturnFlags::empty(),
2313				data: (
2314					array_bytes::hex2array_unchecked::<_, 32>(
2315						"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
2316					),
2317					42u64,
2318				)
2319					.encode()
2320			},
2321		);
2322	}
2323
2324	const CODE_DEPOSIT_EVENT: &str = r#"
2325(module
2326	(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
2327	(import "env" "memory" (memory 1 1))
2328
2329	(func (export "call")
2330		(call $seal_deposit_event
2331			(i32.const 32) ;; Pointer to the start of topics buffer
2332			(i32.const 33) ;; The length of the topics buffer.
2333			(i32.const 8) ;; Pointer to the start of the data buffer
2334			(i32.const 13) ;; Length of the buffer
2335		)
2336	)
2337	(func (export "deploy"))
2338
2339	(data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
2340
2341	;; Encoded Vec<TopicOf<T>>, the buffer has length of 33 bytes.
2342	(data (i32.const 32) "\04\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33"
2343	"\33\33\33\33\33\33\33\33\33")
2344)
2345"#;
2346
2347	#[test]
2348	fn deposit_event() {
2349		let mut mock_ext = MockExt::default();
2350		assert_ok!(execute(CODE_DEPOSIT_EVENT, vec![], &mut mock_ext));
2351
2352		assert_eq!(
2353			mock_ext.events,
2354			vec![(
2355				vec![H256::repeat_byte(0x33)],
2356				vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
2357			)]
2358		);
2359
2360		assert!(mock_ext.gas_meter.gas_left().ref_time() > 0);
2361	}
2362
2363	const CODE_DEPOSIT_EVENT_DUPLICATES: &str = r#"
2364(module
2365	(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
2366	(import "env" "memory" (memory 1 1))
2367
2368	(func (export "call")
2369		(call $seal_deposit_event
2370			(i32.const 32) ;; Pointer to the start of topics buffer
2371			(i32.const 129) ;; The length of the topics buffer.
2372			(i32.const 8) ;; Pointer to the start of the data buffer
2373			(i32.const 13) ;; Length of the buffer
2374		)
2375	)
2376	(func (export "deploy"))
2377
2378	(data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
2379
2380	;; Encoded Vec<TopicOf<T>>, the buffer has length of 129 bytes.
2381	(data (i32.const 32) "\10"
2382"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
2383"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"
2384"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
2385"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04")
2386)
2387"#;
2388
2389	/// Checks that the runtime allows duplicate topics.
2390	#[test]
2391	fn deposit_event_duplicates_allowed() {
2392		let mut mock_ext = MockExt::default();
2393		assert_ok!(execute(CODE_DEPOSIT_EVENT_DUPLICATES, vec![], &mut mock_ext,));
2394
2395		assert_eq!(
2396			mock_ext.events,
2397			vec![(
2398				vec![
2399					H256::repeat_byte(0x01),
2400					H256::repeat_byte(0x02),
2401					H256::repeat_byte(0x01),
2402					H256::repeat_byte(0x04)
2403				],
2404				vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
2405			)]
2406		);
2407	}
2408
2409	const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#"
2410(module
2411	(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
2412	(import "env" "memory" (memory 1 1))
2413
2414	(func (export "call")
2415		(call $seal_deposit_event
2416			(i32.const 32) ;; Pointer to the start of topics buffer
2417			(i32.const 161) ;; The length of the topics buffer.
2418			(i32.const 8) ;; Pointer to the start of the data buffer
2419			(i32.const 13) ;; Length of the buffer
2420		)
2421	)
2422	(func (export "deploy"))
2423
2424	(data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00")
2425
2426	;; Encoded Vec<TopicOf<T>>, the buffer has length of 161 bytes.
2427	(data (i32.const 32) "\14"
2428"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
2429"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"
2430"\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03"
2431"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04"
2432"\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05")
2433)
2434"#;
2435
2436	/// Checks that the runtime traps if there are more than `max_topic_events` topics.
2437	#[test]
2438	fn deposit_event_max_topics() {
2439		assert_eq!(
2440			execute(CODE_DEPOSIT_EVENT_MAX_TOPICS, vec![], MockExt::default(),),
2441			Err(ExecError {
2442				error: Error::<Test>::TooManyTopics.into(),
2443				origin: ErrorOrigin::Caller,
2444			})
2445		);
2446	}
2447
2448	/// calls `seal_block_number` compares the result with the constant 121.
2449	const CODE_BLOCK_NUMBER: &str = r#"
2450(module
2451	(import "seal0" "seal_block_number" (func $seal_block_number (param i32 i32)))
2452	(import "env" "memory" (memory 1 1))
2453
2454	;; size of our buffer is 32 bytes
2455	(data (i32.const 32) "\20")
2456
2457	(func $assert (param i32)
2458		(block $ok
2459			(br_if $ok
2460				(local.get 0)
2461			)
2462			(unreachable)
2463		)
2464	)
2465
2466	(func (export "call")
2467		;; This stores the block height in the buffer
2468		(call $seal_block_number (i32.const 0) (i32.const 32))
2469
2470		;; assert len == 8
2471		(call $assert
2472			(i32.eq
2473				(i32.load (i32.const 32))
2474				(i32.const 8)
2475			)
2476		)
2477
2478		;; assert that contents of the buffer is equal to the i64 value of 121.
2479		(call $assert
2480			(i64.eq
2481				(i64.load (i32.const 0))
2482				(i64.const 121)
2483			)
2484		)
2485	)
2486
2487	(func (export "deploy"))
2488)
2489"#;
2490
2491	#[test]
2492	fn block_number() {
2493		let _ = execute(CODE_BLOCK_NUMBER, vec![], MockExt::default()).unwrap();
2494	}
2495
2496	const CODE_RETURN_WITH_DATA: &str = r#"
2497(module
2498	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
2499	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2500	(import "env" "memory" (memory 1 1))
2501
2502	(data (i32.const 32) "\20")
2503
2504	;; Deploy routine is the same as call.
2505	(func (export "deploy")
2506		(call $call)
2507	)
2508
2509	;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data.
2510	(func $call (export "call")
2511		;; Copy input data this contract memory.
2512		(call $seal_input
2513			(i32.const 0)	;; Pointer where to store input
2514			(i32.const 32)	;; Pointer to the length of the buffer
2515		)
2516
2517		;; Copy all but the first 4 bytes of the input data as the output data.
2518		(call $seal_return
2519			(i32.load (i32.const 0))
2520			(i32.const 4)
2521			(i32.sub (i32.load (i32.const 32)) (i32.const 4))
2522		)
2523		(unreachable)
2524	)
2525)
2526"#;
2527
2528	#[test]
2529	fn seal_return_with_success_status() {
2530		let output = execute(
2531			CODE_RETURN_WITH_DATA,
2532			array_bytes::hex2bytes_unchecked("00000000445566778899"),
2533			MockExt::default(),
2534		)
2535		.unwrap();
2536
2537		assert_eq!(
2538			output,
2539			ExecReturnValue {
2540				flags: ReturnFlags::empty(),
2541				data: array_bytes::hex2bytes_unchecked("445566778899"),
2542			}
2543		);
2544		assert!(!output.did_revert());
2545	}
2546
2547	#[test]
2548	fn return_with_revert_status() {
2549		let output = execute(
2550			CODE_RETURN_WITH_DATA,
2551			array_bytes::hex2bytes_unchecked("010000005566778899"),
2552			MockExt::default(),
2553		)
2554		.unwrap();
2555
2556		assert_eq!(
2557			output,
2558			ExecReturnValue {
2559				flags: ReturnFlags::REVERT,
2560				data: array_bytes::hex2bytes_unchecked("5566778899"),
2561			}
2562		);
2563		assert!(output.did_revert());
2564	}
2565
2566	const CODE_OUT_OF_BOUNDS_ACCESS: &str = r#"
2567(module
2568	(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
2569	(import "env" "memory" (memory 1 1))
2570
2571	(func (export "deploy"))
2572
2573	(func (export "call")
2574		(call $seal_terminate
2575			(i32.const 65536)  ;; Pointer to "account" address (out of bound).
2576			(i32.const 8)  ;; Length of "account" address.
2577		)
2578	)
2579)
2580"#;
2581
2582	#[test]
2583	fn contract_out_of_bounds_access() {
2584		let mut mock_ext = MockExt::default();
2585		let result = execute(CODE_OUT_OF_BOUNDS_ACCESS, vec![], &mut mock_ext);
2586
2587		assert_eq!(
2588			result,
2589			Err(ExecError {
2590				error: Error::<Test>::DecodingFailed.into(),
2591				origin: ErrorOrigin::Caller,
2592			})
2593		);
2594	}
2595
2596	const CODE_DECODE_FAILURE: &str = r#"
2597(module
2598	(import "seal0" "seal_terminate" (func $seal_terminate (param i32 i32)))
2599	(import "env" "memory" (memory 1 1))
2600
2601	(func (export "deploy"))
2602
2603	(func (export "call")
2604		(call $seal_terminate
2605			(i32.const 0)  ;; Pointer to "account" address.
2606			(i32.const 4)  ;; Length of "account" address (too small -> decode fail).
2607		)
2608	)
2609)
2610"#;
2611
2612	#[test]
2613	fn contract_decode_length_ignored() {
2614		let mut mock_ext = MockExt::default();
2615		let result = execute(CODE_DECODE_FAILURE, vec![], &mut mock_ext);
2616		// AccountID implements `MaxEncodeLen` and therefore the supplied length is
2617		// no longer needed nor used to determine how much is read from contract memory.
2618		assert_ok!(result);
2619	}
2620
2621	#[test]
2622	fn debug_message_works() {
2623		const CODE_DEBUG_MESSAGE: &str = r#"
2624(module
2625	(import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32)))
2626	(import "env" "memory" (memory 1 1))
2627
2628	(data (i32.const 0) "Hello World!")
2629
2630	(func (export "call")
2631		(call $seal_debug_message
2632			(i32.const 0)	;; Pointer to the text buffer
2633			(i32.const 12)	;; The size of the buffer
2634		)
2635		drop
2636	)
2637
2638	(func (export "deploy"))
2639)
2640"#;
2641		let mut ext = MockExt::default();
2642		execute(CODE_DEBUG_MESSAGE, vec![], &mut ext).unwrap();
2643
2644		assert_eq!(std::str::from_utf8(&ext.debug_buffer).unwrap(), "Hello World!");
2645	}
2646
2647	#[test]
2648	fn debug_message_invalid_utf8_fails() {
2649		const CODE_DEBUG_MESSAGE_FAIL: &str = r#"
2650(module
2651	(import "seal0" "seal_debug_message" (func $seal_debug_message (param i32 i32) (result i32)))
2652	(import "env" "memory" (memory 1 1))
2653
2654	(data (i32.const 0) "\fc")
2655
2656	(func (export "call")
2657		(call $seal_debug_message
2658			(i32.const 0)	;; Pointer to the text buffer
2659			(i32.const 1)	;; The size of the buffer
2660		)
2661		drop
2662	)
2663
2664	(func (export "deploy"))
2665)
2666"#;
2667		let mut ext = MockExt::default();
2668		let result = execute(CODE_DEBUG_MESSAGE_FAIL, vec![], &mut ext);
2669		assert_ok!(result);
2670		assert!(ext.debug_buffer.is_empty());
2671	}
2672
2673	const CODE_CALL_RUNTIME: &str = r#"
2674(module
2675	(import "seal0" "call_runtime" (func $call_runtime (param i32 i32) (result i32)))
2676	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
2677	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2678	(import "env" "memory" (memory 1 1))
2679
2680	;; 0x1000 = 4k in little endian
2681	;; size of input buffer
2682	(data (i32.const 0) "\00\10")
2683
2684	(func (export "call")
2685		;; Receive the encoded call
2686		(call $seal_input
2687			(i32.const 4)	;; Pointer to the input buffer
2688			(i32.const 0)	;; Size of the length buffer
2689		)
2690		;; Just use the call passed as input and store result to memory
2691		(i32.store (i32.const 0)
2692			(call $call_runtime
2693				(i32.const 4)				;; Pointer where the call is stored
2694				(i32.load (i32.const 0))	;; Size of the call
2695			)
2696		)
2697		(call $seal_return
2698			(i32.const 0)	;; flags
2699			(i32.const 0)	;; returned value
2700			(i32.const 4)	;; length of returned value
2701		)
2702	)
2703
2704	(func (export "deploy"))
2705)
2706"#;
2707
2708	#[test]
2709	fn call_runtime_works() {
2710		let call =
2711			RuntimeCall::System(frame_system::Call::remark { remark: b"Hello World".to_vec() });
2712		let mut ext = MockExt::default();
2713		let result = execute(CODE_CALL_RUNTIME, call.encode(), &mut ext).unwrap();
2714		assert_eq!(*ext.runtime_calls.borrow(), vec![call]);
2715		// 0 = ReturnCode::Success
2716		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0);
2717	}
2718
2719	#[test]
2720	fn call_runtime_panics_on_invalid_call() {
2721		let mut ext = MockExt::default();
2722		let result = execute(CODE_CALL_RUNTIME, vec![0x42], &mut ext);
2723		assert_eq!(
2724			result,
2725			Err(ExecError {
2726				error: Error::<Test>::DecodingFailed.into(),
2727				origin: ErrorOrigin::Caller,
2728			})
2729		);
2730		assert_eq!(*ext.runtime_calls.borrow(), vec![]);
2731	}
2732
2733	#[test]
2734	fn set_storage_works() {
2735		const CODE: &str = r#"
2736(module
2737	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
2738	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2739	(import "seal2" "set_storage" (func $set_storage (param i32 i32 i32 i32) (result i32)))
2740	(import "env" "memory" (memory 1 1))
2741
2742	;; [0, 4) size of input buffer
2743	;; 4k in little endian
2744	(data (i32.const 0) "\00\10")
2745
2746	;; [4, 4100) input buffer
2747
2748	(func (export "call")
2749		;; Receive (key ++ value_to_write)
2750		(call $seal_input
2751			(i32.const 4)	;; Pointer to the input buffer
2752			(i32.const 0)	;; Size of the input buffer
2753		)
2754		;; Store the passed value to the passed key and store result to memory
2755		(i32.store (i32.const 168)
2756			(call $set_storage
2757				(i32.const 8)				;; key_ptr
2758				(i32.load (i32.const 4))		;; key_len
2759				(i32.add				;; value_ptr = 8 + key_len
2760					(i32.const 8)
2761					(i32.load (i32.const 4)))
2762				(i32.sub				;; value_len (input_size - (key_len + key_len_len))
2763					(i32.load (i32.const 0))
2764					(i32.add
2765						(i32.load (i32.const 4))
2766						(i32.const 4)
2767					)
2768				)
2769			)
2770		)
2771		(call $seal_return
2772			(i32.const 0)	;; flags
2773			(i32.const 168)	;; ptr to returned value
2774			(i32.const 4)	;; length of returned value
2775		)
2776	)
2777
2778	(func (export "deploy"))
2779)
2780"#;
2781
2782		let mut ext = MockExt::default();
2783
2784		// value did not exist before -> sentinel returned
2785		let input = (32, [1u8; 32], [42u8, 48]).encode();
2786		let result = execute(CODE, input, &mut ext).unwrap();
2787		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
2788		assert_eq!(ext.storage.get(&[1u8; 32].to_vec()).unwrap(), &[42u8, 48]);
2789
2790		// value do exist -> length of old value returned
2791		let input = (32, [1u8; 32], [0u8; 0]).encode();
2792		let result = execute(CODE, input, &mut ext).unwrap();
2793		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 2);
2794		assert_eq!(ext.storage.get(&[1u8; 32].to_vec()).unwrap(), &[0u8; 0]);
2795
2796		// value do exist -> length of old value returned (test for zero sized val)
2797		let input = (32, [1u8; 32], [99u8]).encode();
2798		let result = execute(CODE, input, &mut ext).unwrap();
2799		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0);
2800		assert_eq!(ext.storage.get(&[1u8; 32].to_vec()).unwrap(), &[99u8]);
2801	}
2802
2803	#[test]
2804	fn get_storage_works() {
2805		const CODE: &str = r#"
2806(module
2807	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
2808	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2809	(import "seal1" "get_storage" (func $get_storage (param i32 i32 i32 i32) (result i32)))
2810	(import "env" "memory" (memory 1 1))
2811
2812	;; [0, 4) size of input buffer (160 bytes as we copy the key+len here)
2813	(data (i32.const 0) "\A0")
2814
2815	;; [4, 8) size of output buffer
2816	;; 4k in little endian
2817	(data (i32.const 4) "\00\10")
2818
2819	;; [8, 168) input buffer
2820	;; [168, 4264) output buffer
2821
2822	(func (export "call")
2823		;; Receive (key ++ value_to_write)
2824		(call $seal_input
2825			(i32.const 8)	;; Pointer to the input buffer
2826			(i32.const 0)	;; Size of the input buffer
2827		)
2828		;; Load a storage value and result of this call into the output buffer
2829		(i32.store (i32.const 168)
2830			(call $get_storage
2831				(i32.const 12)			;; key_ptr
2832				(i32.load (i32.const 8))	;; key_len
2833				(i32.const 172)			;; Pointer to the output buffer
2834				(i32.const 4)			;; Pointer to the size of the buffer
2835			)
2836		)
2837		(call $seal_return
2838			(i32.const 0)				;; flags
2839			(i32.const 168)				;; output buffer ptr
2840			(i32.add				;; length: output size + 4 (retval)
2841				(i32.load (i32.const 4))
2842				(i32.const 4)
2843			)
2844		)
2845	)
2846
2847	(func (export "deploy"))
2848)
2849"#;
2850
2851		let mut ext = MockExt::default();
2852
2853		ext.set_storage(
2854			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
2855			Some(vec![42u8]),
2856			false,
2857		)
2858		.unwrap();
2859
2860		ext.set_storage(
2861			&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap(),
2862			Some(vec![]),
2863			false,
2864		)
2865		.unwrap();
2866
2867		// value does not exist
2868		let input = (63, [1u8; 64]).encode();
2869		let result = execute(CODE, input, &mut ext).unwrap();
2870		assert_eq!(
2871			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
2872			ReturnErrorCode::KeyNotFound as u32
2873		);
2874
2875		// value exists
2876		let input = (64, [1u8; 64]).encode();
2877		let result = execute(CODE, input, &mut ext).unwrap();
2878		assert_eq!(
2879			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
2880			ReturnErrorCode::Success as u32
2881		);
2882		assert_eq!(ext.storage.get(&[1u8; 64].to_vec()).unwrap(), &[42u8]);
2883		assert_eq!(&result.data[4..], &[42u8]);
2884
2885		// value exists (test for 0 sized)
2886		let input = (19, [2u8; 19]).encode();
2887		let result = execute(CODE, input, &mut ext).unwrap();
2888		assert_eq!(
2889			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
2890			ReturnErrorCode::Success as u32
2891		);
2892		assert_eq!(ext.storage.get(&[2u8; 19].to_vec()), Some(&vec![]));
2893		assert_eq!(&result.data[4..], &([] as [u8; 0]));
2894	}
2895
2896	#[test]
2897	fn clear_storage_works() {
2898		const CODE: &str = r#"
2899(module
2900	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
2901	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2902	(import "seal1" "clear_storage" (func $clear_storage (param i32 i32) (result i32)))
2903	(import "env" "memory" (memory 1 1))
2904
2905	;; size of input buffer
2906	;; [0, 4) size of input buffer (128+32 = 160 bytes = 0xA0)
2907	(data (i32.const 0) "\A0")
2908
2909	;; [4, 164) input buffer
2910
2911	(func (export "call")
2912		;; Receive key
2913		(call $seal_input
2914			(i32.const 4)	;; Where we take input and store it
2915			(i32.const 0)	;; Where we take and store the length of thedata
2916		)
2917		;; Call seal_clear_storage and save what it returns at 0
2918		(i32.store (i32.const 0)
2919			(call $clear_storage
2920				(i32.const 8)			;; key_ptr
2921				(i32.load (i32.const 4))	;; key_len
2922			)
2923		)
2924		(call $seal_return
2925			(i32.const 0)	;; flags
2926			(i32.const 0)	;; returned value
2927			(i32.const 4)	;; length of returned value
2928		)
2929	)
2930
2931	(func (export "deploy"))
2932)
2933"#;
2934
2935		let mut ext = MockExt::default();
2936
2937		ext.set_storage(
2938			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
2939			Some(vec![42u8]),
2940			false,
2941		)
2942		.unwrap();
2943		ext.set_storage(
2944			&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap(),
2945			Some(vec![]),
2946			false,
2947		)
2948		.unwrap();
2949
2950		// value did not exist
2951		let input = (32, [3u8; 32]).encode();
2952		let result = execute(CODE, input, &mut ext).unwrap();
2953		// sentinel returned
2954		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
2955		assert_eq!(ext.storage.get(&[3u8; 32].to_vec()), None);
2956
2957		// value did exist
2958		let input = (64, [1u8; 64]).encode();
2959		let result = execute(CODE, input, &mut ext).unwrap();
2960		// length returned
2961		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 1);
2962		// value cleared
2963		assert_eq!(ext.storage.get(&[1u8; 64].to_vec()), None);
2964
2965		// value did not exist (wrong key length)
2966		let input = (63, [1u8; 64]).encode();
2967		let result = execute(CODE, input, &mut ext).unwrap();
2968		// sentinel returned
2969		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
2970		assert_eq!(ext.storage.get(&[1u8; 64].to_vec()), None);
2971
2972		// value exists
2973		let input = (19, [2u8; 19]).encode();
2974		let result = execute(CODE, input, &mut ext).unwrap();
2975		// length returned (test for 0 sized)
2976		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0);
2977		// value cleared
2978		assert_eq!(ext.storage.get(&[2u8; 19].to_vec()), None);
2979	}
2980
2981	#[test]
2982	fn take_storage_works() {
2983		const CODE: &str = r#"
2984(module
2985	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
2986	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
2987	(import "seal0" "take_storage" (func $take_storage (param i32 i32 i32 i32) (result i32)))
2988	(import "env" "memory" (memory 1 1))
2989
2990	;; [0, 4) size of input buffer (160 bytes as we copy the key+len here)
2991	(data (i32.const 0) "\A0")
2992
2993	;; [4, 8) size of output buffer
2994	;; 4k in little endian
2995	(data (i32.const 4) "\00\10")
2996
2997	;; [8, 168) input buffer
2998	;; [168, 4264) output buffer
2999
3000	(func (export "call")
3001		;; Receive key
3002		(call $seal_input
3003			(i32.const 8)	;; Pointer to the input buffer
3004			(i32.const 0)	;; Size of the length buffer
3005		)
3006
3007		;; Load a storage value and result of this call into the output buffer
3008		(i32.store (i32.const 168)
3009			(call $take_storage
3010				(i32.const 12)			;; key_ptr
3011				(i32.load (i32.const 8))	;; key_len
3012				(i32.const 172)			;; Pointer to the output buffer
3013				(i32.const 4)			;; Pointer to the size of the buffer
3014			)
3015		)
3016
3017		;; Return the contents of the buffer
3018		(call $seal_return
3019			(i32.const 0)				;; flags
3020			(i32.const 168)				;; output buffer ptr
3021			(i32.add				;; length: storage size + 4 (retval)
3022				(i32.load (i32.const 4))
3023				(i32.const 4)
3024			)
3025		)
3026	)
3027
3028	(func (export "deploy"))
3029)
3030"#;
3031
3032		let mut ext = MockExt::default();
3033
3034		ext.set_storage(
3035			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
3036			Some(vec![42u8]),
3037			false,
3038		)
3039		.unwrap();
3040
3041		ext.set_storage(
3042			&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap(),
3043			Some(vec![]),
3044			false,
3045		)
3046		.unwrap();
3047
3048		// value does not exist -> error returned
3049		let input = (63, [1u8; 64]).encode();
3050		let result = execute(CODE, input, &mut ext).unwrap();
3051		assert_eq!(
3052			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3053			ReturnErrorCode::KeyNotFound as u32
3054		);
3055
3056		// value did exist -> value returned
3057		let input = (64, [1u8; 64]).encode();
3058		let result = execute(CODE, input, &mut ext).unwrap();
3059		assert_eq!(
3060			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3061			ReturnErrorCode::Success as u32
3062		);
3063		assert_eq!(ext.storage.get(&[1u8; 64].to_vec()), None);
3064		assert_eq!(&result.data[4..], &[42u8]);
3065
3066		// value did exist -> length returned (test for 0 sized)
3067		let input = (19, [2u8; 19]).encode();
3068		let result = execute(CODE, input, &mut ext).unwrap();
3069		assert_eq!(
3070			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3071			ReturnErrorCode::Success as u32
3072		);
3073		assert_eq!(ext.storage.get(&[2u8; 19].to_vec()), None);
3074		assert_eq!(&result.data[4..], &[0u8; 0]);
3075	}
3076
3077	#[test]
3078	fn set_transient_storage_works() {
3079		const CODE: &str = r#"
3080(module
3081	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
3082	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3083	(import "seal0" "set_transient_storage" (func $set_transient_storage (param i32 i32 i32 i32) (result i32)))
3084	(import "env" "memory" (memory 1 1))
3085
3086	;; [0, 4) size of input buffer
3087	;; 4k in little endian
3088	(data (i32.const 0) "\00\10")
3089
3090	;; [4, 4100) input buffer
3091
3092	(func (export "call")
3093		;; Receive (key ++ value_to_write)
3094		(call $seal_input
3095			(i32.const 4)	;; Pointer to the input buffer
3096			(i32.const 0)	;; Size of the input buffer
3097		)
3098		;; Store the passed value to the passed key and store result to memory
3099		(i32.store (i32.const 168)
3100			(call $set_transient_storage
3101				(i32.const 8)				;; key_ptr
3102				(i32.load (i32.const 4))		;; key_len
3103				(i32.add				;; value_ptr = 8 + key_len
3104					(i32.const 8)
3105					(i32.load (i32.const 4)))
3106				(i32.sub				;; value_len (input_size - (key_len + key_len_len))
3107					(i32.load (i32.const 0))
3108					(i32.add
3109						(i32.load (i32.const 4))
3110						(i32.const 4)
3111					)
3112				)
3113			)
3114		)
3115		(call $seal_return
3116			(i32.const 0)	;; flags
3117			(i32.const 168)	;; ptr to returned value
3118			(i32.const 4)	;; length of returned value
3119		)
3120	)
3121
3122	(func (export "deploy"))
3123)
3124"#;
3125
3126		let mut ext = MockExt::default();
3127
3128		// value did not exist before -> sentinel returned
3129		let input = (32, [1u8; 32], [42u8, 48]).encode();
3130		let result = execute(CODE, input, &mut ext).unwrap();
3131		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
3132		assert_eq!(
3133			ext.get_transient_storage(&Key::<Test>::try_from_var([1u8; 32].to_vec()).unwrap()),
3134			Some(vec![42, 48])
3135		);
3136
3137		// value do exist -> length of old value returned
3138		let input = (32, [1u8; 32], [0u8; 0]).encode();
3139		let result = execute(CODE, input, &mut ext).unwrap();
3140		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 2);
3141		assert_eq!(
3142			ext.get_transient_storage(&Key::<Test>::try_from_var([1u8; 32].to_vec()).unwrap()),
3143			Some(vec![])
3144		);
3145
3146		// value do exist -> length of old value returned (test for zero sized val)
3147		let input = (32, [1u8; 32], [99u8]).encode();
3148		let result = execute(CODE, input, &mut ext).unwrap();
3149		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0);
3150		assert_eq!(
3151			ext.get_transient_storage(&Key::<Test>::try_from_var([1u8; 32].to_vec()).unwrap()),
3152			Some(vec![99])
3153		);
3154	}
3155
3156	#[test]
3157	fn get_transient_storage_works() {
3158		const CODE: &str = r#"
3159(module
3160	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
3161	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3162	(import "seal0" "get_transient_storage" (func $get_transient_storage (param i32 i32 i32 i32) (result i32)))
3163	(import "env" "memory" (memory 1 1))
3164
3165	;; [0, 4) size of input buffer (160 bytes as we copy the key+len here)
3166	(data (i32.const 0) "\A0")
3167
3168	;; [4, 8) size of output buffer
3169	;; 4k in little endian
3170	(data (i32.const 4) "\00\10")
3171
3172	;; [8, 168) input buffer
3173	;; [168, 4264) output buffer
3174
3175	(func (export "call")
3176		;; Receive (key ++ value_to_write)
3177		(call $seal_input
3178			(i32.const 8)	;; Pointer to the input buffer
3179			(i32.const 0)	;; Size of the input buffer
3180		)
3181		;; Load a storage value and result of this call into the output buffer
3182		(i32.store (i32.const 168)
3183			(call $get_transient_storage
3184				(i32.const 12)			;; key_ptr
3185				(i32.load (i32.const 8))	;; key_len
3186				(i32.const 172)			;; Pointer to the output buffer
3187				(i32.const 4)			;; Pointer to the size of the buffer
3188			)
3189		)
3190		(call $seal_return
3191			(i32.const 0)				;; flags
3192			(i32.const 168)				;; output buffer ptr
3193			(i32.add				;; length: output size + 4 (retval)
3194				(i32.load (i32.const 4))
3195				(i32.const 4)
3196			)
3197		)
3198	)
3199
3200	(func (export "deploy"))
3201)
3202"#;
3203
3204		let mut ext = MockExt::default();
3205
3206		assert_ok!(ext.set_transient_storage(
3207			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
3208			Some(vec![42u8]),
3209			false
3210		));
3211		assert_ok!(ext.set_transient_storage(
3212			&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap(),
3213			Some(vec![]),
3214			false
3215		));
3216
3217		// value does not exist
3218		let input = (63, [1u8; 64]).encode();
3219		let result = execute(CODE, input, &mut ext).unwrap();
3220		assert_eq!(
3221			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3222			ReturnErrorCode::KeyNotFound as u32
3223		);
3224
3225		// value exists
3226		let input = (64, [1u8; 64]).encode();
3227		let result = execute(CODE, input, &mut ext).unwrap();
3228		assert_eq!(
3229			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3230			ReturnErrorCode::Success as u32
3231		);
3232		assert_eq!(&result.data[4..], &[42u8]);
3233
3234		// value exists (test for 0 sized)
3235		let input = (19, [2u8; 19]).encode();
3236		let result = execute(CODE, input, &mut ext).unwrap();
3237		assert_eq!(
3238			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3239			ReturnErrorCode::Success as u32
3240		);
3241		assert_eq!(&result.data[4..], &([] as [u8; 0]));
3242	}
3243
3244	#[test]
3245	fn clear_transient_storage_works() {
3246		const CODE: &str = r#"
3247(module
3248	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
3249	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3250	(import "seal0" "clear_transient_storage" (func $clear_transient_storage (param i32 i32) (result i32)))
3251	(import "env" "memory" (memory 1 1))
3252
3253	;; size of input buffer
3254	;; [0, 4) size of input buffer (128+32 = 160 bytes = 0xA0)
3255	(data (i32.const 0) "\A0")
3256
3257	;; [4, 164) input buffer
3258
3259	(func (export "call")
3260		;; Receive key
3261		(call $seal_input
3262			(i32.const 4)	;; Where we take input and store it
3263			(i32.const 0)	;; Where we take and store the length of thedata
3264		)
3265		;; Call seal_clear_storage and save what it returns at 0
3266		(i32.store (i32.const 0)
3267			(call $clear_transient_storage
3268				(i32.const 8)			;; key_ptr
3269				(i32.load (i32.const 4))	;; key_len
3270			)
3271		)
3272		(call $seal_return
3273			(i32.const 0)	;; flags
3274			(i32.const 0)	;; returned value
3275			(i32.const 4)	;; length of returned value
3276		)
3277	)
3278
3279	(func (export "deploy"))
3280)
3281"#;
3282
3283		let mut ext = MockExt::default();
3284
3285		assert_ok!(ext.set_transient_storage(
3286			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
3287			Some(vec![42u8]),
3288			false
3289		));
3290
3291		// value did not exist
3292		let input = (32, [3u8; 32]).encode();
3293		let result = execute(CODE, input, &mut ext).unwrap();
3294		// sentinel returned
3295		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
3296
3297		// value did exist
3298		let input = (64, [1u8; 64]).encode();
3299		let result = execute(CODE, input, &mut ext).unwrap();
3300		// length returned
3301		assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 1);
3302		// value cleared
3303		assert_eq!(
3304			ext.get_transient_storage(&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap()),
3305			None
3306		);
3307	}
3308
3309	#[test]
3310	fn take_transient_storage_works() {
3311		const CODE: &str = r#"
3312(module
3313	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3314	(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
3315	(import "seal0" "take_transient_storage" (func $take_transient_storage (param i32 i32 i32 i32) (result i32)))
3316	(import "env" "memory" (memory 1 1))
3317
3318	;; [0, 4) size of input buffer (160 bytes as we copy the key+len here)
3319	(data (i32.const 0) "\A0")
3320
3321	;; [4, 8) size of output buffer
3322	;; 4k in little endian
3323	(data (i32.const 4) "\00\10")
3324
3325	;; [8, 168) input buffer
3326	;; [168, 4264) output buffer
3327
3328	(func (export "call")
3329		;; Receive key
3330		(call $seal_input
3331			(i32.const 8)	;; Pointer to the input buffer
3332			(i32.const 0)	;; Size of the length buffer
3333		)
3334
3335		;; Load a storage value and result of this call into the output buffer
3336		(i32.store (i32.const 168)
3337			(call $take_transient_storage
3338				(i32.const 12)			;; key_ptr
3339				(i32.load (i32.const 8))	;; key_len
3340				(i32.const 172)			;; Pointer to the output buffer
3341				(i32.const 4)			;; Pointer to the size of the buffer
3342			)
3343		)
3344
3345		;; Return the contents of the buffer
3346		(call $seal_return
3347			(i32.const 0)				;; flags
3348			(i32.const 168)				;; output buffer ptr
3349			(i32.add				;; length: storage size + 4 (retval)
3350				(i32.load (i32.const 4))
3351				(i32.const 4)
3352			)
3353		)
3354	)
3355
3356	(func (export "deploy"))
3357)
3358"#;
3359
3360		let mut ext = MockExt::default();
3361
3362		assert_ok!(ext.set_transient_storage(
3363			&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap(),
3364			Some(vec![42u8]),
3365			false
3366		));
3367		assert_ok!(ext.set_transient_storage(
3368			&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap(),
3369			Some(vec![]),
3370			false
3371		));
3372
3373		// value does not exist -> error returned
3374		let input = (63, [1u8; 64]).encode();
3375		let result = execute(CODE, input, &mut ext).unwrap();
3376		assert_eq!(
3377			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3378			ReturnErrorCode::KeyNotFound as u32
3379		);
3380
3381		// value did exist -> value returned
3382		let input = (64, [1u8; 64]).encode();
3383		let result = execute(CODE, input, &mut ext).unwrap();
3384		assert_eq!(
3385			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3386			ReturnErrorCode::Success as u32
3387		);
3388		assert_eq!(
3389			ext.get_transient_storage(&Key::<Test>::try_from_var([1u8; 64].to_vec()).unwrap()),
3390			None
3391		);
3392		assert_eq!(&result.data[4..], &[42u8]);
3393
3394		// value did exist -> length returned (test for 0 sized)
3395		let input = (19, [2u8; 19]).encode();
3396		let result = execute(CODE, input, &mut ext).unwrap();
3397		assert_eq!(
3398			u32::from_le_bytes(result.data[0..4].try_into().unwrap()),
3399			ReturnErrorCode::Success as u32
3400		);
3401		assert_eq!(
3402			ext.get_transient_storage(&Key::<Test>::try_from_var([2u8; 19].to_vec()).unwrap()),
3403			None
3404		);
3405		assert_eq!(&result.data[4..], &[0u8; 0]);
3406	}
3407
3408	#[test]
3409	fn is_contract_works() {
3410		const CODE_IS_CONTRACT: &str = r#"
3411;; This runs `is_contract` check on zero account address
3412(module
3413	(import "seal0" "seal_is_contract" (func $seal_is_contract (param i32) (result i32)))
3414	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3415	(import "env" "memory" (memory 1 1))
3416
3417	;; [0, 32) zero-adress
3418	(data (i32.const 0)
3419		"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
3420		"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
3421	)
3422
3423	;; [32, 36) here we store the return code of the `seal_is_contract`
3424
3425	(func (export "deploy"))
3426
3427	(func (export "call")
3428		(i32.store
3429			(i32.const 32)
3430			(call $seal_is_contract
3431				(i32.const 0) ;; ptr to destination address
3432			)
3433		)
3434		;; exit with success and take `seal_is_contract` return code to the output buffer
3435		(call $seal_return (i32.const 0) (i32.const 32) (i32.const 4))
3436	)
3437)
3438"#;
3439		let output = execute(CODE_IS_CONTRACT, vec![], MockExt::default()).unwrap();
3440
3441		// The mock ext just always returns 1u32 (`true`).
3442		assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 1u32.encode() },);
3443	}
3444
3445	#[test]
3446	fn code_hash_works() {
3447		/// calls `seal_code_hash` and compares the result with the constant.
3448		const CODE_CODE_HASH: &str = r#"
3449(module
3450	(import "seal0" "seal_code_hash" (func $seal_code_hash (param i32 i32 i32) (result i32)))
3451	(import "env" "memory" (memory 1 1))
3452
3453	;; size of our buffer is 32 bytes
3454	(data (i32.const 32) "\20")
3455
3456	(func $assert (param i32)
3457		(block $ok
3458			(br_if $ok
3459				(local.get 0)
3460			)
3461			(unreachable)
3462		)
3463	)
3464
3465	(func (export "call")
3466		;; fill the buffer with the code hash.
3467		(call $seal_code_hash
3468			(i32.const 0) ;; input: address_ptr (before call)
3469			(i32.const 0) ;; output: code_hash_ptr (after call)
3470			(i32.const 32) ;; same 32 bytes length for input and output
3471		)
3472
3473		;; assert size == 32
3474		(call $assert
3475			(i32.eq
3476				(i32.load (i32.const 32))
3477				(i32.const 32)
3478			)
3479		)
3480
3481		;; assert that the first 8 bytes are "1111111111111111"
3482		(call $assert
3483			(i64.eq
3484				(i64.load (i32.const 0))
3485				(i64.const 0x1111111111111111)
3486			)
3487		)
3488		drop
3489	)
3490
3491	(func (export "deploy"))
3492)
3493"#;
3494		assert_ok!(execute(CODE_CODE_HASH, vec![], MockExt::default()));
3495	}
3496
3497	#[test]
3498	fn own_code_hash_works() {
3499		/// calls `seal_own_code_hash` and compares the result with the constant.
3500		const CODE_OWN_CODE_HASH: &str = r#"
3501(module
3502	(import "seal0" "seal_own_code_hash" (func $seal_own_code_hash (param i32 i32)))
3503	(import "env" "memory" (memory 1 1))
3504
3505	;; size of our buffer is 32 bytes
3506	(data (i32.const 32) "\20")
3507
3508	(func $assert (param i32)
3509		(block $ok
3510			(br_if $ok
3511				(local.get 0)
3512			)
3513			(unreachable)
3514		)
3515	)
3516
3517	(func (export "call")
3518		;; fill the buffer with the code hash
3519		(call $seal_own_code_hash
3520			(i32.const 0)  ;; output: code_hash_ptr
3521			(i32.const 32) ;; 32 bytes length of code_hash output
3522		)
3523
3524		;; assert size == 32
3525		(call $assert
3526			(i32.eq
3527				(i32.load (i32.const 32))
3528				(i32.const 32)
3529			)
3530		)
3531
3532		;; assert that the first 8 bytes are "1010101010101010"
3533		(call $assert
3534			(i64.eq
3535				(i64.load (i32.const 0))
3536				(i64.const 0x1010101010101010)
3537			)
3538		)
3539	)
3540
3541	(func (export "deploy"))
3542)
3543"#;
3544		assert_ok!(execute(CODE_OWN_CODE_HASH, vec![], MockExt::default()));
3545	}
3546
3547	#[test]
3548	fn caller_is_origin_works() {
3549		const CODE_CALLER_IS_ORIGIN: &str = r#"
3550;; This runs `caller_is_origin` check on zero account address
3551(module
3552	(import "seal0" "seal_caller_is_origin" (func $seal_caller_is_origin (result i32)))
3553	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3554	(import "env" "memory" (memory 1 1))
3555
3556	;; [0, 4) here the return code of the `seal_caller_is_origin` will be stored
3557	;; we initialize it with non-zero value to be sure that it's being overwritten below
3558	(data (i32.const 0) "\10\10\10\10")
3559
3560	(func (export "deploy"))
3561
3562	(func (export "call")
3563		(i32.store
3564			(i32.const 0)
3565			(call $seal_caller_is_origin)
3566		)
3567		;; exit with success and take `seal_caller_is_origin` return code to the output buffer
3568		(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
3569	)
3570)
3571"#;
3572		let output = execute(CODE_CALLER_IS_ORIGIN, vec![], MockExt::default()).unwrap();
3573
3574		// The mock ext just always returns 0u32 (`false`)
3575		assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 0u32.encode() },);
3576	}
3577
3578	#[test]
3579	fn caller_is_root_works() {
3580		const CODE_CALLER_IS_ROOT: &str = r#"
3581;; This runs `caller_is_root` check on zero account address
3582(module
3583	(import "seal0" "caller_is_root" (func $caller_is_root (result i32)))
3584	(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
3585	(import "env" "memory" (memory 1 1))
3586
3587	;; [0, 4) here the return code of the `caller_is_root` will be stored
3588	;; we initialize it with non-zero value to be sure that it's being overwritten below
3589	(data (i32.const 0) "\10\10\10\10")
3590
3591	(func (export "deploy"))
3592
3593	(func (export "call")
3594		(i32.store
3595			(i32.const 0)
3596			(call $caller_is_root)
3597		)
3598		;; exit with success and take `caller_is_root` return code to the output buffer
3599		(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
3600	)
3601)
3602"#;
3603		// The default `caller` is ALICE. Therefore not root.
3604		let output = execute(CODE_CALLER_IS_ROOT, vec![], MockExt::default()).unwrap();
3605		assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 0u32.encode() },);
3606
3607		// The caller is forced to be root instead of using the default ALICE.
3608		let output = execute(
3609			CODE_CALLER_IS_ROOT,
3610			vec![],
3611			MockExt { caller: Origin::Root, ..MockExt::default() },
3612		)
3613		.unwrap();
3614		assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 1u32.encode() },);
3615	}
3616
3617	#[test]
3618	fn set_code_hash() {
3619		const CODE: &str = r#"
3620(module
3621	(import "seal0" "seal_set_code_hash" (func $seal_set_code_hash (param i32) (result i32)))
3622	(import "env" "memory" (memory 1 1))
3623	(func $assert (param i32)
3624		(block $ok
3625			(br_if $ok
3626				(local.get 0)
3627			)
3628			(unreachable)
3629		)
3630	)
3631	(func (export "call")
3632		(local $exit_code i32)
3633		(local.set $exit_code
3634			(call $seal_set_code_hash (i32.const 0))
3635		)
3636		(call $assert
3637			(i32.eq (local.get $exit_code) (i32.const 0)) ;; ReturnCode::Success
3638		)
3639	)
3640
3641	(func (export "deploy"))
3642
3643	;; Hash of code.
3644	(data (i32.const 0)
3645		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
3646		"\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11"
3647	)
3648)
3649"#;
3650
3651		let mut mock_ext = MockExt::default();
3652		execute(CODE, [0u8; 32].encode(), &mut mock_ext).unwrap();
3653
3654		assert_eq!(mock_ext.code_hashes.pop().unwrap(), H256::from_slice(&[17u8; 32]));
3655	}
3656
3657	#[test]
3658	fn reentrance_count_works() {
3659		const CODE: &str = r#"
3660(module
3661	(import "seal0" "reentrance_count" (func $reentrance_count (result i32)))
3662	(import "env" "memory" (memory 1 1))
3663	(func $assert (param i32)
3664		(block $ok
3665			(br_if $ok
3666				(local.get 0)
3667			)
3668			(unreachable)
3669		)
3670	)
3671	(func (export "call")
3672		(local $return_val i32)
3673		(local.set $return_val
3674			(call $reentrance_count)
3675		)
3676		(call $assert
3677			(i32.eq (local.get $return_val) (i32.const 12))
3678		)
3679	)
3680
3681	(func (export "deploy"))
3682)
3683"#;
3684
3685		let mut mock_ext = MockExt::default();
3686		execute(CODE, vec![], &mut mock_ext).unwrap();
3687	}
3688
3689	#[test]
3690	fn account_reentrance_count_works() {
3691		const CODE: &str = r#"
3692(module
3693	(import "seal0" "account_reentrance_count" (func $account_reentrance_count (param i32) (result i32)))
3694	(import "env" "memory" (memory 1 1))
3695	(func $assert (param i32)
3696		(block $ok
3697			(br_if $ok
3698				(local.get 0)
3699			)
3700			(unreachable)
3701		)
3702	)
3703	(func (export "call")
3704		(local $return_val i32)
3705		(local.set $return_val
3706			(call $account_reentrance_count (i32.const 0))
3707		)
3708		(call $assert
3709			(i32.eq (local.get $return_val) (i32.const 12))
3710		)
3711	)
3712
3713	(func (export "deploy"))
3714)
3715"#;
3716
3717		let mut mock_ext = MockExt::default();
3718		execute(CODE, vec![], &mut mock_ext).unwrap();
3719	}
3720
3721	#[test]
3722	fn instantiation_nonce_works() {
3723		const CODE: &str = r#"
3724(module
3725	(import "seal0" "instantiation_nonce" (func $nonce (result i64)))
3726	(import "env" "memory" (memory 1 1))
3727
3728	(func $assert (param i32)
3729		(block $ok
3730			(br_if $ok
3731				(local.get 0)
3732			)
3733			(unreachable)
3734		)
3735	)
3736	(func (export "call")
3737		(call $assert
3738			(i64.eq (call $nonce) (i64.const 995))
3739		)
3740	)
3741	(func (export "deploy"))
3742)
3743"#;
3744
3745		let mut mock_ext = MockExt::default();
3746		execute(CODE, vec![], &mut mock_ext).unwrap();
3747	}
3748
3749	/// This test check that an unstable interface cannot be deployed. In case of runtime
3750	/// benchmarks we always allow unstable interfaces. This is why this test does not
3751	/// work when this feature is enabled.
3752	#[cfg(not(feature = "runtime-benchmarks"))]
3753	#[test]
3754	fn cannot_deploy_unstable() {
3755		const CANNOT_DEPLOY_UNSTABLE: &str = r#"
3756(module
3757	(import "seal0" "reentrance_count" (func $reentrance_count (result i32)))
3758	(import "env" "memory" (memory 1 1))
3759
3760	(func (export "call"))
3761	(func (export "deploy"))
3762)
3763"#;
3764		assert_err!(
3765			execute_no_unstable(CANNOT_DEPLOY_UNSTABLE, vec![], MockExt::default()),
3766			<Error<Test>>::CodeRejected,
3767		);
3768		assert_ok!(execute(CANNOT_DEPLOY_UNSTABLE, vec![], MockExt::default()));
3769	}
3770
3771	/// The random interface is deprecated and hence new contracts using it should not be deployed.
3772	/// In case of runtime benchmarks we always allow deprecated interfaces. This is why this
3773	/// test doesn't work if this feature is enabled.
3774	#[cfg(not(feature = "runtime-benchmarks"))]
3775	#[test]
3776	fn cannot_deploy_deprecated() {
3777		const CODE_RANDOM_0: &str = r#"
3778(module
3779	(import "seal0" "seal_random" (func $seal_random (param i32 i32 i32 i32)))
3780	(import "env" "memory" (memory 1 1))
3781
3782	(func (export "call"))
3783	(func (export "deploy"))
3784)
3785	"#;
3786		const CODE_RANDOM_1: &str = r#"
3787(module
3788	(import "seal1" "seal_random" (func $seal_random (param i32 i32 i32 i32)))
3789	(import "env" "memory" (memory 1 1))
3790
3791	(func (export "call"))
3792	(func (export "deploy"))
3793)
3794	"#;
3795		const CODE_RANDOM_2: &str = r#"
3796(module
3797	(import "seal0" "random" (func $seal_random (param i32 i32 i32 i32)))
3798	(import "env" "memory" (memory 1 1))
3799
3800	(func (export "call"))
3801	(func (export "deploy"))
3802)
3803	"#;
3804		const CODE_RANDOM_3: &str = r#"
3805(module
3806	(import "seal1" "random" (func $seal_random (param i32 i32 i32 i32)))
3807	(import "env" "memory" (memory 1 1))
3808
3809	(func (export "call"))
3810	(func (export "deploy"))
3811)
3812	"#;
3813
3814		assert_ok!(execute_unvalidated(CODE_RANDOM_0, vec![], MockExt::default()));
3815		assert_err!(
3816			execute_instantiate_unvalidated(CODE_RANDOM_0, vec![], MockExt::default()),
3817			<Error<Test>>::CodeRejected,
3818		);
3819		assert_err!(
3820			execute(CODE_RANDOM_0, vec![], MockExt::default()),
3821			<Error<Test>>::CodeRejected,
3822		);
3823
3824		assert_ok!(execute_unvalidated(CODE_RANDOM_1, vec![], MockExt::default()));
3825		assert_err!(
3826			execute_instantiate_unvalidated(CODE_RANDOM_1, vec![], MockExt::default()),
3827			<Error<Test>>::CodeRejected,
3828		);
3829		assert_err!(
3830			execute(CODE_RANDOM_1, vec![], MockExt::default()),
3831			<Error<Test>>::CodeRejected,
3832		);
3833
3834		assert_ok!(execute_unvalidated(CODE_RANDOM_2, vec![], MockExt::default()));
3835		assert_err!(
3836			execute_instantiate_unvalidated(CODE_RANDOM_2, vec![], MockExt::default()),
3837			<Error<Test>>::CodeRejected,
3838		);
3839		assert_err!(
3840			execute(CODE_RANDOM_2, vec![], MockExt::default()),
3841			<Error<Test>>::CodeRejected,
3842		);
3843
3844		assert_ok!(execute_unvalidated(CODE_RANDOM_3, vec![], MockExt::default()));
3845		assert_err!(
3846			execute_instantiate_unvalidated(CODE_RANDOM_3, vec![], MockExt::default()),
3847			<Error<Test>>::CodeRejected,
3848		);
3849		assert_err!(
3850			execute(CODE_RANDOM_3, vec![], MockExt::default()),
3851			<Error<Test>>::CodeRejected,
3852		);
3853	}
3854
3855	#[test]
3856	fn lock_unlock_delegate_dependency() {
3857		const CODE_LOCK_UNLOCK_DELEGATE_DEPENDENCY: &str = r#"
3858(module
3859	(import "seal0" "lock_delegate_dependency" (func $lock_delegate_dependency (param i32)))
3860	(import "seal0" "unlock_delegate_dependency" (func $unlock_delegate_dependency (param i32)))
3861	(import "env" "memory" (memory 1 1))
3862	(func (export "call")
3863		(call $lock_delegate_dependency (i32.const 0))
3864		(call $lock_delegate_dependency (i32.const 32))
3865		(call $unlock_delegate_dependency (i32.const 32))
3866	)
3867	(func (export "deploy"))
3868
3869	;;  hash1 (32 bytes)
3870	(data (i32.const 0)
3871		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
3872		"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"
3873	)
3874
3875	;;  hash2 (32 bytes)
3876	(data (i32.const 32)
3877		"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"
3878		"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"
3879	)
3880)
3881"#;
3882		let mut mock_ext = MockExt::default();
3883		assert_ok!(execute(&CODE_LOCK_UNLOCK_DELEGATE_DEPENDENCY, vec![], &mut mock_ext));
3884		let delegate_dependencies: Vec<_> =
3885			mock_ext.delegate_dependencies.into_inner().into_iter().collect();
3886		assert_eq!(delegate_dependencies.len(), 1);
3887		assert_eq!(delegate_dependencies[0].as_bytes(), [1; 32]);
3888	}
3889
3890	// This test checks that [`Runtime::read_sandbox_memory_as`] works, when the decoded type has a
3891	// max_len greater than the memory size, but the decoded data fits into the memory.
3892	#[test]
3893	fn read_sandbox_memory_as_works_with_max_len_out_of_bounds_but_fitting_actual_data() {
3894		use frame_support::BoundedVec;
3895		use sp_core::ConstU32;
3896
3897		let mut ext = MockExt::default();
3898		let runtime = Runtime::new(&mut ext, vec![]);
3899		let data = vec![1u8, 2, 3];
3900		let memory = data.encode();
3901		let decoded: BoundedVec<u8, ConstU32<128>> =
3902			runtime.read_sandbox_memory_as(&memory, 0u32).unwrap();
3903		assert_eq!(decoded.into_inner(), data);
3904	}
3905
3906	#[test]
3907	fn run_out_of_gas_in_start_fn() {
3908		const CODE: &str = r#"
3909(module
3910	(import "env" "memory" (memory 1 1))
3911	(start $start)
3912	(func $start
3913		(loop $inf (br $inf)) ;; just run out of gas
3914		(unreachable)
3915	)
3916	(func (export "call"))
3917	(func (export "deploy"))
3918)
3919"#;
3920		let mut mock_ext = MockExt::default();
3921		assert_err!(execute(&CODE, vec![], &mut mock_ext), <Error<Test>>::OutOfGas);
3922	}
3923}