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 value42
2. abool
with valuetrue
3. an array of 32u8
with value0x10
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 value42
2. abool
with valuetrue
3. an array of 32u8
with value0x10
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 LangError
s
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!(),
}