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 FactoryModuleCall = 135,
183 CannotGetAnImmediateCaller = 136,
185 PathIndexOutOfBounds = 137,
187 MaxUserError = 64535,
189 UserErrorTooHigh = 64536,
191 #[cfg(target_arch = "wasm32")]
193 User(u16),
194 #[cfg(not(target_arch = "wasm32"))]
195 User(UserError)
197}
198
199#[cfg(not(target_arch = "wasm32"))]
200#[derive(Debug, Clone)]
201pub struct UserError {
202 code: u16,
203 message: String
204}
205
206#[cfg(not(target_arch = "wasm32"))]
207impl PartialEq for UserError {
208 fn eq(&self, other: &Self) -> bool {
209 if self.message == CASPER_ERROR_GENERIC_NAME || other.message == CASPER_ERROR_GENERIC_NAME {
210 return self.code == other.code;
211 }
212 self.code == other.code && self.message == other.message
214 }
215}
216
217impl ExecutionError {
218 pub fn code(&self) -> u16 {
220 unsafe {
221 match self {
222 #[cfg(target_arch = "wasm32")]
223 ExecutionError::User(code) => *code,
224 #[cfg(not(target_arch = "wasm32"))]
225 ExecutionError::User(UserError { code, .. }) => *code,
226 ExecutionError::MaxUserError => 64535,
227 ExecutionError::UserErrorTooHigh => 64536,
228 _ => ExecutionError::UserErrorTooHigh.code() + *(self as *const Self as *const u16)
229 }
230 }
231 }
232}
233
234impl From<ExecutionError> for OdraError {
235 fn from(error: ExecutionError) -> Self {
236 Self::ExecutionError(error)
237 }
238}
239
240#[derive(Clone, Debug, PartialEq, Eq)]
242pub enum VmError {
243 Serialization,
245 Deserialization,
247 BalanceExceeded,
249 NoSuchMethod(String),
251 InvalidContractAddress,
253 InvalidContext,
255 TypeMismatch {
257 expected: CLType,
259 found: CLType
261 },
262 Other(String),
264 Panic
266}
267
268pub enum CollectionError {
270 IndexOutOfBounds
272}
273
274impl From<CollectionError> for ExecutionError {
275 fn from(error: CollectionError) -> Self {
276 match error {
277 CollectionError::IndexOutOfBounds => Self::IndexOutOfBounds
278 }
279 }
280}
281
282impl From<CollectionError> for OdraError {
283 fn from(error: CollectionError) -> Self {
284 Into::<ExecutionError>::into(error).into()
285 }
286}
287
288#[derive(Clone, Debug, PartialEq)]
290pub enum AddressError {
291 ZeroAddress,
293 AddressCreationError
295}
296
297impl From<AddressError> for ExecutionError {
298 fn from(error: AddressError) -> Self {
299 match error {
300 AddressError::ZeroAddress => Self::ZeroAddress,
301 AddressError::AddressCreationError => Self::AddressCreationFailed
302 }
303 }
304}
305
306impl From<AddressError> for OdraError {
307 fn from(error: AddressError) -> Self {
308 Into::<ExecutionError>::into(error).into()
309 }
310}
311
312#[derive(Debug, PartialEq, Eq, PartialOrd)]
314pub enum EventError {
315 UnexpectedType(String),
317 IndexOutOfBounds,
319 Formatting,
321 Parsing,
323 CouldntExtractName,
325 CouldntExtractEventData,
327 ContractDoesntSupportEvents,
329 TriedToQueryEventForNonContract
331}
332
333pub type OdraResult<T> = Result<T, OdraError>;
335
336impl From<CLValueError> for OdraError {
337 fn from(error: CLValueError) -> Self {
338 match error {
339 CLValueError::Serialization(_) => OdraError::VmError(Serialization),
340 CLValueError::Type(cl_type_mismatch) => OdraError::VmError(VmError::TypeMismatch {
341 expected: cl_type_mismatch.expected.clone(),
342 found: cl_type_mismatch.found.clone()
343 })
344 }
345 }
346}
347
348impl From<BytesReprError> for OdraError {
349 fn from(error: BytesReprError) -> Self {
350 match error {
351 BytesReprError::EarlyEndOfStream => ExecutionError::EarlyEndOfStream,
352 BytesReprError::Formatting => ExecutionError::Formatting,
353 BytesReprError::LeftOverBytes => ExecutionError::LeftOverBytes,
354 BytesReprError::OutOfMemory => ExecutionError::OutOfMemory,
355 BytesReprError::NotRepresentable => ExecutionError::NotRepresentable,
356 BytesReprError::ExceededRecursionDepth => ExecutionError::ExceededRecursionDepth,
357 _ => ExecutionError::Formatting
358 }
359 .into()
360 }
361}
362
363impl From<anyhow::Error> for OdraError {
364 fn from(value: anyhow::Error) -> Self {
365 OdraError::VmError(VmError::Other(value.to_string()))
366 }
367}