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