3

I am writing a chain-extension that is a 1 to 1 map of a pallet. Based on this:

[...] charging the appropriate amount of weight. In order to do so benchmarks must be written and the charge_weight function must be called before carrying out any action that causes the consumption of the chargeable weight.

I wonder if you should charge weight before any call to the pallet:

let base_weight = <T as pallet_dapps_staking::Config>::WeightInfo::bond_and_stake();
env.charge_weight(base_weight)?;
                
let call_result = pallet_dapps_staking::Pallet::<T>::bond_and_stake(
    RawOrigin::Signed(caller).into(),
    contract,
    value,
);

Or if the weight will be charged in the pallet call anyway (and the above code might charge the weight two times).

Also as chain-extension exposes a call function that can dispatch different pallet calls, how to ensure proper weight is handled to not excess max block weight ? basically the equivalent of #[pallet::weight(T::WeightInfo::extrinsic())] for pallets.

Code here

1 Answer 1

1

I wonder if you should charge weight before any call to the pallet:

You need to charge manually as demonstrated in your example. It is only automatically charged when the Call is included in an extrinsic and send to the chain.

Also as chain-extension exposes a call function that can dispatch different pallet calls, how to ensure proper weight is handled to not excess max block weight ? basically the equivalent of #[pallet::weight(T::WeightInfo::extrinsic())] for pallets.

You can have a look at the (unstable) call_runtime API in pallet-contracts which does exactly this:

fn call_runtime(
    ctx: _,
    memory: _,
    call_ptr: u32,
    call_len: u32,
) -> Result<ReturnCode, TrapReason> {
    use frame_support::dispatch::{extract_actual_weight, GetDispatchInfo};
    ctx.charge_gas(RuntimeCosts::CopyFromContract(call_len))?;
    let call: <E::T as Config>::RuntimeCall =
        ctx.read_sandbox_memory_as_unbounded(memory, call_ptr, call_len)?;
    let dispatch_info = call.get_dispatch_info();
    let charged = ctx.charge_gas(RuntimeCosts::CallRuntime(dispatch_info.weight))?;
    let result = ctx.ext.call_runtime(call);
    let actual_weight = extract_actual_weight(&result, &dispatch_info);
    ctx.adjust_gas(charged, RuntimeCosts::CallRuntime(actual_weight));
    match result {
        Ok(_) => Ok(ReturnCode::Success),
        Err(_) => Ok(ReturnCode::CallRuntimeReturnedError),
    }
}

Your Answer

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

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