As ink chain-extension example https://github.com/paritytech/ink/blob/master/examples/rand-extension/runtime/chain-extension-example.rs#L32 . It show how to receive one param.

But if I want receive multiple param. How to handler it ?

such as

pub trait FetchRandom {
    type ErrorCode = RandomReadErr;

    /// Note: this gives the operation a corresponding `func_id` (1101 in this case),
    /// and the chain-side chain extension will get the `func_id` to do further operations.
    #[ink(extension = 1101, returns_result = false)]
    fn fetch_random(subject: [u8; 32], another: Vec<u8> ) -> [u8; 32];

Can I receive another param as above?

2 Answers 2


Pierre is right, your arguments need to be encodeable/decodeable (T: Encode + Decode). By doing this you'll be able to use the read_as method in your chain extension implementation which will try and correctly decode the bytes in the memory buffer into the specified Rust types.

You can then do something like this

let (type_a, type_b): (TypeA, TypeB) = env.read_as()?;

I don't believe having the same field names matters, but having the exact same types definitely does.

Also, as another resource take a look at the Runtime-Contract-Interactions repository.

  • 1
    I don't believe having the same field names matters -> exactly, only types are needed for contextual information (edited my message)
    – P.Ossun
    Jun 14, 2022 at 7:35

All your args will be passed as a SCALE encoded message param. That's why on the runtime you should decode it using a struct that derive Scale Encode + Decode + MaxEncodedLen and have the exact same types.

In your contract:

    // PSP22 transfer
#[ink(extension = 0xdb20f9f5)]
fn transfer(
    asset_id: u32,
    to: <ink_env::DefaultEnvironment as Environment>::AccountId,
    value: <ink_env::DefaultEnvironment as Environment>::Balance,
) -> Result<(), Psp22Error>;

In the runtime:

#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]
pub struct Psp22TransferInput<AssetId, AccountId, Balance> {
    pub asset_id: AssetId,
    pub to: AccountId,
    pub value: Balance,

let input: Psp22TransferInput<T::AssetId, T::AccountId, T::Balance> =

You can check Parity ink! example of PSP22 implementation (more basic as it will serve as an example)

And OpenBrush example PSP22 implementation (more advanced as it targets to be production-ready)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.