Smart-contract users may need to know what happened in case of
error reply (handle_reply
entrypoint) and system signal (handle_signal
entrypoint).
Expected realization of error types must be generalized and stabilized because:
- Mainly, such types are returned from sys-calls which must return backward-compatible data across runtime upgrades after network release.
- We use a lot of generics for
Ext
(sys-calls buisness logic),Environment
(backend unification) and mock tests.
Mindmap. Blue lines mean the same types:
We can see it's quite complicated so we need to refactor core-processor
and backends.
@breathx suggested these levels to improve the situation:
enum Error {
PreExecution(...),
Execution(...),
PostExecution(...),
}
In PreExecution
level we precharge gas for program code and memory, check memory and globals.
In Execution
level we have trap in program - DispatchKindResult::Trap
.
Which contains ExtError
, termination reason or misc runtime checks.
In PostExecution
level we again have memory checks.
New idea is to return [u8; 4]
slice from sys-call. Each element of slice can be simple C enum on different levels.
For example, [1, 1, 4, 0]
can be potentially represented as Execution
level with MemoryError
and its variant InvalidPointer
.
Such idea is simple to be used in other languages (not only in Rust) and very cost-effective because we just return i32
in fact.
For descriptive errors we can simply use gr_read
sys-call which will return UTF-8 string.
System signal can be occured only during WASM execution (e.g. we need only Execution
level) and inside pallet (currently only on waitlist removal). That's why we need a bit different error type:
enum SignalError {
Execution(...),
RemovedFromWaitlist,
}