Calling pallet dispatchables from ink! contracts
There is two available way to call pallet dispatchables from smart-contracts:
- Chain Extension
- Call runtime
Chain Extension is a way to extend contracts_pallet
API by exposing parts of your runtime logic to smart contracts. Added functions should handle security (needs to add unit-tests and be audited) and be benchmarked (to determine the correct amount of weight). In a case of a wrapper around an existing pallet (so that contract can call all functions of this pallet) every pallet dispatchable should be implemented as a chain extension function and unit-tested (see example here).
For example, if a smart contract wants to access pallet-assets, dApp Staking, pallet_xcm or any other pallet, we needed to implement their chain extension counterpart like pallet-assets-ce that will expose pallet methods for smart contracts to use.
Call runtime is a different approach: it’s a function already present in contracts_pallet
API that dispatches a Call passed as an argument. This way contracts can call pallets without having to go through chain extensions. There is no security issue and does not need to be audited (as it calls pallet directly) - weight is also handled (as it uses weight from the pallet). No need to add tests either.
To activate/deactivate dispatchables accessible from a contract it should be added to CallFilter (a white list) by default no call is allowed (check here).
Usage in contracts
let’s take the example of calling a assets_pallet dispatchable from an ink! contract
chain extension
Import the assets_extension
from chain-extension-contracts and use the associated function
AssetsExtension::transfer(Origin::Address, asset_id, target, amount)?;
call runtime
The RuntimeCall should be passed as argument of call_runtime
. Import the types from astar-ink-sdk and add arguments:
self.env()
.call_runtime(&RuntimeCall::Assets(AssetsCall::Transfer {
id,
target: to.into(),
amount
}))
.map_err(|_| RuntimeError::CallRuntimeFailed)
We can see that both approach are straight forward. what is just needed is to import a type and use it. This simplicity will also not bloat the contract size.
The problem with Chain extension
- Every dispatchables (and query) should be implemented (check assets example here) this a quite a work to maintain.
- It should be benchamarked. Most of the weight used will be the same as the underlying dispatchables including the small overhead of calling chain-extension. But weight should be precise and benchmarking of chain extension is really complex
- Every functions should be unit-tested
- It need to be audited
This is not needed with call runtime
- No need for audit, since no new code is added to runtime
- No need to worry about weights and testing. As it is done at pallet-level
- Less code (practically zero) to be added to runtime which is better
- Adding a new piece of code to runtime logic will be be done via pallets, which can be benchmarked and easily tested. This is what we will do to implement XCM contract interface.
But call runtime can not return value - query is not possible YET
This is described in this issue in substrate
A
Dispatchable
can’t return any data on success but rather uses a side channel for that (events). It might be nice to capture those events and copy them back to the contract.Additional ways of improvement would be to add view functions to FRAME which can be used by contracts and add a suite of macros that allow for chain extensions to be derived while generating metadata for ink!.
FRAME pallets should be updated to return values. When this change will be implemented in FRAME pallet, it will be a new host function (probably query_runtime
).
Timeline
Astar ink! SDK
This SDK will contain everything needed to help for the usage of Runtime interface contracts. On top of that we will add usage pattern to push innovation & adoption of this Astar ink! SDK.
Chain Extension
The chain extensions already deployed to Shibuya will remain for now but will never be deployed on mainnets. the chain-extension-contracts repository will not be maintained.
Runtime Interface
pallet asset
-transfer
&transfer_approved
ETA 07/23pallet xcm
-prepare
&send
ETA 07/23- Go live! ETA Q3Q4
pallet asset interface
&pallet xcm interface
live on Shidenpallet asset interface
&pallet xcm interface
live on Astar
pallet xvm interface
Q4- and beyond: implementations of other based on use-cases