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::{AbiEnumVisitor, AbiExample};
28
29 #[cfg_attr(feature = "frozen-abi", derive(AbiExample, AbiEnumVisitor))]
37 #[cfg_attr(
38 feature = "serde",
39 derive(serde_derive::Serialize, serde_derive::Deserialize)
40 )]
41 #[derive(Debug, PartialEq, Eq, Clone)]
42 pub enum InstructionError {
43 GenericError,
46
47 InvalidArgument,
49
50 InvalidInstructionData,
52
53 InvalidAccountData,
55
56 AccountDataTooSmall,
58
59 InsufficientFunds,
61
62 IncorrectProgramId,
64
65 MissingRequiredSignature,
67
68 AccountAlreadyInitialized,
70
71 UninitializedAccount,
73
74 UnbalancedInstruction,
76
77 ModifiedProgramId,
79
80 ExternalAccountLamportSpend,
82
83 ExternalAccountDataModified,
85
86 ReadonlyLamportChange,
88
89 ReadonlyDataModified,
91
92 DuplicateAccountIndex,
95
96 ExecutableModified,
98
99 RentEpochModified,
101
102 #[deprecated(since = "2.1.0", note = "Use InstructionError::MissingAccount instead")]
104 NotEnoughAccountKeys,
105
106 AccountDataSizeChanged,
108
109 AccountNotExecutable,
111
112 AccountBorrowFailed,
114
115 AccountBorrowOutstanding,
117
118 DuplicateAccountOutOfSync,
122
123 Custom(u32),
127
128 InvalidError,
131
132 ExecutableDataModified,
134
135 ExecutableLamportChange,
137
138 ExecutableAccountNotRentExempt,
140
141 UnsupportedProgramId,
143
144 CallDepth,
146
147 MissingAccount,
149
150 ReentrancyNotAllowed,
152
153 MaxSeedLengthExceeded,
155
156 InvalidSeeds,
158
159 InvalidRealloc,
161
162 ComputationalBudgetExceeded,
164
165 PrivilegeEscalation,
167
168 ProgramEnvironmentSetupFailure,
170
171 ProgramFailedToComplete,
173
174 ProgramFailedToCompile,
176
177 Immutable,
179
180 IncorrectAuthority,
182
183 BorshIoError,
185
186 AccountNotRentExempt,
188
189 InvalidAccountOwner,
191
192 ArithmeticOverflow,
194
195 UnsupportedSysvar,
197
198 IllegalOwner,
200
201 MaxAccountsDataAllocationsExceeded,
203
204 MaxAccountsExceeded,
206
207 MaxInstructionTraceLengthExceeded,
209
210 BuiltinProgramsMustConsumeComputeUnits,
212 }
215}
216
217impl core::error::Error for InstructionError {}
218
219impl fmt::Display for InstructionError {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 match self {
222 InstructionError::GenericError => f.write_str("generic instruction error"),
223 InstructionError::InvalidArgument => f.write_str("invalid program argument"),
224 InstructionError::InvalidInstructionData => f.write_str("invalid instruction data"),
225 InstructionError::InvalidAccountData => {
226 f.write_str("invalid account data for instruction")
227 }
228 InstructionError::AccountDataTooSmall => {
229 f.write_str("account data too small for instruction")
230 }
231 InstructionError::InsufficientFunds => {
232 f.write_str("insufficient funds for instruction")
233 }
234 InstructionError::IncorrectProgramId => {
235 f.write_str("incorrect program id for instruction")
236 }
237 InstructionError::MissingRequiredSignature => {
238 f.write_str("missing required signature for instruction")
239 }
240 InstructionError::AccountAlreadyInitialized => {
241 f.write_str("instruction requires an uninitialized account")
242 }
243 InstructionError::UninitializedAccount => {
244 f.write_str("instruction requires an initialized account")
245 }
246 InstructionError::UnbalancedInstruction => {
247 f.write_str("sum of account balances before and after instruction do not match")
248 }
249 InstructionError::ModifiedProgramId => {
250 f.write_str("instruction illegally modified the program id of an account")
251 }
252 InstructionError::ExternalAccountLamportSpend => {
253 f.write_str("instruction spent from the balance of an account it does not own")
254 }
255 InstructionError::ExternalAccountDataModified => {
256 f.write_str("instruction modified data of an account it does not own")
257 }
258 InstructionError::ReadonlyLamportChange => {
259 f.write_str("instruction changed the balance of a read-only account")
260 }
261 InstructionError::ReadonlyDataModified => {
262 f.write_str("instruction modified data of a read-only account")
263 }
264 InstructionError::DuplicateAccountIndex => {
265 f.write_str("instruction contains duplicate accounts")
266 }
267 InstructionError::ExecutableModified => {
268 f.write_str("instruction changed executable bit of an account")
269 }
270 InstructionError::RentEpochModified => {
271 f.write_str("instruction modified rent epoch of an account")
272 }
273 #[allow(deprecated)]
274 InstructionError::NotEnoughAccountKeys => {
275 f.write_str("insufficient account keys for instruction")
276 }
277 InstructionError::AccountDataSizeChanged => f.write_str(
278 "program other than the account's owner changed the size of the account data",
279 ),
280 InstructionError::AccountNotExecutable => {
281 f.write_str("instruction expected an executable account")
282 }
283 InstructionError::AccountBorrowFailed => f.write_str(
284 "instruction tries to borrow reference for an account which is already borrowed",
285 ),
286 InstructionError::AccountBorrowOutstanding => {
287 f.write_str("instruction left account with an outstanding borrowed reference")
288 }
289 InstructionError::DuplicateAccountOutOfSync => {
290 f.write_str("instruction modifications of multiply-passed account differ")
291 }
292 InstructionError::Custom(num) => {
293 write!(f, "custom program error: {num:#x}")
294 }
295 InstructionError::InvalidError => f.write_str("program returned invalid error code"),
296 InstructionError::ExecutableDataModified => {
297 f.write_str("instruction changed executable accounts data")
298 }
299 InstructionError::ExecutableLamportChange => {
300 f.write_str("instruction changed the balance of an executable account")
301 }
302 InstructionError::ExecutableAccountNotRentExempt => {
303 f.write_str("executable accounts must be rent exempt")
304 }
305 InstructionError::UnsupportedProgramId => f.write_str("Unsupported program id"),
306 InstructionError::CallDepth => {
307 f.write_str("Cross-program invocation call depth too deep")
308 }
309 InstructionError::MissingAccount => {
310 f.write_str("An account required by the instruction is missing")
311 }
312 InstructionError::ReentrancyNotAllowed => {
313 f.write_str("Cross-program invocation reentrancy not allowed for this instruction")
314 }
315 InstructionError::MaxSeedLengthExceeded => {
316 f.write_str("Length of the seed is too long for address generation")
317 }
318 InstructionError::InvalidSeeds => {
319 f.write_str("Provided seeds do not result in a valid address")
320 }
321 InstructionError::InvalidRealloc => f.write_str("Failed to reallocate account data"),
322 InstructionError::ComputationalBudgetExceeded => {
323 f.write_str("Computational budget exceeded")
324 }
325 InstructionError::PrivilegeEscalation => {
326 f.write_str("Cross-program invocation with unauthorized signer or writable account")
327 }
328 InstructionError::ProgramEnvironmentSetupFailure => {
329 f.write_str("Failed to create program execution environment")
330 }
331 InstructionError::ProgramFailedToComplete => f.write_str("Program failed to complete"),
332 InstructionError::ProgramFailedToCompile => f.write_str("Program failed to compile"),
333 InstructionError::Immutable => f.write_str("Account is immutable"),
334 InstructionError::IncorrectAuthority => f.write_str("Incorrect authority provided"),
335 InstructionError::BorshIoError => {
336 f.write_str("Failed to serialize or deserialize account data")
337 }
338 InstructionError::AccountNotRentExempt => {
339 f.write_str("An account does not have enough lamports to be rent-exempt")
340 }
341 InstructionError::InvalidAccountOwner => f.write_str("Invalid account owner"),
342 InstructionError::ArithmeticOverflow => f.write_str("Program arithmetic overflowed"),
343 InstructionError::UnsupportedSysvar => f.write_str("Unsupported sysvar"),
344 InstructionError::IllegalOwner => f.write_str("Provided owner is not allowed"),
345 InstructionError::MaxAccountsDataAllocationsExceeded => f.write_str(
346 "Accounts data allocations exceeded the maximum allowed per transaction",
347 ),
348 InstructionError::MaxAccountsExceeded => f.write_str("Max accounts exceeded"),
349 InstructionError::MaxInstructionTraceLengthExceeded => {
350 f.write_str("Max instruction trace length exceeded")
351 }
352 InstructionError::BuiltinProgramsMustConsumeComputeUnits => {
353 f.write_str("Builtin programs must consume compute units")
354 }
355 }
356 }
357}
358
359#[cfg(feature = "num-traits")]
360impl<T> From<T> for InstructionError
361where
362 T: ToPrimitive,
363{
364 fn from(error: T) -> Self {
365 let error = error.to_u64().unwrap_or(0xbad_c0de);
366 match error {
367 CUSTOM_ZERO => Self::Custom(0),
368 INVALID_ARGUMENT => Self::InvalidArgument,
369 INVALID_INSTRUCTION_DATA => Self::InvalidInstructionData,
370 INVALID_ACCOUNT_DATA => Self::InvalidAccountData,
371 ACCOUNT_DATA_TOO_SMALL => Self::AccountDataTooSmall,
372 INSUFFICIENT_FUNDS => Self::InsufficientFunds,
373 INCORRECT_PROGRAM_ID => Self::IncorrectProgramId,
374 MISSING_REQUIRED_SIGNATURES => Self::MissingRequiredSignature,
375 ACCOUNT_ALREADY_INITIALIZED => Self::AccountAlreadyInitialized,
376 UNINITIALIZED_ACCOUNT => Self::UninitializedAccount,
377 #[allow(deprecated)]
378 NOT_ENOUGH_ACCOUNT_KEYS => Self::NotEnoughAccountKeys,
379 ACCOUNT_BORROW_FAILED => Self::AccountBorrowFailed,
380 MAX_SEED_LENGTH_EXCEEDED => Self::MaxSeedLengthExceeded,
381 INVALID_SEEDS => Self::InvalidSeeds,
382 BORSH_IO_ERROR => Self::BorshIoError,
383 ACCOUNT_NOT_RENT_EXEMPT => Self::AccountNotRentExempt,
384 UNSUPPORTED_SYSVAR => Self::UnsupportedSysvar,
385 ILLEGAL_OWNER => Self::IllegalOwner,
386 MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED => Self::MaxAccountsDataAllocationsExceeded,
387 INVALID_ACCOUNT_DATA_REALLOC => Self::InvalidRealloc,
388 MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED => Self::MaxInstructionTraceLengthExceeded,
389 BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS => {
390 Self::BuiltinProgramsMustConsumeComputeUnits
391 }
392 INVALID_ACCOUNT_OWNER => Self::InvalidAccountOwner,
393 ARITHMETIC_OVERFLOW => Self::ArithmeticOverflow,
394 IMMUTABLE => Self::Immutable,
395 INCORRECT_AUTHORITY => Self::IncorrectAuthority,
396 _ => {
397 if error >> solana_program_error::BUILTIN_BIT_SHIFT == 0 {
399 Self::Custom(error as u32)
400 } else {
401 Self::InvalidError
402 }
403 }
404 }
405 }
406}
407
408#[derive(Debug)]
409pub enum LamportsError {
410 ArithmeticUnderflow,
412 ArithmeticOverflow,
414}
415
416impl core::error::Error for LamportsError {}
417
418impl fmt::Display for LamportsError {
419 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420 match self {
421 Self::ArithmeticUnderflow => f.write_str("Arithmetic underflowed"),
422 Self::ArithmeticOverflow => f.write_str("Arithmetic overflowed"),
423 }
424 }
425}
426
427impl From<LamportsError> for InstructionError {
428 fn from(error: LamportsError) -> Self {
429 match error {
430 LamportsError::ArithmeticOverflow => InstructionError::ArithmeticOverflow,
431 LamportsError::ArithmeticUnderflow => InstructionError::ArithmeticOverflow,
432 }
433 }
434}
435
436impl TryFrom<InstructionError> for ProgramError {
437 type Error = InstructionError;
438
439 fn try_from(error: InstructionError) -> Result<Self, Self::Error> {
440 match error {
441 Self::Error::Custom(err) => Ok(Self::Custom(err)),
442 Self::Error::InvalidArgument => Ok(Self::InvalidArgument),
443 Self::Error::InvalidInstructionData => Ok(Self::InvalidInstructionData),
444 Self::Error::InvalidAccountData => Ok(Self::InvalidAccountData),
445 Self::Error::AccountDataTooSmall => Ok(Self::AccountDataTooSmall),
446 Self::Error::InsufficientFunds => Ok(Self::InsufficientFunds),
447 Self::Error::IncorrectProgramId => Ok(Self::IncorrectProgramId),
448 Self::Error::MissingRequiredSignature => Ok(Self::MissingRequiredSignature),
449 Self::Error::AccountAlreadyInitialized => Ok(Self::AccountAlreadyInitialized),
450 Self::Error::UninitializedAccount => Ok(Self::UninitializedAccount),
451 #[allow(deprecated)]
452 Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
453 Self::Error::MissingAccount => Ok(Self::NotEnoughAccountKeys),
454 Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
455 Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
456 Self::Error::InvalidSeeds => Ok(Self::InvalidSeeds),
457 Self::Error::BorshIoError => Ok(Self::BorshIoError),
458 Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
459 Self::Error::UnsupportedSysvar => Ok(Self::UnsupportedSysvar),
460 Self::Error::IllegalOwner => Ok(Self::IllegalOwner),
461 Self::Error::MaxAccountsDataAllocationsExceeded => {
462 Ok(Self::MaxAccountsDataAllocationsExceeded)
463 }
464 Self::Error::InvalidRealloc => Ok(Self::InvalidRealloc),
465 Self::Error::MaxInstructionTraceLengthExceeded => {
466 Ok(Self::MaxInstructionTraceLengthExceeded)
467 }
468 Self::Error::BuiltinProgramsMustConsumeComputeUnits => {
469 Ok(Self::BuiltinProgramsMustConsumeComputeUnits)
470 }
471 Self::Error::InvalidAccountOwner => Ok(Self::InvalidAccountOwner),
472 Self::Error::ArithmeticOverflow => Ok(Self::ArithmeticOverflow),
473 Self::Error::Immutable => Ok(Self::Immutable),
474 Self::Error::IncorrectAuthority => Ok(Self::IncorrectAuthority),
475 _ => Err(error),
476 }
477 }
478}