runtime.rs 99.4 KiB
Newer Older
		// a halt anyways without anymore code being executed.
		if flags.contains(CallFlags::TAIL_CALL) {
			if let Ok(return_value) = call_outcome {
				return Err(TrapReason::Return(ReturnData {
					flags: return_value.flags.bits(),
					data: return_value.data,
		if let Ok(output) = &call_outcome {
			self.write_sandbox_output(
				memory,
				output_ptr,
				output_len_ptr,
				&output.data,
				true,
				|len| Some(RuntimeCosts::CopyToContract(len)),
			)?;
		Ok(Runtime::<E>::exec_into_return_code(call_outcome)?)
	}

	fn instantiate(
		&mut self,
		value_ptr: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		address_ptr: u32,
		address_len_ptr: u32,
		output_ptr: u32,
		output_len_ptr: u32,
		salt_ptr: u32,
		salt_len: u32,
	) -> Result<ReturnCode, TrapReason> {
		self.charge_gas(RuntimeCosts::InstantiateBase { input_data_len, salt_len })?;
		let deposit_limit: BalanceOf<<E as Ext>::T> = if deposit_ptr == SENTINEL {
			BalanceOf::<<E as Ext>::T>::zero()
		} else {
			self.read_sandbox_memory_as(memory, deposit_ptr)?
		};
		let value: BalanceOf<<E as Ext>::T> = self.read_sandbox_memory_as(memory, value_ptr)?;
		if value > 0u32.into() {
			self.charge_gas(RuntimeCosts::InstantiateSurchargeTransfer)?;
		}
		let code_hash: CodeHash<<E as Ext>::T> =
			self.read_sandbox_memory_as(memory, code_hash_ptr)?;
		let input_data = self.read_sandbox_memory(memory, input_data_ptr, input_data_len)?;
		let salt = self.read_sandbox_memory(memory, salt_ptr, salt_len)?;
		let instantiate_outcome =
			self.ext.instantiate(weight, deposit_limit, code_hash, value, input_data, &salt);
		if let Ok((address, output)) = &instantiate_outcome {
			if !output.flags.contains(ReturnFlags::REVERT) {
				self.write_sandbox_output(
					address_ptr,
					address_len_ptr,
					&address.encode(),
					true,
					already_charged,
			self.write_sandbox_output(
				memory,
				output_ptr,
				output_len_ptr,
				&output.data,
				true,
				|len| Some(RuntimeCosts::CopyToContract(len)),
			)?;
		}
		Ok(Runtime::<E>::exec_into_return_code(instantiate_outcome.map(|(_, retval)| retval))?)
	}

	fn terminate(&mut self, memory: &[u8], beneficiary_ptr: u32) -> Result<(), TrapReason> {
		self.charge_gas(RuntimeCosts::Terminate)?;
		let beneficiary: <<E as Ext>::T as frame_system::Config>::AccountId =
			self.read_sandbox_memory_as(memory, beneficiary_ptr)?;
		self.ext.terminate(&beneficiary)?;
		Err(TrapReason::Termination)
	}
// This is the API exposed to contracts.
//
// # Note
//
// Any input that leads to a out of bound error (reading or writing) or failing to decode
// data passed to the supervisor will lead to a trap. This is not documented explicitly
// for every function.
	/// Set the value at the given key in the contract storage.
	///
	/// Equivalent to the newer [`seal1`][`super::api_doc::Version1::set_storage`] version with the
	/// exception of the return type. Still a valid thing to call when not interested in the return
	/// value.
		key_ptr: u32,
		value_ptr: u32,
		value_len: u32,
	) -> Result<(), TrapReason> {
		ctx.set_storage(memory, KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	/// Set the value at the given key in the contract storage.
	///
	/// This version is to be used with a fixed sized storage key. For runtimes supporting
	/// transparent hashing, please use the newer version of this function.
	///
	/// The value length must not exceed the maximum defined by the contracts module parameters.
	/// Specifying a `value_len` of zero will store an empty value.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the location to store the value is placed.
	/// - `value_ptr`: pointer into the linear memory where the value to set is placed.
	/// - `value_len`: the length of the value in bytes.
	///
	/// # Return Value
	///
	/// Returns the size of the pre-existing value at the specified key if any. Otherwise
	/// `SENTINEL` is returned as a sentinel value.
	#[version(1)]
		key_ptr: u32,
		value_ptr: u32,
		value_len: u32,
	) -> Result<u32, TrapReason> {
		ctx.set_storage(memory, KeyType::Fix, key_ptr, value_ptr, value_len)
	/// Set the value at the given key in the contract storage.
	///
	/// The key and value lengths must not exceed the maximums defined by the contracts module
	/// parameters. Specifying a `value_len` of zero will store an empty value.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the location to store the value is placed.
	/// - `key_len`: the length of the key in bytes.
	/// - `value_ptr`: pointer into the linear memory where the value to set is placed.
	/// - `value_len`: the length of the value in bytes.
	///
	/// # Return Value
	///
	/// Returns the size of the pre-existing value at the specified key if any. Otherwise
	/// `SENTINEL` is returned as a sentinel value.
		key_ptr: u32,
		key_len: u32,
		value_ptr: u32,
		value_len: u32,
	) -> Result<u32, TrapReason> {
		ctx.set_storage(memory, KeyType::Var(key_len), key_ptr, value_ptr, value_len)
	/// Clear the value at the given key in the contract storage.
	///
	/// Equivalent to the newer [`seal1`][`super::api_doc::Version1::clear_storage`] version with
	/// the exception of the return type. Still a valid thing to call when not interested in the
	/// return value.
	fn clear_storage(ctx: _, memory: _, key_ptr: u32) -> Result<(), TrapReason> {
		ctx.clear_storage(memory, KeyType::Fix, key_ptr).map(|_| ())
	/// Clear the value at the given key in the contract storage.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the key is placed.
	/// - `key_len`: the length of the key in bytes.
	///
	/// # Return Value
	///
	/// Returns the size of the pre-existing value at the specified key if any. Otherwise
	/// `SENTINEL` is returned as a sentinel value.
	fn clear_storage(ctx: _, memory: _, key_ptr: u32, key_len: u32) -> Result<u32, TrapReason> {
		ctx.clear_storage(memory, KeyType::Var(key_len), key_ptr)
	/// Retrieve the value under the given key from storage.
	///
	/// This version is to be used with a fixed sized storage key. For runtimes supporting
	/// transparent hashing, please use the newer version of this function.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the key of the requested value is placed.
	/// - `out_ptr`: pointer to the linear memory where the value is written to.
	/// - `out_len_ptr`: in-out pointer into linear memory where the buffer length is read from and
	///   the value length is written to.
	///
	/// # Errors
	///
	/// `ReturnCode::KeyNotFound`
		key_ptr: u32,
		out_ptr: u32,
		out_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.get_storage(memory, KeyType::Fix, key_ptr, out_ptr, out_len_ptr)
	/// Retrieve the value under the given key from storage.
	///
	/// This version is to be used with a fixed sized storage key. For runtimes supporting
	/// transparent hashing, please use the newer version of this function.
	///
	/// The key length must not exceed the maximum defined by the contracts module parameter.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the key of the requested value is placed.
	/// - `key_len`: the length of the key in bytes.
	/// - `out_ptr`: pointer to the linear memory where the value is written to.
	/// - `out_len_ptr`: in-out pointer into linear memory where the buffer length is read from and
	///   the value length is written to.
	///
	/// # Errors
	///
		key_ptr: u32,
		key_len: u32,
		out_ptr: u32,
		out_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.get_storage(memory, KeyType::Var(key_len), key_ptr, out_ptr, out_len_ptr)
	/// Checks whether there is a value stored under the given key.
	///
	/// This version is to be used with a fixed sized storage key. For runtimes supporting
	/// transparent hashing, please use the newer version of this function.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the key of the requested value is placed.
	///
	/// # Return Value
	///
	/// Returns the size of the pre-existing value at the specified key if any. Otherwise
	/// `SENTINEL` is returned as a sentinel value.
	fn contains_storage(ctx: _, memory: _, key_ptr: u32) -> Result<u32, TrapReason> {
		ctx.contains_storage(memory, KeyType::Fix, key_ptr)
	/// Checks whether there is a value stored under the given key.
	///
	/// The key length must not exceed the maximum defined by the contracts module parameter.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the key of the requested value is placed.
	/// - `key_len`: the length of the key in bytes.
	///
	/// # Return Value
	///
	/// Returns the size of the pre-existing value at the specified key if any. Otherwise
	/// `SENTINEL` is returned as a sentinel value.
	fn contains_storage(ctx: _, memory: _, key_ptr: u32, key_len: u32) -> Result<u32, TrapReason> {
		ctx.contains_storage(memory, KeyType::Var(key_len), key_ptr)
	/// Retrieve and remove the value under the given key from storage.
	///
	/// # Parameters
	///
	/// - `key_ptr`: pointer into the linear memory where the key of the requested value is placed.
	/// - `key_len`: the length of the key in bytes.
	/// - `out_ptr`: pointer to the linear memory where the value is written to.
	/// - `out_len_ptr`: in-out pointer into linear memory where the buffer length is read from and
	///   the value length is written to.
	///
	/// # Errors
	///
		key_ptr: u32,
		key_len: u32,
		out_ptr: u32,
		out_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
		let charged = ctx.charge_gas(RuntimeCosts::TakeStorage(ctx.ext.max_value_size()))?;
		ensure!(
			key_len <= <<E as Ext>::T as Config>::MaxStorageKeyLen::get(),
			Error::<E::T>::DecodingFailed
		);
		let key = ctx.read_sandbox_memory(memory, key_ptr, key_len)?;
		if let crate::storage::WriteOutcome::Taken(value) = ctx.ext.set_storage(
			&Key::<E::T>::try_from_var(key).map_err(|_| Error::<E::T>::DecodingFailed)?,
			ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(value.len() as u32));
			ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &value, false, already_charged)?;
			ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(0));
	/// Transfer some value to another account.
	///
	/// # Parameters
	///
	/// - `account_ptr`: a pointer to the address of the beneficiary account Should be decodable as
	///   an `T::AccountId`. Traps otherwise.
	/// - `account_len`: length of the address buffer.
	/// - `value_ptr`: a pointer to the buffer with value, how much value to send. Should be
	///   decodable as a `T::Balance`. Traps otherwise.
	/// - `value_len`: length of the value buffer.
		account_ptr: u32,
		value_ptr: u32,
		_value_len: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.charge_gas(RuntimeCosts::Transfer)?;
		let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
			ctx.read_sandbox_memory_as(memory, account_ptr)?;
		let value: BalanceOf<<E as Ext>::T> = ctx.read_sandbox_memory_as(memory, value_ptr)?;
		let result = ctx.ext.transfer(&callee, value);
		match result {
			Ok(()) => Ok(ReturnCode::Success),
			Err(err) => {
				let code = Runtime::<E>::err_into_return_code(err)?;
				Ok(code)
	/// Make a call to another contract.
	///
	/// # New version available
	///
	/// This is equivalent to calling the newer version of this function with
	/// `flags` set to `ALLOW_REENTRY`. See the newer version for documentation.
	///
	/// # Note
	///
	/// The values `_callee_len` and `_value_len` are ignored because the encoded sizes
	/// of those types are fixed through
	/// [`codec::MaxEncodedLen`]. The fields exist
	/// for backwards compatibility. Consider switching to the newest version of this function.
		input_data_ptr: u32,
		input_data_len: u32,
		output_ptr: u32,
		output_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
			CallType::Call {
				callee_ptr,
				value_ptr,
				deposit_ptr: SENTINEL,
				weight: Weight::from_parts(gas, 0),
			},
			input_data_ptr,
			input_data_len,
			output_ptr,
			output_len_ptr,
		)
	}

	/// Make a call to another contract.
	///
	/// Equivalent to the newer [`seal2`][`super::api_doc::Version2::call`] version but works with
	/// *ref_time* Weight only. It is recommended to switch to the latest version, once it's
	/// stabilized.
	#[version(1)]
	#[prefixed_alias]
	fn call(
		ctx: _,
		memory: _,
		flags: u32,
		callee_ptr: u32,
		gas: u64,
		value_ptr: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		output_ptr: u32,
		output_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.call(
			memory,
			CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
			CallType::Call {
				callee_ptr,
				value_ptr,
				deposit_ptr: SENTINEL,
				weight: Weight::from_parts(gas, 0),
			},
			input_data_ptr,
			input_data_len,
			output_ptr,
			output_len_ptr,
		)
	/// Make a call to another contract.
	///
	/// The callees output buffer is copied to `output_ptr` and its length to `output_len_ptr`.
	/// The copy of the output buffer can be skipped by supplying the sentinel value
	/// of `SENTINEL` to `output_ptr`.
	///
	/// # Parameters
	///
	/// - `flags`: See `crate::wasm::runtime::CallFlags` for a documentation of the supported flags.
	/// - `callee_ptr`: a pointer to the address of the callee contract. Should be decodable as an
	///   `T::AccountId`. Traps otherwise.
	/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
	/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
	/// - `deposit_ptr`: a pointer to the buffer with value of the storage deposit limit for the
	///   call. Should be decodable as a `T::Balance`. Traps otherwise. Passing `SENTINEL` means
	///   setting no specific limit for the call, which implies storage usage up to the limit of the
	///   parent call.
	/// - `value_ptr`: a pointer to the buffer with value, how much value to send. Should be
	///   decodable as a `T::Balance`. Traps otherwise.
	/// - `input_data_ptr`: a pointer to a buffer to be used as input data to the callee.
	/// - `input_data_len`: length of the input data buffer.
	/// - `output_ptr`: a pointer where the output buffer is copied to.
	/// - `output_len_ptr`: in-out pointer to where the length of the buffer is read from and the
	///   actual length is written to.
	///
	/// # Errors
	///
	/// An error means that the call wasn't successful output buffer is returned unless
	/// stated otherwise.
	///
	/// - `ReturnCode::CalleeReverted`: Output buffer is returned.
	/// - `ReturnCode::CalleeTrapped`
	/// - `ReturnCode::TransferFailed`
	/// - `ReturnCode::NotCallable`
Sergey Pepyakin's avatar
Sergey Pepyakin committed
		callee_ptr: u32,
		ref_time_limit: u64,
		proof_size_limit: u64,
		deposit_ptr: u32,
Sergey Pepyakin's avatar
Sergey Pepyakin committed
		value_ptr: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		output_ptr: u32,
		output_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
			CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
			CallType::Call {
				callee_ptr,
				value_ptr,
				deposit_ptr,
				weight: Weight::from_parts(ref_time_limit, proof_size_limit),
			},
			input_data_ptr,
			input_data_len,
			output_ptr,
			output_len_ptr,
		)
	/// Execute code in the context (storage, caller, value) of the current contract.
	///
	/// Reentrancy protection is always disabled since the callee is allowed
	/// to modify the callers storage. This makes going through a reentrancy attack
	/// unnecessary for the callee when it wants to exploit the caller.
	///
	/// # Parameters
	///
	/// - `flags`: see `crate::wasm::runtime::CallFlags` for a documentation of the supported flags.
	/// - `code_hash`: a pointer to the hash of the code to be called.
	/// - `input_data_ptr`: a pointer to a buffer to be used as input data to the callee.
	/// - `input_data_len`: length of the input data buffer.
	/// - `output_ptr`: a pointer where the output buffer is copied to.
	/// - `output_len_ptr`: in-out pointer to where the length of the buffer is read from and the
	///   actual length is written to.
	///
	/// # Errors
	///
	/// An error means that the call wasn't successful and no output buffer is returned unless
	/// stated otherwise.
	///
	/// - `ReturnCode::CalleeReverted`: Output buffer is returned.
	/// - `ReturnCode::CalleeTrapped`
	/// - `ReturnCode::CodeNotFound`
		flags: u32,
		code_hash_ptr: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		output_ptr: u32,
		output_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
			CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
			CallType::DelegateCall { code_hash_ptr },
			input_data_ptr,
			input_data_len,
			output_ptr,
			output_len_ptr,
		)
	/// Instantiate a contract with the specified code hash.
	///
	/// # New version available
	///
	/// This is equivalent to calling the newer version of this function. The newer version
	/// drops the now unnecessary length fields.
	///
	/// # Note
	///
	/// The values `_code_hash_len` and `_value_len` are ignored because the encoded sizes
	/// of those types are fixed through [`codec::MaxEncodedLen`]. The fields exist
	/// for backwards compatibility. Consider switching to the newest version of this function.
		code_hash_ptr: u32,
		_code_hash_len: u32,
		gas: u64,
		value_ptr: u32,
		_value_len: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		address_ptr: u32,
		address_len_ptr: u32,
		output_ptr: u32,
		output_len_ptr: u32,
		salt_ptr: u32,
		salt_len: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.instantiate(
			Weight::from_parts(gas, 0),
			SENTINEL,
			value_ptr,
			input_data_ptr,
			input_data_len,
			address_ptr,
			address_len_ptr,
			output_ptr,
			output_len_ptr,
			salt_ptr,
			salt_len,
		)
	}

	/// Instantiate a contract with the specified code hash.
	///
	/// Equivalent to the newer [`seal2`][`super::api_doc::Version2::instantiate`] version but works
	/// with *ref_time* Weight only. It is recommended to switch to the latest version, once it's
	/// stabilized.
	#[version(1)]
	#[prefixed_alias]
	fn instantiate(
		ctx: _,
		memory: _,
		code_hash_ptr: u32,
		gas: u64,
		value_ptr: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		address_ptr: u32,
		address_len_ptr: u32,
		output_ptr: u32,
		output_len_ptr: u32,
		salt_ptr: u32,
		salt_len: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.instantiate(
			memory,
			code_hash_ptr,
			Weight::from_parts(gas, 0),
			SENTINEL,
			value_ptr,
			input_data_ptr,
			input_data_len,
			address_ptr,
			address_len_ptr,
			output_ptr,
			output_len_ptr,
			salt_ptr,
			salt_len,
		)
	/// Instantiate a contract with the specified code hash.
	///
	/// This function creates an account and executes the constructor defined in the code specified
	/// by the code hash. The address of this new account is copied to `address_ptr` and its length
	/// to `address_len_ptr`. The constructors output buffer is copied to `output_ptr` and its
	/// length to `output_len_ptr`. The copy of the output buffer and address can be skipped by
	/// supplying the sentinel value of `SENTINEL` to `output_ptr` or `address_ptr`.
	///
	/// # Parameters
	///
	/// - `code_hash_ptr`: a pointer to the buffer that contains the initializer code.
	/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
	/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
	/// - `deposit_ptr`: a pointer to the buffer with value of the storage deposit limit for
	///   instantiation. Should be decodable as a `T::Balance`. Traps otherwise. Passing `SENTINEL`
	///   means setting no specific limit for the call, which implies storage usage up to the limit
	///   of the parent call.
	/// - `value_ptr`: a pointer to the buffer with value, how much value to send. Should be
	///   decodable as a `T::Balance`. Traps otherwise.
	/// - `input_data_ptr`: a pointer to a buffer to be used as input data to the initializer code.
	/// - `input_data_len`: length of the input data buffer.
	/// - `address_ptr`: a pointer where the new account's address is copied to. `SENTINEL` means
	///   not to copy.
	/// - `address_len_ptr`: pointer to where put the length of the address.
	/// - `output_ptr`: a pointer where the output buffer is copied to. `SENTINEL` means not to
	///   copy.
	/// - `output_len_ptr`: in-out pointer to where the length of the buffer is read from and the
	///   actual length is written to.
	/// - `salt_ptr`: Pointer to raw bytes used for address derivation. See `fn contract_address`.
	/// - `salt_len`: length in bytes of the supplied salt.
	///
	/// # Errors
	///
	/// Please consult the `ReturnCode` enum declaration for more information on those
	/// errors. Here we only note things specific to this function.
	///
	/// An error means that the account wasn't created and no address or output buffer
	/// is returned unless stated otherwise.
	///
	/// - `ReturnCode::CalleeReverted`: Output buffer is returned.
	/// - `ReturnCode::CalleeTrapped`
	/// - `ReturnCode::TransferFailed`
	/// - `ReturnCode::CodeNotFound`
		code_hash_ptr: u32,
		ref_time_limit: u64,
		proof_size_limit: u64,
		deposit_ptr: u32,
Sergey Pepyakin's avatar
Sergey Pepyakin committed
		value_ptr: u32,
		input_data_ptr: u32,
		input_data_len: u32,
		address_ptr: u32,
		address_len_ptr: u32,
		output_ptr: u32,
		salt_len: u32,
	) -> Result<ReturnCode, TrapReason> {
			Weight::from_parts(ref_time_limit, proof_size_limit),
			deposit_ptr,
			value_ptr,
			input_data_ptr,
			input_data_len,
			address_ptr,
			address_len_ptr,
			output_ptr,
			output_len_ptr,
			salt_ptr,
			salt_len,
		)
	/// Remove the calling account and transfer remaining balance.
	///
	/// # New version available
	///
	/// This is equivalent to calling the newer version of this function. The newer version
	/// drops the now unnecessary length fields.
	///
	/// # Note
	///
	/// The value `_beneficiary_len` is ignored because the encoded sizes
	/// this type is fixed through `[`MaxEncodedLen`]. The field exist for backwards
	/// compatibility. Consider switching to the newest version of this function.
		beneficiary_ptr: u32,
		_beneficiary_len: u32,
	) -> Result<(), TrapReason> {
	/// Remove the calling account and transfer remaining **free** balance.
	///
	/// This function never returns. Either the termination was successful and the
	/// execution of the destroyed contract is halted. Or it failed during the termination
	/// which is considered fatal and results in a trap + rollback.
	///
	/// - `beneficiary_ptr`: a pointer to the address of the beneficiary account where all where all
	///   remaining funds of the caller are transferred. Should be decodable as an `T::AccountId`.
	///   Traps otherwise.
	///
	/// # Traps
	///
	/// - The contract is live i.e is already on the call stack.
	/// - Failed to send the balance to the beneficiary.
	/// - The deletion queue is full.
	#[version(1)]
	fn terminate(ctx: _, memory: _, beneficiary_ptr: u32) -> Result<(), TrapReason> {
		ctx.terminate(memory, beneficiary_ptr)
	/// Stores the input passed by the caller into the supplied buffer.
	///
	/// The value is stored to linear memory at the address pointed to by `out_ptr`.
	/// `out_len_ptr` must point to a u32 value that describes the available space at
	/// `out_ptr`. This call overwrites it with the size of the value. If the available
	/// space at `out_ptr` is less than the size of the value a trap is triggered.
	///
	/// # Note
	///
	/// This function traps if the input was previously forwarded by a [`call()`][`Self::call()`].
	fn input(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
		ctx.charge_gas(RuntimeCosts::InputBase)?;
		if let Some(input) = ctx.input_data.take() {
			ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &input, false, |len| {
				Some(RuntimeCosts::CopyToContract(len))
			Err(Error::<E::T>::InputForwarded.into())
	/// Cease contract execution and save a data buffer as a result of the execution.
	///
	/// This function never returns as it stops execution of the caller.
	/// This is the only way to return a data buffer to the caller. Returning from
	/// execution without calling this function is equivalent to calling:
	/// seal_return(0, 0, 0);
	/// ```
	///
	/// The flags argument is a bitfield that can be used to signal special return
	/// conditions to the supervisor:
	/// --- lsb ---
	/// bit 0      : REVERT - Revert all storage changes made by the caller.
	/// bit [1, 31]: Reserved for future use.
	/// --- msb ---
	///
	/// Using a reserved bit triggers a trap.
	fn seal_return(
		flags: u32,
		data_ptr: u32,
		data_len: u32,
	) -> Result<(), TrapReason> {
		ctx.charge_gas(RuntimeCosts::Return(data_len))?;
			data: ctx.read_sandbox_memory(memory, data_ptr, data_len)?,
	/// Stores the address of the caller into the supplied buffer.
	///
	/// The value is stored to linear memory at the address pointed to by `out_ptr`.
	/// `out_len_ptr` must point to a u32 value that describes the available space at
	/// `out_ptr`. This call overwrites it with the size of the value. If the available
	/// space at `out_ptr` is less than the size of the value a trap is triggered.
	///
	/// If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the
	/// extrinsic will be returned. Otherwise, if this call is initiated by another contract then
	/// the address of the contract will be returned. The value is encoded as T::AccountId.
	///
	/// If there is no address associated with the caller (e.g. because the caller is root) then
	/// it traps with `BadOrigin`.
	fn caller(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
		ctx.charge_gas(RuntimeCosts::Caller)?;
		let caller = ctx.ext.caller().account_id()?.clone();
	/// Checks whether a specified address belongs to a contract.
	///
	/// # Parameters
	///
	/// - `account_ptr`: a pointer to the address of the beneficiary account Should be decodable as
	///   an `T::AccountId`. Traps otherwise.
	/// Returned value is a `u32`-encoded boolean: (0 = false, 1 = true).
	fn is_contract(ctx: _, memory: _, account_ptr: u32) -> Result<u32, TrapReason> {
		ctx.charge_gas(RuntimeCosts::IsContract)?;
		let address: <<E as Ext>::T as frame_system::Config>::AccountId =
			ctx.read_sandbox_memory_as(memory, account_ptr)?;
	/// Retrieve the code hash for a specified contract address.
	///
	/// # Parameters
	///
	/// - `account_ptr`: a pointer to the address in question. Should be decodable as an
	///   `T::AccountId`. Traps otherwise.
	/// - `out_ptr`: pointer to the linear memory where the returning value is written to.
	/// - `out_len_ptr`: in-out pointer into linear memory where the buffer length is read from and
	///   the value length is written to.
	///
	/// # Errors
	///
		account_ptr: u32,
		out_ptr: u32,
		out_len_ptr: u32,
	) -> Result<ReturnCode, TrapReason> {
		ctx.charge_gas(RuntimeCosts::CodeHash)?;
		let address: <<E as Ext>::T as frame_system::Config>::AccountId =
			ctx.read_sandbox_memory_as(memory, account_ptr)?;
		if let Some(value) = ctx.ext.code_hash(&address) {
				out_ptr,
				out_len_ptr,
				&value.encode(),
				false,
				already_charged,
			)?;
			Ok(ReturnCode::Success)
		} else {
			Ok(ReturnCode::KeyNotFound)
		}
	/// Retrieve the code hash of the currently executing contract.
	///
	/// # Parameters
	///
	/// - `out_ptr`: pointer to the linear memory where the returning value is written to.
	/// - `out_len_ptr`: in-out pointer into linear memory where the buffer length is read from and
	///   the value length is written to.
	fn own_code_hash(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
		ctx.charge_gas(RuntimeCosts::OwnCodeHash)?;
		let code_hash_encoded = &ctx.ext.own_code_hash().encode();
		Ok(ctx.write_sandbox_output(
			out_ptr,
			out_len_ptr,
			code_hash_encoded,
			false,
			already_charged,
		)?)
	}
	/// Checks whether the caller of the current contract is the origin of the whole call stack.
	///
	/// Prefer this over [`is_contract()`][`Self::is_contract`] when checking whether your contract
	/// is being called by a contract or a plain account. The reason is that it performs better
	/// since it does not need to do any storage lookups.
	/// A return value of `true` indicates that this contract is being called by a plain account
	/// and `false` indicates that the caller is another contract.
	///
	/// Returned value is a `u32`-encoded boolean: (`0 = false`, `1 = true`).
	fn caller_is_origin(ctx: _, _memory: _) -> Result<u32, TrapReason> {
		ctx.charge_gas(RuntimeCosts::CallerIsOrigin)?;
		Ok(ctx.ext.caller_is_origin() as u32)
	/// Checks whether the caller of the current contract is root.
	///
	/// Note that only the origin of the call stack can be root. Hence this function returning
	/// `true` implies that the contract is being called by the origin.
	///
	/// A return value of `true` indicates that this contract is being called by a root origin,
	/// and `false` indicates that the caller is a signed origin.
	///
	/// Returned value is a `u32`-encoded boolean: (`0 = false`, `1 = true`).
	#[unstable]
	fn caller_is_root(ctx: _, _memory: _) -> Result<u32, TrapReason> {
		ctx.charge_gas(RuntimeCosts::CallerIsRoot)?;
		Ok(ctx.ext.caller_is_root() as u32)
	}

	/// Stores the address of the current contract into the supplied buffer.
	///
	/// The value is stored to linear memory at the address pointed to by `out_ptr`.
	/// `out_len_ptr` must point to a u32 value that describes the available space at
	/// `out_ptr`. This call overwrites it with the size of the value. If the available
	/// space at `out_ptr` is less than the size of the value a trap is triggered.
	fn address(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
		ctx.charge_gas(RuntimeCosts::Address)?;
			out_ptr,
			out_len_ptr,
			&ctx.ext.address().encode(),
			false,
			already_charged,
	/// Stores the price for the specified amount of gas into the supplied buffer.
	///
	/// Equivalent to the newer [`seal1`][`super::api_doc::Version2::weight_to_fee`] version but
	/// works with *ref_time* Weight only. It is recommended to switch to the latest version, once
	/// it's stabilized.
	#[prefixed_alias]
	fn weight_to_fee(
		ctx: _,
		memory: _,
		gas: u64,
		out_ptr: u32,
		out_len_ptr: u32,
	) -> Result<(), TrapReason> {
		let gas = Weight::from_parts(gas, 0);
		ctx.charge_gas(RuntimeCosts::WeightToFee)?;
		Ok(ctx.write_sandbox_output(
			memory,
			out_ptr,
			out_len_ptr,
			&ctx.ext.get_weight_price(gas).encode(),
			false,