referrerpolicy=no-referrer-when-downgrade

pallet_contracts/wasm/
runtime.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//! Environment definition of the wasm smart-contract runtime.
19
20use crate::{
21	exec::{ExecError, ExecResult, Ext, Key, TopicOf},
22	gas::{ChargedAmount, Token},
23	primitives::ExecReturnValue,
24	weights::WeightInfo,
25	BalanceOf, CodeHash, Config, DebugBufferVec, Error, SENTINEL,
26};
27use alloc::{boxed::Box, vec, vec::Vec};
28use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen};
29use core::fmt;
30use frame_support::{
31	dispatch::DispatchInfo, ensure, pallet_prelude::DispatchResultWithPostInfo, parameter_types,
32	traits::Get, weights::Weight,
33};
34use pallet_contracts_proc_macro::define_env;
35use pallet_contracts_uapi::{CallFlags, ReturnFlags};
36use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256};
37use sp_runtime::{
38	traits::{Bounded, Zero},
39	Debug, DispatchError,
40};
41use wasmi::{core::HostError, errors::LinkerError, Linker, Memory, Store};
42
43type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
44
45/// The maximum nesting depth a contract can use when encoding types.
46const MAX_DECODE_NESTING: u32 = 256;
47
48/// Passed to [`Environment`] to determine whether it should expose deprecated interfaces.
49pub enum AllowDeprecatedInterface {
50	/// No deprecated interfaces are exposed.
51	No,
52	/// Deprecated interfaces are exposed.
53	Yes,
54}
55
56/// Passed to [`Environment`] to determine whether it should expose unstable interfaces.
57pub enum AllowUnstableInterface {
58	/// No unstable interfaces are exposed.
59	No,
60	/// Unstable interfaces are exposed.
61	Yes,
62}
63
64/// Trait implemented by the [`define_env`](pallet_contracts_proc_macro::define_env) macro for the
65/// emitted `Env` struct.
66pub trait Environment<HostState> {
67	/// Adds all declared functions to the supplied [`Linker`](wasmi::Linker) and
68	/// [`Store`](wasmi::Store).
69	fn define(
70		store: &mut Store<HostState>,
71		linker: &mut Linker<HostState>,
72		allow_unstable: AllowUnstableInterface,
73		allow_deprecated: AllowDeprecatedInterface,
74	) -> Result<(), LinkerError>;
75}
76
77/// Type of a storage key.
78enum KeyType {
79	/// Legacy fix sized key `[u8;32]`.
80	Fix,
81	/// Variable sized key used in transparent hashing,
82	/// cannot be larger than MaxStorageKeyLen.
83	Var(u32),
84}
85
86pub use pallet_contracts_uapi::ReturnErrorCode;
87
88parameter_types! {
89	/// Getter types used by [`crate::api_doc::Current::call_runtime`]
90	const CallRuntimeFailed: ReturnErrorCode = ReturnErrorCode::CallRuntimeFailed;
91	/// Getter types used by [`crate::api_doc::Current::xcm_execute`]
92	const XcmExecutionFailed: ReturnErrorCode = ReturnErrorCode::XcmExecutionFailed;
93}
94
95impl From<ExecReturnValue> for ReturnErrorCode {
96	fn from(from: ExecReturnValue) -> Self {
97		if from.flags.contains(ReturnFlags::REVERT) {
98			Self::CalleeReverted
99		} else {
100			Self::Success
101		}
102	}
103}
104
105/// The data passed through when a contract uses `seal_return`.
106#[derive(Debug)]
107pub struct ReturnData {
108	/// The flags as passed through by the contract. They are still unchecked and
109	/// will later be parsed into a `ReturnFlags` bitflags struct.
110	flags: u32,
111	/// The output buffer passed by the contract as return data.
112	data: Vec<u8>,
113}
114
115/// Enumerates all possible reasons why a trap was generated.
116///
117/// This is either used to supply the caller with more information about why an error
118/// occurred (the SupervisorError variant).
119/// The other case is where the trap does not constitute an error but rather was invoked
120/// as a quick way to terminate the application (all other variants).
121#[derive(Debug)]
122pub enum TrapReason {
123	/// The supervisor trapped the contract because of an error condition occurred during
124	/// execution in privileged code.
125	SupervisorError(DispatchError),
126	/// Signals that trap was generated in response to call `seal_return` host function.
127	Return(ReturnData),
128	/// Signals that a trap was generated in response to a successful call to the
129	/// `seal_terminate` host function.
130	Termination,
131}
132
133impl<T: Into<DispatchError>> From<T> for TrapReason {
134	fn from(from: T) -> Self {
135		Self::SupervisorError(from.into())
136	}
137}
138
139impl fmt::Display for TrapReason {
140	fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
141		Ok(())
142	}
143}
144
145impl HostError for TrapReason {}
146
147#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
148#[derive(Copy, Clone)]
149pub enum RuntimeCosts {
150	/// Base Weight of calling a host function.
151	HostFn,
152	/// Weight charged for copying data from the sandbox.
153	CopyFromContract(u32),
154	/// Weight charged for copying data to the sandbox.
155	CopyToContract(u32),
156	/// Weight of calling `seal_caller`.
157	Caller,
158	/// Weight of calling `seal_is_contract`.
159	IsContract,
160	/// Weight of calling `seal_code_hash`.
161	CodeHash,
162	/// Weight of calling `seal_own_code_hash`.
163	OwnCodeHash,
164	/// Weight of calling `seal_caller_is_origin`.
165	CallerIsOrigin,
166	/// Weight of calling `caller_is_root`.
167	CallerIsRoot,
168	/// Weight of calling `seal_address`.
169	Address,
170	/// Weight of calling `seal_gas_left`.
171	GasLeft,
172	/// Weight of calling `seal_balance`.
173	Balance,
174	/// Weight of calling `seal_value_transferred`.
175	ValueTransferred,
176	/// Weight of calling `seal_minimum_balance`.
177	MinimumBalance,
178	/// Weight of calling `seal_block_number`.
179	BlockNumber,
180	/// Weight of calling `seal_now`.
181	Now,
182	/// Weight of calling `seal_weight_to_fee`.
183	WeightToFee,
184	/// Weight of calling `seal_terminate`, passing the number of locked dependencies.
185	Terminate(u32),
186	/// Weight of calling `seal_random`. It includes the weight for copying the subject.
187	Random,
188	/// Weight of calling `seal_deposit_event` with the given number of topics and event size.
189	DepositEvent { num_topic: u32, len: u32 },
190	/// Weight of calling `seal_debug_message` per byte of passed message.
191	DebugMessage(u32),
192	/// Weight of calling `seal_set_storage` for the given storage item sizes.
193	SetStorage { old_bytes: u32, new_bytes: u32 },
194	/// Weight of calling `seal_clear_storage` per cleared byte.
195	ClearStorage(u32),
196	/// Weight of calling `seal_contains_storage` per byte of the checked item.
197	ContainsStorage(u32),
198	/// Weight of calling `seal_get_storage` with the specified size in storage.
199	GetStorage(u32),
200	/// Weight of calling `seal_take_storage` for the given size.
201	TakeStorage(u32),
202	/// Weight of calling `seal_set_transient_storage` for the given storage item sizes.
203	SetTransientStorage { old_bytes: u32, new_bytes: u32 },
204	/// Weight of calling `seal_clear_transient_storage` per cleared byte.
205	ClearTransientStorage(u32),
206	/// Weight of calling `seal_contains_transient_storage` per byte of the checked item.
207	ContainsTransientStorage(u32),
208	/// Weight of calling `seal_get_transient_storage` with the specified size in storage.
209	GetTransientStorage(u32),
210	/// Weight of calling `seal_take_transient_storage` for the given size.
211	TakeTransientStorage(u32),
212	/// Weight of calling `seal_transfer`.
213	Transfer,
214	/// Base weight of calling `seal_call`.
215	CallBase,
216	/// Weight of calling `seal_delegate_call` for the given input size.
217	DelegateCallBase,
218	/// Weight of the transfer performed during a call.
219	CallTransferSurcharge,
220	/// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag.
221	CallInputCloned(u32),
222	/// Weight of calling `seal_instantiate` for the given input length and salt.
223	Instantiate { input_data_len: u32, salt_len: u32 },
224	/// Weight of calling `seal_hash_sha_256` for the given input size.
225	HashSha256(u32),
226	/// Weight of calling `seal_hash_keccak_256` for the given input size.
227	HashKeccak256(u32),
228	/// Weight of calling `seal_hash_blake2_256` for the given input size.
229	HashBlake256(u32),
230	/// Weight of calling `seal_hash_blake2_128` for the given input size.
231	HashBlake128(u32),
232	/// Weight of calling `seal_ecdsa_recover`.
233	EcdsaRecovery,
234	/// Weight of calling `seal_sr25519_verify` for the given input size.
235	Sr25519Verify(u32),
236	/// Weight charged by a chain extension through `seal_call_chain_extension`.
237	ChainExtension(Weight),
238	/// Weight charged for calling into the runtime.
239	CallRuntime(Weight),
240	/// Weight charged for calling xcm_execute.
241	CallXcmExecute(Weight),
242	/// Weight of calling `seal_set_code_hash`
243	SetCodeHash,
244	/// Weight of calling `ecdsa_to_eth_address`
245	EcdsaToEthAddress,
246	/// Weight of calling `reentrance_count`
247	ReentranceCount,
248	/// Weight of calling `account_reentrance_count`
249	AccountReentranceCount,
250	/// Weight of calling `instantiation_nonce`
251	InstantiationNonce,
252	/// Weight of calling `lock_delegate_dependency`
253	LockDelegateDependency,
254	/// Weight of calling `unlock_delegate_dependency`
255	UnlockDelegateDependency,
256}
257
258/// For functions that modify storage, benchmarks are performed with one item in the
259/// storage. To account for the worst-case scenario, the weight of the overhead of
260/// writing to or reading from full storage is included. For transient storage writes,
261/// the rollback weight is added to reflect the worst-case scenario for this operation.
262macro_rules! cost_storage {
263    (write_transient, $name:ident $(, $arg:expr )*) => {
264        T::WeightInfo::$name($( $arg ),*)
265            .saturating_add(T::WeightInfo::rollback_transient_storage())
266            .saturating_add(T::WeightInfo::set_transient_storage_full()
267            .saturating_sub(T::WeightInfo::set_transient_storage_empty()))
268    };
269
270    (read_transient, $name:ident $(, $arg:expr )*) => {
271        T::WeightInfo::$name($( $arg ),*)
272            .saturating_add(T::WeightInfo::get_transient_storage_full()
273            .saturating_sub(T::WeightInfo::get_transient_storage_empty()))
274    };
275
276    (write, $name:ident $(, $arg:expr )*) => {
277        T::WeightInfo::$name($( $arg ),*)
278            .saturating_add(T::WeightInfo::set_storage_full()
279            .saturating_sub(T::WeightInfo::set_storage_empty()))
280    };
281
282    (read, $name:ident $(, $arg:expr )*) => {
283        T::WeightInfo::$name($( $arg ),*)
284            .saturating_add(T::WeightInfo::get_storage_full()
285            .saturating_sub(T::WeightInfo::get_storage_empty()))
286    };
287}
288
289macro_rules! cost_args {
290	// cost_args!(name, a, b, c) -> T::WeightInfo::name(a, b, c).saturating_sub(T::WeightInfo::name(0, 0, 0))
291	($name:ident, $( $arg: expr ),+) => {
292		(T::WeightInfo::$name($( $arg ),+).saturating_sub(cost_args!(@call_zero $name, $( $arg ),+)))
293	};
294	// Transform T::WeightInfo::name(a, b, c) into T::WeightInfo::name(0, 0, 0)
295	(@call_zero $name:ident, $( $arg:expr ),*) => {
296		T::WeightInfo::$name($( cost_args!(@replace_token $arg) ),*)
297	};
298	// Replace the token with 0.
299	(@replace_token $_in:tt) => { 0 };
300}
301
302impl<T: Config> Token<T> for RuntimeCosts {
303	fn influence_lowest_gas_limit(&self) -> bool {
304		match self {
305			&Self::CallXcmExecute(_) => false,
306			_ => true,
307		}
308	}
309
310	fn weight(&self) -> Weight {
311		use self::RuntimeCosts::*;
312		match *self {
313			HostFn => cost_args!(noop_host_fn, 1),
314			CopyToContract(len) => T::WeightInfo::seal_input(len),
315			CopyFromContract(len) => T::WeightInfo::seal_return(len),
316			Caller => T::WeightInfo::seal_caller(),
317			IsContract => T::WeightInfo::seal_is_contract(),
318			CodeHash => T::WeightInfo::seal_code_hash(),
319			OwnCodeHash => T::WeightInfo::seal_own_code_hash(),
320			CallerIsOrigin => T::WeightInfo::seal_caller_is_origin(),
321			CallerIsRoot => T::WeightInfo::seal_caller_is_root(),
322			Address => T::WeightInfo::seal_address(),
323			GasLeft => T::WeightInfo::seal_gas_left(),
324			Balance => T::WeightInfo::seal_balance(),
325			ValueTransferred => T::WeightInfo::seal_value_transferred(),
326			MinimumBalance => T::WeightInfo::seal_minimum_balance(),
327			BlockNumber => T::WeightInfo::seal_block_number(),
328			Now => T::WeightInfo::seal_now(),
329			WeightToFee => T::WeightInfo::seal_weight_to_fee(),
330			Terminate(locked_dependencies) => T::WeightInfo::seal_terminate(locked_dependencies),
331			Random => T::WeightInfo::seal_random(),
332			// Given a 2-second block time and hardcoding a `ref_time` of 60,000 picoseconds per
333			// byte  (event_ref_time), the max allocation size is 32MB per block.
334			DepositEvent { num_topic, len } => T::WeightInfo::seal_deposit_event(num_topic, len)
335				.saturating_add(Weight::from_parts(
336					T::Schedule::get().limits.event_ref_time.saturating_mul(len.into()),
337					0,
338				)),
339			DebugMessage(len) => T::WeightInfo::seal_debug_message(len),
340			SetStorage { new_bytes, old_bytes } => {
341				cost_storage!(write, seal_set_storage, new_bytes, old_bytes)
342			},
343			ClearStorage(len) => cost_storage!(write, seal_clear_storage, len),
344			ContainsStorage(len) => cost_storage!(read, seal_contains_storage, len),
345			GetStorage(len) => cost_storage!(read, seal_get_storage, len),
346			TakeStorage(len) => cost_storage!(write, seal_take_storage, len),
347			SetTransientStorage { new_bytes, old_bytes } => {
348				cost_storage!(write_transient, seal_set_transient_storage, new_bytes, old_bytes)
349			},
350			ClearTransientStorage(len) => {
351				cost_storage!(write_transient, seal_clear_transient_storage, len)
352			},
353			ContainsTransientStorage(len) => {
354				cost_storage!(read_transient, seal_contains_transient_storage, len)
355			},
356			GetTransientStorage(len) => {
357				cost_storage!(read_transient, seal_get_transient_storage, len)
358			},
359			TakeTransientStorage(len) => {
360				cost_storage!(write_transient, seal_take_transient_storage, len)
361			},
362			Transfer => T::WeightInfo::seal_transfer(),
363			CallBase => T::WeightInfo::seal_call(0, 0),
364			DelegateCallBase => T::WeightInfo::seal_delegate_call(),
365			CallTransferSurcharge => cost_args!(seal_call, 1, 0),
366			CallInputCloned(len) => cost_args!(seal_call, 0, len),
367			Instantiate { input_data_len, salt_len } => {
368				T::WeightInfo::seal_instantiate(input_data_len, salt_len)
369			},
370			HashSha256(len) => T::WeightInfo::seal_hash_sha2_256(len),
371			HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len),
372			HashBlake256(len) => T::WeightInfo::seal_hash_blake2_256(len),
373			HashBlake128(len) => T::WeightInfo::seal_hash_blake2_128(len),
374			EcdsaRecovery => T::WeightInfo::seal_ecdsa_recover(),
375			Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len),
376			ChainExtension(weight) | CallRuntime(weight) | CallXcmExecute(weight) => weight,
377			SetCodeHash => T::WeightInfo::seal_set_code_hash(),
378			EcdsaToEthAddress => T::WeightInfo::seal_ecdsa_to_eth_address(),
379			ReentranceCount => T::WeightInfo::seal_reentrance_count(),
380			AccountReentranceCount => T::WeightInfo::seal_account_reentrance_count(),
381			InstantiationNonce => T::WeightInfo::seal_instantiation_nonce(),
382			LockDelegateDependency => T::WeightInfo::lock_delegate_dependency(),
383			UnlockDelegateDependency => T::WeightInfo::unlock_delegate_dependency(),
384		}
385	}
386}
387
388/// Same as [`Runtime::charge_gas`].
389///
390/// We need this access as a macro because sometimes hiding the lifetimes behind
391/// a function won't work out.
392macro_rules! charge_gas {
393	($runtime:expr, $costs:expr) => {{
394		$runtime.ext.gas_meter_mut().charge($costs)
395	}};
396}
397
398/// The kind of call that should be performed.
399enum CallType {
400	/// Execute another instantiated contract
401	Call { callee_ptr: u32, value_ptr: u32, deposit_ptr: u32, weight: Weight },
402	/// Execute deployed code in the context (storage, account ID, value) of the caller contract
403	DelegateCall { code_hash_ptr: u32 },
404}
405
406impl CallType {
407	fn cost(&self) -> RuntimeCosts {
408		match self {
409			CallType::Call { .. } => RuntimeCosts::CallBase,
410			CallType::DelegateCall { .. } => RuntimeCosts::DelegateCallBase,
411		}
412	}
413}
414
415/// This is only appropriate when writing out data of constant size that does not depend on user
416/// input. In this case the costs for this copy was already charged as part of the token at
417/// the beginning of the API entry point.
418fn already_charged(_: u32) -> Option<RuntimeCosts> {
419	None
420}
421
422/// Can only be used for one call.
423pub struct Runtime<'a, E: Ext + 'a> {
424	ext: &'a mut E,
425	input_data: Option<Vec<u8>>,
426	memory: Option<Memory>,
427	chain_extension: Option<Box<<E::T as Config>::ChainExtension>>,
428}
429
430impl<'a, E: Ext + 'a> Runtime<'a, E> {
431	pub fn new(ext: &'a mut E, input_data: Vec<u8>) -> Self {
432		Runtime {
433			ext,
434			input_data: Some(input_data),
435			memory: None,
436			chain_extension: Some(Box::new(Default::default())),
437		}
438	}
439
440	pub fn memory(&self) -> Option<Memory> {
441		self.memory
442	}
443
444	pub fn set_memory(&mut self, memory: Memory) {
445		self.memory = Some(memory);
446	}
447
448	/// Converts the sandbox result and the runtime state into the execution outcome.
449	pub fn to_execution_result(self, sandbox_result: Result<(), wasmi::Error>) -> ExecResult {
450		use wasmi::{
451			core::TrapCode,
452			errors::{ErrorKind, FuelError},
453		};
454		use TrapReason::*;
455
456		let Err(error) = sandbox_result else {
457			// Contract returned from main function -> no data was returned.
458			return Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() });
459		};
460		if let ErrorKind::Fuel(FuelError::OutOfFuel) = error.kind() {
461			// `OutOfGas` when host asks engine to consume more than left in the _store_.
462			// We should never get this case, as gas meter is being charged (and hence raises error)
463			// first.
464			return Err(Error::<E::T>::OutOfGas.into());
465		}
466		match error.as_trap_code() {
467			Some(TrapCode::OutOfFuel) => {
468				// `OutOfGas` during engine execution.
469				return Err(Error::<E::T>::OutOfGas.into());
470			},
471			Some(_trap_code) => {
472				// Otherwise the trap came from the contract itself.
473				return Err(Error::<E::T>::ContractTrapped.into());
474			},
475			None => {},
476		}
477		// If we encoded a reason then it is some abort generated by a host function.
478		if let Some(reason) = &error.downcast_ref::<TrapReason>() {
479			match &reason {
480				Return(ReturnData { flags, data }) => {
481					let flags =
482						ReturnFlags::from_bits(*flags).ok_or(Error::<E::T>::InvalidCallFlags)?;
483					return Ok(ExecReturnValue { flags, data: data.to_vec() });
484				},
485				Termination => {
486					return Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
487				},
488				SupervisorError(error) => return Err((*error).into()),
489			}
490		}
491
492		// Any other error is returned only if instantiation or linking failed (i.e.
493		// wasm binary tried to import a function that is not provided by the host).
494		// This shouldn't happen because validation process ought to reject such binaries.
495		//
496		// Because panics are really undesirable in the runtime code, we treat this as
497		// a trap for now. Eventually, we might want to revisit this.
498		log::debug!("Code rejected: {:?}", error);
499		Err(Error::<E::T>::CodeRejected.into())
500	}
501
502	/// Get a mutable reference to the inner `Ext`.
503	///
504	/// This is mainly for the chain extension to have access to the environment the
505	/// contract is executing in.
506	pub fn ext(&mut self) -> &mut E {
507		self.ext
508	}
509
510	/// Charge the gas meter with the specified token.
511	///
512	/// Returns `Err(HostError)` if there is not enough gas.
513	pub fn charge_gas(&mut self, costs: RuntimeCosts) -> Result<ChargedAmount, DispatchError> {
514		charge_gas!(self, costs)
515	}
516
517	/// Adjust a previously charged amount down to its actual amount.
518	///
519	/// This is when a maximum a priori amount was charged and then should be partially
520	/// refunded to match the actual amount.
521	pub fn adjust_gas(&mut self, charged: ChargedAmount, actual_costs: RuntimeCosts) {
522		self.ext.gas_meter_mut().adjust_gas(charged, actual_costs);
523	}
524
525	/// Charge, Run and adjust gas, for executing the given dispatchable.
526	fn call_dispatchable<ErrorReturnCode: Get<ReturnErrorCode>>(
527		&mut self,
528		dispatch_info: DispatchInfo,
529		runtime_cost: impl Fn(Weight) -> RuntimeCosts,
530		run: impl FnOnce(&mut Self) -> DispatchResultWithPostInfo,
531	) -> Result<ReturnErrorCode, TrapReason> {
532		use frame_support::dispatch::extract_actual_weight;
533		let charged = self.charge_gas(runtime_cost(dispatch_info.call_weight))?;
534		let result = run(self);
535		let actual_weight = extract_actual_weight(&result, &dispatch_info);
536		self.adjust_gas(charged, runtime_cost(actual_weight));
537		match result {
538			Ok(_) => Ok(ReturnErrorCode::Success),
539			Err(e) => {
540				if self.ext.debug_buffer_enabled() {
541					self.ext.append_debug_buffer("call failed with: ");
542					self.ext.append_debug_buffer(e.into());
543				};
544				Ok(ErrorReturnCode::get())
545			},
546		}
547	}
548
549	/// Read designated chunk from the sandbox memory.
550	///
551	/// Returns `Err` if one of the following conditions occurs:
552	///
553	/// - requested buffer is not within the bounds of the sandbox memory.
554	pub fn read_sandbox_memory(
555		&self,
556		memory: &[u8],
557		ptr: u32,
558		len: u32,
559	) -> Result<Vec<u8>, DispatchError> {
560		ensure!(len <= self.ext.schedule().limits.max_memory_size(), Error::<E::T>::OutOfBounds);
561		let mut buf = vec![0u8; len as usize];
562		self.read_sandbox_memory_into_buf(memory, ptr, buf.as_mut_slice())?;
563		Ok(buf)
564	}
565
566	/// Read designated chunk from the sandbox memory into the supplied buffer.
567	///
568	/// Returns `Err` if one of the following conditions occurs:
569	///
570	/// - requested buffer is not within the bounds of the sandbox memory.
571	pub fn read_sandbox_memory_into_buf(
572		&self,
573		memory: &[u8],
574		ptr: u32,
575		buf: &mut [u8],
576	) -> Result<(), DispatchError> {
577		let ptr = ptr as usize;
578		let bound_checked =
579			memory.get(ptr..ptr + buf.len()).ok_or_else(|| Error::<E::T>::OutOfBounds)?;
580		buf.copy_from_slice(bound_checked);
581		Ok(())
582	}
583
584	/// Reads and decodes a type with a size fixed at compile time from contract memory.
585	///
586	/// # Note
587	///
588	/// The weight of reading a fixed value is included in the overall weight of any
589	/// contract callable function.
590	pub fn read_sandbox_memory_as<D: Decode + MaxEncodedLen>(
591		&self,
592		memory: &[u8],
593		ptr: u32,
594	) -> Result<D, DispatchError> {
595		let ptr = ptr as usize;
596		let mut bound_checked = memory.get(ptr..).ok_or_else(|| Error::<E::T>::OutOfBounds)?;
597
598		let decoded = D::decode_with_depth_limit(MAX_DECODE_NESTING, &mut bound_checked)
599			.map_err(|_| DispatchError::from(Error::<E::T>::DecodingFailed))?;
600		Ok(decoded)
601	}
602
603	/// Read designated chunk from the sandbox memory and attempt to decode into the specified type.
604	///
605	/// Returns `Err` if one of the following conditions occurs:
606	///
607	/// - requested buffer is not within the bounds of the sandbox memory.
608	/// - the buffer contents cannot be decoded as the required type.
609	///
610	/// # Note
611	///
612	/// There must be an extra benchmark for determining the influence of `len` with
613	/// regard to the overall weight.
614	pub fn read_sandbox_memory_as_unbounded<D: Decode>(
615		&self,
616		memory: &[u8],
617		ptr: u32,
618		len: u32,
619	) -> Result<D, DispatchError> {
620		let ptr = ptr as usize;
621		let mut bound_checked =
622			memory.get(ptr..ptr + len as usize).ok_or_else(|| Error::<E::T>::OutOfBounds)?;
623
624		let decoded = D::decode_all_with_depth_limit(MAX_DECODE_NESTING, &mut bound_checked)
625			.map_err(|_| DispatchError::from(Error::<E::T>::DecodingFailed))?;
626
627		Ok(decoded)
628	}
629
630	/// Write the given buffer and its length to the designated locations in sandbox memory and
631	/// charge gas according to the token returned by `create_token`.
632	//
633	/// `out_ptr` is the location in sandbox memory where `buf` should be written to.
634	/// `out_len_ptr` is an in-out location in sandbox memory. It is read to determine the
635	/// length of the buffer located at `out_ptr`. If that buffer is large enough the actual
636	/// `buf.len()` is written to this location.
637	///
638	/// If `out_ptr` is set to the sentinel value of `SENTINEL` and `allow_skip` is true the
639	/// operation is skipped and `Ok` is returned. This is supposed to help callers to make copying
640	/// output optional. For example to skip copying back the output buffer of an `seal_call`
641	/// when the caller is not interested in the result.
642	///
643	/// `create_token` can optionally instruct this function to charge the gas meter with the token
644	/// it returns. `create_token` receives the variable amount of bytes that are about to be copied
645	/// by this function.
646	///
647	/// In addition to the error conditions of `write_sandbox_memory` this functions returns
648	/// `Err` if the size of the buffer located at `out_ptr` is too small to fit `buf`.
649	pub fn write_sandbox_output(
650		&mut self,
651		memory: &mut [u8],
652		out_ptr: u32,
653		out_len_ptr: u32,
654		buf: &[u8],
655		allow_skip: bool,
656		create_token: impl FnOnce(u32) -> Option<RuntimeCosts>,
657	) -> Result<(), DispatchError> {
658		if allow_skip && out_ptr == SENTINEL {
659			return Ok(());
660		}
661
662		let buf_len = buf.len() as u32;
663		let len: u32 = self.read_sandbox_memory_as(memory, out_len_ptr)?;
664
665		if len < buf_len {
666			return Err(Error::<E::T>::OutputBufferTooSmall.into());
667		}
668
669		if let Some(costs) = create_token(buf_len) {
670			self.charge_gas(costs)?;
671		}
672
673		self.write_sandbox_memory(memory, out_ptr, buf)?;
674		self.write_sandbox_memory(memory, out_len_ptr, &buf_len.encode())
675	}
676
677	/// Write the given buffer to the designated location in the sandbox memory.
678	///
679	/// Returns `Err` if one of the following conditions occurs:
680	///
681	/// - designated area is not within the bounds of the sandbox memory.
682	fn write_sandbox_memory(
683		&self,
684		memory: &mut [u8],
685		ptr: u32,
686		buf: &[u8],
687	) -> Result<(), DispatchError> {
688		let ptr = ptr as usize;
689		let bound_checked =
690			memory.get_mut(ptr..ptr + buf.len()).ok_or_else(|| Error::<E::T>::OutOfBounds)?;
691		bound_checked.copy_from_slice(buf);
692		Ok(())
693	}
694
695	/// Computes the given hash function on the supplied input.
696	///
697	/// Reads from the sandboxed input buffer into an intermediate buffer.
698	/// Returns the result directly to the output buffer of the sandboxed memory.
699	///
700	/// It is the callers responsibility to provide an output buffer that
701	/// is large enough to hold the expected amount of bytes returned by the
702	/// chosen hash function.
703	///
704	/// # Note
705	///
706	/// The `input` and `output` buffers may overlap.
707	fn compute_hash_on_intermediate_buffer<F, R>(
708		&self,
709		memory: &mut [u8],
710		hash_fn: F,
711		input_ptr: u32,
712		input_len: u32,
713		output_ptr: u32,
714	) -> Result<(), DispatchError>
715	where
716		F: FnOnce(&[u8]) -> R,
717		R: AsRef<[u8]>,
718	{
719		// Copy input into supervisor memory.
720		let input = self.read_sandbox_memory(memory, input_ptr, input_len)?;
721		// Compute the hash on the input buffer using the given hash function.
722		let hash = hash_fn(&input);
723		// Write the resulting hash back into the sandboxed output buffer.
724		self.write_sandbox_memory(memory, output_ptr, hash.as_ref())?;
725		Ok(())
726	}
727
728	/// Fallible conversion of `DispatchError` to `ReturnErrorCode`.
729	fn err_into_return_code(from: DispatchError) -> Result<ReturnErrorCode, DispatchError> {
730		use ReturnErrorCode::*;
731
732		let transfer_failed = Error::<E::T>::TransferFailed.into();
733		let no_code = Error::<E::T>::CodeNotFound.into();
734		let not_found = Error::<E::T>::ContractNotFound.into();
735
736		match from {
737			x if x == transfer_failed => Ok(TransferFailed),
738			x if x == no_code => Ok(CodeNotFound),
739			x if x == not_found => Ok(NotCallable),
740			err => Err(err),
741		}
742	}
743
744	/// Fallible conversion of a `ExecResult` to `ReturnErrorCode`.
745	fn exec_into_return_code(from: ExecResult) -> Result<ReturnErrorCode, DispatchError> {
746		use crate::exec::ErrorOrigin::Callee;
747
748		let ExecError { error, origin } = match from {
749			Ok(retval) => return Ok(retval.into()),
750			Err(err) => err,
751		};
752
753		match (error, origin) {
754			(_, Callee) => Ok(ReturnErrorCode::CalleeTrapped),
755			(err, _) => Self::err_into_return_code(err),
756		}
757	}
758	fn decode_key(
759		&self,
760		memory: &[u8],
761		key_type: KeyType,
762		key_ptr: u32,
763	) -> Result<crate::exec::Key<E::T>, TrapReason> {
764		let res = match key_type {
765			KeyType::Fix => {
766				let key = self.read_sandbox_memory(memory, key_ptr, 32u32)?;
767				Key::try_from_fix(key)
768			},
769			KeyType::Var(len) => {
770				ensure!(
771					len <= <<E as Ext>::T as Config>::MaxStorageKeyLen::get(),
772					Error::<E::T>::DecodingFailed
773				);
774				let key = self.read_sandbox_memory(memory, key_ptr, len)?;
775				Key::try_from_var(key)
776			},
777		};
778
779		res.map_err(|_| Error::<E::T>::DecodingFailed.into())
780	}
781
782	fn set_storage(
783		&mut self,
784		memory: &[u8],
785		key_type: KeyType,
786		key_ptr: u32,
787		value_ptr: u32,
788		value_len: u32,
789	) -> Result<u32, TrapReason> {
790		let max_size = self.ext.max_value_size();
791		let charged = self
792			.charge_gas(RuntimeCosts::SetStorage { new_bytes: value_len, old_bytes: max_size })?;
793		if value_len > max_size {
794			return Err(Error::<E::T>::ValueTooLarge.into());
795		}
796		let key = self.decode_key(memory, key_type, key_ptr)?;
797		let value = Some(self.read_sandbox_memory(memory, value_ptr, value_len)?);
798		let write_outcome = self.ext.set_storage(&key, value, false)?;
799
800		self.adjust_gas(
801			charged,
802			RuntimeCosts::SetStorage { new_bytes: value_len, old_bytes: write_outcome.old_len() },
803		);
804		Ok(write_outcome.old_len_with_sentinel())
805	}
806
807	fn clear_storage(
808		&mut self,
809		memory: &[u8],
810		key_type: KeyType,
811		key_ptr: u32,
812	) -> Result<u32, TrapReason> {
813		let charged = self.charge_gas(RuntimeCosts::ClearStorage(self.ext.max_value_size()))?;
814		let key = self.decode_key(memory, key_type, key_ptr)?;
815		let outcome = self.ext.set_storage(&key, None, false)?;
816
817		self.adjust_gas(charged, RuntimeCosts::ClearStorage(outcome.old_len()));
818		Ok(outcome.old_len_with_sentinel())
819	}
820
821	fn get_storage(
822		&mut self,
823		memory: &mut [u8],
824		key_type: KeyType,
825		key_ptr: u32,
826		out_ptr: u32,
827		out_len_ptr: u32,
828	) -> Result<ReturnErrorCode, TrapReason> {
829		let charged = self.charge_gas(RuntimeCosts::GetStorage(self.ext.max_value_size()))?;
830		let key = self.decode_key(memory, key_type, key_ptr)?;
831		let outcome = self.ext.get_storage(&key);
832
833		if let Some(value) = outcome {
834			self.adjust_gas(charged, RuntimeCosts::GetStorage(value.len() as u32));
835			self.write_sandbox_output(
836				memory,
837				out_ptr,
838				out_len_ptr,
839				&value,
840				false,
841				already_charged,
842			)?;
843			Ok(ReturnErrorCode::Success)
844		} else {
845			self.adjust_gas(charged, RuntimeCosts::GetStorage(0));
846			Ok(ReturnErrorCode::KeyNotFound)
847		}
848	}
849
850	fn contains_storage(
851		&mut self,
852		memory: &[u8],
853		key_type: KeyType,
854		key_ptr: u32,
855	) -> Result<u32, TrapReason> {
856		let charged = self.charge_gas(RuntimeCosts::ContainsStorage(self.ext.max_value_size()))?;
857		let key = self.decode_key(memory, key_type, key_ptr)?;
858		let outcome = self.ext.get_storage_size(&key);
859
860		self.adjust_gas(charged, RuntimeCosts::ContainsStorage(outcome.unwrap_or(0)));
861		Ok(outcome.unwrap_or(SENTINEL))
862	}
863
864	fn set_transient_storage(
865		&mut self,
866		memory: &[u8],
867		key_type: KeyType,
868		key_ptr: u32,
869		value_ptr: u32,
870		value_len: u32,
871	) -> Result<u32, TrapReason> {
872		let max_size = self.ext.max_value_size();
873		let charged = self.charge_gas(RuntimeCosts::SetTransientStorage {
874			new_bytes: value_len,
875			old_bytes: max_size,
876		})?;
877		if value_len > max_size {
878			return Err(Error::<E::T>::ValueTooLarge.into());
879		}
880		let key = self.decode_key(memory, key_type, key_ptr)?;
881		let value = Some(self.read_sandbox_memory(memory, value_ptr, value_len)?);
882		let write_outcome = self.ext.set_transient_storage(&key, value, false)?;
883		self.adjust_gas(
884			charged,
885			RuntimeCosts::SetTransientStorage {
886				new_bytes: value_len,
887				old_bytes: write_outcome.old_len(),
888			},
889		);
890		Ok(write_outcome.old_len_with_sentinel())
891	}
892
893	fn clear_transient_storage(
894		&mut self,
895		memory: &[u8],
896		key_type: KeyType,
897		key_ptr: u32,
898	) -> Result<u32, TrapReason> {
899		let charged =
900			self.charge_gas(RuntimeCosts::ClearTransientStorage(self.ext.max_value_size()))?;
901		let key = self.decode_key(memory, key_type, key_ptr)?;
902		let outcome = self.ext.set_transient_storage(&key, None, false)?;
903
904		self.adjust_gas(charged, RuntimeCosts::ClearTransientStorage(outcome.old_len()));
905		Ok(outcome.old_len_with_sentinel())
906	}
907
908	fn get_transient_storage(
909		&mut self,
910		memory: &mut [u8],
911		key_type: KeyType,
912		key_ptr: u32,
913		out_ptr: u32,
914		out_len_ptr: u32,
915	) -> Result<ReturnErrorCode, TrapReason> {
916		let charged =
917			self.charge_gas(RuntimeCosts::GetTransientStorage(self.ext.max_value_size()))?;
918		let key = self.decode_key(memory, key_type, key_ptr)?;
919		let outcome = self.ext.get_transient_storage(&key);
920
921		if let Some(value) = outcome {
922			self.adjust_gas(charged, RuntimeCosts::GetTransientStorage(value.len() as u32));
923			self.write_sandbox_output(
924				memory,
925				out_ptr,
926				out_len_ptr,
927				&value,
928				false,
929				already_charged,
930			)?;
931			Ok(ReturnErrorCode::Success)
932		} else {
933			self.adjust_gas(charged, RuntimeCosts::GetTransientStorage(0));
934			Ok(ReturnErrorCode::KeyNotFound)
935		}
936	}
937
938	fn contains_transient_storage(
939		&mut self,
940		memory: &[u8],
941		key_type: KeyType,
942		key_ptr: u32,
943	) -> Result<u32, TrapReason> {
944		let charged =
945			self.charge_gas(RuntimeCosts::ContainsTransientStorage(self.ext.max_value_size()))?;
946		let key = self.decode_key(memory, key_type, key_ptr)?;
947		let outcome = self.ext.get_transient_storage_size(&key);
948
949		self.adjust_gas(charged, RuntimeCosts::ContainsTransientStorage(outcome.unwrap_or(0)));
950		Ok(outcome.unwrap_or(SENTINEL))
951	}
952
953	fn take_transient_storage(
954		&mut self,
955		memory: &mut [u8],
956		key_type: KeyType,
957		key_ptr: u32,
958		out_ptr: u32,
959		out_len_ptr: u32,
960	) -> Result<ReturnErrorCode, TrapReason> {
961		let charged =
962			self.charge_gas(RuntimeCosts::TakeTransientStorage(self.ext.max_value_size()))?;
963		let key = self.decode_key(memory, key_type, key_ptr)?;
964		if let crate::storage::WriteOutcome::Taken(value) =
965			self.ext.set_transient_storage(&key, None, true)?
966		{
967			self.adjust_gas(charged, RuntimeCosts::TakeTransientStorage(value.len() as u32));
968			self.write_sandbox_output(
969				memory,
970				out_ptr,
971				out_len_ptr,
972				&value,
973				false,
974				already_charged,
975			)?;
976			Ok(ReturnErrorCode::Success)
977		} else {
978			self.adjust_gas(charged, RuntimeCosts::TakeTransientStorage(0));
979			Ok(ReturnErrorCode::KeyNotFound)
980		}
981	}
982
983	fn call(
984		&mut self,
985		memory: &mut [u8],
986		flags: CallFlags,
987		call_type: CallType,
988		input_data_ptr: u32,
989		input_data_len: u32,
990		output_ptr: u32,
991		output_len_ptr: u32,
992	) -> Result<ReturnErrorCode, TrapReason> {
993		self.charge_gas(call_type.cost())?;
994
995		let input_data = if flags.contains(CallFlags::CLONE_INPUT) {
996			let input = self.input_data.as_ref().ok_or(Error::<E::T>::InputForwarded)?;
997			charge_gas!(self, RuntimeCosts::CallInputCloned(input.len() as u32))?;
998			input.clone()
999		} else if flags.contains(CallFlags::FORWARD_INPUT) {
1000			self.input_data.take().ok_or(Error::<E::T>::InputForwarded)?
1001		} else {
1002			self.charge_gas(RuntimeCosts::CopyFromContract(input_data_len))?;
1003			self.read_sandbox_memory(memory, input_data_ptr, input_data_len)?
1004		};
1005
1006		let call_outcome = match call_type {
1007			CallType::Call { callee_ptr, value_ptr, deposit_ptr, weight } => {
1008				let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
1009					self.read_sandbox_memory_as(memory, callee_ptr)?;
1010				let deposit_limit: BalanceOf<<E as Ext>::T> = if deposit_ptr == SENTINEL {
1011					BalanceOf::<<E as Ext>::T>::zero()
1012				} else {
1013					self.read_sandbox_memory_as(memory, deposit_ptr)?
1014				};
1015				let read_only = flags.contains(CallFlags::READ_ONLY);
1016				let value: BalanceOf<<E as Ext>::T> =
1017					self.read_sandbox_memory_as(memory, value_ptr)?;
1018				if value > 0u32.into() {
1019					// If the call value is non-zero and state change is not allowed, issue an
1020					// error.
1021					if read_only || self.ext.is_read_only() {
1022						return Err(Error::<E::T>::StateChangeDenied.into());
1023					}
1024					self.charge_gas(RuntimeCosts::CallTransferSurcharge)?;
1025				}
1026				self.ext.call(
1027					weight,
1028					deposit_limit,
1029					callee,
1030					value,
1031					input_data,
1032					flags.contains(CallFlags::ALLOW_REENTRY),
1033					read_only,
1034				)
1035			},
1036			CallType::DelegateCall { code_hash_ptr } => {
1037				if flags.intersects(CallFlags::ALLOW_REENTRY | CallFlags::READ_ONLY) {
1038					return Err(Error::<E::T>::InvalidCallFlags.into());
1039				}
1040				let code_hash = self.read_sandbox_memory_as(memory, code_hash_ptr)?;
1041				self.ext.delegate_call(code_hash, input_data)
1042			},
1043		};
1044
1045		// `TAIL_CALL` only matters on an `OK` result. Otherwise the call stack comes to
1046		// a halt anyways without anymore code being executed.
1047		if flags.contains(CallFlags::TAIL_CALL) {
1048			if let Ok(return_value) = call_outcome {
1049				return Err(TrapReason::Return(ReturnData {
1050					flags: return_value.flags.bits(),
1051					data: return_value.data,
1052				}));
1053			}
1054		}
1055
1056		if let Ok(output) = &call_outcome {
1057			self.write_sandbox_output(
1058				memory,
1059				output_ptr,
1060				output_len_ptr,
1061				&output.data,
1062				true,
1063				|len| Some(RuntimeCosts::CopyToContract(len)),
1064			)?;
1065		}
1066		Ok(Runtime::<E>::exec_into_return_code(call_outcome)?)
1067	}
1068
1069	fn instantiate(
1070		&mut self,
1071		memory: &mut [u8],
1072		code_hash_ptr: u32,
1073		weight: Weight,
1074		deposit_ptr: u32,
1075		value_ptr: u32,
1076		input_data_ptr: u32,
1077		input_data_len: u32,
1078		address_ptr: u32,
1079		address_len_ptr: u32,
1080		output_ptr: u32,
1081		output_len_ptr: u32,
1082		salt_ptr: u32,
1083		salt_len: u32,
1084	) -> Result<ReturnErrorCode, TrapReason> {
1085		self.charge_gas(RuntimeCosts::Instantiate { input_data_len, salt_len })?;
1086		let deposit_limit: BalanceOf<<E as Ext>::T> = if deposit_ptr == SENTINEL {
1087			BalanceOf::<<E as Ext>::T>::zero()
1088		} else {
1089			self.read_sandbox_memory_as(memory, deposit_ptr)?
1090		};
1091		let value: BalanceOf<<E as Ext>::T> = self.read_sandbox_memory_as(memory, value_ptr)?;
1092		let code_hash: CodeHash<<E as Ext>::T> =
1093			self.read_sandbox_memory_as(memory, code_hash_ptr)?;
1094		let input_data = self.read_sandbox_memory(memory, input_data_ptr, input_data_len)?;
1095		let salt = self.read_sandbox_memory(memory, salt_ptr, salt_len)?;
1096		let instantiate_outcome =
1097			self.ext.instantiate(weight, deposit_limit, code_hash, value, input_data, &salt);
1098		if let Ok((address, output)) = &instantiate_outcome {
1099			if !output.flags.contains(ReturnFlags::REVERT) {
1100				self.write_sandbox_output(
1101					memory,
1102					address_ptr,
1103					address_len_ptr,
1104					&address.encode(),
1105					true,
1106					already_charged,
1107				)?;
1108			}
1109			self.write_sandbox_output(
1110				memory,
1111				output_ptr,
1112				output_len_ptr,
1113				&output.data,
1114				true,
1115				|len| Some(RuntimeCosts::CopyToContract(len)),
1116			)?;
1117		}
1118		Ok(Runtime::<E>::exec_into_return_code(instantiate_outcome.map(|(_, retval)| retval))?)
1119	}
1120
1121	fn terminate(&mut self, memory: &[u8], beneficiary_ptr: u32) -> Result<(), TrapReason> {
1122		let count = self.ext.locked_delegate_dependencies_count() as _;
1123		self.charge_gas(RuntimeCosts::Terminate(count))?;
1124
1125		let beneficiary: <<E as Ext>::T as frame_system::Config>::AccountId =
1126			self.read_sandbox_memory_as(memory, beneficiary_ptr)?;
1127		self.ext.terminate(&beneficiary)?;
1128		Err(TrapReason::Termination)
1129	}
1130}
1131
1132// This is the API exposed to contracts.
1133//
1134// # Note
1135//
1136// Any input that leads to a out of bound error (reading or writing) or failing to decode
1137// data passed to the supervisor will lead to a trap. This is not documented explicitly
1138// for every function.
1139#[define_env(doc)]
1140pub mod env {
1141
1142	/// Noop function used to benchmark the time it takes to execute an empty function.
1143	#[cfg(feature = "runtime-benchmarks")]
1144	#[unstable]
1145	fn noop(ctx: _, memory: _) -> Result<(), TrapReason> {
1146		Ok(())
1147	}
1148
1149	/// Set the value at the given key in the contract storage.
1150	/// See [`pallet_contracts_uapi::HostFn::set_storage`]
1151	#[prefixed_alias]
1152	#[mutating]
1153	fn set_storage(
1154		ctx: _,
1155		memory: _,
1156		key_ptr: u32,
1157		value_ptr: u32,
1158		value_len: u32,
1159	) -> Result<(), TrapReason> {
1160		ctx.set_storage(memory, KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
1161	}
1162
1163	/// Set the value at the given key in the contract storage.
1164	/// See [`pallet_contracts_uapi::HostFn::set_storage_v1`]
1165	#[version(1)]
1166	#[prefixed_alias]
1167	#[mutating]
1168	fn set_storage(
1169		ctx: _,
1170		memory: _,
1171		key_ptr: u32,
1172		value_ptr: u32,
1173		value_len: u32,
1174	) -> Result<u32, TrapReason> {
1175		ctx.set_storage(memory, KeyType::Fix, key_ptr, value_ptr, value_len)
1176	}
1177
1178	/// Set the value at the given key in the contract storage.
1179	/// See [`pallet_contracts_uapi::HostFn::set_storage_v2`]
1180	#[version(2)]
1181	#[prefixed_alias]
1182	#[mutating]
1183	fn set_storage(
1184		ctx: _,
1185		memory: _,
1186		key_ptr: u32,
1187		key_len: u32,
1188		value_ptr: u32,
1189		value_len: u32,
1190	) -> Result<u32, TrapReason> {
1191		ctx.set_storage(memory, KeyType::Var(key_len), key_ptr, value_ptr, value_len)
1192	}
1193
1194	/// Clear the value at the given key in the contract storage.
1195	/// See [`pallet_contracts_uapi::HostFn::clear_storage`]
1196	#[prefixed_alias]
1197	#[mutating]
1198	fn clear_storage(ctx: _, memory: _, key_ptr: u32) -> Result<(), TrapReason> {
1199		ctx.clear_storage(memory, KeyType::Fix, key_ptr).map(|_| ())
1200	}
1201
1202	/// Clear the value at the given key in the contract storage.
1203	/// See [`pallet_contracts_uapi::HostFn::clear_storage_v1`]
1204	#[version(1)]
1205	#[prefixed_alias]
1206	#[mutating]
1207	fn clear_storage(ctx: _, memory: _, key_ptr: u32, key_len: u32) -> Result<u32, TrapReason> {
1208		ctx.clear_storage(memory, KeyType::Var(key_len), key_ptr)
1209	}
1210
1211	/// Retrieve the value under the given key from storage.
1212	/// See [`pallet_contracts_uapi::HostFn::get_storage`]
1213	#[prefixed_alias]
1214	fn get_storage(
1215		ctx: _,
1216		memory: _,
1217		key_ptr: u32,
1218		out_ptr: u32,
1219		out_len_ptr: u32,
1220	) -> Result<ReturnErrorCode, TrapReason> {
1221		ctx.get_storage(memory, KeyType::Fix, key_ptr, out_ptr, out_len_ptr)
1222	}
1223
1224	/// Retrieve the value under the given key from storage.
1225	/// See [`pallet_contracts_uapi::HostFn::get_storage_v1`]
1226	#[version(1)]
1227	#[prefixed_alias]
1228	fn get_storage(
1229		ctx: _,
1230		memory: _,
1231		key_ptr: u32,
1232		key_len: u32,
1233		out_ptr: u32,
1234		out_len_ptr: u32,
1235	) -> Result<ReturnErrorCode, TrapReason> {
1236		ctx.get_storage(memory, KeyType::Var(key_len), key_ptr, out_ptr, out_len_ptr)
1237	}
1238
1239	/// Checks whether there is a value stored under the given key.
1240	/// See [`pallet_contracts_uapi::HostFn::contains_storage`]
1241	#[prefixed_alias]
1242	fn contains_storage(ctx: _, memory: _, key_ptr: u32) -> Result<u32, TrapReason> {
1243		ctx.contains_storage(memory, KeyType::Fix, key_ptr)
1244	}
1245
1246	/// Checks whether there is a value stored under the given key.
1247	/// See [`pallet_contracts_uapi::HostFn::contains_storage_v1`]
1248	#[version(1)]
1249	#[prefixed_alias]
1250	fn contains_storage(ctx: _, memory: _, key_ptr: u32, key_len: u32) -> Result<u32, TrapReason> {
1251		ctx.contains_storage(memory, KeyType::Var(key_len), key_ptr)
1252	}
1253
1254	/// Retrieve and remove the value under the given key from storage.
1255	/// See [`pallet_contracts_uapi::HostFn::take_storage`]
1256	#[prefixed_alias]
1257	#[mutating]
1258	fn take_storage(
1259		ctx: _,
1260		memory: _,
1261		key_ptr: u32,
1262		key_len: u32,
1263		out_ptr: u32,
1264		out_len_ptr: u32,
1265	) -> Result<ReturnErrorCode, TrapReason> {
1266		let charged = ctx.charge_gas(RuntimeCosts::TakeStorage(ctx.ext.max_value_size()))?;
1267		ensure!(
1268			key_len <= <<E as Ext>::T as Config>::MaxStorageKeyLen::get(),
1269			Error::<E::T>::DecodingFailed
1270		);
1271		let key = ctx.read_sandbox_memory(memory, key_ptr, key_len)?;
1272		if let crate::storage::WriteOutcome::Taken(value) = ctx.ext.set_storage(
1273			&Key::<E::T>::try_from_var(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
1274			None,
1275			true,
1276		)? {
1277			ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(value.len() as u32));
1278			ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &value, false, already_charged)?;
1279			Ok(ReturnErrorCode::Success)
1280		} else {
1281			ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(0));
1282			Ok(ReturnErrorCode::KeyNotFound)
1283		}
1284	}
1285
1286	/// Set the value at the given key in the contract transient storage.
1287	#[unstable]
1288	fn set_transient_storage(
1289		ctx: _,
1290		memory: _,
1291		key_ptr: u32,
1292		key_len: u32,
1293		value_ptr: u32,
1294		value_len: u32,
1295	) -> Result<u32, TrapReason> {
1296		ctx.set_transient_storage(memory, KeyType::Var(key_len), key_ptr, value_ptr, value_len)
1297	}
1298
1299	/// Clear the value at the given key in the contract storage.
1300	#[unstable]
1301	fn clear_transient_storage(
1302		ctx: _,
1303		memory: _,
1304		key_ptr: u32,
1305		key_len: u32,
1306	) -> Result<u32, TrapReason> {
1307		ctx.clear_transient_storage(memory, KeyType::Var(key_len), key_ptr)
1308	}
1309
1310	/// Retrieve the value under the given key from transient storage.
1311	#[unstable]
1312	fn get_transient_storage(
1313		ctx: _,
1314		memory: _,
1315		key_ptr: u32,
1316		key_len: u32,
1317		out_ptr: u32,
1318		out_len_ptr: u32,
1319	) -> Result<ReturnErrorCode, TrapReason> {
1320		ctx.get_transient_storage(memory, KeyType::Var(key_len), key_ptr, out_ptr, out_len_ptr)
1321	}
1322
1323	/// Checks whether there is a value stored under the given key in transient storage.
1324	#[unstable]
1325	fn contains_transient_storage(
1326		ctx: _,
1327		memory: _,
1328		key_ptr: u32,
1329		key_len: u32,
1330	) -> Result<u32, TrapReason> {
1331		ctx.contains_transient_storage(memory, KeyType::Var(key_len), key_ptr)
1332	}
1333
1334	/// Retrieve and remove the value under the given key from transient storage.
1335	#[unstable]
1336	fn take_transient_storage(
1337		ctx: _,
1338		memory: _,
1339		key_ptr: u32,
1340		key_len: u32,
1341		out_ptr: u32,
1342		out_len_ptr: u32,
1343	) -> Result<ReturnErrorCode, TrapReason> {
1344		ctx.take_transient_storage(memory, KeyType::Var(key_len), key_ptr, out_ptr, out_len_ptr)
1345	}
1346
1347	/// Transfer some value to another account.
1348	/// See [`pallet_contracts_uapi::HostFn::transfer`].
1349	#[prefixed_alias]
1350	#[mutating]
1351	fn transfer(
1352		ctx: _,
1353		memory: _,
1354		account_ptr: u32,
1355		_account_len: u32,
1356		value_ptr: u32,
1357		_value_len: u32,
1358	) -> Result<ReturnErrorCode, TrapReason> {
1359		ctx.charge_gas(RuntimeCosts::Transfer)?;
1360		let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
1361			ctx.read_sandbox_memory_as(memory, account_ptr)?;
1362		let value: BalanceOf<<E as Ext>::T> = ctx.read_sandbox_memory_as(memory, value_ptr)?;
1363		let result = ctx.ext.transfer(&callee, value);
1364		match result {
1365			Ok(()) => Ok(ReturnErrorCode::Success),
1366			Err(err) => {
1367				let code = Runtime::<E>::err_into_return_code(err)?;
1368				Ok(code)
1369			},
1370		}
1371	}
1372
1373	/// Make a call to another contract.
1374	///
1375	/// # Note
1376	///
1377	/// The values `_callee_len` and `_value_len` are ignored because the encoded sizes of those
1378	/// types are fixed through [`codec::MaxEncodedLen`]. The fields exist for backwards
1379	/// compatibility. Consider switching to the newest version of this function.
1380	#[prefixed_alias]
1381	fn call(
1382		ctx: _,
1383		memory: _,
1384		callee_ptr: u32,
1385		_callee_len: u32,
1386		gas: u64,
1387		value_ptr: u32,
1388		_value_len: u32,
1389		input_data_ptr: u32,
1390		input_data_len: u32,
1391		output_ptr: u32,
1392		output_len_ptr: u32,
1393	) -> Result<ReturnErrorCode, TrapReason> {
1394		ctx.call(
1395			memory,
1396			CallFlags::ALLOW_REENTRY,
1397			CallType::Call {
1398				callee_ptr,
1399				value_ptr,
1400				deposit_ptr: SENTINEL,
1401				weight: Weight::from_parts(gas, 0),
1402			},
1403			input_data_ptr,
1404			input_data_len,
1405			output_ptr,
1406			output_len_ptr,
1407		)
1408	}
1409
1410	/// Make a call to another contract.
1411	/// See [`pallet_contracts_uapi::HostFn::call_v1`].
1412	#[version(1)]
1413	#[prefixed_alias]
1414	fn call(
1415		ctx: _,
1416		memory: _,
1417		flags: u32,
1418		callee_ptr: u32,
1419		gas: u64,
1420		value_ptr: u32,
1421		input_data_ptr: u32,
1422		input_data_len: u32,
1423		output_ptr: u32,
1424		output_len_ptr: u32,
1425	) -> Result<ReturnErrorCode, TrapReason> {
1426		ctx.call(
1427			memory,
1428			CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
1429			CallType::Call {
1430				callee_ptr,
1431				value_ptr,
1432				deposit_ptr: SENTINEL,
1433				weight: Weight::from_parts(gas, 0),
1434			},
1435			input_data_ptr,
1436			input_data_len,
1437			output_ptr,
1438			output_len_ptr,
1439		)
1440	}
1441
1442	/// Make a call to another contract.
1443	/// See [`pallet_contracts_uapi::HostFn::call_v2`].
1444	#[version(2)]
1445	fn call(
1446		ctx: _,
1447		memory: _,
1448		flags: u32,
1449		callee_ptr: u32,
1450		ref_time_limit: u64,
1451		proof_size_limit: u64,
1452		deposit_ptr: u32,
1453		value_ptr: u32,
1454		input_data_ptr: u32,
1455		input_data_len: u32,
1456		output_ptr: u32,
1457		output_len_ptr: u32,
1458	) -> Result<ReturnErrorCode, TrapReason> {
1459		ctx.call(
1460			memory,
1461			CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
1462			CallType::Call {
1463				callee_ptr,
1464				value_ptr,
1465				deposit_ptr,
1466				weight: Weight::from_parts(ref_time_limit, proof_size_limit),
1467			},
1468			input_data_ptr,
1469			input_data_len,
1470			output_ptr,
1471			output_len_ptr,
1472		)
1473	}
1474
1475	/// Execute code in the context (storage, caller, value) of the current contract.
1476	/// See [`pallet_contracts_uapi::HostFn::delegate_call`].
1477	#[prefixed_alias]
1478	fn delegate_call(
1479		ctx: _,
1480		memory: _,
1481		flags: u32,
1482		code_hash_ptr: u32,
1483		input_data_ptr: u32,
1484		input_data_len: u32,
1485		output_ptr: u32,
1486		output_len_ptr: u32,
1487	) -> Result<ReturnErrorCode, TrapReason> {
1488		ctx.call(
1489			memory,
1490			CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
1491			CallType::DelegateCall { code_hash_ptr },
1492			input_data_ptr,
1493			input_data_len,
1494			output_ptr,
1495			output_len_ptr,
1496		)
1497	}
1498
1499	/// Instantiate a contract with the specified code hash.
1500	/// See [`pallet_contracts_uapi::HostFn::instantiate`].
1501	///
1502	/// # Note
1503	///
1504	/// The values `_code_hash_len` and `_value_len` are ignored because the encoded sizes
1505	/// of those types are fixed through [`codec::MaxEncodedLen`]. The fields exist
1506	/// for backwards compatibility. Consider switching to the newest version of this function.
1507	#[prefixed_alias]
1508	#[mutating]
1509	fn instantiate(
1510		ctx: _,
1511		memory: _,
1512		code_hash_ptr: u32,
1513		_code_hash_len: u32,
1514		gas: u64,
1515		value_ptr: u32,
1516		_value_len: u32,
1517		input_data_ptr: u32,
1518		input_data_len: u32,
1519		address_ptr: u32,
1520		address_len_ptr: u32,
1521		output_ptr: u32,
1522		output_len_ptr: u32,
1523		salt_ptr: u32,
1524		salt_len: u32,
1525	) -> Result<ReturnErrorCode, TrapReason> {
1526		ctx.instantiate(
1527			memory,
1528			code_hash_ptr,
1529			Weight::from_parts(gas, 0),
1530			SENTINEL,
1531			value_ptr,
1532			input_data_ptr,
1533			input_data_len,
1534			address_ptr,
1535			address_len_ptr,
1536			output_ptr,
1537			output_len_ptr,
1538			salt_ptr,
1539			salt_len,
1540		)
1541	}
1542
1543	/// Instantiate a contract with the specified code hash.
1544	/// See [`pallet_contracts_uapi::HostFn::instantiate_v1`].
1545	#[version(1)]
1546	#[prefixed_alias]
1547	#[mutating]
1548	fn instantiate(
1549		ctx: _,
1550		memory: _,
1551		code_hash_ptr: u32,
1552		gas: u64,
1553		value_ptr: u32,
1554		input_data_ptr: u32,
1555		input_data_len: u32,
1556		address_ptr: u32,
1557		address_len_ptr: u32,
1558		output_ptr: u32,
1559		output_len_ptr: u32,
1560		salt_ptr: u32,
1561		salt_len: u32,
1562	) -> Result<ReturnErrorCode, TrapReason> {
1563		ctx.instantiate(
1564			memory,
1565			code_hash_ptr,
1566			Weight::from_parts(gas, 0),
1567			SENTINEL,
1568			value_ptr,
1569			input_data_ptr,
1570			input_data_len,
1571			address_ptr,
1572			address_len_ptr,
1573			output_ptr,
1574			output_len_ptr,
1575			salt_ptr,
1576			salt_len,
1577		)
1578	}
1579
1580	/// Instantiate a contract with the specified code hash.
1581	/// See [`pallet_contracts_uapi::HostFn::instantiate_v2`].
1582	#[version(2)]
1583	#[mutating]
1584	fn instantiate(
1585		ctx: _,
1586		memory: _,
1587		code_hash_ptr: u32,
1588		ref_time_limit: u64,
1589		proof_size_limit: u64,
1590		deposit_ptr: u32,
1591		value_ptr: u32,
1592		input_data_ptr: u32,
1593		input_data_len: u32,
1594		address_ptr: u32,
1595		address_len_ptr: u32,
1596		output_ptr: u32,
1597		output_len_ptr: u32,
1598		salt_ptr: u32,
1599		salt_len: u32,
1600	) -> Result<ReturnErrorCode, TrapReason> {
1601		ctx.instantiate(
1602			memory,
1603			code_hash_ptr,
1604			Weight::from_parts(ref_time_limit, proof_size_limit),
1605			deposit_ptr,
1606			value_ptr,
1607			input_data_ptr,
1608			input_data_len,
1609			address_ptr,
1610			address_len_ptr,
1611			output_ptr,
1612			output_len_ptr,
1613			salt_ptr,
1614			salt_len,
1615		)
1616	}
1617
1618	/// Remove the calling account and transfer remaining balance.
1619	/// See [`pallet_contracts_uapi::HostFn::terminate`].
1620	///
1621	/// # Note
1622	///
1623	/// The value `_beneficiary_len` is ignored because the encoded sizes
1624	/// this type is fixed through `[`MaxEncodedLen`]. The field exist for backwards
1625	/// compatibility. Consider switching to the newest version of this function.
1626	#[prefixed_alias]
1627	#[mutating]
1628	fn terminate(
1629		ctx: _,
1630		memory: _,
1631		beneficiary_ptr: u32,
1632		_beneficiary_len: u32,
1633	) -> Result<(), TrapReason> {
1634		ctx.terminate(memory, beneficiary_ptr)
1635	}
1636
1637	/// Remove the calling account and transfer remaining **free** balance.
1638	/// See [`pallet_contracts_uapi::HostFn::terminate_v1`].
1639	#[version(1)]
1640	#[prefixed_alias]
1641	#[mutating]
1642	fn terminate(ctx: _, memory: _, beneficiary_ptr: u32) -> Result<(), TrapReason> {
1643		ctx.terminate(memory, beneficiary_ptr)
1644	}
1645
1646	/// Stores the input passed by the caller into the supplied buffer.
1647	/// See [`pallet_contracts_uapi::HostFn::input`].
1648	#[prefixed_alias]
1649	fn input(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1650		if let Some(input) = ctx.input_data.take() {
1651			ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &input, false, |len| {
1652				Some(RuntimeCosts::CopyToContract(len))
1653			})?;
1654			ctx.input_data = Some(input);
1655			Ok(())
1656		} else {
1657			Err(Error::<E::T>::InputForwarded.into())
1658		}
1659	}
1660
1661	/// Cease contract execution and save a data buffer as a result of the execution.
1662	/// See [`pallet_contracts_uapi::HostFn::return_value`].
1663	fn seal_return(
1664		ctx: _,
1665		memory: _,
1666		flags: u32,
1667		data_ptr: u32,
1668		data_len: u32,
1669	) -> Result<(), TrapReason> {
1670		ctx.charge_gas(RuntimeCosts::CopyFromContract(data_len))?;
1671		Err(TrapReason::Return(ReturnData {
1672			flags,
1673			data: ctx.read_sandbox_memory(memory, data_ptr, data_len)?,
1674		}))
1675	}
1676
1677	/// Stores the address of the caller into the supplied buffer.
1678	/// See [`pallet_contracts_uapi::HostFn::caller`].
1679	#[prefixed_alias]
1680	fn caller(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1681		ctx.charge_gas(RuntimeCosts::Caller)?;
1682		let caller = ctx.ext.caller().account_id()?.clone();
1683		Ok(ctx.write_sandbox_output(
1684			memory,
1685			out_ptr,
1686			out_len_ptr,
1687			&caller.encode(),
1688			false,
1689			already_charged,
1690		)?)
1691	}
1692
1693	/// Checks whether a specified address belongs to a contract.
1694	/// See [`pallet_contracts_uapi::HostFn::is_contract`].
1695	#[prefixed_alias]
1696	fn is_contract(ctx: _, memory: _, account_ptr: u32) -> Result<u32, TrapReason> {
1697		ctx.charge_gas(RuntimeCosts::IsContract)?;
1698		let address: <<E as Ext>::T as frame_system::Config>::AccountId =
1699			ctx.read_sandbox_memory_as(memory, account_ptr)?;
1700
1701		Ok(ctx.ext.is_contract(&address) as u32)
1702	}
1703
1704	/// Retrieve the code hash for a specified contract address.
1705	/// See [`pallet_contracts_uapi::HostFn::code_hash`].
1706	#[prefixed_alias]
1707	fn code_hash(
1708		ctx: _,
1709		memory: _,
1710		account_ptr: u32,
1711		out_ptr: u32,
1712		out_len_ptr: u32,
1713	) -> Result<ReturnErrorCode, TrapReason> {
1714		ctx.charge_gas(RuntimeCosts::CodeHash)?;
1715		let address: <<E as Ext>::T as frame_system::Config>::AccountId =
1716			ctx.read_sandbox_memory_as(memory, account_ptr)?;
1717		if let Some(value) = ctx.ext.code_hash(&address) {
1718			ctx.write_sandbox_output(
1719				memory,
1720				out_ptr,
1721				out_len_ptr,
1722				&value.encode(),
1723				false,
1724				already_charged,
1725			)?;
1726			Ok(ReturnErrorCode::Success)
1727		} else {
1728			Ok(ReturnErrorCode::KeyNotFound)
1729		}
1730	}
1731
1732	/// Retrieve the code hash of the currently executing contract.
1733	/// See [`pallet_contracts_uapi::HostFn::own_code_hash`].
1734	#[prefixed_alias]
1735	fn own_code_hash(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1736		ctx.charge_gas(RuntimeCosts::OwnCodeHash)?;
1737		let code_hash_encoded = &ctx.ext.own_code_hash().encode();
1738		Ok(ctx.write_sandbox_output(
1739			memory,
1740			out_ptr,
1741			out_len_ptr,
1742			code_hash_encoded,
1743			false,
1744			already_charged,
1745		)?)
1746	}
1747
1748	/// Checks whether the caller of the current contract is the origin of the whole call stack.
1749	/// See [`pallet_contracts_uapi::HostFn::caller_is_origin`].
1750	#[prefixed_alias]
1751	fn caller_is_origin(ctx: _, _memory: _) -> Result<u32, TrapReason> {
1752		ctx.charge_gas(RuntimeCosts::CallerIsOrigin)?;
1753		Ok(ctx.ext.caller_is_origin() as u32)
1754	}
1755
1756	/// Checks whether the caller of the current contract is root.
1757	/// See [`pallet_contracts_uapi::HostFn::caller_is_root`].
1758	fn caller_is_root(ctx: _, _memory: _) -> Result<u32, TrapReason> {
1759		ctx.charge_gas(RuntimeCosts::CallerIsRoot)?;
1760		Ok(ctx.ext.caller_is_root() as u32)
1761	}
1762
1763	/// Stores the address of the current contract into the supplied buffer.
1764	/// See [`pallet_contracts_uapi::HostFn::address`].
1765	#[prefixed_alias]
1766	fn address(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1767		ctx.charge_gas(RuntimeCosts::Address)?;
1768		Ok(ctx.write_sandbox_output(
1769			memory,
1770			out_ptr,
1771			out_len_ptr,
1772			&ctx.ext.address().encode(),
1773			false,
1774			already_charged,
1775		)?)
1776	}
1777
1778	/// Stores the price for the specified amount of gas into the supplied buffer.
1779	/// See [`pallet_contracts_uapi::HostFn::weight_to_fee`].
1780	#[prefixed_alias]
1781	fn weight_to_fee(
1782		ctx: _,
1783		memory: _,
1784		gas: u64,
1785		out_ptr: u32,
1786		out_len_ptr: u32,
1787	) -> Result<(), TrapReason> {
1788		let gas = Weight::from_parts(gas, 0);
1789		ctx.charge_gas(RuntimeCosts::WeightToFee)?;
1790		Ok(ctx.write_sandbox_output(
1791			memory,
1792			out_ptr,
1793			out_len_ptr,
1794			&ctx.ext.get_weight_price(gas).encode(),
1795			false,
1796			already_charged,
1797		)?)
1798	}
1799
1800	/// Stores the price for the specified amount of weight into the supplied buffer.
1801	/// See [`pallet_contracts_uapi::HostFn::weight_to_fee_v1`].
1802	#[version(1)]
1803	#[unstable]
1804	fn weight_to_fee(
1805		ctx: _,
1806		memory: _,
1807		ref_time_limit: u64,
1808		proof_size_limit: u64,
1809		out_ptr: u32,
1810		out_len_ptr: u32,
1811	) -> Result<(), TrapReason> {
1812		let weight = Weight::from_parts(ref_time_limit, proof_size_limit);
1813		ctx.charge_gas(RuntimeCosts::WeightToFee)?;
1814		Ok(ctx.write_sandbox_output(
1815			memory,
1816			out_ptr,
1817			out_len_ptr,
1818			&ctx.ext.get_weight_price(weight).encode(),
1819			false,
1820			already_charged,
1821		)?)
1822	}
1823
1824	/// Stores the weight left into the supplied buffer.
1825	/// See [`pallet_contracts_uapi::HostFn::gas_left`].
1826	#[prefixed_alias]
1827	fn gas_left(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1828		ctx.charge_gas(RuntimeCosts::GasLeft)?;
1829		let gas_left = &ctx.ext.gas_meter().gas_left().ref_time().encode();
1830		Ok(ctx.write_sandbox_output(
1831			memory,
1832			out_ptr,
1833			out_len_ptr,
1834			gas_left,
1835			false,
1836			already_charged,
1837		)?)
1838	}
1839
1840	/// Stores the amount of weight left into the supplied buffer.
1841	/// See [`pallet_contracts_uapi::HostFn::gas_left_v1`].
1842	#[version(1)]
1843	#[unstable]
1844	fn gas_left(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1845		ctx.charge_gas(RuntimeCosts::GasLeft)?;
1846		let gas_left = &ctx.ext.gas_meter().gas_left().encode();
1847		Ok(ctx.write_sandbox_output(
1848			memory,
1849			out_ptr,
1850			out_len_ptr,
1851			gas_left,
1852			false,
1853			already_charged,
1854		)?)
1855	}
1856
1857	/// Stores the *free* balance of the current account into the supplied buffer.
1858	/// See [`pallet_contracts_uapi::HostFn::balance`].
1859	#[prefixed_alias]
1860	fn balance(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1861		ctx.charge_gas(RuntimeCosts::Balance)?;
1862		Ok(ctx.write_sandbox_output(
1863			memory,
1864			out_ptr,
1865			out_len_ptr,
1866			&ctx.ext.balance().encode(),
1867			false,
1868			already_charged,
1869		)?)
1870	}
1871
1872	/// Stores the value transferred along with this call/instantiate into the supplied buffer.
1873	/// See [`pallet_contracts_uapi::HostFn::value_transferred`].
1874	#[prefixed_alias]
1875	fn value_transferred(
1876		ctx: _,
1877		memory: _,
1878		out_ptr: u32,
1879		out_len_ptr: u32,
1880	) -> Result<(), TrapReason> {
1881		ctx.charge_gas(RuntimeCosts::ValueTransferred)?;
1882		Ok(ctx.write_sandbox_output(
1883			memory,
1884			out_ptr,
1885			out_len_ptr,
1886			&ctx.ext.value_transferred().encode(),
1887			false,
1888			already_charged,
1889		)?)
1890	}
1891
1892	/// Stores a random number for the current block and the given subject into the supplied buffer.
1893	///
1894	/// The value is stored to linear memory at the address pointed to by `out_ptr`.
1895	/// `out_len_ptr` must point to a u32 value that describes the available space at
1896	/// `out_ptr`. This call overwrites it with the size of the value. If the available
1897	/// space at `out_ptr` is less than the size of the value a trap is triggered.
1898	///
1899	/// The data is encoded as `T::Hash`.
1900	#[prefixed_alias]
1901	#[deprecated]
1902	fn random(
1903		ctx: _,
1904		memory: _,
1905		subject_ptr: u32,
1906		subject_len: u32,
1907		out_ptr: u32,
1908		out_len_ptr: u32,
1909	) -> Result<(), TrapReason> {
1910		ctx.charge_gas(RuntimeCosts::Random)?;
1911		if subject_len > ctx.ext.schedule().limits.subject_len {
1912			return Err(Error::<E::T>::RandomSubjectTooLong.into());
1913		}
1914		let subject_buf = ctx.read_sandbox_memory(memory, subject_ptr, subject_len)?;
1915		Ok(ctx.write_sandbox_output(
1916			memory,
1917			out_ptr,
1918			out_len_ptr,
1919			&ctx.ext.random(&subject_buf).0.encode(),
1920			false,
1921			already_charged,
1922		)?)
1923	}
1924
1925	/// Stores a random number for the current block and the given subject into the supplied buffer.
1926	///
1927	/// The value is stored to linear memory at the address pointed to by `out_ptr`.
1928	/// `out_len_ptr` must point to a u32 value that describes the available space at
1929	/// `out_ptr`. This call overwrites it with the size of the value. If the available
1930	/// space at `out_ptr` is less than the size of the value a trap is triggered.
1931	///
1932	/// The data is encoded as (`T::Hash`, `frame_system::pallet_prelude::BlockNumberFor::<T>`).
1933	///
1934	/// # Changes from v0
1935	///
1936	/// In addition to the seed it returns the block number since which it was determinable
1937	/// by chain observers.
1938	///
1939	/// # Note
1940	///
1941	/// The returned seed should only be used to distinguish commitments made before
1942	/// the returned block number. If the block number is too early (i.e. commitments were
1943	/// made afterwards), then ensure no further commitments may be made and repeatedly
1944	/// call this on later blocks until the block number returned is later than the latest
1945	/// commitment.
1946	#[version(1)]
1947	#[prefixed_alias]
1948	#[deprecated]
1949	fn random(
1950		ctx: _,
1951		memory: _,
1952		subject_ptr: u32,
1953		subject_len: u32,
1954		out_ptr: u32,
1955		out_len_ptr: u32,
1956	) -> Result<(), TrapReason> {
1957		ctx.charge_gas(RuntimeCosts::Random)?;
1958		if subject_len > ctx.ext.schedule().limits.subject_len {
1959			return Err(Error::<E::T>::RandomSubjectTooLong.into());
1960		}
1961		let subject_buf = ctx.read_sandbox_memory(memory, subject_ptr, subject_len)?;
1962		Ok(ctx.write_sandbox_output(
1963			memory,
1964			out_ptr,
1965			out_len_ptr,
1966			&ctx.ext.random(&subject_buf).encode(),
1967			false,
1968			already_charged,
1969		)?)
1970	}
1971
1972	/// Load the latest block timestamp into the supplied buffer
1973	/// See [`pallet_contracts_uapi::HostFn::now`].
1974	#[prefixed_alias]
1975	fn now(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
1976		ctx.charge_gas(RuntimeCosts::Now)?;
1977		Ok(ctx.write_sandbox_output(
1978			memory,
1979			out_ptr,
1980			out_len_ptr,
1981			&ctx.ext.now().encode(),
1982			false,
1983			already_charged,
1984		)?)
1985	}
1986
1987	/// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer.
1988	/// See [`pallet_contracts_uapi::HostFn::minimum_balance`].
1989	#[prefixed_alias]
1990	fn minimum_balance(
1991		ctx: _,
1992		memory: _,
1993		out_ptr: u32,
1994		out_len_ptr: u32,
1995	) -> Result<(), TrapReason> {
1996		ctx.charge_gas(RuntimeCosts::MinimumBalance)?;
1997		Ok(ctx.write_sandbox_output(
1998			memory,
1999			out_ptr,
2000			out_len_ptr,
2001			&ctx.ext.minimum_balance().encode(),
2002			false,
2003			already_charged,
2004		)?)
2005	}
2006
2007	/// Stores the tombstone deposit into the supplied buffer.
2008	///
2009	/// The value is stored to linear memory at the address pointed to by `out_ptr`.
2010	/// `out_len_ptr` must point to a u32 value that describes the available space at
2011	/// `out_ptr`. This call overwrites it with the size of the value. If the available
2012	/// space at `out_ptr` is less than the size of the value a trap is triggered.
2013	///
2014	/// # Note
2015	///
2016	/// There is no longer a tombstone deposit. This function always returns `0`.
2017	#[prefixed_alias]
2018	#[deprecated]
2019	fn tombstone_deposit(
2020		ctx: _,
2021		memory: _,
2022		out_ptr: u32,
2023		out_len_ptr: u32,
2024	) -> Result<(), TrapReason> {
2025		ctx.charge_gas(RuntimeCosts::Balance)?;
2026		let deposit = <BalanceOf<E::T>>::zero().encode();
2027		Ok(ctx.write_sandbox_output(
2028			memory,
2029			out_ptr,
2030			out_len_ptr,
2031			&deposit,
2032			false,
2033			already_charged,
2034		)?)
2035	}
2036
2037	/// Was used to restore the given destination contract sacrificing the caller.
2038	///
2039	/// # Note
2040	///
2041	/// The state rent functionality was removed. This is stub only exists for
2042	/// backwards compatibility
2043	#[prefixed_alias]
2044	#[deprecated]
2045	fn restore_to(
2046		ctx: _,
2047		memory: _,
2048		_dest_ptr: u32,
2049		_dest_len: u32,
2050		_code_hash_ptr: u32,
2051		_code_hash_len: u32,
2052		_rent_allowance_ptr: u32,
2053		_rent_allowance_len: u32,
2054		_delta_ptr: u32,
2055		_delta_count: u32,
2056	) -> Result<(), TrapReason> {
2057		ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
2058		Ok(())
2059	}
2060
2061	/// Was used to restore the given destination contract sacrificing the caller.
2062	///
2063	/// # Note
2064	///
2065	/// The state rent functionality was removed. This is stub only exists for
2066	/// backwards compatibility
2067	#[version(1)]
2068	#[prefixed_alias]
2069	#[deprecated]
2070	fn restore_to(
2071		ctx: _,
2072		memory: _,
2073		_dest_ptr: u32,
2074		_code_hash_ptr: u32,
2075		_rent_allowance_ptr: u32,
2076		_delta_ptr: u32,
2077		_delta_count: u32,
2078	) -> Result<(), TrapReason> {
2079		ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
2080		Ok(())
2081	}
2082
2083	/// Was used to set rent allowance of the contract.
2084	///
2085	/// # Note
2086	///
2087	/// The state rent functionality was removed. This is stub only exists for
2088	/// backwards compatibility.
2089	#[prefixed_alias]
2090	#[deprecated]
2091	fn set_rent_allowance(
2092		ctx: _,
2093		memory: _,
2094		_value_ptr: u32,
2095		_value_len: u32,
2096	) -> Result<(), TrapReason> {
2097		ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
2098		Ok(())
2099	}
2100
2101	/// Was used to set rent allowance of the contract.
2102	///
2103	/// # Note
2104	///
2105	/// The state rent functionality was removed. This is stub only exists for
2106	/// backwards compatibility.
2107	#[version(1)]
2108	#[prefixed_alias]
2109	#[deprecated]
2110	fn set_rent_allowance(ctx: _, _memory: _, _value_ptr: u32) -> Result<(), TrapReason> {
2111		ctx.charge_gas(RuntimeCosts::DebugMessage(0))?;
2112		Ok(())
2113	}
2114
2115	/// Was used to store the rent allowance into the supplied buffer.
2116	///
2117	/// # Note
2118	///
2119	/// The state rent functionality was removed. This is stub only exists for
2120	/// backwards compatibility.
2121	#[prefixed_alias]
2122	#[deprecated]
2123	fn rent_allowance(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
2124		ctx.charge_gas(RuntimeCosts::Balance)?;
2125		let rent_allowance = <BalanceOf<E::T>>::max_value().encode();
2126		Ok(ctx.write_sandbox_output(
2127			memory,
2128			out_ptr,
2129			out_len_ptr,
2130			&rent_allowance,
2131			false,
2132			already_charged,
2133		)?)
2134	}
2135
2136	/// Deposit a contract event with the data buffer and optional list of topics.
2137	/// See [pallet_contracts_uapi::HostFn::deposit_event]
2138	#[prefixed_alias]
2139	#[mutating]
2140	fn deposit_event(
2141		ctx: _,
2142		memory: _,
2143		topics_ptr: u32,
2144		topics_len: u32,
2145		data_ptr: u32,
2146		data_len: u32,
2147	) -> Result<(), TrapReason> {
2148		let num_topic = topics_len
2149			.checked_div(core::mem::size_of::<TopicOf<E::T>>() as u32)
2150			.ok_or("Zero sized topics are not allowed")?;
2151		ctx.charge_gas(RuntimeCosts::DepositEvent { num_topic, len: data_len })?;
2152		if data_len > ctx.ext.max_value_size() {
2153			return Err(Error::<E::T>::ValueTooLarge.into());
2154		}
2155
2156		let topics: Vec<TopicOf<<E as Ext>::T>> = match topics_len {
2157			0 => Vec::new(),
2158			_ => ctx.read_sandbox_memory_as_unbounded(memory, topics_ptr, topics_len)?,
2159		};
2160
2161		// If there are more than `event_topics`, then trap.
2162		if topics.len() > ctx.ext.schedule().limits.event_topics as usize {
2163			return Err(Error::<E::T>::TooManyTopics.into());
2164		}
2165
2166		let event_data = ctx.read_sandbox_memory(memory, data_ptr, data_len)?;
2167
2168		ctx.ext.deposit_event(topics, event_data);
2169
2170		Ok(())
2171	}
2172
2173	/// Stores the current block number of the current contract into the supplied buffer.
2174	/// See [`pallet_contracts_uapi::HostFn::block_number`].
2175	#[prefixed_alias]
2176	fn block_number(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
2177		ctx.charge_gas(RuntimeCosts::BlockNumber)?;
2178		Ok(ctx.write_sandbox_output(
2179			memory,
2180			out_ptr,
2181			out_len_ptr,
2182			&ctx.ext.block_number().encode(),
2183			false,
2184			already_charged,
2185		)?)
2186	}
2187
2188	/// Computes the SHA2 256-bit hash on the given input buffer.
2189	/// See [`pallet_contracts_uapi::HostFn::hash_sha2_256`].
2190	#[prefixed_alias]
2191	fn hash_sha2_256(
2192		ctx: _,
2193		memory: _,
2194		input_ptr: u32,
2195		input_len: u32,
2196		output_ptr: u32,
2197	) -> Result<(), TrapReason> {
2198		ctx.charge_gas(RuntimeCosts::HashSha256(input_len))?;
2199		Ok(ctx.compute_hash_on_intermediate_buffer(
2200			memory, sha2_256, input_ptr, input_len, output_ptr,
2201		)?)
2202	}
2203
2204	/// Computes the KECCAK 256-bit hash on the given input buffer.
2205	/// See [`pallet_contracts_uapi::HostFn::hash_keccak_256`].
2206	#[prefixed_alias]
2207	fn hash_keccak_256(
2208		ctx: _,
2209		memory: _,
2210		input_ptr: u32,
2211		input_len: u32,
2212		output_ptr: u32,
2213	) -> Result<(), TrapReason> {
2214		ctx.charge_gas(RuntimeCosts::HashKeccak256(input_len))?;
2215		Ok(ctx.compute_hash_on_intermediate_buffer(
2216			memory, keccak_256, input_ptr, input_len, output_ptr,
2217		)?)
2218	}
2219
2220	/// Computes the BLAKE2 256-bit hash on the given input buffer.
2221	/// See [`pallet_contracts_uapi::HostFn::hash_blake2_256`].
2222	#[prefixed_alias]
2223	fn hash_blake2_256(
2224		ctx: _,
2225		memory: _,
2226		input_ptr: u32,
2227		input_len: u32,
2228		output_ptr: u32,
2229	) -> Result<(), TrapReason> {
2230		ctx.charge_gas(RuntimeCosts::HashBlake256(input_len))?;
2231		Ok(ctx.compute_hash_on_intermediate_buffer(
2232			memory, blake2_256, input_ptr, input_len, output_ptr,
2233		)?)
2234	}
2235
2236	/// Computes the BLAKE2 128-bit hash on the given input buffer.
2237	/// See [`pallet_contracts_uapi::HostFn::hash_blake2_128`].
2238	#[prefixed_alias]
2239	fn hash_blake2_128(
2240		ctx: _,
2241		memory: _,
2242		input_ptr: u32,
2243		input_len: u32,
2244		output_ptr: u32,
2245	) -> Result<(), TrapReason> {
2246		ctx.charge_gas(RuntimeCosts::HashBlake128(input_len))?;
2247		Ok(ctx.compute_hash_on_intermediate_buffer(
2248			memory, blake2_128, input_ptr, input_len, output_ptr,
2249		)?)
2250	}
2251
2252	/// Call into the chain extension provided by the chain if any.
2253	/// See [`pallet_contracts_uapi::HostFn::call_chain_extension`].
2254	#[prefixed_alias]
2255	fn call_chain_extension(
2256		ctx: _,
2257		memory: _,
2258		id: u32,
2259		input_ptr: u32,
2260		input_len: u32,
2261		output_ptr: u32,
2262		output_len_ptr: u32,
2263	) -> Result<u32, TrapReason> {
2264		use crate::chain_extension::{ChainExtension, Environment, RetVal};
2265		if !<E::T as Config>::ChainExtension::enabled() {
2266			return Err(Error::<E::T>::NoChainExtension.into());
2267		}
2268		let mut chain_extension = ctx.chain_extension.take().expect(
2269			"Constructor initializes with `Some`. This is the only place where it is set to `None`.\
2270			It is always reset to `Some` afterwards. qed"
2271		);
2272		let env =
2273			Environment::new(ctx, memory, id, input_ptr, input_len, output_ptr, output_len_ptr);
2274		let ret = match chain_extension.call(env)? {
2275			RetVal::Converging(val) => Ok(val),
2276			RetVal::Diverging { flags, data } => {
2277				Err(TrapReason::Return(ReturnData { flags: flags.bits(), data }))
2278			},
2279		};
2280		ctx.chain_extension = Some(chain_extension);
2281		ret
2282	}
2283
2284	/// Emit a custom debug message.
2285	///
2286	/// No newlines are added to the supplied message.
2287	/// Specifying invalid UTF-8 just drops the message with no trap.
2288	///
2289	/// This is a no-op if debug message recording is disabled which is always the case
2290	/// when the code is executing on-chain. The message is interpreted as UTF-8 and
2291	/// appended to the debug buffer which is then supplied to the calling RPC client.
2292	///
2293	/// # Note
2294	///
2295	/// Even though no action is taken when debug message recording is disabled there is still
2296	/// a non trivial overhead (and weight cost) associated with calling this function. Contract
2297	/// languages should remove calls to this function (either at runtime or compile time) when
2298	/// not being executed as an RPC. For example, they could allow users to disable logging
2299	/// through compile time flags (cargo features) for on-chain deployment. Additionally, the
2300	/// return value of this function can be cached in order to prevent further calls at runtime.
2301	#[prefixed_alias]
2302	fn debug_message(
2303		ctx: _,
2304		memory: _,
2305		str_ptr: u32,
2306		str_len: u32,
2307	) -> Result<ReturnErrorCode, TrapReason> {
2308		let str_len = str_len.min(DebugBufferVec::<E::T>::bound() as u32);
2309		ctx.charge_gas(RuntimeCosts::DebugMessage(str_len))?;
2310		if ctx.ext.append_debug_buffer("") {
2311			let data = ctx.read_sandbox_memory(memory, str_ptr, str_len)?;
2312			if let Some(msg) = core::str::from_utf8(&data).ok() {
2313				ctx.ext.append_debug_buffer(msg);
2314			}
2315		}
2316		Ok(ReturnErrorCode::Success)
2317	}
2318
2319	/// Call some dispatchable of the runtime.
2320	/// See [`frame_support::traits::call_runtime`].
2321	#[mutating]
2322	fn call_runtime(
2323		ctx: _,
2324		memory: _,
2325		call_ptr: u32,
2326		call_len: u32,
2327	) -> Result<ReturnErrorCode, TrapReason> {
2328		use frame_support::dispatch::GetDispatchInfo;
2329		ctx.charge_gas(RuntimeCosts::CopyFromContract(call_len))?;
2330		let call: <E::T as Config>::RuntimeCall =
2331			ctx.read_sandbox_memory_as_unbounded(memory, call_ptr, call_len)?;
2332		ctx.call_dispatchable::<CallRuntimeFailed>(
2333			call.get_dispatch_info(),
2334			RuntimeCosts::CallRuntime,
2335			|ctx| ctx.ext.call_runtime(call),
2336		)
2337	}
2338
2339	/// Execute an XCM program locally, using the contract's address as the origin.
2340	/// See [`pallet_contracts_uapi::HostFn::execute_xcm`].
2341	#[mutating]
2342	fn xcm_execute(
2343		ctx: _,
2344		memory: _,
2345		msg_ptr: u32,
2346		msg_len: u32,
2347	) -> Result<ReturnErrorCode, TrapReason> {
2348		use frame_support::dispatch::DispatchInfo;
2349		use xcm::VersionedXcm;
2350		use xcm_builder::{ExecuteController, ExecuteControllerWeightInfo};
2351
2352		ctx.charge_gas(RuntimeCosts::CopyFromContract(msg_len))?;
2353		let message: VersionedXcm<CallOf<E::T>> =
2354			ctx.read_sandbox_memory_as_unbounded(memory, msg_ptr, msg_len)?;
2355
2356		let execute_weight =
2357			<<E::T as Config>::Xcm as ExecuteController<_, _>>::WeightInfo::execute();
2358		let weight = ctx.ext.gas_meter().gas_left().max(execute_weight);
2359		let dispatch_info = DispatchInfo { call_weight: weight, ..Default::default() };
2360
2361		ctx.call_dispatchable::<XcmExecutionFailed>(
2362			dispatch_info,
2363			RuntimeCosts::CallXcmExecute,
2364			|ctx| {
2365				let origin = crate::RawOrigin::Signed(ctx.ext.address().clone()).into();
2366				let weight_used = <<E::T as Config>::Xcm>::execute(
2367					origin,
2368					Box::new(message),
2369					weight.saturating_sub(execute_weight),
2370				)?;
2371
2372				Ok(Some(weight_used.saturating_add(execute_weight)).into())
2373			},
2374		)
2375	}
2376
2377	/// Send an XCM program from the contract to the specified destination.
2378	/// See [`pallet_contracts_uapi::HostFn::send_xcm`].
2379	#[mutating]
2380	fn xcm_send(
2381		ctx: _,
2382		memory: _,
2383		dest_ptr: u32,
2384		msg_ptr: u32,
2385		msg_len: u32,
2386		output_ptr: u32,
2387	) -> Result<ReturnErrorCode, TrapReason> {
2388		use xcm::{VersionedLocation, VersionedXcm};
2389		use xcm_builder::{SendController, SendControllerWeightInfo};
2390
2391		ctx.charge_gas(RuntimeCosts::CopyFromContract(msg_len))?;
2392		let dest: VersionedLocation = ctx.read_sandbox_memory_as(memory, dest_ptr)?;
2393
2394		let message: VersionedXcm<()> =
2395			ctx.read_sandbox_memory_as_unbounded(memory, msg_ptr, msg_len)?;
2396		let weight = <<E::T as Config>::Xcm as SendController<_>>::WeightInfo::send();
2397		ctx.charge_gas(RuntimeCosts::CallRuntime(weight))?;
2398		let origin = crate::RawOrigin::Signed(ctx.ext.address().clone()).into();
2399
2400		match <<E::T as Config>::Xcm>::send(origin, dest.into(), message.into()) {
2401			Ok(message_id) => {
2402				ctx.write_sandbox_memory(memory, output_ptr, &message_id.encode())?;
2403				Ok(ReturnErrorCode::Success)
2404			},
2405			Err(e) => {
2406				if ctx.ext.append_debug_buffer("") {
2407					ctx.ext.append_debug_buffer("seal0::xcm_send failed with: ");
2408					ctx.ext.append_debug_buffer(e.into());
2409				};
2410				Ok(ReturnErrorCode::XcmSendFailed)
2411			},
2412		}
2413	}
2414
2415	/// Recovers the ECDSA public key from the given message hash and signature.
2416	/// See [`pallet_contracts_uapi::HostFn::ecdsa_recover`].
2417	#[prefixed_alias]
2418	fn ecdsa_recover(
2419		ctx: _,
2420		memory: _,
2421		signature_ptr: u32,
2422		message_hash_ptr: u32,
2423		output_ptr: u32,
2424	) -> Result<ReturnErrorCode, TrapReason> {
2425		ctx.charge_gas(RuntimeCosts::EcdsaRecovery)?;
2426
2427		let mut signature: [u8; 65] = [0; 65];
2428		ctx.read_sandbox_memory_into_buf(memory, signature_ptr, &mut signature)?;
2429		let mut message_hash: [u8; 32] = [0; 32];
2430		ctx.read_sandbox_memory_into_buf(memory, message_hash_ptr, &mut message_hash)?;
2431
2432		let result = ctx.ext.ecdsa_recover(&signature, &message_hash);
2433
2434		match result {
2435			Ok(pub_key) => {
2436				// Write the recovered compressed ecdsa public key back into the sandboxed output
2437				// buffer.
2438				ctx.write_sandbox_memory(memory, output_ptr, pub_key.as_ref())?;
2439
2440				Ok(ReturnErrorCode::Success)
2441			},
2442			Err(_) => Ok(ReturnErrorCode::EcdsaRecoveryFailed),
2443		}
2444	}
2445
2446	/// Verify a sr25519 signature
2447	/// See [`pallet_contracts_uapi::HostFn::sr25519_verify`].
2448	fn sr25519_verify(
2449		ctx: _,
2450		memory: _,
2451		signature_ptr: u32,
2452		pub_key_ptr: u32,
2453		message_len: u32,
2454		message_ptr: u32,
2455	) -> Result<ReturnErrorCode, TrapReason> {
2456		ctx.charge_gas(RuntimeCosts::Sr25519Verify(message_len))?;
2457
2458		let mut signature: [u8; 64] = [0; 64];
2459		ctx.read_sandbox_memory_into_buf(memory, signature_ptr, &mut signature)?;
2460
2461		let mut pub_key: [u8; 32] = [0; 32];
2462		ctx.read_sandbox_memory_into_buf(memory, pub_key_ptr, &mut pub_key)?;
2463
2464		let message: Vec<u8> = ctx.read_sandbox_memory(memory, message_ptr, message_len)?;
2465
2466		if ctx.ext.sr25519_verify(&signature, &message, &pub_key) {
2467			Ok(ReturnErrorCode::Success)
2468		} else {
2469			Ok(ReturnErrorCode::Sr25519VerifyFailed)
2470		}
2471	}
2472
2473	/// Replace the contract code at the specified address with new code.
2474	/// See [`pallet_contracts_uapi::HostFn::set_code_hash`].
2475	#[prefixed_alias]
2476	#[mutating]
2477	fn set_code_hash(ctx: _, memory: _, code_hash_ptr: u32) -> Result<ReturnErrorCode, TrapReason> {
2478		ctx.charge_gas(RuntimeCosts::SetCodeHash)?;
2479		let code_hash: CodeHash<<E as Ext>::T> =
2480			ctx.read_sandbox_memory_as(memory, code_hash_ptr)?;
2481		match ctx.ext.set_code_hash(code_hash) {
2482			Err(err) => {
2483				let code = Runtime::<E>::err_into_return_code(err)?;
2484				Ok(code)
2485			},
2486			Ok(()) => Ok(ReturnErrorCode::Success),
2487		}
2488	}
2489
2490	/// Calculates Ethereum address from the ECDSA compressed public key and stores
2491	/// See [`pallet_contracts_uapi::HostFn::ecdsa_to_eth_address`].
2492	#[prefixed_alias]
2493	fn ecdsa_to_eth_address(
2494		ctx: _,
2495		memory: _,
2496		key_ptr: u32,
2497		out_ptr: u32,
2498	) -> Result<ReturnErrorCode, TrapReason> {
2499		ctx.charge_gas(RuntimeCosts::EcdsaToEthAddress)?;
2500		let mut compressed_key: [u8; 33] = [0; 33];
2501		ctx.read_sandbox_memory_into_buf(memory, key_ptr, &mut compressed_key)?;
2502		let result = ctx.ext.ecdsa_to_eth_address(&compressed_key);
2503		match result {
2504			Ok(eth_address) => {
2505				ctx.write_sandbox_memory(memory, out_ptr, eth_address.as_ref())?;
2506				Ok(ReturnErrorCode::Success)
2507			},
2508			Err(_) => Ok(ReturnErrorCode::EcdsaRecoveryFailed),
2509		}
2510	}
2511
2512	/// Returns the number of times the currently executing contract exists on the call stack in
2513	/// addition to the calling instance.
2514	/// See [`pallet_contracts_uapi::HostFn::reentrance_count`].
2515	#[unstable]
2516	fn reentrance_count(ctx: _, memory: _) -> Result<u32, TrapReason> {
2517		ctx.charge_gas(RuntimeCosts::ReentranceCount)?;
2518		Ok(ctx.ext.reentrance_count())
2519	}
2520
2521	/// Returns the number of times specified contract exists on the call stack. Delegated calls are
2522	/// not counted as separate calls.
2523	/// See [`pallet_contracts_uapi::HostFn::account_reentrance_count`].
2524	#[unstable]
2525	fn account_reentrance_count(ctx: _, memory: _, account_ptr: u32) -> Result<u32, TrapReason> {
2526		ctx.charge_gas(RuntimeCosts::AccountReentranceCount)?;
2527		let account_id: <<E as Ext>::T as frame_system::Config>::AccountId =
2528			ctx.read_sandbox_memory_as(memory, account_ptr)?;
2529		Ok(ctx.ext.account_reentrance_count(&account_id))
2530	}
2531
2532	/// Returns a nonce that is unique per contract instantiation.
2533	/// See [`pallet_contracts_uapi::HostFn::instantiation_nonce`].
2534	fn instantiation_nonce(ctx: _, _memory: _) -> Result<u64, TrapReason> {
2535		ctx.charge_gas(RuntimeCosts::InstantiationNonce)?;
2536		Ok(ctx.ext.nonce())
2537	}
2538
2539	/// Adds a new delegate dependency to the contract.
2540	/// See [`pallet_contracts_uapi::HostFn::lock_delegate_dependency`].
2541	#[mutating]
2542	fn lock_delegate_dependency(ctx: _, memory: _, code_hash_ptr: u32) -> Result<(), TrapReason> {
2543		ctx.charge_gas(RuntimeCosts::LockDelegateDependency)?;
2544		let code_hash = ctx.read_sandbox_memory_as(memory, code_hash_ptr)?;
2545		ctx.ext.lock_delegate_dependency(code_hash)?;
2546		Ok(())
2547	}
2548
2549	/// Removes the delegate dependency from the contract.
2550	/// see [`pallet_contracts_uapi::HostFn::unlock_delegate_dependency`].
2551	#[mutating]
2552	fn unlock_delegate_dependency(ctx: _, memory: _, code_hash_ptr: u32) -> Result<(), TrapReason> {
2553		ctx.charge_gas(RuntimeCosts::UnlockDelegateDependency)?;
2554		let code_hash = ctx.read_sandbox_memory_as(memory, code_hash_ptr)?;
2555		ctx.ext.unlock_delegate_dependency(&code_hash)?;
2556		Ok(())
2557	}
2558}