Runtime interface contracts - Goodbye chain-extensions Welcome call-runtime

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

  1. pallet asset - transfer & transfer_approved ETA 07/23
  2. pallet xcm - prepare & send ETA 07/23
  3. Go live! ETA Q3Q4
    • pallet asset interface & pallet xcm interface live on Shiden
    • pallet asset interface & pallet xcm interface live on Astar
  4. pallet xvm interface Q4
  5. and beyond: implementations of other based on use-cases
8 Likes

Thanks for the really informative post. There is any repository with (even draft) of pallet xvm interface?

1 Like

Hey Tomasz.
There is no XVM interface yet. As said in the post above it will come later.
4. pallet xvm interface Q4
This is because XVM pallet is still in active development. When ready xvm interface will be added to Astar ink! SDK

2 Likes

After an internal review, we need to adjust the current timeline. The priority for this ink! SDK has been changed. The current impact on our builder’s community is very low because of low activity in our native environment (ink! smart contracts).

Because the demand to have a better EVM XCM SDK is higher, we will switch the priority. Having this change will not mean that we will not work on it, but the timeline for having it delivered will be delayed.

Feel free to tag me or Pierre in case of any questions.

2 Likes