1use casper_types::bytesrepr::Error as BytesReprError;
2use casper_types::{CLType, CLValueError};
3use core::any::Any;
4
5use crate::arithmetic::ArithmeticsError;
6use crate::prelude::*;
7use crate::VmError::Serialization;
8
9pub const CASPER_ERROR_GENERIC_NAME: &str = "CasperExecError";
14
15#[repr(u16)]
17#[derive(Clone, Debug, PartialEq)]
18pub enum OdraError {
19 ExecutionError(ExecutionError),
21 VmError(VmError)
23}
24
25impl OdraError {
26 pub fn code(&self) -> u16 {
28 match self {
29 OdraError::ExecutionError(e) => e.code(),
30 OdraError::VmError(_e) => 0
31 }
32 }
33
34 #[cfg(target_arch = "wasm32")]
35 pub fn user(code: u16) -> Self {
37 if code >= ExecutionError::UserErrorTooHigh.code() {
38 ExecutionError::UserErrorTooHigh.into()
39 } else {
40 ExecutionError::User(code).into()
41 }
42 }
43
44 #[cfg(not(target_arch = "wasm32"))]
45 pub fn user(code: u16, msg: &str) -> Self {
47 if code >= ExecutionError::UserErrorTooHigh.code() {
48 ExecutionError::UserErrorTooHigh.into()
49 } else {
50 ExecutionError::User(UserError {
51 code,
52 message: msg.to_string()
53 })
54 .into()
55 }
56 }
57}
58
59impl From<ArithmeticsError> for ExecutionError {
60 fn from(error: ArithmeticsError) -> Self {
61 match error {
62 ArithmeticsError::AdditionOverflow => Self::AdditionOverflow,
63 ArithmeticsError::SubtractingOverflow => Self::SubtractionOverflow,
64 ArithmeticsError::ConversionError => Self::ConversionError
65 }
66 }
67}
68
69impl From<ArithmeticsError> for OdraError {
70 fn from(error: ArithmeticsError) -> Self {
71 Into::<ExecutionError>::into(error).into()
72 }
73}
74
75impl From<Box<dyn Any + Send>> for OdraError {
76 fn from(_: Box<dyn Any + Send>) -> Self {
77 OdraError::VmError(VmError::Panic)
78 }
79}
80
81impl From<casper_types::bytesrepr::Error> for ExecutionError {
82 fn from(error: casper_types::bytesrepr::Error) -> Self {
83 match error {
84 casper_types::bytesrepr::Error::EarlyEndOfStream => Self::EarlyEndOfStream,
85 casper_types::bytesrepr::Error::Formatting => Self::Formatting,
86 casper_types::bytesrepr::Error::LeftOverBytes => Self::LeftOverBytes,
87 casper_types::bytesrepr::Error::OutOfMemory => Self::OutOfMemory,
88 casper_types::bytesrepr::Error::NotRepresentable => Self::NotRepresentable,
89 casper_types::bytesrepr::Error::ExceededRecursionDepth => Self::ExceededRecursionDepth,
90 _ => Self::Formatting
91 }
92 }
93}
94
95#[repr(u16)]
105#[derive(Clone, Debug, PartialEq)]
106pub enum ExecutionError {
107 UnwrapError = 1,
109 UnexpectedError = 2,
111 AdditionOverflow = 100,
113 SubtractionOverflow = 101,
115 NonPayable = 102,
117 TransferToContract = 103,
119 ReentrantCall = 104,
121 CannotOverrideKeys = 105,
123 UnknownConstructor = 106,
125 NativeTransferError = 107,
127 IndexOutOfBounds = 108,
129 ZeroAddress = 109,
131 AddressCreationFailed = 110,
133 EarlyEndOfStream = 111,
135 Formatting = 112,
137 LeftOverBytes = 113,
139 OutOfMemory = 114,
141 NotRepresentable = 115,
143 ExceededRecursionDepth = 116,
145 KeyNotFound = 117,
147 CouldNotDeserializeSignature = 118,
149 TypeMismatch = 119,
151 CouldNotSignMessage = 120,
153 EmptyDictionaryName = 121,
155 MissingArg = 122,
157 MissingAddress = 123,
159 OutOfGas = 124,
161 MainPurseError = 125,
163 ConversionError = 126,
165 ContractDeploymentError = 127,
167 CannotExtractCallerInfo = 128,
169 ContractNotInstalled = 129,
171 UpgradingWithoutPreviousVersion = 130,
173 UpgradingNotAContract = 131,
175 SchemaMismatch = 132,
177 CannotDisablePreviousVersion = 133,
179 CannotUpgradeWithoutUpgrade = 134,
181 MaxUserError = 64535,
183 UserErrorTooHigh = 64536,
185 #[cfg(target_arch = "wasm32")]
187 User(u16),
188 #[cfg(not(target_arch = "wasm32"))]
189 User(UserError)
191}
192
193#[cfg(not(target_arch = "wasm32"))]
194#[derive(Debug, Clone)]
195pub struct UserError {
196 code: u16,
197 message: String
198}
199
200#[cfg(not(target_arch = "wasm32"))]
201impl PartialEq for UserError {
202 fn eq(&self, other: &Self) -> bool {
203 if self.message == CASPER_ERROR_GENERIC_NAME || other.message == CASPER_ERROR_GENERIC_NAME {
204 return self.code == other.code;
205 }
206 self.code == other.code && self.message == other.message
208 }
209}
210
211impl ExecutionError {
212 pub fn code(&self) -> u16 {
214 unsafe {
215 match self {
216 #[cfg(target_arch = "wasm32")]
217 ExecutionError::User(code) => *code,
218 #[cfg(not(target_arch = "wasm32"))]
219 ExecutionError::User(UserError { code, .. }) => *code,
220 ExecutionError::MaxUserError => 64535,
221 ExecutionError::UserErrorTooHigh => 64536,
222 _ => ExecutionError::UserErrorTooHigh.code() + *(self as *const Self as *const u16)
223 }
224 }
225 }
226}
227
228impl From<ExecutionError> for OdraError {
229 fn from(error: ExecutionError) -> Self {
230 Self::ExecutionError(error)
231 }
232}
233
234#[derive(Clone, Debug, PartialEq, Eq)]
236pub enum VmError {
237 Serialization,
239 Deserialization,
241 BalanceExceeded,
243 NoSuchMethod(String),
245 InvalidContractAddress,
247 InvalidContext,
249 TypeMismatch {
251 expected: CLType,
253 found: CLType
255 },
256 Other(String),
258 Panic
260}
261
262pub enum CollectionError {
264 IndexOutOfBounds
266}
267
268impl From<CollectionError> for ExecutionError {
269 fn from(error: CollectionError) -> Self {
270 match error {
271 CollectionError::IndexOutOfBounds => Self::IndexOutOfBounds
272 }
273 }
274}
275
276impl From<CollectionError> for OdraError {
277 fn from(error: CollectionError) -> Self {
278 Into::<ExecutionError>::into(error).into()
279 }
280}
281
282#[derive(Clone, Debug, PartialEq)]
284pub enum AddressError {
285 ZeroAddress,
287 AddressCreationError
289}
290
291impl From<AddressError> for ExecutionError {
292 fn from(error: AddressError) -> Self {
293 match error {
294 AddressError::ZeroAddress => Self::ZeroAddress,
295 AddressError::AddressCreationError => Self::AddressCreationFailed
296 }
297 }
298}
299
300impl From<AddressError> for OdraError {
301 fn from(error: AddressError) -> Self {
302 Into::<ExecutionError>::into(error).into()
303 }
304}
305
306#[derive(Debug, PartialEq, Eq, PartialOrd)]
308pub enum EventError {
309 UnexpectedType(String),
311 IndexOutOfBounds,
313 Formatting,
315 Parsing,
317 CouldntExtractName,
319 CouldntExtractEventData,
321 ContractDoesntSupportEvents,
323 TriedToQueryEventForNonContract
325}
326
327pub type OdraResult<T> = Result<T, OdraError>;
329
330impl From<CLValueError> for OdraError {
331 fn from(error: CLValueError) -> Self {
332 match error {
333 CLValueError::Serialization(_) => OdraError::VmError(Serialization),
334 CLValueError::Type(cl_type_mismatch) => OdraError::VmError(VmError::TypeMismatch {
335 expected: cl_type_mismatch.expected.clone(),
336 found: cl_type_mismatch.found.clone()
337 })
338 }
339 }
340}
341
342impl From<BytesReprError> for OdraError {
343 fn from(error: BytesReprError) -> Self {
344 match error {
345 BytesReprError::EarlyEndOfStream => ExecutionError::EarlyEndOfStream,
346 BytesReprError::Formatting => ExecutionError::Formatting,
347 BytesReprError::LeftOverBytes => ExecutionError::LeftOverBytes,
348 BytesReprError::OutOfMemory => ExecutionError::OutOfMemory,
349 BytesReprError::NotRepresentable => ExecutionError::NotRepresentable,
350 BytesReprError::ExceededRecursionDepth => ExecutionError::ExceededRecursionDepth,
351 _ => ExecutionError::Formatting
352 }
353 .into()
354 }
355}
356
357impl From<anyhow::Error> for OdraError {
358 fn from(value: anyhow::Error) -> Self {
359 OdraError::VmError(VmError::Other(value.to_string()))
360 }
361}