Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
eef15f1
upgrade to wasmi 0.29
agryaznov May 3, 2023
dee28ff
prepare cleanup
agryaznov May 3, 2023
efeb0bd
sync ref_time w engine from the stack frame
agryaznov May 3, 2023
4fdd5c8
proc_macro: sync gas in host funcs
agryaznov May 4, 2023
cac61c6
clean benchmarks & schedule: w_base = w_i64const
agryaznov May 5, 2023
be0df3c
scale gas values btw engine and gas meter
agryaznov May 5, 2023
8a32757
(re)instrumentation & code_cache removed
agryaznov May 5, 2023
f8abec4
remove gas() host fn, continue clean-up
agryaznov May 8, 2023
22440ae
address review comments
agryaznov Jun 9, 2023
c94821d
Merge branch 'master' into ag-wasmeter
agryaznov Jun 9, 2023
2010ff7
move from CodeStorage&PrefabWasmModule to PristineCode&WasmBlob
agryaznov Jun 9, 2023
100cdcd
refactor: no reftime_limit&schedule passes, no CodeStorage
agryaznov Jun 9, 2023
85a0340
bugs fixing
agryaznov Jun 10, 2023
505f750
fix tests: expected deposit amount
agryaznov Jun 10, 2023
c25f634
fix prepare::tests
agryaznov Jun 10, 2023
7f46e7e
update tests and fix bugs
agryaznov Jun 10, 2023
7bf4fbe
update docs
agryaznov Jun 11, 2023
cc05e88
bump wasmi 0.30.0
agryaznov Jun 12, 2023
0e2b0ab
benchmarks updated, tests pass
agryaznov Jun 12, 2023
e6e3563
refactoring
agryaznov Jun 12, 2023
f4ffcf2
s/OwnerInfo/CodeInfo/g;
agryaznov Jun 12, 2023
a50b7cf
migration: draft, compiles
agryaznov Jun 12, 2023
c6b9f74
migration: draft, runs
agryaznov Jun 13, 2023
132e9ce
migration: draft, runs (fixing)
agryaznov Jun 13, 2023
9935e92
deposits repaid non pro rata
agryaznov Jun 13, 2023
0b9125a
deposits repaid pro rata
agryaznov Jun 13, 2023
08a15b7
better try-runtime output
agryaznov Jun 13, 2023
5f6c1ac
even better try-runtime output
agryaznov Jun 13, 2023
b1290f0
benchmark migration
agryaznov Jun 14, 2023
9ffca5d
Merge branch 'master' into ag-wasmeter
agryaznov Jun 14, 2023
94f8476
fix merge leftover
agryaznov Jun 14, 2023
ba67751
add forgotten fixtures, fix docs
agryaznov Jun 14, 2023
0ee3293
address review comments
agryaznov Jun 14, 2023
a45c538
ci fixes
agryaznov Jun 14, 2023
f24a267
cleanup
agryaznov Jun 15, 2023
e6c21f3
benchmarks::prepare to return DispatchError
agryaznov Jun 15, 2023
444a97b
Merge branch 'master' into ag-wasmeter
agryaznov Jun 15, 2023
d3f59b2
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 15, 2023
f12927d
store memory limits to CodeInfo
agryaznov Jun 16, 2023
0a9b351
ci: roll back weights
agryaznov Jun 16, 2023
cff9da7
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 16, 2023
f0e24c5
".git/.scripts/commands/bench-vm/bench-vm.sh" pallet dev pallet_contr…
Jun 16, 2023
2e07393
drive-by: update Readme and pallet rustdoc
agryaznov Jun 16, 2023
f465ecf
Merge branch 'master' into ag-wasmeter
agryaznov Jun 17, 2023
94be691
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 17, 2023
721d4b6
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 17, 2023
e226c0e
use wasmi 0.29
agryaznov Jun 18, 2023
e57596f
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jun 18, 2023
d687f1c
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 18, 2023
76a8c20
use wasmi 0.30 again
agryaznov Jun 20, 2023
fbc43ae
query memory limits from wasmi
agryaznov Jun 20, 2023
cd54ff2
save: scan_exports ported, compiles
agryaznov Jun 20, 2023
b548064
save (wip, not compiles)
agryaznov Jun 20, 2023
0b4bb91
query memory limits from wasmi
agryaznov Jun 20, 2023
b15d5a9
better migration types
agryaznov Jun 20, 2023
8eb8710
ci: pull weights from master
agryaznov Jun 20, 2023
dae3f32
Merge branch 'master' into ag-wasmeter
agryaznov Jun 21, 2023
f42db5d
refactoring
agryaznov Jun 21, 2023
b789e6b
".git/.scripts/commands/bench-vm/bench-vm.sh" pallet dev pallet_contr…
Jun 21, 2023
3cadbb1
Merge branch 'ag-wasmeter' into ag-wasmi-validation
agryaznov Jun 21, 2023
eba148b
scan_imports ported
agryaznov Jun 21, 2023
ca5938d
scan_export ported, other checks removed
agryaznov Jun 22, 2023
c2c3d9b
tests fixed
agryaznov Jun 22, 2023
56dc2df
drop wasmparser and parity-wasm dependencies
agryaznov Jun 23, 2023
086e219
typo fix
agryaznov Jun 27, 2023
2544972
addressing review comments
agryaznov Jun 27, 2023
387bec9
refactor
agryaznov Jun 27, 2023
8be0537
address review comments
agryaznov Jun 29, 2023
ffdb8d1
optimize migration
agryaznov Jun 30, 2023
eaf7a31
Merge branch 'master' into ag-wasmeter
agryaznov Jun 30, 2023
f4dad0f
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jun 30, 2023
b5ad1de
another review round comments addressed
agryaznov Jun 30, 2023
0e0155f
ci fix one
agryaznov Jun 30, 2023
d139757
clippy fix
agryaznov Jun 30, 2023
670ff1a
ci fix two
agryaznov Jun 30, 2023
18236e1
Merge branch 'ag-wasmeter' into ag-wasmi-validation
agryaznov Jul 3, 2023
0f83c77
allow stored modules to have no memory imports
agryaznov Jul 3, 2023
ca111cf
Merge branch 'master' into ag-wasmi-validation
agryaznov Jul 3, 2023
bf52770
rollback: allow stored modules to have no memory imports
agryaznov Jul 3, 2023
824ef6d
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jul 3, 2023
b55dbcb
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jul 3, 2023
39fb730
address review comments
agryaznov Jul 4, 2023
ac9d5c2
Merge branch 'ag-wasmi-validation'
agryaznov Jul 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update docs
  • Loading branch information
agryaznov committed Jun 11, 2023
commit 7bf4fbe067f134397b7fe0544aaf0ff97d79211f
1 change: 0 additions & 1 deletion frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,6 @@ where
self.initial_transfer()?;

// Call into the Wasm blob.
// We pass `reftime_left` into the execution engine to initialize its gas metering.
let output = executable
.execute(self, &entry_point, input_data)
.map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;
Expand Down
8 changes: 3 additions & 5 deletions frame/contracts/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,7 @@ impl<T: Config> GasMeter<T> {
/// Amount is calculated by the given `token`.
///
/// Returns `OutOfGas` if there is not enough gas or addition of the specified
/// amount of gas has lead to overflow. On success returns `Proceed`.
///
/// Any charged amount less than base instruction weight is rounded up to it.
/// amount of gas has lead to overflow.
///
/// NOTE that amount isn't consumed if there is not enough gas. This is considered
/// safe because we always charge gas before performing any resource-spending action.
Expand Down Expand Up @@ -187,15 +185,15 @@ impl<T: Config> GasMeter<T> {
self.gas_left = self.gas_left.saturating_add(adjustment).min(self.gas_limit);
}

/// This method is used for gas syncs with the engine in every host function.
/// This method is used for gas syncs with the engine at start of every host function call.
///
/// Updates internal `engine_comsumed` tracker of engine fuel consumption.
///
/// Charges self with the `ref_time` Weight corresponding to `wasmi_fuel` consumed on the engine
/// side. Passed value is scaled by multiplying it by the weight of a basic operation, as such
/// an operation in wasmi engine costs 1.
///
/// Returns the updated `gas_left` Weight value from the meter.
/// Returns the updated `gas_left` `Weight` value from the meter.
/// Normally this would never fail, as engine should fail first when out of gas.
pub fn sync_fuel(&mut self, wasmi_fuel: u64) -> Result<Weight, DispatchError> {
if !wasmi_fuel.is_zero() {
Expand Down
30 changes: 6 additions & 24 deletions frame/contracts/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,34 +138,14 @@ impl Limits {
}
}

/// Describes the weight for all categories of supported wasm instructions.
///
/// There there is one field for each wasm instruction that describes the weight to
/// execute one instruction of that name. There are a few exceptions:
///
/// 1. If there is a i64 and a i32 variant of an instruction we use the weight
/// of the former for both.
/// 2. The following instructions are free of charge because they merely structure the
/// wasm module and cannot be spammed without making the module invalid (and rejected):
/// End, Unreachable, Return, Else
/// 3. The following instructions cannot be benchmarked because they are removed by any
/// real world execution engine as a preprocessing step and therefore don't yield a
/// meaningful benchmark result. However, in contrast to the instructions mentioned
/// in 2. they can be spammed. We price them with the same weight as the "default"
/// instruction (i64.const): Block, Loop, Nop
/// 4. We price both i64.const and drop as InstructionWeights.i64const / 2. The reason
/// for that is that we cannot benchmark either of them on its own but we need their
/// individual values to derive (by subtraction) the weight of all other instructions
/// that use them as supporting instructions. Supporting means mainly pushing arguments
/// and dropping return values in order to maintain a valid module.
/// TODO update doc
/// Gas metering of Wasm executed instructions is being done on the engine side.
/// This struct holds a reference value used to gas units scaling between host and engine.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, TypeInfo)]
#[scale_info(skip_type_params(T))]
pub struct InstructionWeights<T: Config> {
/// Base instruction ref_time weight.
/// Used to gas units scaling between host and engine.
/// Should match to wasmi's 1 fuel (see <https://github.com/paritytech/wasmi/issues/701>).
/// Base instruction `ref_time` Weight.
/// Should match to wasmi's `1` fuel (see <https://github.com/paritytech/wasmi/issues/701>).
pub base: u32,
/// The type parameter is used in the default implementation.
#[codec(skip)]
Expand Down Expand Up @@ -424,6 +404,8 @@ impl Default for Limits {
}

impl<T: Config> Default for InstructionWeights<T> {
/// We price both `i64.const` and `drop` as `instr_i64const / 2`. The reason
/// for that is that we cannot benchmark either of them on its own.
fn default() -> Self {
Self { base: cost_instr!(instr_i64const, 1), _phantom: PhantomData }
}
Expand Down
65 changes: 33 additions & 32 deletions frame/contracts/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,40 +56,40 @@ use wasmi::{
Module, StackLimits, Store,
};

/// TODO: docs
/// Validated Wasm module ready for execution.
/// This data structure is immutable once created and stored.
#[derive(Encode, Decode, scale_info::TypeInfo)]
#[codec(mel_bound())]
#[scale_info(skip_type_params(T))]
pub struct WasmBlob<T: Config> {
code: CodeVec<T>,
// This isn't needed for contract execution and does not get loaded from storage by default.
// It is `Some` if and only if this struct was generated from code.
// This isn't needed for contract execution and is not stored alongside it.
#[codec(skip)]
pub owner_info: OwnerInfo<T>,
}

/// Contract metadata, such as:
/// - owner of the contract,
/// Contract code related data, such as:
/// - owner of the contract, i.e. account uploaded its code,
/// - storage deposit amount,
/// - reference count
/// - determinism marker
/// TODO: rename this struct
/// - reference count,
/// - determinism marker.
/// TODO: rename this struct to `CodeInfo`?
///
/// It is stored in a separate storage entry to avoid loading the code when not necessary.
#[derive(Clone, Encode, Decode, scale_info::TypeInfo, MaxEncodedLen)]
#[codec(mel_bound())]
#[scale_info(skip_type_params(T))]
pub struct OwnerInfo<T: Config> {
/// The account that has deployed the contract and hence is allowed to remove it.
/// The account that has uploaded the contract code and hence is allowed to remove it.
owner: AccountIdOf<T>,
/// The amount of balance that was deposited by the owner in order to deploy it.
/// The amount of balance that was deposited by the owner in order to store it on-chain.
#[codec(compact)]
deposit: BalanceOf<T>,
/// The number of contracts that use this as their code.
/// The number of instantiated contracts that use this as their code.
#[codec(compact)]
refcount: u64,
/// Marks if the code might contain non deterministic features and is therefore never allowed
/// to be run on chain. Specifically, such a code can never be instantiated into a contract
/// Marks if the code might contain non-deterministic features and is therefore never allowed
/// to be run on-chain. Specifically, such a code can never be instantiated into a contract
/// and can just be used through a delegate call.
determinism: Determinism,
}
Expand Down Expand Up @@ -139,7 +139,7 @@ impl<T: Config> Token<T> for CodeToken {
// In case of `Load` we already covered the general costs of
// calling the storage but still need to account for the actual size of the
// contract code. This is why we subtract `T::*::(0)`. We need to do this at this
// point because when charging the general weight for calling the contract we not know the
// point because when charging the general weight for calling the contract we don't know the
// size of the contract.
match *self {
Load(len) => T::WeightInfo::call_with_code_per_byte(len)
Expand Down Expand Up @@ -195,8 +195,8 @@ impl<T: Config> WasmBlob<T> {
/// Creates and returns an instance of the supplied code.
///
/// This is either used for later executing a contract or for validation of a contract.
/// When validating we pass `()` a `host_state`. Please note that such a dummy instance must
/// **never** be called/executed since it will panic the executor.
/// When validating we pass `()` as `host_state`. Please note that such a dummy instance must
/// **never** be called/executed, since it will panic the executor.
pub fn instantiate<E, H>(
code: &[u8],
host_state: H,
Expand Down Expand Up @@ -231,9 +231,8 @@ impl<T: Config> WasmBlob<T> {
},
allow_deprecated,
)?;

// Here we allocate this memory in the _store_. It allocates _inital_ val, but allows it to
// grow up to max number of mem pages, if neccesary.
// Here we allocate this memory in the _store_. It allocates _inital_ value, but allows it
// to grow up to maximum number of memory pages, if neccesary.
let memory =
Memory::new(&mut store, MemoryType::new(memory_limits.0, Some(memory_limits.1))?)
.expect(
Expand All @@ -252,8 +251,8 @@ impl<T: Config> WasmBlob<T> {

/// Put the module blob into storage.
///
/// Increments the refcount of the in-storage `prefab_module` if it already exists in storage
/// under the specified `code_hash`.
/// Increments the reference count of the in-storage `WasmBlob`, if it already exists in
/// storage.
fn store_code(mut module: Self, instantiated: bool) -> DispatchResult {
let code_hash = &module.code_hash();
<OwnerInfoOf<T>>::mutate(code_hash, |stored_owner_info| {
Expand All @@ -275,7 +274,7 @@ impl<T: Config> WasmBlob<T> {
Some(_) => Ok(()),
// Upload a new contract code.
//
// We need to store the code and its owner info, and collect the deposit.
// We need to store the code and its owner_info, and collect the deposit.
None => {
// This `None` case happens only in freshly uploaded modules. This means that
// the `owner` is always the origin of the current transaction.
Expand Down Expand Up @@ -326,12 +325,12 @@ impl<T: Config> WasmBlob<T> {
Ok(code)
}

/// Decrement the refcount of a code in-storage by one.
/// Decrement the reference count of a stored code by one.
///
/// # Note
///
/// A contract whose refcount dropped to zero isn't automatically removed. A `remove_code`
/// transaction must be submitted by the original uploader to do so.
/// A contract whose reference count dropped to zero isn't automatically removed. A
/// `remove_code` transaction must be submitted by the original uploader to do so.
fn decrement_refcount(code_hash: CodeHash<T>) {
<OwnerInfoOf<T>>::mutate(code_hash, |existing| {
if let Some(info) = existing {
Expand All @@ -340,11 +339,12 @@ impl<T: Config> WasmBlob<T> {
});
}

/// Increment the refcount of a code in-storage by one.
/// Increment the reference count of a of a stored code by one.
///
/// # Errors
///
/// [`Error::CodeNotFound`] is returned if the specified `code_hash` does not exist.
/// [`Error::CodeNotFound`] is returned if no stored code found having the specified
/// `code_hash`.
fn increment_refcount(code_hash: CodeHash<T>) -> Result<(), DispatchError> {
<OwnerInfoOf<T>>::mutate(code_hash, |existing| -> Result<(), DispatchError> {
if let Some(info) = existing {
Expand Down Expand Up @@ -400,10 +400,10 @@ impl<T: Config> Executable<T> for WasmBlob<T> {
) -> Result<Self, DispatchError> {
let code = Self::load_code(code_hash, gas_meter)?;
let code_hash = T::Hashing::hash(&code);
// We store owner_info at the same time as contract code,
// We store `owner_info` at the same time as contract code,
// therefore this query shouldn't really fail.
// We consider its failure equal to CodeNotFound, as contract code without
// owner_info is unusable in this pallet.
// We consider its failure equal to `CodeNotFound`, as contract code without
// `owner_info` is unusable in this pallet.
let owner_info = <OwnerInfoOf<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;

Ok(Self { code, owner_info })
Expand All @@ -424,8 +424,9 @@ impl<T: Config> Executable<T> for WasmBlob<T> {
input_data: Vec<u8>,
) -> ExecResult {
let code = self.code.as_slice();
// Extract memory limits from the module.
let contract_module = prepare::ContractModule::new(code)?;
// Extract memory limits from the module.
// This also checks that module's memory import satisfies the schedule.
let memory_limits =
prepare::get_memory_limits(contract_module.scan_imports::<T>(&[])?, ext.schedule())?;
// Instantiate the Wasm module to the engine.
Expand All @@ -447,7 +448,7 @@ impl<T: Config> Executable<T> for WasmBlob<T> {
store.data_mut().set_memory(memory);

// Set fuel limit for the wasmi execution.
// We normalize it by the base instruction weight, as its cost in wasmi engine is 1.
// We normalize it by the base instruction weight, as its cost in wasmi engine is `1`.
let fuel_limit = store
.data_mut()
.ext()
Expand Down
28 changes: 13 additions & 15 deletions frame/contracts/src/wasm/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,7 @@ pub fn get_memory_limits<T: Config>(

/// Check that given `code` satisfies constraints required for the contract Wasm module.
///
/// On success it returns back the code together with its `(initial, maximum)`
/// memory limits. The memory requirement was also validated against the `schedule`.
/// On success it returns back the code.
fn validate<E, T>(
code: &[u8],
schedule: &Schedule<T>,
Expand Down Expand Up @@ -367,7 +366,8 @@ where
contract_module.ensure_local_variable_limit(schedule.limits.locals)?;
contract_module.ensure_parameter_limit(schedule.limits.parameters)?;
contract_module.ensure_br_table_size_limit(schedule.limits.br_table_size)?;
// We do it here just to check that module imported memory satisfies the Schedule limits
// Extract memory limits from the module.
// This also checks that module's memory import satisfies the schedule.
let memory_limits = get_memory_limits(contract_module.scan_imports::<T>(&[])?, schedule)?;

let code = contract_module.into_wasm_code()?;
Expand All @@ -381,8 +381,8 @@ where

// This will make sure that the module can be actually run within wasmi:
//
// - Doesn't use any unknown imports.
// - Doesn't explode the wasmi bytecode generation.
// - It doesn't use any unknown imports.
// - It doesn't explode the wasmi bytecode generation.
if matches!(try_instantiate, TryInstantiate::Instantiate) {
// We don't actually ever run any code so we can get away with a minimal stack which
// reduces the amount of memory that needs to be zeroed.
Expand All @@ -405,12 +405,11 @@ where

/// Validates the given binary `code` is a valid Wasm module satisfying following constraints:
///
/// - the module doesn't define an internal memory instance;
/// - imported memory (if any) doesn't reserve more memory than permitted by the `schedule`;
/// - all imported functions from the external environment matches defined by `env` module.
/// - The module doesn't define an internal memory instance.
/// - Imported memory (if any) doesn't reserve more memory than permitted by the `schedule`.
/// - All imported functions from the external environment match defined by `env` module.
///
/// TODO: re-phrase
/// Also constructs contract owner_info (metadata?) by calculating the storage deposit.
/// Also constructs contract `owner_info` by calculating the storage deposit.
pub fn prepare<E, T>(
code: CodeVec<T>,
schedule: &Schedule<T>,
Expand All @@ -433,7 +432,7 @@ where
(<Error<T>>::CodeTooLarge.into(), "preparation altered the code")
);

// Calculate deposit for storing contract code and owner info in two different storage items.
// Calculate deposit for storing contract code and `owner_info` in two different storage items.
let bytes_added = code.len().saturating_add(<OwnerInfo<T>>::max_encoded_len()) as u32;
let deposit = Diff { bytes_added, items_added: 2, ..Default::default() }
.update_contract::<T>(None)
Expand All @@ -447,14 +446,13 @@ where
/// Alternate (possibly unsafe) preparation functions used only for benchmarking and testing.
///
/// For benchmarking we need to construct special contracts that might not pass our
/// sanity checks. We hide functions
/// allowing this behind a feature that is only set during benchmarking or testing to
/// prevent usage in production code.
/// sanity checks. We hide functions allowing this behind a feature that is only set during
/// benchmarking or testing to prevent usage in production code.
#[cfg(any(test, feature = "runtime-benchmarks"))]
pub mod benchmarking {
use super::*;

/// Prepare function that does not check the passed in code.
/// Prepare function that does not perform most checks on the passed in code.
pub fn prepare<T: Config>(
code: Vec<u8>,
schedule: &Schedule<T>,
Expand Down
5 changes: 2 additions & 3 deletions frame/contracts/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ pub struct ReturnData {
/// as a quick way to terminate the application (all other variants).
#[derive(RuntimeDebug)]
pub enum TrapReason {
// InstructionTrap(DispatchError),
/// The supervisor trapped the contract because of an error condition occurred during
/// execution in privileged code.
SupervisorError(DispatchError),
Expand Down Expand Up @@ -488,15 +487,15 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> {
match sandbox_result {
// Contract returned from main function -> no data was returned.
Ok(_) => Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }),
// OutOfGas when host asks engine to consume more than left in the _store_.
// `OutOfGas` when host asks engine to consume more than left in the _store_.
// We should never get this case, as gas meter is being charged (and hence raises error)
// first.
Err(wasmi::Error::Store(_)) => Err(Error::<E::T>::OutOfGas.into()),
// Contract either trapped or some host function aborted the execution.
Err(wasmi::Error::Trap(trap)) => {
if let Some(code) = trap.trap_code() {
match code {
// OutOfGas during engine execution.
// `OutOfGas` during engine execution.
OutOfFuel => return Err(Error::<E::T>::OutOfGas.into()),
_ => (),
}
Expand Down