spl_token_interface/
error.rs

1//! Error types
2
3use {
4    num_derive::FromPrimitive,
5    solana_program_error::{ProgramError, ToStr},
6    thiserror::Error,
7};
8
9/// Errors that may be returned by the Token program.
10#[cfg_attr(test, derive(strum_macros::FromRepr, strum_macros::EnumIter))]
11#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
12pub enum TokenError {
13    // 0
14    /// Lamport balance below rent-exempt threshold.
15    #[error("Lamport balance below rent-exempt threshold")]
16    NotRentExempt,
17    /// Insufficient funds for the operation requested.
18    #[error("Insufficient funds")]
19    InsufficientFunds,
20    /// Invalid Mint.
21    #[error("Invalid Mint")]
22    InvalidMint,
23    /// Account not associated with this Mint.
24    #[error("Account not associated with this Mint")]
25    MintMismatch,
26    /// Owner does not match.
27    #[error("Owner does not match")]
28    OwnerMismatch,
29
30    // 5
31    /// This token's supply is fixed and new tokens cannot be minted.
32    #[error("Fixed supply")]
33    FixedSupply,
34    /// The account cannot be initialized because it is already being used.
35    #[error("Already in use")]
36    AlreadyInUse,
37    /// Invalid number of provided signers.
38    #[error("Invalid number of provided signers")]
39    InvalidNumberOfProvidedSigners,
40    /// Invalid number of required signers.
41    #[error("Invalid number of required signers")]
42    InvalidNumberOfRequiredSigners,
43    /// State is uninitialized.
44    #[error("State is uninitialized")]
45    UninitializedState,
46
47    // 10
48    /// Instruction does not support native tokens
49    #[error("Instruction does not support native tokens")]
50    NativeNotSupported,
51    /// Non-native account can only be closed if its balance is zero
52    #[error("Non-native account can only be closed if its balance is zero")]
53    NonNativeHasBalance,
54    /// Invalid instruction
55    #[error("Invalid instruction")]
56    InvalidInstruction,
57    /// State is invalid for requested operation.
58    #[error("State is invalid for requested operation")]
59    InvalidState,
60    /// Operation overflowed
61    #[error("Operation overflowed")]
62    Overflow,
63
64    // 15
65    /// Account does not support specified authority type.
66    #[error("Account does not support specified authority type")]
67    AuthorityTypeNotSupported,
68    /// This token mint cannot freeze accounts.
69    #[error("This token mint cannot freeze accounts")]
70    MintCannotFreeze,
71    /// Account is frozen; all account operations will fail
72    #[error("Account is frozen")]
73    AccountFrozen,
74    /// Mint decimals mismatch between the client and mint
75    #[error("The provided decimals value different from the Mint decimals")]
76    MintDecimalsMismatch,
77    /// Instruction does not support non-native tokens
78    #[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}