pendulum-chain / api-solang

This is the code for the npm package @pendulum-chain/api-solang
0 stars 0 forks source link

Bug: Correctly detect whether a contract call reverted #20

Closed TorstenStueber closed 1 month ago

TorstenStueber commented 1 month ago

In the currently supported version of polkadot-js the return value of an RPC contract call is not correctly decoded to indicate whether the contract reverted.

Situation in the runtime

When executing a contract call via RPC, then the runtime call pallet_contracts -> call will be executed. This executes the function bare_call of pallet-contracts, which returns a ContractExecResult<BalanceOf<T>, EventRecordOf<T>>.

This return type contains an element result, which is of type Result<ExecReturnValue, DispatchError>.

If this value is Ok, then it contains an ExecReturnValue, which itself is a struct with entry flags: ReturnFlags.

ReturnFlags is a u32, with bitflags. The only bitflag defined is REVERT, which is the value 0x0000_0001 and symbolizes that the contract reverted (although the Result is Ok).

Situation in Polkadot.js

The return value of the RPC call is defined in polkadot-js as the TypeScript type ContractExecResult, which is the equivalent of the according Rust type.

This type is defined equivalently to the Rust type and in case the result is Ok it contains a struct with the entry flags: ContractReturnFlags.

ContractReturnFlags is defined to be

interface ContractReturnFlags extends Set {
    readonly isRevert: boolean;
}

which reflects the REVERT bit flag.

Contradictory Decoding/Typing

In the past it was sufficient to read the isRevert boolean entry of the ContractReturnFlags value. However, the value is decoded differently now – in contradiction to the typing – and it is only an object of the form { bits: number }, where the number is the u32 set of bitflags (which can currently only be 0 or 1 as only the REVERT bitflag is defined).