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).
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 functionbare_call
of pallet-contracts, which returns aContractExecResult<BalanceOf<T>, EventRecordOf<T>>
.This return type contains an element
result
, which is of typeResult<ExecReturnValue, DispatchError>
.If this value is
Ok
, then it contains anExecReturnValue
, which itself is a struct with entryflags: ReturnFlags
.ReturnFlags
is au32
, with bitflags. The only bitflag defined isREVERT
, which is the value0x0000_0001
and symbolizes that the contract reverted (although theResult
isOk
).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 entryflags: ContractReturnFlags
.ContractReturnFlags
is defined to bewhich reflects the
REVERT
bit flag.Contradictory Decoding/Typing
In the past it was sufficient to read the
isRevert
boolean entry of theContractReturnFlags
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 theu32
set of bitflags (which can currently only be 0 or 1 as only theREVERT
bitflag is defined).