1use solana_program::program_error::ProgramError;
27use thiserror::Error;
28use std::{
29 result::Result as StdResult
30};
31
32#[derive(Error, Debug, Copy, Clone)]
33pub enum ErrorCode {
34 #[error("overflow")]
35 Overflow,
36 #[error("underflow")]
37 Underflow,
38 #[error("division by zero")]
39 DivisionByZero,
40}
41
42impl From<ErrorCode> for ProgramError {
43 fn from(e:ErrorCode) -> Self {
44 ProgramError::Custom(e as u32)
45 }
46}
47
48pub trait SafeMath {
50 type Output;
51
52 fn safe_add(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError>;
53 fn safe_sub(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError>;
54 fn safe_div(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError>;
55 fn safe_mul(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError>;
56 fn safe_pow(&self, exp: u32) -> StdResult<Self::Output, ProgramError>;
57}
58
59macro_rules! safe_math {
60 ($type: ident) => {
61 impl SafeMath for $type {
63 type Output = $type;
64
65 fn safe_add(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError> {
66 match self.checked_add(rhs) {
67 Some(result) => Ok(result),
68 None => return Err(ErrorCode::Overflow.into())
69 }
70 }
71
72 fn safe_sub(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError> {
73 match self.checked_sub(rhs) {
74 Some(result) => Ok(result),
75 None => return Err(ErrorCode::Underflow.into())
76 }
77 }
78
79 fn safe_mul(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError> {
80 match self.checked_mul(rhs) {
81 Some(result) => Ok(result),
82 None => return Err(ErrorCode::Underflow.into())
83 }
84 }
85
86 fn safe_div(&self, rhs: Self::Output) -> StdResult<Self::Output, ProgramError> {
87 match self.checked_div(rhs) {
88 Some(result) => Ok(result),
89 None => return Err(ErrorCode::DivisionByZero.into())
90 }
91 }
92
93 fn safe_pow(&self, exp: u32) -> StdResult<Self::Output, ProgramError> {
94 match self.checked_pow(exp) {
95 Some(result) => Ok(result),
96 None => return Err(ErrorCode::Overflow.into())
97 }
98 }
99 }
100 }
101}
102
103safe_math!(u128);
104safe_math!(u64);
105safe_math!(u32);
106safe_math!(u16);
107safe_math!(u8);