spl_token_interface/
error.rs1use {
4 num_derive::FromPrimitive,
5 solana_program_error::{ProgramError, ToStr},
6 thiserror::Error,
7};
8
9#[cfg_attr(test, derive(strum_macros::FromRepr, strum_macros::EnumIter))]
11#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
12pub enum TokenError {
13 #[error("Lamport balance below rent-exempt threshold")]
16 NotRentExempt,
17 #[error("Insufficient funds")]
19 InsufficientFunds,
20 #[error("Invalid Mint")]
22 InvalidMint,
23 #[error("Account not associated with this Mint")]
25 MintMismatch,
26 #[error("Owner does not match")]
28 OwnerMismatch,
29
30 #[error("Fixed supply")]
33 FixedSupply,
34 #[error("Already in use")]
36 AlreadyInUse,
37 #[error("Invalid number of provided signers")]
39 InvalidNumberOfProvidedSigners,
40 #[error("Invalid number of required signers")]
42 InvalidNumberOfRequiredSigners,
43 #[error("State is uninitialized")]
45 UninitializedState,
46
47 #[error("Instruction does not support native tokens")]
50 NativeNotSupported,
51 #[error("Non-native account can only be closed if its balance is zero")]
53 NonNativeHasBalance,
54 #[error("Invalid instruction")]
56 InvalidInstruction,
57 #[error("State is invalid for requested operation")]
59 InvalidState,
60 #[error("Operation overflowed")]
62 Overflow,
63
64 #[error("Account does not support specified authority type")]
67 AuthorityTypeNotSupported,
68 #[error("This token mint cannot freeze accounts")]
70 MintCannotFreeze,
71 #[error("Account is frozen")]
73 AccountFrozen,
74 #[error("The provided decimals value different from the Mint decimals")]
76 MintDecimalsMismatch,
77 #[error("Instruction does not support non-native tokens")]
79 NonNativeNotSupported,
80}
81impl From<TokenError> for ProgramError {
82 fn from(e: TokenError) -> Self {
83 ProgramError::Custom(e as u32)
84 }
85}
86
87impl TryFrom<u32> for TokenError {
88 type Error = ProgramError;
89 fn try_from(error: u32) -> Result<Self, Self::Error> {
90 match error {
91 0 => Ok(TokenError::NotRentExempt),
92 1 => Ok(TokenError::InsufficientFunds),
93 2 => Ok(TokenError::InvalidMint),
94 3 => Ok(TokenError::MintMismatch),
95 4 => Ok(TokenError::OwnerMismatch),
96 5 => Ok(TokenError::FixedSupply),
97 6 => Ok(TokenError::AlreadyInUse),
98 7 => Ok(TokenError::InvalidNumberOfProvidedSigners),
99 8 => Ok(TokenError::InvalidNumberOfRequiredSigners),
100 9 => Ok(TokenError::UninitializedState),
101 10 => Ok(TokenError::NativeNotSupported),
102 11 => Ok(TokenError::NonNativeHasBalance),
103 12 => Ok(TokenError::InvalidInstruction),
104 13 => Ok(TokenError::InvalidState),
105 14 => Ok(TokenError::Overflow),
106 15 => Ok(TokenError::AuthorityTypeNotSupported),
107 16 => Ok(TokenError::MintCannotFreeze),
108 17 => Ok(TokenError::AccountFrozen),
109 18 => Ok(TokenError::MintDecimalsMismatch),
110 19 => Ok(TokenError::NonNativeNotSupported),
111 _ => Err(ProgramError::InvalidArgument),
112 }
113 }
114}
115
116impl ToStr for TokenError {
117 fn to_str(&self) -> &'static str {
118 match self {
119 TokenError::NotRentExempt => "Error: Lamport balance below rent-exempt threshold",
120 TokenError::InsufficientFunds => "Error: insufficient funds",
121 TokenError::InvalidMint => "Error: Invalid Mint",
122 TokenError::MintMismatch => "Error: Account not associated with this Mint",
123 TokenError::OwnerMismatch => "Error: owner does not match",
124 TokenError::FixedSupply => "Error: the total supply of this token is fixed",
125 TokenError::AlreadyInUse => "Error: account or token already in use",
126 TokenError::InvalidNumberOfProvidedSigners => {
127 "Error: Invalid number of provided signers"
128 }
129 TokenError::InvalidNumberOfRequiredSigners => {
130 "Error: Invalid number of required signers"
131 }
132 TokenError::UninitializedState => "Error: State is uninitialized",
133 TokenError::NativeNotSupported => "Error: Instruction does not support native tokens",
134 TokenError::NonNativeHasBalance => {
135 "Error: Non-native account can only be closed if its balance is zero"
136 }
137 TokenError::InvalidInstruction => "Error: Invalid instruction",
138 TokenError::InvalidState => "Error: Invalid account state for operation",
139 TokenError::Overflow => "Error: Operation overflowed",
140 TokenError::AuthorityTypeNotSupported => {
141 "Error: Account does not support specified authority type"
142 }
143 TokenError::MintCannotFreeze => "Error: This token mint cannot freeze accounts",
144 TokenError::AccountFrozen => "Error: Account is frozen",
145 TokenError::MintDecimalsMismatch => "Error: decimals different from the Mint decimals",
146 TokenError::NonNativeNotSupported => {
147 "Error: Instruction does not support non-native tokens"
148 }
149 }
150 }
151}
152
153#[cfg(test)]
154mod test {
155 use {super::*, strum::IntoEnumIterator};
156 #[test]
157 fn test_parse_error_from_primitive_exhaustive() {
158 for variant in TokenError::iter() {
159 let variant_u32 = variant as u32;
160 assert_eq!(
161 TokenError::from_repr(variant_u32 as usize).unwrap(),
162 TokenError::try_from(variant_u32).unwrap()
163 );
164 }
165 }
166}