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,
}