1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
4#[cfg(feature = "num-traits")]
5use num_traits::ToPrimitive;
6#[cfg(feature = "frozen-abi")]
7extern crate std;
8use {core::fmt, solana_program_error::ProgramError};
9pub use {
10 instruction_error_module::*,
11 solana_program_error::{
12 ACCOUNT_ALREADY_INITIALIZED, ACCOUNT_BORROW_FAILED, ACCOUNT_DATA_TOO_SMALL,
13 ACCOUNT_NOT_RENT_EXEMPT, ARITHMETIC_OVERFLOW, BORSH_IO_ERROR,
14 BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS, CUSTOM_ZERO, ILLEGAL_OWNER, IMMUTABLE,
15 INCORRECT_AUTHORITY, INCORRECT_PROGRAM_ID, INSUFFICIENT_FUNDS, INVALID_ACCOUNT_DATA,
16 INVALID_ACCOUNT_DATA_REALLOC, INVALID_ACCOUNT_OWNER, INVALID_ARGUMENT,
17 INVALID_INSTRUCTION_DATA, INVALID_SEEDS, MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED,
18 MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED, MAX_SEED_LENGTH_EXCEEDED,
19 MISSING_REQUIRED_SIGNATURES, NOT_ENOUGH_ACCOUNT_KEYS, UNINITIALIZED_ACCOUNT,
20 UNSUPPORTED_SYSVAR,
21 },
22};
23
24#[allow(deprecated)]
25mod instruction_error_module {
26 #[cfg(feature = "frozen-abi")]
27 use solana_frozen_abi_macro::{
28 frozen_abi, AbiEnumVisitor, AbiExample, StableAbi, StableAbiSample,
29 };
30
31 #[cfg_attr(
39 feature = "frozen-abi",
40 derive(AbiExample, AbiEnumVisitor, StableAbi, StableAbiSample),
41 frozen_abi(
42 abi_digest = "99sLbFrZmSAM4i28P5vPDJFtB6xDgvyT92iEJpKiMPpF",
43 abi_serializer = ["bincode", "wincode"],
44 test_roundtrip = "eq_and_wire"
45 )
46 )]
47 #[cfg_attr(
48 feature = "serde",
49 derive(serde_derive::Serialize, serde_derive::Deserialize)
50 )]
51 #[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
52 #[derive(Debug, PartialEq, Eq, Clone)]
53 pub enum InstructionError {
54 GenericError,
57
58 InvalidArgument,
60
61 InvalidInstructionData,
63
64 InvalidAccountData,
66
67 AccountDataTooSmall,
69
70 InsufficientFunds,
72
73 IncorrectProgramId,
75
76 MissingRequiredSignature,
78
79 AccountAlreadyInitialized,
81
82 UninitializedAccount,
84
85 UnbalancedInstruction,
87
88 ModifiedProgramId,
90
91 ExternalAccountLamportSpend,
93
94 ExternalAccountDataModified,
96
97 ReadonlyLamportChange,
99
100 ReadonlyDataModified,
102
103 DuplicateAccountIndex,
106
107 ExecutableModified,
109
110 RentEpochModified,
112
113 #[deprecated(since = "2.1.0", note = "Use InstructionError::MissingAccount instead")]
115 NotEnoughAccountKeys,
116
117 AccountDataSizeChanged,
119
120 AccountNotExecutable,
122
123 AccountBorrowFailed,
125
126 AccountBorrowOutstanding,
128
129 DuplicateAccountOutOfSync,
133
134 Custom(u32),
138
139 InvalidError,
142
143 ExecutableDataModified,
145
146 ExecutableLamportChange,
148
149 ExecutableAccountNotRentExempt,
151
152 UnsupportedProgramId,
154
155 CallDepth,
157
158 MissingAccount,
160
161 ReentrancyNotAllowed,
163
164 MaxSeedLengthExceeded,
166
167 InvalidSeeds,
169
170 InvalidRealloc,
172
173 ComputationalBudgetExceeded,
175
176 PrivilegeEscalation,
178
179 ProgramEnvironmentSetupFailure,
181
182 ProgramFailedToComplete,
184
185 ProgramFailedToCompile,
187
188 Immutable,
190
191 IncorrectAuthority,
193
194 BorshIoError,
196
197 AccountNotRentExempt,
199
200 InvalidAccountOwner,
202
203 ArithmeticOverflow,
205
206 UnsupportedSysvar,
208
209 IllegalOwner,
211
212 MaxAccountsDataAllocationsExceeded,
214
215 MaxAccountsExceeded,
217
218 MaxInstructionTraceLengthExceeded,
220
221 BuiltinProgramsMustConsumeComputeUnits,
223 }
226}
227
228impl core::error::Error for InstructionError {}
229
230impl fmt::Display for InstructionError {
231 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232 match self {
233 InstructionError::GenericError => f.write_str("generic instruction error"),
234 InstructionError::InvalidArgument => f.write_str("invalid program argument"),
235 InstructionError::InvalidInstructionData => f.write_str("invalid instruction data"),
236 InstructionError::InvalidAccountData => {
237 f.write_str("invalid account data for instruction")
238 }
239 InstructionError::AccountDataTooSmall => {
240 f.write_str("account data too small for instruction")
241 }
242 InstructionError::InsufficientFunds => {
243 f.write_str("insufficient funds for instruction")
244 }
245 InstructionError::IncorrectProgramId => {
246 f.write_str("incorrect program id for instruction")
247 }
248 InstructionError::MissingRequiredSignature => {
249 f.write_str("missing required signature for instruction")
250 }
251 InstructionError::AccountAlreadyInitialized => {
252 f.write_str("instruction requires an uninitialized account")
253 }
254 InstructionError::UninitializedAccount => {
255 f.write_str("instruction requires an initialized account")
256 }
257 InstructionError::UnbalancedInstruction => {
258 f.write_str("sum of account balances before and after instruction do not match")
259 }
260 InstructionError::ModifiedProgramId => {
261 f.write_str("instruction illegally modified the program id of an account")
262 }
263 InstructionError::ExternalAccountLamportSpend => {
264 f.write_str("instruction spent from the balance of an account it does not own")
265 }
266 InstructionError::ExternalAccountDataModified => {
267 f.write_str("instruction modified data of an account it does not own")
268 }
269 InstructionError::ReadonlyLamportChange => {
270 f.write_str("instruction changed the balance of a read-only account")
271 }
272 InstructionError::ReadonlyDataModified => {
273 f.write_str("instruction modified data of a read-only account")
274 }
275 InstructionError::DuplicateAccountIndex => {
276 f.write_str("instruction contains duplicate accounts")
277 }
278 InstructionError::ExecutableModified => {
279 f.write_str("instruction changed executable bit of an account")
280 }
281 InstructionError::RentEpochModified => {
282 f.write_str("instruction modified rent epoch of an account")
283 }
284 #[allow(deprecated)]
285 InstructionError::NotEnoughAccountKeys => {
286 f.write_str("insufficient account keys for instruction")
287 }
288 InstructionError::AccountDataSizeChanged => f.write_str(
289 "program other than the account's owner changed the size of the account data",
290 ),
291 InstructionError::AccountNotExecutable => {
292 f.write_str("instruction expected an executable account")
293 }
294 InstructionError::AccountBorrowFailed => f.write_str(
295 "instruction tries to borrow reference for an account which is already borrowed",
296 ),
297 InstructionError::AccountBorrowOutstanding => {
298 f.write_str("instruction left account with an outstanding borrowed reference")
299 }
300 InstructionError::DuplicateAccountOutOfSync => {
301 f.write_str("instruction modifications of multiply-passed account differ")
302 }
303 InstructionError::Custom(num) => {
304 write!(f, "custom program error: {num:#x}")
305 }
306 InstructionError::InvalidError => f.write_str("program returned invalid error code"),
307 InstructionError::ExecutableDataModified => {
308 f.write_str("instruction changed executable accounts data")
309 }
310 InstructionError::ExecutableLamportChange => {
311 f.write_str("instruction changed the balance of an executable account")
312 }
313 InstructionError::ExecutableAccountNotRentExempt => {
314 f.write_str("executable accounts must be rent exempt")
315 }
316 InstructionError::UnsupportedProgramId => f.write_str("Unsupported program id"),
317 InstructionError::CallDepth => {
318 f.write_str("Cross-program invocation call depth too deep")
319 }
320 InstructionError::MissingAccount => {
321 f.write_str("An account required by the instruction is missing")
322 }
323 InstructionError::ReentrancyNotAllowed => {
324 f.write_str("Cross-program invocation reentrancy not allowed for this instruction")
325 }
326 InstructionError::MaxSeedLengthExceeded => {
327 f.write_str("Length of the seed is too long for address generation")
328 }
329 InstructionError::InvalidSeeds => {
330 f.write_str("Provided seeds do not result in a valid address")
331 }
332 InstructionError::InvalidRealloc => f.write_str("Failed to reallocate account data"),
333 InstructionError::ComputationalBudgetExceeded => {
334 f.write_str("Computational budget exceeded")
335 }
336 InstructionError::PrivilegeEscalation => {
337 f.write_str("Cross-program invocation with unauthorized signer or writable account")
338 }
339 InstructionError::ProgramEnvironmentSetupFailure => {
340 f.write_str("Failed to create program execution environment")
341 }
342 InstructionError::ProgramFailedToComplete => f.write_str("Program failed to complete"),
343 InstructionError::ProgramFailedToCompile => f.write_str("Program failed to compile"),
344 InstructionError::Immutable => f.write_str("Account is immutable"),
345 InstructionError::IncorrectAuthority => f.write_str("Incorrect authority provided"),
346 InstructionError::BorshIoError => {
347 f.write_str("Failed to serialize or deserialize account data")
348 }
349 InstructionError::AccountNotRentExempt => {
350 f.write_str("An account does not have enough lamports to be rent-exempt")
351 }
352 InstructionError::InvalidAccountOwner => f.write_str("Invalid account owner"),
353 InstructionError::ArithmeticOverflow => f.write_str("Program arithmetic overflowed"),
354 InstructionError::UnsupportedSysvar => f.write_str("Unsupported sysvar"),
355 InstructionError::IllegalOwner => f.write_str("Provided owner is not allowed"),
356 InstructionError::MaxAccountsDataAllocationsExceeded => f.write_str(
357 "Accounts data allocations exceeded the maximum allowed per transaction",
358 ),
359 InstructionError::MaxAccountsExceeded => f.write_str("Max accounts exceeded"),
360 InstructionError::MaxInstructionTraceLengthExceeded => {
361 f.write_str("Max instruction trace length exceeded")
362 }
363 InstructionError::BuiltinProgramsMustConsumeComputeUnits => {
364 f.write_str("Builtin programs must consume compute units")
365 }
366 }
367 }
368}
369
370#[cfg(feature = "num-traits")]
371impl<T> From<T> for InstructionError
372where
373 T: ToPrimitive,
374{
375 fn from(error: T) -> Self {
376 let error = error.to_u64().unwrap_or(0xbad_c0de);
377 match error {
378 CUSTOM_ZERO => Self::Custom(0),
379 INVALID_ARGUMENT => Self::InvalidArgument,
380 INVALID_INSTRUCTION_DATA => Self::InvalidInstructionData,
381 INVALID_ACCOUNT_DATA => Self::InvalidAccountData,
382 ACCOUNT_DATA_TOO_SMALL => Self::AccountDataTooSmall,
383 INSUFFICIENT_FUNDS => Self::InsufficientFunds,
384 INCORRECT_PROGRAM_ID => Self::IncorrectProgramId,
385 MISSING_REQUIRED_SIGNATURES => Self::MissingRequiredSignature,
386 ACCOUNT_ALREADY_INITIALIZED => Self::AccountAlreadyInitialized,
387 UNINITIALIZED_ACCOUNT => Self::UninitializedAccount,
388 #[allow(deprecated)]
389 NOT_ENOUGH_ACCOUNT_KEYS => Self::NotEnoughAccountKeys,
390 ACCOUNT_BORROW_FAILED => Self::AccountBorrowFailed,
391 MAX_SEED_LENGTH_EXCEEDED => Self::MaxSeedLengthExceeded,
392 INVALID_SEEDS => Self::InvalidSeeds,
393 BORSH_IO_ERROR => Self::BorshIoError,
394 ACCOUNT_NOT_RENT_EXEMPT => Self::AccountNotRentExempt,
395 UNSUPPORTED_SYSVAR => Self::UnsupportedSysvar,
396 ILLEGAL_OWNER => Self::IllegalOwner,
397 MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED => Self::MaxAccountsDataAllocationsExceeded,
398 INVALID_ACCOUNT_DATA_REALLOC => Self::InvalidRealloc,
399 MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED => Self::MaxInstructionTraceLengthExceeded,
400 BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS => {
401 Self::BuiltinProgramsMustConsumeComputeUnits
402 }
403 INVALID_ACCOUNT_OWNER => Self::InvalidAccountOwner,
404 ARITHMETIC_OVERFLOW => Self::ArithmeticOverflow,
405 IMMUTABLE => Self::Immutable,
406 INCORRECT_AUTHORITY => Self::IncorrectAuthority,
407 _ => {
408 if error >> solana_program_error::BUILTIN_BIT_SHIFT == 0 {
410 Self::Custom(error as u32)
411 } else {
412 Self::InvalidError
413 }
414 }
415 }
416 }
417}
418
419#[derive(Debug)]
420pub enum LamportsError {
421 ArithmeticUnderflow,
423 ArithmeticOverflow,
425}
426
427impl core::error::Error for LamportsError {}
428
429impl fmt::Display for LamportsError {
430 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
431 match self {
432 Self::ArithmeticUnderflow => f.write_str("Arithmetic underflowed"),
433 Self::ArithmeticOverflow => f.write_str("Arithmetic overflowed"),
434 }
435 }
436}
437
438impl From<LamportsError> for InstructionError {
439 fn from(error: LamportsError) -> Self {
440 match error {
441 LamportsError::ArithmeticOverflow => InstructionError::ArithmeticOverflow,
442 LamportsError::ArithmeticUnderflow => InstructionError::ArithmeticOverflow,
443 }
444 }
445}
446
447impl TryFrom<InstructionError> for ProgramError {
448 type Error = InstructionError;
449
450 fn try_from(error: InstructionError) -> Result<Self, Self::Error> {
451 match error {
452 Self::Error::Custom(err) => Ok(Self::Custom(err)),
453 Self::Error::InvalidArgument => Ok(Self::InvalidArgument),
454 Self::Error::InvalidInstructionData => Ok(Self::InvalidInstructionData),
455 Self::Error::InvalidAccountData => Ok(Self::InvalidAccountData),
456 Self::Error::AccountDataTooSmall => Ok(Self::AccountDataTooSmall),
457 Self::Error::InsufficientFunds => Ok(Self::InsufficientFunds),
458 Self::Error::IncorrectProgramId => Ok(Self::IncorrectProgramId),
459 Self::Error::MissingRequiredSignature => Ok(Self::MissingRequiredSignature),
460 Self::Error::AccountAlreadyInitialized => Ok(Self::AccountAlreadyInitialized),
461 Self::Error::UninitializedAccount => Ok(Self::UninitializedAccount),
462 #[allow(deprecated)]
463 Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
464 Self::Error::MissingAccount => Ok(Self::NotEnoughAccountKeys),
465 Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
466 Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
467 Self::Error::InvalidSeeds => Ok(Self::InvalidSeeds),
468 Self::Error::BorshIoError => Ok(Self::BorshIoError),
469 Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
470 Self::Error::UnsupportedSysvar => Ok(Self::UnsupportedSysvar),
471 Self::Error::IllegalOwner => Ok(Self::IllegalOwner),
472 Self::Error::MaxAccountsDataAllocationsExceeded => {
473 Ok(Self::MaxAccountsDataAllocationsExceeded)
474 }
475 Self::Error::InvalidRealloc => Ok(Self::InvalidRealloc),
476 Self::Error::MaxInstructionTraceLengthExceeded => {
477 Ok(Self::MaxInstructionTraceLengthExceeded)
478 }
479 Self::Error::BuiltinProgramsMustConsumeComputeUnits => {
480 Ok(Self::BuiltinProgramsMustConsumeComputeUnits)
481 }
482 Self::Error::InvalidAccountOwner => Ok(Self::InvalidAccountOwner),
483 Self::Error::ArithmeticOverflow => Ok(Self::ArithmeticOverflow),
484 Self::Error::Immutable => Ok(Self::Immutable),
485 Self::Error::IncorrectAuthority => Ok(Self::IncorrectAuthority),
486 _ => Err(error),
487 }
488 }
489}