1use super::{action_params::ActionParams, ResumeCall, ResumeCreate};
24use cfx_db_errors::statedb::{Error as DbError, Result as DbResult};
25use cfx_types::{Address, U256};
26use solidity_abi::ABIDecodeError;
27use std::fmt;
28
29#[derive(Debug, Clone)]
30pub enum TrapKind {
31 Call(ActionParams),
32 Create(ActionParams),
33}
34
35pub enum TrapError<Call, Create> {
36 Call(ActionParams, Call),
37 Create(ActionParams, Create),
38}
39
40#[derive(Debug, PartialEq)]
42pub enum Error {
43 OutOfGas,
49 BadJumpDestination {
52 destination: usize,
54 },
55 BadInstruction {
57 instruction: u8,
59 },
60 StackUnderflow {
63 instruction: &'static str,
65 wanted: usize,
67 on_stack: usize,
69 },
70 OutOfStack {
72 instruction: &'static str,
74 wanted: usize,
76 limit: usize,
78 },
79 SubStackUnderflow {
82 wanted: usize,
84 on_stack: usize,
86 },
87 OutOfSubStack {
89 wanted: usize,
91 limit: usize,
93 },
94 InvalidSubEntry,
95 NotEnoughBalanceForStorage {
99 required: U256,
100 got: U256,
101 },
102 ExceedStorageLimit,
105 BuiltIn(String),
107 InternalContract(String),
109 MutableCallInStaticContext,
111 CreateInitCodeSizeLimit,
113 StateDbError(PartialEqWrapper<DbError>),
115 Wasm(String),
117 OutOfBounds,
119 Reverted,
121 InvalidAddress(Address),
123 ConflictAddress(Address),
125 NonceOverflow(Address),
127 CreateContractStartingWithEF,
129}
130
131#[derive(Debug)]
132pub struct PartialEqWrapper<T: std::fmt::Debug>(pub T);
133
134impl<T: std::fmt::Debug> PartialEq for PartialEqWrapper<T> {
135 fn eq(&self, other: &Self) -> bool {
136 format!("{:?}", self.0) == format!("{:?}", other.0)
137 }
138}
139
140impl From<DbError> for Error {
141 fn from(err: DbError) -> Self { Error::StateDbError(PartialEqWrapper(err)) }
142}
143
144impl From<ABIDecodeError> for Error {
145 fn from(err: ABIDecodeError) -> Self {
146 Error::InternalContract(format!("ABI decode error: {}", err.0))
147 }
148}
149
150impl fmt::Display for Error {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 use self::Error::*;
153 match *self {
154 OutOfGas => write!(f, "Out of gas"),
155 BadJumpDestination { destination } => {
156 write!(f, "Bad jump destination {:x}", destination)
157 }
158 BadInstruction { instruction } => {
159 write!(f, "Bad instruction {:x}", instruction)
160 }
161 StackUnderflow {
162 instruction,
163 wanted,
164 on_stack,
165 } => write!(
166 f,
167 "Stack underflow {} {}/{}",
168 instruction, wanted, on_stack
169 ),
170 OutOfStack {
171 instruction,
172 wanted,
173 limit,
174 } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit),
175 SubStackUnderflow { wanted, on_stack } => {
176 write!(f, "Subroutine stack underflow {}/{}", wanted, on_stack)
177 }
178 InvalidSubEntry => {
179 write!(f, "Invalid Subroutine Entry via BEGINSUB")
180 }
181 OutOfSubStack { wanted, limit } => {
182 write!(f, "Out of subroutine stack {}/{}", wanted, limit)
183 }
184 NotEnoughBalanceForStorage { required, got } => {
185 write!(f, "Not enough balance for storage {}/{}", required, got,)
186 }
187 ExceedStorageLimit => write!(f, "Exceed storage limit"),
188 BuiltIn(ref name) => write!(f, "Built-in failed: {}", name),
189 InternalContract(ref name) => {
190 write!(f, "InternalContract failed: {}", name)
191 }
192 StateDbError(ref msg) => {
193 write!(f, "Irrecoverable state db error: {}", msg.0)
194 }
195 MutableCallInStaticContext => {
196 write!(f, "Mutable call in static context")
197 }
198 CreateInitCodeSizeLimit => {
199 write!(f, "Exceed create initcode size limit")
200 }
201 Wasm(ref msg) => write!(f, "Internal error: {}", msg),
202 OutOfBounds => write!(f, "Out of bounds"),
203 Reverted => write!(f, "Reverted by bytecode"),
204 InvalidAddress(ref addr) => write!(f, "InvalidAddress: {}", addr),
205 ConflictAddress(ref addr) => {
206 write!(f, "Contract creation on an existing address: {}", addr)
207 }
208 NonceOverflow(ref addr) => {
209 write!(f, "Address nonce overflow: {}", addr)
210 }
211 CreateContractStartingWithEF => {
212 write!(f, "Create contract starting with EF")
213 }
214 }
215 }
216}
217
218pub type Result<T> = ::std::result::Result<T, Error>;
219
220pub fn separate_out_db_error<T>(result: Result<T>) -> DbResult<Result<T>> {
225 match result {
226 Err(Error::StateDbError(err)) => Err(err.0),
227 x => Ok(x),
228 }
229}
230
231pub enum TrapResult<T, Call, Create> {
232 Return(Result<T>),
233 SubCallCreate(TrapError<Call, Create>),
234}
235
236impl<T, Call, Create> TrapResult<T, Call, Create> {
237 #[cfg(any(test, feature = "testonly_code"))]
238 pub fn ok(self) -> Option<Result<T>> {
239 if let TrapResult::Return(result) = self {
240 Some(result)
241 } else {
242 None
243 }
244 }
245}
246
247pub type ExecTrapResult<T> =
248 TrapResult<T, Box<dyn ResumeCall>, Box<dyn ResumeCreate>>;
249
250pub type ExecTrapError = TrapError<Box<dyn ResumeCall>, Box<dyn ResumeCreate>>;