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 ContractAlreadyInstalled = 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 MaxUserError = 64535,
171 UserErrorTooHigh = 64536,
173 #[cfg(target_arch = "wasm32")]
175 User(u16),
176 #[cfg(not(target_arch = "wasm32"))]
177 User(UserError)
179}
180
181#[cfg(not(target_arch = "wasm32"))]
182#[derive(Debug, Clone)]
183pub struct UserError {
184 code: u16,
185 message: String
186}
187
188#[cfg(not(target_arch = "wasm32"))]
189impl PartialEq for UserError {
190 fn eq(&self, other: &Self) -> bool {
191 if self.message == CASPER_ERROR_GENERIC_NAME || other.message == CASPER_ERROR_GENERIC_NAME {
192 return self.code == other.code;
193 }
194 self.code == other.code && self.message == other.message
196 }
197}
198
199impl ExecutionError {
200 pub fn code(&self) -> u16 {
202 unsafe {
203 match self {
204 #[cfg(target_arch = "wasm32")]
205 ExecutionError::User(code) => *code,
206 #[cfg(not(target_arch = "wasm32"))]
207 ExecutionError::User(UserError { code, .. }) => *code,
208 ExecutionError::MaxUserError => 64535,
209 ExecutionError::UserErrorTooHigh => 64536,
210 _ => ExecutionError::UserErrorTooHigh.code() + *(self as *const Self as *const u16)
211 }
212 }
213 }
214}
215
216impl From<ExecutionError> for OdraError {
217 fn from(error: ExecutionError) -> Self {
218 Self::ExecutionError(error)
219 }
220}
221
222#[derive(Clone, Debug, PartialEq, Eq)]
224pub enum VmError {
225 Serialization,
227 Deserialization,
229 BalanceExceeded,
231 NoSuchMethod(String),
233 InvalidContractAddress,
235 InvalidContext,
237 TypeMismatch {
239 expected: CLType,
241 found: CLType
243 },
244 Other(String),
246 Panic
248}
249
250pub enum CollectionError {
252 IndexOutOfBounds
254}
255
256impl From<CollectionError> for ExecutionError {
257 fn from(error: CollectionError) -> Self {
258 match error {
259 CollectionError::IndexOutOfBounds => Self::IndexOutOfBounds
260 }
261 }
262}
263
264impl From<CollectionError> for OdraError {
265 fn from(error: CollectionError) -> Self {
266 Into::<ExecutionError>::into(error).into()
267 }
268}
269
270#[derive(Clone, Debug, PartialEq)]
272pub enum AddressError {
273 ZeroAddress,
275 AddressCreationError
277}
278
279impl From<AddressError> for ExecutionError {
280 fn from(error: AddressError) -> Self {
281 match error {
282 AddressError::ZeroAddress => Self::ZeroAddress,
283 AddressError::AddressCreationError => Self::AddressCreationFailed
284 }
285 }
286}
287
288impl From<AddressError> for OdraError {
289 fn from(error: AddressError) -> Self {
290 Into::<ExecutionError>::into(error).into()
291 }
292}
293
294#[derive(Debug, PartialEq, Eq, PartialOrd)]
296pub enum EventError {
297 UnexpectedType(String),
299 IndexOutOfBounds,
301 Formatting,
303 Parsing,
305 CouldntExtractName,
307 CouldntExtractEventData,
309 ContractDoesntSupportEvents,
311 TriedToQueryEventForNonContract
313}
314
315pub type OdraResult<T> = Result<T, OdraError>;
317
318impl From<CLValueError> for OdraError {
319 fn from(error: CLValueError) -> Self {
320 match error {
321 CLValueError::Serialization(_) => OdraError::VmError(Serialization),
322 CLValueError::Type(cl_type_mismatch) => OdraError::VmError(VmError::TypeMismatch {
323 expected: cl_type_mismatch.expected.clone(),
324 found: cl_type_mismatch.found.clone()
325 })
326 }
327 }
328}
329
330impl From<BytesReprError> for OdraError {
331 fn from(error: BytesReprError) -> Self {
332 match error {
333 BytesReprError::EarlyEndOfStream => ExecutionError::EarlyEndOfStream,
334 BytesReprError::Formatting => ExecutionError::Formatting,
335 BytesReprError::LeftOverBytes => ExecutionError::LeftOverBytes,
336 BytesReprError::OutOfMemory => ExecutionError::OutOfMemory,
337 BytesReprError::NotRepresentable => ExecutionError::NotRepresentable,
338 BytesReprError::ExceededRecursionDepth => ExecutionError::ExceededRecursionDepth,
339 _ => ExecutionError::Formatting
340 }
341 .into()
342 }
343}
344
345impl From<anyhow::Error> for OdraError {
346 fn from(value: anyhow::Error) -> Self {
347 OdraError::VmError(VmError::Other(value.to_string()))
348 }
349}