Skip to main content

Whitebox Functions Reference

Introduction​

This page contains a list of all the currently available functions for the Rust Testing Framework, specifically the ones that the BlockchainStateWrapper type provides.

Note: You will notice that most functions use the num_bigint::BigUint type for numbers. This is NOT the same as the BigUint type you use inside smart contracts. It comes from a Rust library, and they are different types. It is recommended to always use the Rust version outside of lambda functions, and only use the managed type when interacting with the sc directly.

State-checking functions​

These functions check the blockchain state. They will panic and the test will fail if the check is unsuccessful.

check_egld_balance​

check_egld_balance(&self, address: &Address, expected_balance: &num_bigint::BigUint)

Checks the EGLD balance for the given address.

check_esdt_balance​

check_esdt_balance(&self, address: &Address, token_id: &[u8], expected_balance: &num_bigint::BigUint)

Checks the fungible ESDT balance for the given address.

check_nft_balance​

check_nft_balance<T>(&self, address: &Address, token_id: &[u8], nonce: u64, expected_balance: &num_bigint::BigUint, opt_expected_attributes: Option<&T>)

Where T has to implement TopEncode, TopDecode, PartialEq, and core::fmt::Debug. This is usually done through #[derive(TopEncode, TopDecode, PartialEq, Debug)].

This function checks the NFT balance for a specific nonce for an address, and optionally checks the NFT attributes as well. If you are only interested in the balance, pass Option::None for opt_expected_attributes. The Rust compiler might complain that it can't deduce the generic T, in which case, you can do one of the following:

b_mock.check_nft_balance::<Empty>(..., None);

b_mock.check_nft_balance(..., Option::<Empty>::None);

Where ... are the rest of the arguments.

State-getter functions​

These functions get the current state. They are generally used after a transaction to check that the tokens reached their intended destination. Most functions will panic if they're given an invalid address as argument.

get_egld_balance​

get_egld_balance(&self, address: &Address) -> num_bigint::BigUint

Gets the EGLD balance for the given account.

get_esdt_balance​

get_esdt_balance(&self, address: &Address, token_id: &[u8], token_nonce: u64) -> num_bigint::BigUint

Gets the ESDT balance for the given account. If you're interested in fungible token balance, set token_nonce to 0.

get_nft_attributes​

get_nft_attributes<T: TopDecode>(&self, address: &Address, token_id: &[u8], token_nonce: u64) -> Option<T>

Gets the NFT attributes for a token owned by the given address. Will return Option::None if there are no attributes.

dump_state​

dump_state(&self)

Prints the current state to console. Useful for debugging.

dump_state_for_account_hex_attributes​

dump_state_for_account_hex_attributes(&self, address: &Address)

Similar to the function before, but dumps state only for the given account.

dump_state_for_account​

dump_state_for_account<AttributesType: TopDecode + core::fmt::Debug>(&self, address: &Address)

Similar to the function before, but prints the attributes in a user-friendly format, given by the generic type given. This is useful for debugging NFT attributes.

State-altering functions​

These functions alter the state in some way.

create_user_account​

create_user_account(&mut self, egld_balance: &num_bigint::BigUint) -> Address

Creates a new user account, with the given EGLD balance. The Address is pseudo-randomly generated by the framework.

create_user_account_fixed_address​

create_user_account_fixed_address(&mut self, address: &Address, egld_balance: &num_bigint::BigUint)

Same as the function above, but it lets you create an account with a fixed address, for the few cases when it's needed.

create_sc_account​

create_sc_account<CB, ContractObjBuilder>(&mut self, egld_balance: &num_bigint::BigUint, owner: Option<&Address>, obj_builder: ContractObjBuilder, contract_wasm_path: &str) -> ContractObjWrapper<CB, ContractObjBuilder>

Where:

    CB: ContractBase<Api = DebugApi> + CallableContract + 'static,
ContractObjBuilder: 'static + Copy + Fn() -> CB,

Creates a smart contract account. For obj_builder, you will have to pass sc_namespace::contract_obj. This function will return a ContractObjWrapper, which contains the address of the newly created SC, and the function that is used to create instances of your contract.

The ContractObjWrapper will be used whenever you interact with the SC, which will be through the execution functions. If you only need the address (for setting balance, for example), you can use the address_ref method to get a reference to the stored address.

contract_wasm_path is the path towards the wasm file. This path is relative to the tests folder that the current test file resides in. The most usual path will be output/wasm_file_name.wasm.

create_sc_account_fixed_address​

create_sc_account_fixed_address<CB, ContractObjBuilder>(&mut self, address: &Address, egld_balance: &num_bigint::BigUint, owner: Option<&Address>, obj_builder: ContractObjBuilder, contract_wasm_path: &str) -> ContractObjWrapper<CB, ContractObjBuilder>

Same as the function above, but the address can be set by the caller instead of being randomly generated.

set_egld_balance​

set_egld_balance(&mut self, address: &Address, balance: &num_bigint::BigUint)

Sets the EGLD balance for the given account.

set_esdt_balance​

set_esdt_balance(&mut self, address: &Address, token_id: &[u8], balance: &num_bigint::BigUint)

Sets the fungible token balance for the given account.

set_nft_balance​

set_nft_balance<T: TopEncode>(&mut self, address: &Address, token_id: &[u8], nonce: u64, balance: &num_bigint::BigUint, attributes: &T)

Sets the non-fungible token balance for the given account, and the attributes. Attributes can be any serializable type. If you don't need attributes, you can pass "empty" in various ways: &(), &Vec::<u8>::new(), BoxedBytes::empty(), etc.

set_esdt_local_roles​

set_esdt_local_roles(&mut self, address: &Address, token_id: &[u8], roles: &[EsdtLocalRole])

Sets the ESDT token roles for the given address and token. Usually used during setup steps.

set_block_epoch​

set_block_epoch(&mut self, block_epoch: u64)

set_block_nonce​

et_block_nonce(&mut self, block_nonce: u64)

set_block_round​

set_block_round(&mut self, block_round: u64)

set_block_timestamp​

set_block_timestamp(&mut self, block_timestamp: u64)

set_block_random_seed​

set_block_random_seed(&mut self, block_random_seed: Box<[u8; 48]>)

Set various values for the current block info.

set_prev_block_epoch​

set_prev_block_epoch(&mut self, block_epoch: u64)

set_prev_block_nonce​

set_prev_block_nonce(&mut self, block_nonce: u64)

set_prev_block_round​

set_prev_block_round(&mut self, block_round: u64)

set_prev_block_timestamp​

set_prev_block_timestamp(&mut self, block_timestamp: u64)

set_prev_block_random_seed​

set_prev_block_random_seed(&mut self, block_random_seed: Box<[u8; 48]>)

Same as the ones above, but sets the block info for the previous block.

Smart Contract execution functions​

These functions help interacting with smart contracts. While they would still fit into the state-altering category, we feel they deserve their own section.

Note: We will shorten the signatures by not specifying the complete types for the ContractObjWrapper. For reference, the contract wrapper is of type ContractObjWrapper<CB, ContractObjBuilder>, where

    CB: ContractBase<Api = DebugApi> + CallableContract + 'static,
ContractObjBuilder: 'static + Copy + Fn() -> CB,

execute_tx​

execute_tx(&mut self, caller: &Address, sc_wrapper: &ContractObjWrapper<...>, egld_payment: &num_bigint::BigUint, tx_fn: TxFn) -> TxResult

Executes a transaction towards the given SC (defined by the wrapper), with optional EGLD payment (pass 0 if you want no payment). tx_fn is a lambda function that accepts a contract object as an argument. For more details about how to write such a lambda, you can take a look at the Crowdfunding test examples.

execute_esdt_transfer​

execute_esdt_transfer(&mut self, caller: &Address, sc_wrapper: &ContractObjWrapper<...>, token_id: &[u8], esdt_nonce: u64, esdt_amount: &num_bigint::BigUint, tx_fn: TxFn) -> TxResult

Same as the function above, but executes an ESDT/NFT transfer instead of EGLD transfer.

execute_esdt_multi_transfer​

execute_esdt_multi_transfer(&mut self, caller: &Address, sc_wrapper: &ContractObjWrapper<...>, esdt_transfers: &[TxInputESDT], tx_fn: TxFn) -> TxResult

Same as the function above, but executes a MultiESDTNFT transfer instead.

execute_query​

execute_query(&mut self, sc_wrapper: &ContractObjWrapper<...>, query_fn: TxFn) -> TxResult

Executes a SCQuery on the SC. None of the changes are committed into the state, but it still needs to be a mutable function to perform the temporary changes. Just like on the real blockchain, there is no caller and no token transfer for queries.

execute_in_managed_environment​

execute_in_managed_environment(&self, f: Func) -> T

Executes an arbitrary function and returns its result. The result can be any type. This function is rarely used. It can be useful when you want to perform some checks that involve managed types and such. (since you cannot create managed types outside of the lambda functions).

Undocumented functions​

There are some scenario generation functions that have not been included, but we recommend not bothering with scenario generation. The process is very time-consuming and the results are some unreadable scenario files. If you need to write scenarios, we recommend writing them yourself. If you still want to dabble into the scenario generation, there are some examples in the Crowdfunding test examples.