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