1use core::any::Any;
2
3use alloc::{boxed::Box, string::String};
4
5use crate::arithmetic::ArithmeticsError;
6
7const MAX_USER_ERROR: u16 = 32767;
8const USER_ERROR_TOO_HIGH: u16 = 32768;
9const UNWRAP_ERROR: u16 = 1;
10
11const CODE_ADDITION_OVERFLOW: u16 = 100;
12const CODE_SUBTRACTION_OVERFLOW: u16 = 101;
13const CODE_NON_PAYABLE: u16 = 102;
14const CODE_TRANSFER_TO_CONTRACT: u16 = 103;
15const CODE_REENTRANT_CALL: u16 = 104;
16const CODE_CONTRACT_ALREADY_INSTALLED: u16 = 105;
17const CODE_UNKNOWN_CONSTRUCTOR: u16 = 106;
18const CODE_NATIVE_TRANSFER_ERROR: u16 = 107;
19const CODE_INDEX_OUT_OF_BOUNDS: u16 = 108;
20const CODE_ZERO_ADDRESS: u16 = 109;
21const CODE_ADDRESS_CREATION_FAILED: u16 = 110;
22const CODE_SERIALIZATION_FAILED: u16 = 111;
23
24#[derive(Clone, Debug, PartialEq)]
26pub enum OdraError {
27 ExecutionError(ExecutionError),
29 VmError(VmError)
31}
32
33impl From<ArithmeticsError> for ExecutionError {
34 fn from(error: ArithmeticsError) -> Self {
35 match error {
36 ArithmeticsError::AdditionOverflow => Self::addition_overflow(),
37 ArithmeticsError::SubtractingOverflow => Self::subtraction_overflow()
38 }
39 }
40}
41
42impl From<ArithmeticsError> for OdraError {
43 fn from(error: ArithmeticsError) -> Self {
44 Into::<ExecutionError>::into(error).into()
45 }
46}
47
48impl From<Box<dyn Any + Send>> for OdraError {
49 fn from(_: Box<dyn Any + Send>) -> Self {
50 OdraError::VmError(VmError::Panic)
51 }
52}
53
54impl From<casper_types::bytesrepr::Error> for ExecutionError {
55 fn from(value: casper_types::bytesrepr::Error) -> Self {
56 Self::sys(
57 CODE_SERIALIZATION_FAILED,
58 match value {
59 casper_types::bytesrepr::Error::EarlyEndOfStream => "Early end of stream",
60 casper_types::bytesrepr::Error::Formatting => "Formatting",
61 casper_types::bytesrepr::Error::LeftOverBytes => "Leftover bytes",
62 casper_types::bytesrepr::Error::OutOfMemory => "Out of memory",
63 casper_types::bytesrepr::Error::NotRepresentable => "Not representable",
64 casper_types::bytesrepr::Error::ExceededRecursionDepth => {
65 "Exceeded recursion depth"
66 }
67 _ => "Serialization failed"
68 }
69 )
70 }
71}
72
73#[derive(Clone, Debug)]
83pub struct ExecutionError(u16, String);
84
85impl ExecutionError {
86 pub fn new(code: u16, msg: &str) -> Self {
90 if code > MAX_USER_ERROR {
91 Self(
92 USER_ERROR_TOO_HIGH,
93 String::from("User error too high. The code should be in range 0..32767.")
94 )
95 } else {
96 Self(code, String::from(msg))
97 }
98 }
99
100 fn sys(code: u16, msg: &str) -> Self {
102 ExecutionError(code + USER_ERROR_TOO_HIGH, String::from(msg))
103 }
104
105 pub fn code(&self) -> u16 {
107 self.0
108 }
109
110 pub fn unwrap_error() -> Self {
112 Self::sys(UNWRAP_ERROR, "Unwrap error")
113 }
114
115 pub fn non_payable() -> Self {
116 Self::sys(CODE_NON_PAYABLE, "Method does not accept deposit")
117 }
118
119 pub fn can_not_transfer_to_contract() -> Self {
120 Self::sys(
121 CODE_TRANSFER_TO_CONTRACT,
122 "Can't transfer tokens to contract."
123 )
124 }
125
126 pub fn reentrant_call() -> Self {
127 Self::sys(CODE_REENTRANT_CALL, "Reentrant call.")
128 }
129
130 pub fn contract_already_installed() -> Self {
131 Self::sys(
132 CODE_CONTRACT_ALREADY_INSTALLED,
133 "Contract already installed."
134 )
135 }
136
137 pub fn unknown_constructor() -> Self {
138 Self::sys(CODE_UNKNOWN_CONSTRUCTOR, "Unknown constructor.")
139 }
140
141 pub fn native_token_transfer_error() -> Self {
142 Self::sys(CODE_NATIVE_TRANSFER_ERROR, "Native token transfer error.")
143 }
144
145 pub fn addition_overflow() -> Self {
146 Self::sys(CODE_ADDITION_OVERFLOW, "Addition overflow")
147 }
148
149 pub fn subtraction_overflow() -> Self {
150 Self::sys(CODE_SUBTRACTION_OVERFLOW, "Subtraction overflow")
151 }
152
153 pub fn index_out_of_bounds() -> Self {
154 Self::sys(CODE_INDEX_OUT_OF_BOUNDS, "Index out of bounds")
155 }
156
157 pub fn zero_address() -> Self {
158 Self::sys(CODE_ZERO_ADDRESS, "Zero address")
159 }
160
161 pub fn address_creation_failed() -> Self {
162 Self::sys(CODE_ADDRESS_CREATION_FAILED, "Address creation failed")
163 }
164}
165
166impl PartialEq for ExecutionError {
167 fn eq(&self, other: &Self) -> bool {
168 self.0 == other.0
169 }
170}
171
172impl From<ExecutionError> for OdraError {
173 fn from(error: ExecutionError) -> Self {
174 Self::ExecutionError(error)
175 }
176}
177
178#[derive(Clone, Debug, PartialEq, Eq)]
180pub enum VmError {
181 Serialization,
183 Deserialization,
185 BalanceExceeded,
187 NoSuchMethod(String),
189 InvalidContractAddress,
191 InvalidContext,
193 MissingArg,
195 Other(String),
197 Panic
199}
200
201pub enum CollectionError {
203 IndexOutOfBounds
205}
206
207impl From<CollectionError> for ExecutionError {
208 fn from(error: CollectionError) -> Self {
209 match error {
210 CollectionError::IndexOutOfBounds => Self::index_out_of_bounds()
211 }
212 }
213}
214
215impl From<CollectionError> for OdraError {
216 fn from(error: CollectionError) -> Self {
217 Into::<ExecutionError>::into(error).into()
218 }
219}
220
221#[derive(Clone, Debug, PartialEq)]
223pub enum AddressError {
224 ZeroAddress,
226 AddressCreationError
228}
229
230impl From<AddressError> for ExecutionError {
231 fn from(error: AddressError) -> Self {
232 match error {
233 AddressError::ZeroAddress => Self::zero_address(),
234 AddressError::AddressCreationError => Self::address_creation_failed()
235 }
236 }
237}
238
239impl From<AddressError> for OdraError {
240 fn from(error: AddressError) -> Self {
241 Into::<ExecutionError>::into(error).into()
242 }
243}