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