aurora_evm/core/
error.rs

1use super::prelude::*;
2use super::Opcode;
3
4/// Trap which indicates that an `ExternalOpcode` has to be handled.
5pub type Trap = Opcode;
6
7/// Capture represents the result of execution.
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum Capture<E, T> {
10    /// The machine has exited. It cannot be executed again.
11    Exit(E),
12    /// The machine has trapped. It is waiting for external information, and can
13    /// be executed again.
14    Trap(T),
15}
16
17/// Exit reason.
18#[derive(Clone, Debug, Eq, PartialEq)]
19#[cfg_attr(
20    feature = "with-codec",
21    derive(scale_codec::Encode, scale_codec::Decode, scale_info::TypeInfo)
22)]
23#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
24pub enum ExitReason {
25    /// Machine has succeeded.
26    Succeed(ExitSucceed),
27    /// Machine returns a normal EVM error.
28    Error(ExitError),
29    /// Machine encountered an explicit revert.
30    Revert(ExitRevert),
31    /// Machine encountered an error that is not supposed to be normal EVM
32    /// errors, such as requiring too much memory to execute.
33    Fatal(ExitFatal),
34}
35
36impl ExitReason {
37    /// Whether the exit is succeeded.
38    #[must_use]
39    pub const fn is_succeed(&self) -> bool {
40        matches!(self, Self::Succeed(_))
41    }
42
43    /// Whether the exit is error.
44    #[must_use]
45    pub const fn is_error(&self) -> bool {
46        matches!(self, Self::Error(_))
47    }
48
49    /// Whether the exit is revert.
50    #[must_use]
51    pub const fn is_revert(&self) -> bool {
52        matches!(self, Self::Revert(_))
53    }
54
55    /// Whether the exit is fatal.
56    #[must_use]
57    pub const fn is_fatal(&self) -> bool {
58        matches!(self, Self::Fatal(_))
59    }
60}
61
62/// Exit succeed reason.
63#[derive(Clone, Copy, Debug, Eq, PartialEq)]
64#[cfg_attr(
65    feature = "with-codec",
66    derive(scale_codec::Encode, scale_codec::Decode, scale_info::TypeInfo)
67)]
68#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
69pub enum ExitSucceed {
70    /// Machine encountered an explicit stop.
71    Stopped,
72    /// Machine encountered an explicit return.
73    Returned,
74    /// Machine encountered an explicit suicide.
75    Suicided,
76}
77
78impl From<ExitSucceed> for ExitReason {
79    fn from(s: ExitSucceed) -> Self {
80        Self::Succeed(s)
81    }
82}
83
84/// Exit revert reason.
85#[derive(Clone, Copy, Debug, Eq, PartialEq)]
86#[cfg_attr(
87    feature = "with-codec",
88    derive(scale_codec::Encode, scale_codec::Decode, scale_info::TypeInfo)
89)]
90#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
91pub enum ExitRevert {
92    /// Machine encountered an explicit revert.
93    Reverted,
94}
95
96impl From<ExitRevert> for ExitReason {
97    fn from(s: ExitRevert) -> Self {
98        Self::Revert(s)
99    }
100}
101
102/// Exit error reason.
103#[derive(Clone, Debug, Eq, PartialEq)]
104#[cfg_attr(
105    feature = "with-codec",
106    derive(scale_codec::Encode, scale_codec::Decode, scale_info::TypeInfo)
107)]
108#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
109pub enum ExitError {
110    /// Trying to pop from an empty stack.
111    #[cfg_attr(feature = "with-codec", codec(index = 0))]
112    StackUnderflow,
113    /// Trying to push into a stack over stack limit.
114    #[cfg_attr(feature = "with-codec", codec(index = 1))]
115    StackOverflow,
116    /// Jump destination is invalid.
117    #[cfg_attr(feature = "with-codec", codec(index = 2))]
118    InvalidJump,
119    /// An opcode accesses memory region, but the region is invalid.
120    #[cfg_attr(feature = "with-codec", codec(index = 3))]
121    InvalidRange,
122    /// Encountered the designated invalid opcode.
123    #[cfg_attr(feature = "with-codec", codec(index = 4))]
124    DesignatedInvalid,
125    /// Call stack is too deep (runtime).
126    #[cfg_attr(feature = "with-codec", codec(index = 5))]
127    CallTooDeep,
128    /// Create opcode encountered collision (runtime).
129    #[cfg_attr(feature = "with-codec", codec(index = 6))]
130    CreateCollision,
131    /// Create init code exceeds limit (runtime).
132    #[cfg_attr(feature = "with-codec", codec(index = 7))]
133    CreateContractLimit,
134
135    /// Invalid opcode during execution or starting byte is 0xef. See [EIP-3541](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3541.md).
136    #[cfg_attr(feature = "with-codec", codec(index = 15))]
137    InvalidCode(Opcode),
138
139    /// An opcode accesses external information, but the request is off offset
140    /// limit (runtime).
141    #[cfg_attr(feature = "with-codec", codec(index = 8))]
142    OutOfOffset,
143    /// Execution runs out of gas (runtime).
144    #[cfg_attr(feature = "with-codec", codec(index = 9))]
145    OutOfGas,
146    /// Not enough fund to start the execution (runtime).
147    #[cfg_attr(feature = "with-codec", codec(index = 10))]
148    OutOfFund,
149
150    /// PC underflowed (unused).
151    #[allow(clippy::upper_case_acronyms)]
152    #[cfg_attr(feature = "with-codec", codec(index = 11))]
153    PCUnderflow,
154
155    /// Attempt to create an empty account (runtime, unused).
156    #[cfg_attr(feature = "with-codec", codec(index = 12))]
157    CreateEmpty,
158
159    /// Other normal errors.
160    #[cfg_attr(feature = "with-codec", codec(index = 13))]
161    Other(Cow<'static, str>),
162
163    /// Nonce reached maximum value of 2^64-1
164    /// <https://eips.ethereum.org/EIPS/eip-2681>
165    #[cfg_attr(feature = "with-codec", codec(index = 14))]
166    MaxNonce,
167
168    /// `usize` casting overflow
169    #[cfg_attr(feature = "with-codec", codec(index = 15))]
170    UsizeOverflow,
171    #[cfg_attr(feature = "with-codec", codec(index = 16))]
172    CreateContractStartingWithEF,
173}
174
175impl From<ExitError> for ExitReason {
176    fn from(s: ExitError) -> Self {
177        Self::Error(s)
178    }
179}
180
181/// Exit fatal reason.
182#[derive(Clone, Debug, Eq, PartialEq)]
183#[cfg_attr(
184    feature = "with-codec",
185    derive(scale_codec::Encode, scale_codec::Decode, scale_info::TypeInfo)
186)]
187#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
188pub enum ExitFatal {
189    /// The operation is not supported.
190    NotSupported,
191    /// The trap (interrupt) is unhandled.
192    UnhandledInterrupt,
193    /// The environment explicitly set call errors as fatal error.
194    CallErrorAsFatal(ExitError),
195
196    /// Other fatal errors.
197    Other(Cow<'static, str>),
198}
199
200impl From<ExitFatal> for ExitReason {
201    fn from(s: ExitFatal) -> Self {
202        Self::Fatal(s)
203    }
204}