light_token_interface/
error.rs

1use light_zero_copy::errors::ZeroCopyError;
2use thiserror::Error;
3
4#[derive(Debug, PartialEq, Error)]
5pub enum TokenError {
6    #[error("Invalid instruction data provided")]
7    InvalidInstructionData,
8
9    #[error("Invalid account data format")]
10    InvalidAccountData,
11
12    #[error("Arithmetic operation resulted in overflow")]
13    ArithmeticOverflow,
14
15    #[error("Failed to compute hash for data")]
16    HashComputationError,
17
18    #[error("Invalid or malformed extension data")]
19    InvalidExtensionData,
20
21    #[error("Missing required mint authority")]
22    MissingMintAuthority,
23
24    #[error("Missing required freeze authority")]
25    MissingFreezeAuthority,
26
27    #[error("Invalid metadata pointer configuration")]
28    InvalidMetadataPointer,
29
30    #[error("Token metadata validation failed")]
31    InvalidTokenMetadata,
32
33    #[error("Insufficient token supply for operation")]
34    InsufficientSupply,
35
36    #[error("Token account is frozen and cannot be modified")]
37    AccountFrozen,
38
39    #[error("Invalid compressed proof provided")]
40    InvalidProof,
41
42    #[error("Address derivation failed")]
43    AddressDerivationFailed,
44
45    #[error("Extension type not supported")]
46    UnsupportedExtension,
47
48    #[error("Maximum number of extensions exceeded")]
49    TooManyExtensions,
50
51    #[error("Invalid merkle tree root index")]
52    InvalidRootIndex,
53
54    #[error("Compressed account data size exceeds limit")]
55    DataSizeExceeded,
56
57    #[error("Invalid compression mode")]
58    InvalidCompressionMode,
59
60    #[error("Insufficient funds for compression.")]
61    CompressInsufficientFunds,
62
63    #[error("Failed to access sysvar")]
64    SysvarAccessError,
65
66    #[error("Compressed token account TLV is unimplemented.")]
67    CompressedTokenAccountTlvUnimplemented,
68
69    #[error("Input accounts lamports length mismatch")]
70    InputAccountsLamportsLengthMismatch,
71
72    #[error("Output accounts lamports length mismatch")]
73    OutputAccountsLamportsLengthMismatch,
74
75    #[error("Invalid token data version")]
76    InvalidTokenDataVersion,
77
78    #[error("Instruction data expected mint authority")]
79    InstructionDataExpectedMintAuthority,
80
81    #[error("Zero-copy expected mint authority")]
82    ZeroCopyExpectedMintAuthority,
83
84    #[error("Instruction data expected freeze authority")]
85    InstructionDataExpectedFreezeAuthority,
86
87    #[error("Zero-copy expected mint authority")]
88    ZeroCopyExpectedFreezeAuthority,
89
90    #[error("Invalid authority type provided")]
91    InvalidAuthorityType,
92
93    #[error("Expected mint signer account")]
94    ExpectedMintSignerAccount,
95
96    #[error("Light hasher error: {0}")]
97    HasherError(#[from] light_hasher::HasherError),
98
99    #[error("Light zero copy error: {0}")]
100    ZeroCopyError(#[from] ZeroCopyError),
101
102    #[error("Light compressed account error: {0}")]
103    CompressedAccountError(#[from] light_compressed_account::CompressedAccountError),
104
105    #[error("Invalid token metadata version")]
106    InvalidTokenMetadataVersion,
107    #[error("InvalidExtensionConfig")]
108    InvalidExtensionConfig,
109    #[error("InstructionDataExpectedDelegate")]
110    InstructionDataExpectedDelegate,
111    #[error("ZeroCopyExpectedDelegate")]
112    ZeroCopyExpectedDelegate,
113    #[error("Unsupported TLV extension type - only CompressedOnly is currently implemented")]
114    UnsupportedTlvExtensionType,
115    #[error("InvalidAccountState")]
116    InvalidAccountState,
117    #[error("BorshFailed")]
118    BorshFailed,
119    #[error(
120        "Too many input compressed accounts. Maximum 8 input accounts allowed per instruction"
121    )]
122    TooManyInputAccounts,
123
124    #[error("Too many additional metadata elements. Maximum 20 allowed")]
125    TooManyAdditionalMetadata,
126
127    #[error("Duplicate metadata key found in additional metadata")]
128    DuplicateMetadataKey,
129
130    #[error("Too many PDA seeds. Maximum {0} seeds allowed")]
131    TooManySeeds(usize),
132
133    #[error("write_top_up exceeds max_top_up from RentConfig")]
134    WriteTopUpExceedsMaximum,
135
136    #[error("Calculated top-up exceeds sender's max_top_up limit")]
137    MaxTopUpExceeded,
138
139    #[error("Mint account has invalid owner")]
140    InvalidMintOwner,
141
142    #[error("Mint account is not initialized")]
143    MintNotInitialized,
144
145    #[error("Failed to borrow Mint account data")]
146    MintBorrowFailed,
147
148    #[error("Failed to deserialize Mint account data")]
149    MintDeserializationFailed,
150
151    #[error("CompressedOnly tokens cannot have compressed outputs - must decompress only")]
152    CompressedOnlyBlocksTransfer,
153
154    #[error("Output TLV data count must match number of compressed outputs")]
155    OutTlvOutputCountMismatch,
156
157    #[error("in_lamports field is not yet implemented")]
158    InLamportsUnimplemented,
159
160    #[error("out_lamports field is not yet implemented")]
161    OutLamportsUnimplemented,
162
163    #[error("TLV extension length mismatch - exactly one extension required")]
164    TlvExtensionLengthMismatch,
165
166    #[error("InvalidAccountType")]
167    InvalidAccountType,
168
169    #[error("Duplicate compression_index found in input TLV data")]
170    DuplicateCompressionIndex,
171
172    #[error("Decompress destination Token is not a fresh account")]
173    DecompressDestinationNotFresh,
174
175    #[error("Token account missing required Compressible extension")]
176    MissingCompressibleExtension,
177
178    #[error("Decompress destination doesn't match source account")]
179    DecompressDestinationMismatch,
180
181    #[error("Token account mint does not match expected mint")]
182    MintMismatch,
183
184    #[error("Decompress has delegated_amount but no delegate pubkey provided")]
185    DecompressDelegatedAmountWithoutDelegate,
186
187    #[error(
188        "Decompress has withheld_transfer_fee but destination lacks TransferFeeAccount extension"
189    )]
190    DecompressWithheldFeeWithoutExtension,
191
192    #[error("Missing required payer account")]
193    MissingPayer,
194
195    #[error("Failed to borrow account data")]
196    BorrowFailed,
197
198    #[error("Token account has invalid owner")]
199    InvalidTokenOwner,
200
201    #[error("Decompress amount mismatch between compression instruction and input token data")]
202    DecompressAmountMismatch,
203
204    #[error("Compression index exceeds maximum allowed value")]
205    CompressionIndexOutOfBounds,
206
207    #[error("ATA derivation failed or mismatched for is_ata compressed token")]
208    InvalidAtaDerivation,
209}
210
211impl From<TokenError> for u32 {
212    fn from(e: TokenError) -> u32 {
213        match e {
214            TokenError::InvalidInstructionData => 18001,
215            TokenError::InvalidAccountData => 18002,
216            TokenError::ArithmeticOverflow => 18003,
217            TokenError::HashComputationError => 18004,
218            TokenError::InvalidExtensionData => 18005,
219            TokenError::MissingMintAuthority => 18006,
220            TokenError::MissingFreezeAuthority => 18007,
221            TokenError::InvalidMetadataPointer => 18008,
222            TokenError::InvalidTokenMetadata => 18009,
223            TokenError::InsufficientSupply => 18010,
224            TokenError::AccountFrozen => 18011,
225            TokenError::InvalidProof => 18012,
226            TokenError::AddressDerivationFailed => 18013,
227            TokenError::UnsupportedExtension => 18014,
228            TokenError::TooManyExtensions => 18015,
229            TokenError::InvalidRootIndex => 18016,
230            TokenError::DataSizeExceeded => 18017,
231            TokenError::InvalidCompressionMode => 18018,
232            TokenError::CompressInsufficientFunds => 18019,
233            TokenError::SysvarAccessError => 18020,
234            TokenError::CompressedTokenAccountTlvUnimplemented => 18021,
235            TokenError::InputAccountsLamportsLengthMismatch => 18022,
236            TokenError::OutputAccountsLamportsLengthMismatch => 18023,
237            TokenError::InvalidTokenDataVersion => 18028,
238            TokenError::InstructionDataExpectedMintAuthority => 18024,
239            TokenError::ZeroCopyExpectedMintAuthority => 18025,
240            TokenError::InstructionDataExpectedFreezeAuthority => 18026,
241            TokenError::ZeroCopyExpectedFreezeAuthority => 18027,
242            TokenError::InvalidAuthorityType => 18029,
243            TokenError::ExpectedMintSignerAccount => 18030,
244            TokenError::InvalidTokenMetadataVersion => 18031,
245            TokenError::InvalidExtensionConfig => 18032,
246            TokenError::InstructionDataExpectedDelegate => 18033,
247            TokenError::ZeroCopyExpectedDelegate => 18034,
248            TokenError::UnsupportedTlvExtensionType => 18035,
249            TokenError::InvalidAccountState => 18036,
250            TokenError::BorshFailed => 18037,
251            TokenError::TooManyInputAccounts => 18038,
252            TokenError::TooManyAdditionalMetadata => 18039,
253            TokenError::DuplicateMetadataKey => 18040,
254            TokenError::TooManySeeds(_) => 18041,
255            TokenError::WriteTopUpExceedsMaximum => 18042,
256            TokenError::MaxTopUpExceeded => 18043,
257            TokenError::InvalidMintOwner => 18044,
258            TokenError::MintNotInitialized => 18045,
259            TokenError::MintBorrowFailed => 18046,
260            TokenError::MintDeserializationFailed => 18047,
261            TokenError::CompressedOnlyBlocksTransfer => 18048,
262            TokenError::OutTlvOutputCountMismatch => 18049,
263            TokenError::InLamportsUnimplemented => 18050,
264            TokenError::OutLamportsUnimplemented => 18051,
265            TokenError::TlvExtensionLengthMismatch => 18052,
266            TokenError::InvalidAccountType => 18053,
267            TokenError::DuplicateCompressionIndex => 18054,
268            TokenError::DecompressDestinationNotFresh => 18055,
269            TokenError::MissingCompressibleExtension => 18056,
270            TokenError::DecompressDestinationMismatch => 18057,
271            TokenError::MintMismatch => 18058,
272            TokenError::DecompressDelegatedAmountWithoutDelegate => 18059,
273            TokenError::DecompressWithheldFeeWithoutExtension => 18060,
274            TokenError::MissingPayer => 18061,
275            TokenError::BorrowFailed => 18062,
276            TokenError::InvalidTokenOwner => 18063,
277            TokenError::DecompressAmountMismatch => 18064,
278            TokenError::CompressionIndexOutOfBounds => 18065,
279            TokenError::InvalidAtaDerivation => 18066,
280            TokenError::HasherError(e) => u32::from(e),
281            TokenError::ZeroCopyError(e) => u32::from(e),
282            TokenError::CompressedAccountError(e) => u32::from(e),
283        }
284    }
285}
286
287#[cfg(all(feature = "solana", not(feature = "anchor")))]
288impl From<TokenError> for solana_program_error::ProgramError {
289    fn from(e: TokenError) -> Self {
290        solana_program_error::ProgramError::Custom(e.into())
291    }
292}
293
294impl From<TokenError> for pinocchio::program_error::ProgramError {
295    fn from(e: TokenError) -> Self {
296        pinocchio::program_error::ProgramError::Custom(e.into())
297    }
298}
299
300#[cfg(feature = "anchor")]
301impl From<TokenError> for anchor_lang::prelude::ProgramError {
302    fn from(e: TokenError) -> Self {
303        anchor_lang::prelude::ProgramError::Custom(e.into())
304    }
305}