VM Execution Result#
Result Kinds#
Return
Represents successful execution of a sub-VM
VMError
Represents a VM produced error, such as non-zero exit code or exceeding resource limits.
It uses predefined string error codes.
VM Error Code Format#
vm-error-code := public-code [ " # " detail ]
public-code— a sequence ofsnake_casecomponents separated by single spaces, drawn from the predefined codes. It never contains#.detail— optional free-form UTF-8 diagnostic. When present, it is separated from the public code by#surrounded by a single space on each side.
The detail MUST be a deterministic function of execution (the full string is covered by the Execution Hash), but its content carries no compatibility promise — see VM Error Code Compatibility.
Consumers MUST compare and match VM error codes only by the public code (the
part before the first `` # ). A consumer matching a known code ``P MUST
treat a code as matching iff its public code equals P or extends P
with further space-separated components.
UserError
Represents a user-produced error in utf-8 format.
InternalError#
It is a special Result Kinds that represents an internal error in the VM, such as: Host communication failures or Module unavailability.
Internal errors are not visible by the contracts. Most likely Host will vote timeout if encounters such an error
Non-Deterministic Block Result Encoding#
Return: Arbitrary structure in Calldata Encoding
UserError: utf-8 string
VMError: utf-8 string
Contract Result Encoding#
Return#
Arbitrary structure in Calldata Encoding
UserError and VMError#
The error value (UserError value or VMError error code string) is reported
alongside two fingerprint fields, each Calldata Encoding encoded:
backtrace — the WASM call stack captured at the failure point:
[
{
"module_name": "<module_name>",
"func": "<number: function_index>"
}
]
wasm_store_hashes — per-module memory fingerprint:
{
"<module_name>": {
"memories": [
"<bytes: 32_byte_blake3_hash>"
]
}
}
For sake of preventing skipping execution for error results, validators are obligated to calculate the VM fingerprint on error.
Both fields are serialized using Calldata Encoding to be deterministic, and have the following structure:
backtraceframes are ordered from most recent to oldest one (most likely,_start)Function index is an index of function in WASM module
Memories are ordered by their index in WASM module
Memories are hashed using BLAKE3 hash function, which is cryptographically secure and provides acceptable performance
Execution Hash#
Every run produces an execution hash: a SHA3-256 digest over a Calldata Encoding encoding of the consensus-visible result, as a map with the following keys (in this order):
backtracedata— the contract result valuedata_fees_remainingkind— the Result Kinds result codestorage_changessubvm_hashes— see Sub-VM Result Hashwasm_store_hashes
Two runs that agree on the deterministic result produce the same execution hash, so consensus can compare a single 32-byte value instead of the full result.
Sub-VM Result Hash#
A deterministic run accumulates the result of each deterministic sub-VM call
into a rolling SHA3-256 accumulator. The finalized accumulator is the
subvm_hashes field of the parent’s Execution Hash.
For each deterministic sub-VM, its small hash is folded into the accumulator. The small hash is a SHA3-256 digest over a Calldata Encoding encoded map:
kind— the exact string"Return","UserError", or"VMError"result— forReturn/UserErrorthe result value in Calldata Encoding; forVMErrorthe error code stringsubvm_hashes— that sub-VM’s own finalized accumulator, making the hash recursive over the whole deterministic call treewasm_store_hashes
Non-deterministic sub-calls do not contribute. A run with no deterministic sub-calls finalizes its accumulator to a fixed digest, so that error and edge results hash uniformly.
Post-Execution Result Validation#
A consumer in Sync Mode or Validator Mode
consumes one leader-proposed result per non-deterministic block it runs. If the
leader supplied more results than the run consumed, the surplus blocks were
never reached: the run’s result is replaced by
leader_output extra, whose
parameter is the first 6 characters of the GVM32 (Base32) encoding of the
sha3_256 digest of the complete [result_code][data]
sub-VM result buffer the run would
otherwise have returned — the whole wire buffer as emitted, not a decoded
payload or alternate representation. No non-deterministic disagreement is caused
by this.