3

I'm encountering an issue where a contract is only able to called functions in my chain extension if they are enumerated with function ids 0 and 1.

My chain extension has four functions, lets say func1, func2, func3, and func4, with function ids enumerated as 1, 2, 3, 4 (1 -> func1, ..., 4 -> func4). Accordingly, in my contract I registered the chain extension with the appropriate function ids. With this configuration (see code below), I was only able to execute the function associated with function id 1, with function ids 2, 3, and 4 resulting in the contract being trapped when invoked from the contract. I have verified that the functions work and are callable by modifying the contract and extension and testing with func1 as func id = 1, func2 as func id = 1, and so on (i.e. when mapping 1 => funcN it works without getting trapped, but x > 1 => funcN does is always trapped).

The chain extension:

impl ChainExtension<Runtime> for IrisExtension {
fn call<E: Ext>(
    func_id: u32,
    env: Environment<E, InitState>,
) -> Result<RetVal, DispatchError>
where
    <E::T as SysConfig>::AccountId:
        UncheckedFrom<<E::T as SysConfig>::Hash> + AsRef<[u8]>,
{
    match func_id { 
        1 => {
            // read args and call extrinsic 1
            Ok(RetVal::Converging(func_id))
        },
        2 => {
            // read args and call extrinsic 2
            Ok(RetVal::Converging(func_id))
        },
        3 => {
            ...
        },
        4 => {
            ...
        },
        _ => {
            error!("Called an unregistered `func_id`: {:}", func_id);
            return Err(DispatchError::Other("Unimplemented func_id"))
        }
    }
}

and in the contract:

#[ink(extension = 1, returns_result = false)]
fn func1(caller: ink_env::AccountId, target: ink_env::AccountId, asset_id: u32, amount: u64) -> [u8; 32];

#[ink(extension = 2, returns_result = false)]
fn func2(caller: ink_env::AccountId, target: ink_env::AccountId, asset_id: u32, amount: u64) -> [u8; 32];

#[ink(extension = 3, returns_result = false)]
fn func3(amount: u64) -> [u8; 32];

#[ink(extension = 4, returns_result = false)]
fn func4(target: ink_env::AccountId) -> [u8; 32];

}

Further, I updated the enumeration to start from 0, so 0, 1, 2, 3, and now I'm able to execute functions with func id 0 or 1, but 2 and 3 result in contract trapped (but if I update the configuration so those functions that results in contract trapped are enumerated with 0 and 1, they work, but the previously functioning functions which are now enumerated with 2 and 3 become trapped, i.e. (0 => funcN, 1 => funcM both work, but 2 => funcN results in COntractTrapped). I tried enumerating as 0, 1, 10, 100 as well, with the same behavior. Only func id 0 and 1 allow me to call the chain extension, all others result in ContractTrapped.

My contract: https://github.com/driemworks/contracts/blob/dev/iris_asset_exchange/lib.rs

My chain extension: https://github.com/driemworks/substrate/blob/4d001219e3c8ac41c15bd646d25e3b9caccc8e3b/bin/node-template/runtime/src/lib.rs#L847

1 Answer 1

4

I figured it out. I had not added the additional function ids to the FromStatusCode implementation. After updating it to the below, it works as intended.

impl ink_env::chain_extension::FromStatusCode for IrisErr {
fn from_status_code(status_code: u32) -> Result<(), Self> {
    match status_code {
        0 => Err(Self::FailTransferAsset),
        1 => Err(Self::FailMintAssets),
        2 => Err(Self::FailLockCurrency),
        3 => Err(Self::FailUnlockCurrency),
        _ => panic!("encountered unknown status code"),
    }
}

}

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.