Function build_call

Source
pub fn build_call<E>() -> CallBuilder<E, Unset<Call>, Unset<ExecutionInput<EmptyArgumentList<DefaultAbi>, DefaultAbi>>, Unset<ReturnType<()>>>
where E: Environment,
Expand description

Returns a new CallBuilder to build up the parameters to a cross-contract call that uses the “default” ABI for calls for the ink! project.

§Note

The “default” ABI for calls is “ink”, unless the ABI is set to “sol” in the ink! project’s manifest file (i.e. Cargo.toml).

§Example

Note: The shown examples panic because there is currently no cross-calling support in the off-chain testing environment. However, this code should work fine in on-chain environments.

§Example 1: No Return Value

The below example shows calling of a message of another contract that does not return any value back to its caller. The called function:

  • has a selector equal to 0xDEADBEEF
  • is provided with 5000 units of gas for its execution
  • is provided with 10 units of transferred value for the contract instance
  • receives the following arguments in order 1. an i32 with value 42 2. a bool with value true 3. an array of 32 u8 with value 0x10

type AccountId = <DefaultEnvironment as Environment>::AccountId;
build_call::<DefaultEnvironment>()
    .call(Address::from([0x42; 20]))
    .ref_time_limit(5000)
    .transferred_value(ink::U256::from(10))
    .exec_input(
        ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF]))
            .push_arg(42u8)
            .push_arg(true)
            .push_arg(&[0x10u8; 32]),
    )
    .returns::<()>()
    .invoke();

§Example 2: With Return Value

The below example shows calling of a message of another contract that does return a i32 value back to its caller. The called function:

  • has a selector equal to 0xDEADBEEF
  • is provided with 5000 units of gas for its execution
  • is provided with 10 units of transferred value for the contract instance
  • receives the following arguments in order 1. an i32 with value 42 2. a bool with value true 3. an array of 32 u8 with value 0x10
let my_return_value: i32 = build_call::<DefaultEnvironment>()
    .call_type(Call::new(ink::Address::from([0x42; 20])))
    .ref_time_limit(5000)
    .transferred_value(ink::U256::from(10))
    .exec_input(
        ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF]))
            .push_arg(42u8)
            .push_arg(true)
            .push_arg(&[0x10u8; 32]),
    )
    .returns::<i32>()
    .invoke();

§Example 3: Delegate call

Note: The shown example panics because there is currently no delegate calling support in the off-chain testing environment. However, this code should work fine in on-chain environments.

use ink::Address;
let my_return_value: i32 = build_call::<DefaultEnvironment>()
    .delegate(Address::zero())
    .exec_input(
        ExecutionInput::new(Selector::new([0xDE, 0xAD, 0xBE, 0xEF]))
            .push_arg(42u8)
            .push_arg(true)
            .push_arg(&[0x10u8; 32])
    )
    .returns::<i32>()
    .invoke();

§Handling LangErrors

It is also important to note that there are certain types of errors which can happen during cross-contract calls which can be handled know as [LangError][ink_primitives::LangError].

If you want to handle these errors use the CallBuilder::try_invoke methods instead of the CallBuilder::invoke ones.

Note: The shown examples panic because there is currently no cross-calling support in the off-chain testing environment. However, this code should work fine in on-chain environments.

§Example: Handling a LangError


type AccountId = <DefaultEnvironment as Environment>::AccountId;
let call_result = build_call::<DefaultEnvironment>()
    .call(Address::from([0x42; 20]))
    .ref_time_limit(5000)
    .transferred_value(ink::U256::from(10))
    .try_invoke()
    .expect("Got an error from the Contract's pallet.");

match call_result {
    Ok(_) => unimplemented!(),
    Err(e @ ink_primitives::LangError::CouldNotReadInput) => unimplemented!(),
    Err(_) => unimplemented!(),
}