spl_token_2022/
error.rs

1//! Error types
2
3#[cfg(not(target_os = "solana"))]
4use spl_token_confidential_transfer_proof_generation::errors::TokenProofGenerationError;
5use {
6    num_derive::FromPrimitive,
7    solana_program::{
8        decode_error::DecodeError,
9        msg,
10        program_error::{PrintProgramError, ProgramError},
11    },
12    spl_token_confidential_transfer_proof_extraction::errors::TokenProofExtractionError,
13    thiserror::Error,
14};
15
16/// Errors that may be returned by the Token program.
17#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
18pub enum TokenError {
19    // 0
20    /// Lamport balance below rent-exempt threshold.
21    #[error("Lamport balance below rent-exempt threshold")]
22    NotRentExempt,
23    /// Insufficient funds for the operation requested.
24    #[error("Insufficient funds")]
25    InsufficientFunds,
26    /// Invalid Mint.
27    #[error("Invalid Mint")]
28    InvalidMint,
29    /// Account not associated with this Mint.
30    #[error("Account not associated with this Mint")]
31    MintMismatch,
32    /// Owner does not match.
33    #[error("Owner does not match")]
34    OwnerMismatch,
35
36    // 5
37    /// This token's supply is fixed and new tokens cannot be minted.
38    #[error("Fixed supply")]
39    FixedSupply,
40    /// The account cannot be initialized because it is already being used.
41    #[error("Already in use")]
42    AlreadyInUse,
43    /// Invalid number of provided signers.
44    #[error("Invalid number of provided signers")]
45    InvalidNumberOfProvidedSigners,
46    /// Invalid number of required signers.
47    #[error("Invalid number of required signers")]
48    InvalidNumberOfRequiredSigners,
49    /// State is uninitialized.
50    #[error("State is uninitialized")]
51    UninitializedState,
52
53    // 10
54    /// Instruction does not support native tokens
55    #[error("Instruction does not support native tokens")]
56    NativeNotSupported,
57    /// Non-native account can only be closed if its balance is zero
58    #[error("Non-native account can only be closed if its balance is zero")]
59    NonNativeHasBalance,
60    /// Invalid instruction
61    #[error("Invalid instruction")]
62    InvalidInstruction,
63    /// State is invalid for requested operation.
64    #[error("State is invalid for requested operation")]
65    InvalidState,
66    /// Operation overflowed
67    #[error("Operation overflowed")]
68    Overflow,
69
70    // 15
71    /// Account does not support specified authority type.
72    #[error("Account does not support specified authority type")]
73    AuthorityTypeNotSupported,
74    /// This token mint cannot freeze accounts.
75    #[error("This token mint cannot freeze accounts")]
76    MintCannotFreeze,
77    /// Account is frozen; all account operations will fail
78    #[error("Account is frozen")]
79    AccountFrozen,
80    /// Mint decimals mismatch between the client and mint
81    #[error("The provided decimals value different from the Mint decimals")]
82    MintDecimalsMismatch,
83    /// Instruction does not support non-native tokens
84    #[error("Instruction does not support non-native tokens")]
85    NonNativeNotSupported,
86
87    // 20
88    /// Extension type does not match already existing extensions
89    #[error("Extension type does not match already existing extensions")]
90    ExtensionTypeMismatch,
91    /// Extension does not match the base type provided
92    #[error("Extension does not match the base type provided")]
93    ExtensionBaseMismatch,
94    /// Extension already initialized on this account
95    #[error("Extension already initialized on this account")]
96    ExtensionAlreadyInitialized,
97    /// An account can only be closed if its confidential balance is zero
98    #[error("An account can only be closed if its confidential balance is zero")]
99    ConfidentialTransferAccountHasBalance,
100    /// Account not approved for confidential transfers
101    #[error("Account not approved for confidential transfers")]
102    ConfidentialTransferAccountNotApproved,
103
104    // 25
105    /// Account not accepting deposits or transfers
106    #[error("Account not accepting deposits or transfers")]
107    ConfidentialTransferDepositsAndTransfersDisabled,
108    /// ElGamal public key mismatch
109    #[error("ElGamal public key mismatch")]
110    ConfidentialTransferElGamalPubkeyMismatch,
111    /// Balance mismatch
112    #[error("Balance mismatch")]
113    ConfidentialTransferBalanceMismatch,
114    /// Mint has non-zero supply. Burn all tokens before closing the mint.
115    #[error("Mint has non-zero supply. Burn all tokens before closing the mint")]
116    MintHasSupply,
117    /// No authority exists to perform the desired operation
118    #[error("No authority exists to perform the desired operation")]
119    NoAuthorityExists,
120
121    // 30
122    /// Transfer fee exceeds maximum of 10,000 basis points
123    #[error("Transfer fee exceeds maximum of 10,000 basis points")]
124    TransferFeeExceedsMaximum,
125    /// Mint required for this account to transfer tokens, use
126    /// `transfer_checked` or `transfer_checked_with_fee`
127    #[error("Mint required for this account to transfer tokens, use `transfer_checked` or `transfer_checked_with_fee`")]
128    MintRequiredForTransfer,
129    /// Calculated fee does not match expected fee
130    #[error("Calculated fee does not match expected fee")]
131    FeeMismatch,
132    /// Fee parameters associated with confidential transfer zero-knowledge
133    /// proofs do not match fee parameters in mint
134    #[error(
135        "Fee parameters associated with zero-knowledge proofs do not match fee parameters in mint"
136    )]
137    FeeParametersMismatch,
138    /// The owner authority cannot be changed
139    #[error("The owner authority cannot be changed")]
140    ImmutableOwner,
141
142    // 35
143    /// An account can only be closed if its withheld fee balance is zero,
144    /// harvest fees to the mint and try again
145    #[error("An account can only be closed if its withheld fee balance is zero, harvest fees to the mint and try again")]
146    AccountHasWithheldTransferFees,
147    /// No memo in previous instruction; required for recipient to receive a
148    /// transfer
149    #[error("No memo in previous instruction; required for recipient to receive a transfer")]
150    NoMemo,
151    /// Transfer is disabled for this mint
152    #[error("Transfer is disabled for this mint")]
153    NonTransferable,
154    /// Non-transferable tokens can't be minted to an account without immutable
155    /// ownership
156    #[error("Non-transferable tokens can't be minted to an account without immutable ownership")]
157    NonTransferableNeedsImmutableOwnership,
158    /// The total number of `Deposit` and `Transfer` instructions to an account
159    /// cannot exceed the associated
160    /// `maximum_pending_balance_credit_counter`
161    #[error(
162        "The total number of `Deposit` and `Transfer` instructions to an account cannot exceed
163            the associated `maximum_pending_balance_credit_counter`"
164    )]
165    MaximumPendingBalanceCreditCounterExceeded,
166
167    // 40
168    /// The deposit amount for the confidential extension exceeds the maximum
169    /// limit
170    #[error("Deposit amount exceeds maximum limit")]
171    MaximumDepositAmountExceeded,
172    /// CPI Guard cannot be enabled or disabled in CPI
173    #[error("CPI Guard cannot be enabled or disabled in CPI")]
174    CpiGuardSettingsLocked,
175    /// CPI Guard is enabled, and a program attempted to transfer user funds
176    /// without using a delegate
177    #[error("CPI Guard is enabled, and a program attempted to transfer user funds via CPI without using a delegate")]
178    CpiGuardTransferBlocked,
179    /// CPI Guard is enabled, and a program attempted to burn user funds without
180    /// using a delegate
181    #[error(
182        "CPI Guard is enabled, and a program attempted to burn user funds via CPI without using a delegate"
183    )]
184    CpiGuardBurnBlocked,
185    /// CPI Guard is enabled, and a program attempted to close an account
186    /// without returning lamports to owner
187    #[error("CPI Guard is enabled, and a program attempted to close an account via CPI without returning lamports to owner")]
188    CpiGuardCloseAccountBlocked,
189
190    // 45
191    /// CPI Guard is enabled, and a program attempted to approve a delegate
192    #[error("CPI Guard is enabled, and a program attempted to approve a delegate via CPI")]
193    CpiGuardApproveBlocked,
194    /// CPI Guard is enabled, and a program attempted to add or replace an
195    /// authority
196    #[error(
197        "CPI Guard is enabled, and a program attempted to add or replace an authority via CPI"
198    )]
199    CpiGuardSetAuthorityBlocked,
200    /// Account ownership cannot be changed while CPI Guard is enabled
201    #[error("Account ownership cannot be changed while CPI Guard is enabled")]
202    CpiGuardOwnerChangeBlocked,
203    /// Extension not found in account data
204    #[error("Extension not found in account data")]
205    ExtensionNotFound,
206    /// Account does not accept non-confidential transfers
207    #[error("Non-confidential transfers disabled")]
208    NonConfidentialTransfersDisabled,
209
210    // 50
211    /// An account can only be closed if the confidential withheld fee is zero
212    #[error("An account can only be closed if the confidential withheld fee is zero")]
213    ConfidentialTransferFeeAccountHasWithheldFee,
214    /// A mint or an account is initialized to an invalid combination of
215    /// extensions
216    #[error("A mint or an account is initialized to an invalid combination of extensions")]
217    InvalidExtensionCombination,
218    /// Extension allocation with overwrite must use the same length
219    #[error("Extension allocation with overwrite must use the same length")]
220    InvalidLengthForAlloc,
221    /// Failed to decrypt a confidential transfer account
222    #[error("Failed to decrypt a confidential transfer account")]
223    AccountDecryption,
224    /// Failed to generate a zero-knowledge proof needed for a token instruction
225    #[error("Failed to generate proof")]
226    ProofGeneration,
227
228    // 55
229    /// An invalid proof instruction offset was provided
230    #[error("An invalid proof instruction offset was provided")]
231    InvalidProofInstructionOffset,
232    /// Harvest of withheld tokens to mint is disabled
233    #[error("Harvest of withheld tokens to mint is disabled")]
234    HarvestToMintDisabled,
235    /// Split proof context state accounts not supported for instruction
236    #[error("Split proof context state accounts not supported for instruction")]
237    SplitProofContextStateAccountsNotSupported,
238    /// Not enough proof context state accounts provided
239    #[error("Not enough proof context state accounts provided")]
240    NotEnoughProofContextStateAccounts,
241    /// Ciphertext is malformed
242    #[error("Ciphertext is malformed")]
243    MalformedCiphertext,
244
245    // 60
246    /// Ciphertext arithmetic failed
247    #[error("Ciphertext arithmetic failed")]
248    CiphertextArithmeticFailed,
249    /// Pedersen commitments did not match
250    #[error("Pedersen commitment mismatch")]
251    PedersenCommitmentMismatch,
252    /// Range proof length did not match
253    #[error("Range proof length mismatch")]
254    RangeProofLengthMismatch,
255    /// Illegal transfer amount bit length
256    #[error("Illegal transfer amount bit length")]
257    IllegalBitLength,
258    /// Fee calculation failed
259    #[error("Fee calculation failed")]
260    FeeCalculation,
261
262    //65
263    /// Withdraw / Deposit not allowed for confidential-mint-burn
264    #[error("Withdraw / Deposit not allowed for confidential-mint-burn")]
265    IllegalMintBurnConversion,
266    /// Invalid scale for scaled ui amount
267    #[error("Invalid scale for scaled ui amount")]
268    InvalidScale,
269    /// Transferring, minting, and burning is paused on this mint
270    #[error("Transferring, minting, and burning is paused on this mint")]
271    MintPaused,
272}
273impl From<TokenError> for ProgramError {
274    fn from(e: TokenError) -> Self {
275        ProgramError::Custom(e as u32)
276    }
277}
278impl<T> DecodeError<T> for TokenError {
279    fn type_of() -> &'static str {
280        "TokenError"
281    }
282}
283
284impl PrintProgramError for TokenError {
285    fn print<E>(&self)
286    where
287        E: 'static + std::error::Error + DecodeError<E> + num_traits::FromPrimitive,
288    {
289        match self {
290            TokenError::NotRentExempt => msg!("Error: Lamport balance below rent-exempt threshold"),
291            TokenError::InsufficientFunds => msg!("Error: insufficient funds"),
292            TokenError::InvalidMint => msg!("Error: Invalid Mint"),
293            TokenError::MintMismatch => msg!("Error: Account not associated with this Mint"),
294            TokenError::OwnerMismatch => msg!("Error: owner does not match"),
295            TokenError::FixedSupply => msg!("Error: the total supply of this token is fixed"),
296            TokenError::AlreadyInUse => msg!("Error: account or token already in use"),
297            TokenError::InvalidNumberOfProvidedSigners => {
298                msg!("Error: Invalid number of provided signers")
299            }
300            TokenError::InvalidNumberOfRequiredSigners => {
301                msg!("Error: Invalid number of required signers")
302            }
303            TokenError::UninitializedState => msg!("Error: State is uninitialized"),
304            TokenError::NativeNotSupported => {
305                msg!("Error: Instruction does not support native tokens")
306            }
307            TokenError::NonNativeHasBalance => {
308                msg!("Error: Non-native account can only be closed if its balance is zero")
309            }
310            TokenError::InvalidInstruction => msg!("Error: Invalid instruction"),
311            TokenError::InvalidState => msg!("Error: Invalid account state for operation"),
312            TokenError::Overflow => msg!("Error: Operation overflowed"),
313            TokenError::AuthorityTypeNotSupported => {
314                msg!("Error: Account does not support specified authority type")
315            }
316            TokenError::MintCannotFreeze => msg!("Error: This token mint cannot freeze accounts"),
317            TokenError::AccountFrozen => msg!("Error: Account is frozen"),
318            TokenError::MintDecimalsMismatch => {
319                msg!("Error: decimals different from the Mint decimals")
320            }
321            TokenError::NonNativeNotSupported => {
322                msg!("Error: Instruction does not support non-native tokens")
323            }
324            TokenError::ExtensionTypeMismatch => {
325                msg!("Error: New extension type does not match already existing extensions")
326            }
327            TokenError::ExtensionBaseMismatch => {
328                msg!("Error: Extension does not match the base type provided")
329            }
330            TokenError::ExtensionAlreadyInitialized => {
331                msg!("Error: Extension already initialized on this account")
332            }
333            TokenError::ConfidentialTransferAccountHasBalance => {
334                msg!("Error: An account can only be closed if its confidential balance is zero")
335            }
336            TokenError::ConfidentialTransferAccountNotApproved => {
337                msg!("Error: Account not approved for confidential transfers")
338            }
339            TokenError::ConfidentialTransferDepositsAndTransfersDisabled => {
340                msg!("Error: Account not accepting deposits or transfers")
341            }
342            TokenError::ConfidentialTransferElGamalPubkeyMismatch => {
343                msg!("Error: ElGamal public key mismatch")
344            }
345            TokenError::ConfidentialTransferBalanceMismatch => {
346                msg!("Error: Balance mismatch")
347            }
348            TokenError::MintHasSupply => {
349                msg!("Error: Mint has non-zero supply. Burn all tokens before closing the mint")
350            }
351            TokenError::NoAuthorityExists => {
352                msg!("Error: No authority exists to perform the desired operation");
353            }
354            TokenError::TransferFeeExceedsMaximum => {
355                msg!("Error: Transfer fee exceeds maximum of 10,000 basis points");
356            }
357            TokenError::MintRequiredForTransfer => {
358                msg!("Mint required for this account to transfer tokens, use `transfer_checked` or `transfer_checked_with_fee`");
359            }
360            TokenError::FeeMismatch => {
361                msg!("Calculated fee does not match expected fee");
362            }
363            TokenError::FeeParametersMismatch => {
364                msg!("Fee parameters associated with zero-knowledge proofs do not match fee parameters in mint")
365            }
366            TokenError::ImmutableOwner => {
367                msg!("The owner authority cannot be changed");
368            }
369            TokenError::AccountHasWithheldTransferFees => {
370                msg!("Error: An account can only be closed if its withheld fee balance is zero, harvest fees to the mint and try again");
371            }
372            TokenError::NoMemo => {
373                msg!("Error: No memo in previous instruction; required for recipient to receive a transfer");
374            }
375            TokenError::NonTransferable => {
376                msg!("Transfer is disabled for this mint");
377            }
378            TokenError::NonTransferableNeedsImmutableOwnership => {
379                msg!("Non-transferable tokens can't be minted to an account without immutable ownership");
380            }
381            TokenError::MaximumPendingBalanceCreditCounterExceeded => {
382                msg!("The total number of `Deposit` and `Transfer` instructions to an account cannot exceed the associated `maximum_pending_balance_credit_counter`");
383            }
384            TokenError::MaximumDepositAmountExceeded => {
385                msg!("Deposit amount exceeds maximum limit")
386            }
387            TokenError::CpiGuardSettingsLocked => {
388                msg!("CPI Guard status cannot be changed in CPI")
389            }
390            TokenError::CpiGuardTransferBlocked => {
391                msg!("CPI Guard is enabled, and a program attempted to transfer user funds without using a delegate")
392            }
393            TokenError::CpiGuardBurnBlocked => {
394                msg!("CPI Guard is enabled, and a program attempted to burn user funds without using a delegate")
395            }
396            TokenError::CpiGuardCloseAccountBlocked => {
397                msg!("CPI Guard is enabled, and a program attempted to close an account without returning lamports to owner")
398            }
399            TokenError::CpiGuardApproveBlocked => {
400                msg!("CPI Guard is enabled, and a program attempted to approve a delegate")
401            }
402            TokenError::CpiGuardSetAuthorityBlocked => {
403                msg!("CPI Guard is enabled, and a program attempted to add or change an authority")
404            }
405            TokenError::CpiGuardOwnerChangeBlocked => {
406                msg!("Account ownership cannot be changed while CPI Guard is enabled")
407            }
408            TokenError::ExtensionNotFound => {
409                msg!("Extension not found in account data")
410            }
411            TokenError::NonConfidentialTransfersDisabled => {
412                msg!("Non-confidential transfers disabled")
413            }
414            TokenError::ConfidentialTransferFeeAccountHasWithheldFee => {
415                msg!("Account has non-zero confidential withheld fee")
416            }
417            TokenError::InvalidExtensionCombination => {
418                msg!("Mint or account is initialized to an invalid combination of extensions")
419            }
420            TokenError::InvalidLengthForAlloc => {
421                msg!("Extension allocation with overwrite must use the same length")
422            }
423            TokenError::AccountDecryption => {
424                msg!("Failed to decrypt a confidential transfer account")
425            }
426            TokenError::ProofGeneration => {
427                msg!("Failed to generate proof")
428            }
429            TokenError::InvalidProofInstructionOffset => {
430                msg!("An invalid proof instruction offset was provided")
431            }
432            TokenError::HarvestToMintDisabled => {
433                msg!("Harvest of withheld tokens to mint is disabled")
434            }
435            TokenError::SplitProofContextStateAccountsNotSupported => {
436                msg!("Split proof context state accounts not supported for instruction")
437            }
438            TokenError::NotEnoughProofContextStateAccounts => {
439                msg!("Not enough proof context state accounts provided")
440            }
441            TokenError::MalformedCiphertext => {
442                msg!("Ciphertext is malformed")
443            }
444            TokenError::CiphertextArithmeticFailed => {
445                msg!("Ciphertext arithmetic failed")
446            }
447            TokenError::PedersenCommitmentMismatch => {
448                msg!("Pedersen commitments did not match")
449            }
450            TokenError::RangeProofLengthMismatch => {
451                msg!("Range proof lengths did not match")
452            }
453            TokenError::IllegalBitLength => {
454                msg!("Illegal transfer amount bit length")
455            }
456            TokenError::FeeCalculation => {
457                msg!("Transfer fee calculation failed")
458            }
459            TokenError::IllegalMintBurnConversion => {
460                msg!("Conversions from normal to confidential token balance and vice versa are illegal if the confidential-mint-burn extension is enabled")
461            }
462            TokenError::InvalidScale => {
463                msg!("Invalid scale for scaled ui amount")
464            }
465            TokenError::MintPaused => {
466                msg!("Transferring, minting, and burning is paused on this mint")
467            }
468        }
469    }
470}
471
472#[cfg(not(target_os = "solana"))]
473impl From<TokenProofGenerationError> for TokenError {
474    fn from(e: TokenProofGenerationError) -> Self {
475        match e {
476            TokenProofGenerationError::ProofGeneration(_) => TokenError::ProofGeneration,
477            TokenProofGenerationError::NotEnoughFunds => TokenError::InsufficientFunds,
478            TokenProofGenerationError::IllegalAmountBitLength => TokenError::IllegalBitLength,
479            TokenProofGenerationError::FeeCalculation => TokenError::FeeCalculation,
480            TokenProofGenerationError::CiphertextExtraction => TokenError::MalformedCiphertext,
481        }
482    }
483}
484
485impl From<TokenProofExtractionError> for TokenError {
486    fn from(e: TokenProofExtractionError) -> Self {
487        match e {
488            TokenProofExtractionError::ElGamalPubkeyMismatch => {
489                TokenError::ConfidentialTransferElGamalPubkeyMismatch
490            }
491            TokenProofExtractionError::PedersenCommitmentMismatch => {
492                TokenError::PedersenCommitmentMismatch
493            }
494            TokenProofExtractionError::RangeProofLengthMismatch => {
495                TokenError::RangeProofLengthMismatch
496            }
497            TokenProofExtractionError::FeeParametersMismatch => TokenError::FeeParametersMismatch,
498            TokenProofExtractionError::CurveArithmetic => TokenError::CiphertextArithmeticFailed,
499            TokenProofExtractionError::CiphertextExtraction => TokenError::MalformedCiphertext,
500        }
501    }
502}