Newer
Older
Alexander Theißen
committed
true,
|len| Some(RuntimeCosts::CopyToContract(len)),
)?;
}
Ok(Runtime::<E>::exec_into_return_code(instantiate_outcome.map(|(_, retval)| retval))?)
}
Alexander Theißen
committed
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 =
Alexander Theißen
committed
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.
Sasha Gryaznov
committed
#[define_env(doc)]
pub mod env {
/// Set the value at the given key in the contract storage.
///
Sasha Gryaznov
committed
/// 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.
Sasha Gryaznov
committed
#[prefixed_alias]
fn set_storage(
Alexander Theißen
committed
ctx: _,
memory: _,
key_ptr: u32,
value_ptr: u32,
value_len: u32,
) -> Result<(), TrapReason> {
Alexander Theißen
committed
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)]
Sasha Gryaznov
committed
#[prefixed_alias]
fn set_storage(
Alexander Theißen
committed
ctx: _,
memory: _,
key_ptr: u32,
value_ptr: u32,
value_len: u32,
) -> Result<u32, TrapReason> {
Alexander Theißen
committed
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.
Sasha Gryaznov
committed
#[prefixed_alias]
fn set_storage(
Alexander Theißen
committed
ctx: _,
memory: _,
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.
///
Sasha Gryaznov
committed
/// 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.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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`
Sasha Gryaznov
committed
#[prefixed_alias]
fn get_storage(
Alexander Theißen
committed
ctx: _,
memory: _,
key_ptr: u32,
out_ptr: u32,
out_len_ptr: u32,
) -> Result<ReturnCode, TrapReason> {
Alexander Theißen
committed
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
///
Sasha Gryaznov
committed
/// - `ReturnCode::KeyNotFound`
Sasha Gryaznov
committed
#[prefixed_alias]
fn get_storage(
Alexander Theißen
committed
ctx: _,
memory: _,
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.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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
///
Sasha Gryaznov
committed
/// - `ReturnCode::KeyNotFound`
Sasha Gryaznov
committed
#[prefixed_alias]
fn take_storage(
Alexander Theißen
committed
ctx: _,
memory: _,
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
);
Alexander Theißen
committed
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)?,
None,
true,
)? {
ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(value.len() as u32));
Alexander Theißen
committed
ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &value, false, already_charged)?;
Ok(ReturnCode::Success)
} else {
ctx.adjust_gas(charged, RuntimeCosts::TakeStorage(0));
Ok(ReturnCode::KeyNotFound)
}
/// Transfer some value to another account.
///
/// # Parameters
///
Sasha Gryaznov
committed
/// - `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.
///
/// # Errors
///
Sasha Gryaznov
committed
/// - `ReturnCode::TransferFailed`
Sasha Gryaznov
committed
#[prefixed_alias]
fn transfer(
Alexander Theißen
committed
ctx: _,
memory: _,
_value_len: u32,
) -> Result<ReturnCode, TrapReason> {
ctx.charge_gas(RuntimeCosts::Transfer)?;
let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
Alexander Theißen
committed
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);
Alexander Theißen
committed
match result {
Ok(()) => Ok(ReturnCode::Success),
Err(err) => {
let code = Runtime::<E>::err_into_return_code(err)?;
Ok(code)
Alexander Theißen
committed
}
/// 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
Sasha Gryaznov
committed
/// of those types are fixed through
/// [`codec::MaxEncodedLen`]. The fields exist
/// for backwards compatibility. Consider switching to the newest version of this function.
Sasha Gryaznov
committed
#[prefixed_alias]
fn call(
Alexander Theißen
committed
ctx: _,
memory: _,
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(
Alexander Theißen
committed
memory,
CallFlags::ALLOW_REENTRY,
Sasha Gryaznov
committed
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
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.
Sasha Gryaznov
committed
/// - `callee_ptr`: a pointer to the address of the callee contract. Should be decodable as an
/// `T::AccountId`. Traps otherwise.
Sasha Gryaznov
committed
/// - `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.
Sasha Gryaznov
committed
/// - `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.
///
Sasha Gryaznov
committed
/// - `ReturnCode::CalleeReverted`: Output buffer is returned.
/// - `ReturnCode::CalleeTrapped`
/// - `ReturnCode::TransferFailed`
/// - `ReturnCode::NotCallable`
Sasha Gryaznov
committed
#[version(2)]
#[unstable]
Sasha Gryaznov
committed
fn call(
Alexander Theißen
committed
ctx: _,
memory: _,
flags: u32,
Sasha Gryaznov
committed
ref_time_limit: u64,
proof_size_limit: u64,
deposit_ptr: u32,
input_data_len: u32,
output_ptr: u32,
output_len_ptr: u32,
) -> Result<ReturnCode, TrapReason> {
ctx.call(
Alexander Theißen
committed
memory,
CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
Sasha Gryaznov
committed
CallType::Call {
callee_ptr,
value_ptr,
deposit_ptr,
weight: Weight::from_parts(ref_time_limit, proof_size_limit),
},
Yarik Bratashchuk
committed
input_data_ptr,
input_data_len,
output_ptr,
output_len_ptr,
)
Yarik Bratashchuk
committed
/// 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
///
Sasha Gryaznov
committed
/// - `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.
///
Sasha Gryaznov
committed
/// - `ReturnCode::CalleeReverted`: Output buffer is returned.
/// - `ReturnCode::CalleeTrapped`
/// - `ReturnCode::CodeNotFound`
Sasha Gryaznov
committed
#[prefixed_alias]
fn delegate_call(
Alexander Theißen
committed
ctx: _,
memory: _,
Yarik Bratashchuk
committed
flags: u32,
code_hash_ptr: u32,
input_data_ptr: u32,
input_data_len: u32,
output_ptr: u32,
output_len_ptr: u32,
) -> Result<ReturnCode, TrapReason> {
Yarik Bratashchuk
committed
ctx.call(
Alexander Theißen
committed
memory,
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
Sasha Gryaznov
committed
/// of those types are fixed through [`codec::MaxEncodedLen`]. The fields exist
Sasha Gryaznov
committed
/// for backwards compatibility. Consider switching to the newest version of this function.
Sasha Gryaznov
committed
#[prefixed_alias]
fn instantiate(
Alexander Theißen
committed
ctx: _,
memory: _,
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(
Alexander Theißen
committed
memory,
Sasha Gryaznov
committed
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
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
///
Sasha Gryaznov
committed
/// - `code_hash_ptr`: a pointer to the buffer that contains the initializer code.
Sasha Gryaznov
committed
/// - `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.
Sasha Gryaznov
committed
/// - `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.
Sasha Gryaznov
committed
/// - `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.
Sasha Gryaznov
committed
/// - `output_len_ptr`: in-out pointer to where the length of the buffer is read from and the
/// actual length is written to.
Sasha Gryaznov
committed
/// - `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.
///
Sasha Gryaznov
committed
/// - `ReturnCode::CalleeReverted`: Output buffer is returned.
/// - `ReturnCode::CalleeTrapped`
/// - `ReturnCode::TransferFailed`
/// - `ReturnCode::CodeNotFound`
Sasha Gryaznov
committed
#[version(2)]
#[unstable]
Sasha Gryaznov
committed
fn instantiate(
Alexander Theißen
committed
ctx: _,
memory: _,
Sasha Gryaznov
committed
ref_time_limit: u64,
proof_size_limit: u64,
deposit_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> {
Alexander Theißen
committed
memory,
Sasha Gryaznov
committed
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.
Sasha Gryaznov
committed
#[prefixed_alias]
fn terminate(
Alexander Theißen
committed
ctx: _,
memory: _,
beneficiary_ptr: u32,
_beneficiary_len: u32,
) -> Result<(), TrapReason> {
Alexander Theißen
committed
ctx.terminate(memory, beneficiary_ptr)
/// 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.
///
Sasha Gryaznov
committed
/// - `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)]
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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
///
Sasha Gryaznov
committed
/// This function traps if the input was previously forwarded by a [`call()`][`Self::call()`].
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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() {
Alexander Theißen
committed
ctx.write_sandbox_output(memory, out_ptr, out_len_ptr, &input, false, |len| {
Some(RuntimeCosts::CopyToContract(len))
Alexander Theißen
committed
})?;
ctx.input_data = Some(input);
Alexander Theißen
committed
Ok(())
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:
Sasha Gryaznov
committed
/// ```nocompile
/// 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(
Alexander Theißen
committed
ctx: _,
memory: _,
flags: u32,
data_ptr: u32,
data_len: u32,
) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::Return(data_len))?;
Alexander Theißen
committed
Err(TrapReason::Return(ReturnData {
Alexander Theißen
committed
data: ctx.read_sandbox_memory(memory, data_ptr, data_len)?,
Alexander Theißen
committed
}))
/// 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`.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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();
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
false,
already_charged,
Alexander Theißen
committed
)?)
/// Checks whether a specified address belongs to a contract.
///
/// # Parameters
///
Sasha Gryaznov
committed
/// - `account_ptr`: a pointer to the address of the beneficiary account Should be decodable as
/// an `T::AccountId`. Traps otherwise.
Sasha Gryaznov
committed
/// Returned value is a `u32`-encoded boolean: (0 = false, 1 = true).
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
fn is_contract(ctx: _, memory: _, account_ptr: u32) -> Result<u32, TrapReason> {
Sasha Gryaznov
committed
ctx.charge_gas(RuntimeCosts::IsContract)?;
let address: <<E as Ext>::T as frame_system::Config>::AccountId =
Alexander Theißen
committed
ctx.read_sandbox_memory_as(memory, account_ptr)?;
Sasha Gryaznov
committed
Ok(ctx.ext.is_contract(&address) as u32)
Sasha Gryaznov
committed
/// 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
///
Sasha Gryaznov
committed
/// - `ReturnCode::KeyNotFound`
Sasha Gryaznov
committed
#[prefixed_alias]
fn code_hash(
Alexander Theißen
committed
ctx: _,
memory: _,
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 =
Alexander Theißen
committed
ctx.read_sandbox_memory_as(memory, account_ptr)?;
if let Some(value) = ctx.ext.code_hash(&address) {
ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
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.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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(
Alexander Theißen
committed
memory,
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.
///
Sasha Gryaznov
committed
/// 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.
Sasha Gryaznov
committed
/// 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.
///
Sasha Gryaznov
committed
/// Returned value is a `u32`-encoded boolean: (`0 = false`, `1 = true`).
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
fn caller_is_origin(ctx: _, _memory: _) -> Result<u32, TrapReason> {
Sasha Gryaznov
committed
ctx.charge_gas(RuntimeCosts::CallerIsOrigin)?;
Ok(ctx.ext.caller_is_origin() as u32)
Sasha Gryaznov
committed
/// 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.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
fn address(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::Address)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.address().encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// Stores the price for the specified amount of gas into the supplied buffer.
///
Sasha Gryaznov
committed
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
/// 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,
already_charged,
)?)
}
/// Stores the price for the specified amount of weight into the supplied buffer.
///
/// # Parameters
///
/// - `out_ptr`: pointer to the linear memory where the returning value is written to. If the
/// available space at `out_ptr` is less than the size of the value a trap is triggered.
/// - `out_len_ptr`: in-out pointer into linear memory where the buffer length is read from and
/// the value length is written to.
Sasha Gryaznov
committed
/// The data is encoded as `T::Balance`.
///
/// # Note
///
Sasha Gryaznov
committed
/// It is recommended to avoid specifying very small values for `ref_time_limit` and
/// `proof_size_limit` as the prices for a single gas can be smaller than the basic balance
/// unit.
#[version(1)]
#[unstable]
Sasha Gryaznov
committed
fn weight_to_fee(
Alexander Theißen
committed
ctx: _,
memory: _,
Sasha Gryaznov
committed
ref_time_limit: u64,
proof_size_limit: u64,
out_ptr: u32,
out_len_ptr: u32,
) -> Result<(), TrapReason> {
Sasha Gryaznov
committed
let weight = Weight::from_parts(ref_time_limit, proof_size_limit);
ctx.charge_gas(RuntimeCosts::WeightToFee)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
Sasha Gryaznov
committed
&ctx.ext.get_weight_price(weight).encode(),
false,
already_charged,
)?)
}
/// Stores the weight left into the supplied buffer.
///
/// Equivalent to the newer [`seal1`][`super::api_doc::Version2::gas_left`] version but
/// works with *ref_time* Weight only. It is recommended to switch to the latest version, once
/// it's stabilized.
#[prefixed_alias]
fn gas_left(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::GasLeft)?;
let gas_left = &ctx.ext.gas_meter().gas_left().ref_time().encode();
Ok(ctx.write_sandbox_output(
memory,
out_ptr,
out_len_ptr,
gas_left,
false,
already_charged,
Alexander Theißen
committed
)?)
Sasha Gryaznov
committed
/// Stores the amount of weight left 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.
///
Sasha Gryaznov
committed
/// The data is encoded as Weight.
#[version(1)]
#[unstable]
Alexander Theißen
committed
fn gas_left(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {