Newer
Older
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.
#[define_env]
pub mod env {
/// Account for used gas. Traps if gas used is greater than gas limit.
///
/// NOTE: This is a implementation defined call and is NOT a part of the public API.
/// This call is supposed to be called only by instrumentation injected code.
///
/// - amount: How much gas is used.
Alexander Theißen
committed
fn gas(ctx: _, _memory: _, amount: u64) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::MeteringBlock(amount))?;
Ok(())
/// Set the value at the given key in the contract storage.
///
/// Equivalent to the newer version of `seal_set_storage` 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> {
Alexander Theißen
committed
ctx.set_storage(memory, KeyType::Variable(key_len), key_ptr, value_ptr, value_len)
/// Clear the value at the given key in the contract storage.
///
/// Equivalent to the newer version of `seal_clear_storage` 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::Variable(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
///
/// `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> {
Alexander Theißen
committed
ctx.get_storage(memory, KeyType::Variable(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::Variable(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
///
/// `ReturnCode::KeyNotFound`
#[unstable]
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()))?;
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_transparent(
&VarSizedKey::<E::T>::try_from(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
///
/// - 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
///
/// `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.
///
/// # Deprecation
///
/// 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 `[`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,
CallType::Call { callee_ptr, value_ptr, gas },
input_data_ptr,
input_data_len,
output_ptr,
output_len_ptr,
)
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
/// 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 [`CallFlags`] for a documenation of the supported flags.
/// - callee_ptr: a pointer to the address of the callee contract. Should be decodable as an
/// `T::AccountId`. Traps otherwise.
/// - gas: how much gas to devote to the execution.
/// - 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`
#[version(1)]
Sasha Gryaznov
committed
#[prefixed_alias]
fn call(
Alexander Theißen
committed
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(
Alexander Theißen
committed
memory,
CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?,
CallType::Call { callee_ptr, value_ptr, gas },
Yarik Bratashchuk
committed
input_data_ptr,
input_data_len,
output_ptr,
output_len_ptr,
)
Yarik Bratashchuk
committed
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
/// 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 [`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`
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.
///
/// # Deprecation
///
/// 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 `[`MaxEncodedLen`]. The fields exist 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,
code_hash_ptr,
gas,
value_ptr,
input_data_ptr,
input_data_len,
address_ptr,
address_len_ptr,
output_ptr,
output_len_ptr,
salt_ptr,
salt_len,
)
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
/// 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`.
///
/// `value` must be at least the minimum balance. Otherwise the instantiation fails and the
/// contract is not created.
///
/// # Parameters
///
/// - code_hash_ptr: a pointer to the buffer that contains the initializer code.
/// - gas: how much gas to devote to the execution of the initializer code.
/// - 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.
/// - address_len_ptr: in-out pointer to where the length of the buffer is read from and the
/// actual length is written to.
/// - 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.
/// - 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`
#[version(1)]
Sasha Gryaznov
committed
#[prefixed_alias]
fn instantiate(
Alexander Theißen
committed
ctx: _,
memory: _,
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> {
Alexander Theißen
committed
memory,
code_hash_ptr,
gas,
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.
///
/// # Deprecation
///
/// 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.
///
/// - 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
///
/// This function traps if the input was previously forwarded by a `seal_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:
/// ```
/// 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.
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)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.caller().encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// 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).
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
///
/// `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.
///
/// Prefer this over `seal_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).
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
/// 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.
///
/// 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.
///
/// The data is encoded as T::Balance.
///
/// # Note
///
/// It is recommended to avoid specifying very small values for `gas` as the prices for a single
/// gas can be smaller than one.
Sasha Gryaznov
committed
#[prefixed_alias]
fn weight_to_fee(
Alexander Theißen
committed
ctx: _,
memory: _,
gas: u64,
out_ptr: u32,
out_len_ptr: u32,
) -> Result<(), TrapReason> {
let gas = Weight::from_ref_time(gas);
ctx.charge_gas(RuntimeCosts::WeightToFee)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.get_weight_price(gas).encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// Stores the amount of gas 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.
///
/// The data is encoded as Gas.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
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();
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
memory,
out_ptr,
out_len_ptr,
gas_left,
false,
already_charged,
)?)
}
/// Stores the **free* balance of the current account 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.
///
/// The data is encoded as T::Balance.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
fn balance(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::Balance)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.balance().encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// Stores the value transferred along with this call/instantiate 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.
///
/// The data is encoded as T::Balance.
Sasha Gryaznov
committed
#[prefixed_alias]
fn value_transferred(
Alexander Theißen
committed
ctx: _,
memory: _,
out_ptr: u32,
out_len_ptr: u32,
) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::ValueTransferred)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.value_transferred().encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// Stores a random number for the current block and the given subject 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.
///
/// The data is encoded as T::Hash.
///
/// # Deprecation
///
/// This function is deprecated. Users should migrate to the version in the "seal1" module.
Sasha Gryaznov
committed
#[prefixed_alias]
fn random(
Alexander Theißen
committed
ctx: _,
memory: _,
subject_ptr: u32,
subject_len: u32,
out_ptr: u32,
out_len_ptr: u32,
) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::Random)?;
if subject_len > ctx.ext.schedule().limits.subject_len {
return Err(Error::<E::T>::RandomSubjectTooLong.into())
Alexander Theißen
committed
let subject_buf = ctx.read_sandbox_memory(memory, subject_ptr, subject_len)?;
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.random(&subject_buf).0.encode(),
false,
already_charged,
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
/// Stores a random number for the current block and the given subject 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.
///
/// The data is encoded as (T::Hash, T::BlockNumber).
///
/// # Changes from v0
///
/// In addition to the seed it returns the block number since which it was determinable
/// by chain observers.
///
/// # Note
///
/// The returned seed should only be used to distinguish commitments made before
/// the returned block number. If the block number is too early (i.e. commitments were
/// made afterwards), then ensure no further commitments may be made and repeatedly
/// call this on later blocks until the block number returned is later than the latest
/// commitment.
#[version(1)]
Sasha Gryaznov
committed
#[prefixed_alias]
fn random(
Alexander Theißen
committed
ctx: _,
memory: _,
subject_ptr: u32,
subject_len: u32,
out_ptr: u32,
out_len_ptr: u32,
) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::Random)?;
if subject_len > ctx.ext.schedule().limits.subject_len {
return Err(Error::<E::T>::RandomSubjectTooLong.into())
Alexander Theißen
committed
let subject_buf = ctx.read_sandbox_memory(memory, subject_ptr, subject_len)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.random(&subject_buf).encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// Load the latest block timestamp 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 now(ctx: _, memory: _, out_ptr: u32, out_len_ptr: u32) -> Result<(), TrapReason> {
ctx.charge_gas(RuntimeCosts::Now)?;
Alexander Theißen
committed
Ok(ctx.write_sandbox_output(
Alexander Theißen
committed
memory,
out_ptr,
out_len_ptr,
&ctx.ext.now().encode(),
false,
already_charged,
Alexander Theißen
committed
)?)
/// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer.
///
/// The data is encoded as T::Balance.
Sasha Gryaznov
committed
#[prefixed_alias]
Alexander Theißen
committed
fn minimum_balance(
ctx: _,
memory: _,
out_ptr: u32,