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