#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
#[cfg(feature = "num-traits")]
use num_traits::ToPrimitive;
#[cfg(feature = "frozen-abi")]
extern crate std;
use {core::fmt, solana_program_error::ProgramError};
pub use {
instruction_error_module::*,
solana_program_error::{
ACCOUNT_ALREADY_INITIALIZED, ACCOUNT_BORROW_FAILED, ACCOUNT_DATA_TOO_SMALL,
ACCOUNT_NOT_RENT_EXEMPT, ARITHMETIC_OVERFLOW, BORSH_IO_ERROR,
BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS, CUSTOM_ZERO, ILLEGAL_OWNER, IMMUTABLE,
INCORRECT_AUTHORITY, INCORRECT_PROGRAM_ID, INSUFFICIENT_FUNDS, INVALID_ACCOUNT_DATA,
INVALID_ACCOUNT_DATA_REALLOC, INVALID_ACCOUNT_OWNER, INVALID_ARGUMENT,
INVALID_INSTRUCTION_DATA, INVALID_SEEDS, MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED,
MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED, MAX_SEED_LENGTH_EXCEEDED,
MISSING_REQUIRED_SIGNATURES, NOT_ENOUGH_ACCOUNT_KEYS, UNINITIALIZED_ACCOUNT,
UNSUPPORTED_SYSVAR,
},
};
#[allow(deprecated)]
mod instruction_error_module {
#[cfg(feature = "frozen-abi")]
use solana_frozen_abi_macro::{AbiEnumVisitor, AbiExample};
#[cfg_attr(feature = "frozen-abi", derive(AbiExample, AbiEnumVisitor))]
#[cfg_attr(
feature = "serde",
derive(serde_derive::Serialize, serde_derive::Deserialize)
)]
#[cfg_attr(feature = "wincode", derive(wincode::SchemaWrite, wincode::SchemaRead))]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum InstructionError {
GenericError,
InvalidArgument,
InvalidInstructionData,
InvalidAccountData,
AccountDataTooSmall,
InsufficientFunds,
IncorrectProgramId,
MissingRequiredSignature,
AccountAlreadyInitialized,
UninitializedAccount,
UnbalancedInstruction,
ModifiedProgramId,
ExternalAccountLamportSpend,
ExternalAccountDataModified,
ReadonlyLamportChange,
ReadonlyDataModified,
DuplicateAccountIndex,
ExecutableModified,
RentEpochModified,
#[deprecated(since = "2.1.0", note = "Use InstructionError::MissingAccount instead")]
NotEnoughAccountKeys,
AccountDataSizeChanged,
AccountNotExecutable,
AccountBorrowFailed,
AccountBorrowOutstanding,
DuplicateAccountOutOfSync,
Custom(u32),
InvalidError,
ExecutableDataModified,
ExecutableLamportChange,
ExecutableAccountNotRentExempt,
UnsupportedProgramId,
CallDepth,
MissingAccount,
ReentrancyNotAllowed,
MaxSeedLengthExceeded,
InvalidSeeds,
InvalidRealloc,
ComputationalBudgetExceeded,
PrivilegeEscalation,
ProgramEnvironmentSetupFailure,
ProgramFailedToComplete,
ProgramFailedToCompile,
Immutable,
IncorrectAuthority,
BorshIoError,
AccountNotRentExempt,
InvalidAccountOwner,
ArithmeticOverflow,
UnsupportedSysvar,
IllegalOwner,
MaxAccountsDataAllocationsExceeded,
MaxAccountsExceeded,
MaxInstructionTraceLengthExceeded,
BuiltinProgramsMustConsumeComputeUnits,
}
}
impl core::error::Error for InstructionError {}
impl fmt::Display for InstructionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InstructionError::GenericError => f.write_str("generic instruction error"),
InstructionError::InvalidArgument => f.write_str("invalid program argument"),
InstructionError::InvalidInstructionData => f.write_str("invalid instruction data"),
InstructionError::InvalidAccountData => {
f.write_str("invalid account data for instruction")
}
InstructionError::AccountDataTooSmall => {
f.write_str("account data too small for instruction")
}
InstructionError::InsufficientFunds => {
f.write_str("insufficient funds for instruction")
}
InstructionError::IncorrectProgramId => {
f.write_str("incorrect program id for instruction")
}
InstructionError::MissingRequiredSignature => {
f.write_str("missing required signature for instruction")
}
InstructionError::AccountAlreadyInitialized => {
f.write_str("instruction requires an uninitialized account")
}
InstructionError::UninitializedAccount => {
f.write_str("instruction requires an initialized account")
}
InstructionError::UnbalancedInstruction => {
f.write_str("sum of account balances before and after instruction do not match")
}
InstructionError::ModifiedProgramId => {
f.write_str("instruction illegally modified the program id of an account")
}
InstructionError::ExternalAccountLamportSpend => {
f.write_str("instruction spent from the balance of an account it does not own")
}
InstructionError::ExternalAccountDataModified => {
f.write_str("instruction modified data of an account it does not own")
}
InstructionError::ReadonlyLamportChange => {
f.write_str("instruction changed the balance of a read-only account")
}
InstructionError::ReadonlyDataModified => {
f.write_str("instruction modified data of a read-only account")
}
InstructionError::DuplicateAccountIndex => {
f.write_str("instruction contains duplicate accounts")
}
InstructionError::ExecutableModified => {
f.write_str("instruction changed executable bit of an account")
}
InstructionError::RentEpochModified => {
f.write_str("instruction modified rent epoch of an account")
}
#[allow(deprecated)]
InstructionError::NotEnoughAccountKeys => {
f.write_str("insufficient account keys for instruction")
}
InstructionError::AccountDataSizeChanged => f.write_str(
"program other than the account's owner changed the size of the account data",
),
InstructionError::AccountNotExecutable => {
f.write_str("instruction expected an executable account")
}
InstructionError::AccountBorrowFailed => f.write_str(
"instruction tries to borrow reference for an account which is already borrowed",
),
InstructionError::AccountBorrowOutstanding => {
f.write_str("instruction left account with an outstanding borrowed reference")
}
InstructionError::DuplicateAccountOutOfSync => {
f.write_str("instruction modifications of multiply-passed account differ")
}
InstructionError::Custom(num) => {
write!(f, "custom program error: {num:#x}")
}
InstructionError::InvalidError => f.write_str("program returned invalid error code"),
InstructionError::ExecutableDataModified => {
f.write_str("instruction changed executable accounts data")
}
InstructionError::ExecutableLamportChange => {
f.write_str("instruction changed the balance of an executable account")
}
InstructionError::ExecutableAccountNotRentExempt => {
f.write_str("executable accounts must be rent exempt")
}
InstructionError::UnsupportedProgramId => f.write_str("Unsupported program id"),
InstructionError::CallDepth => {
f.write_str("Cross-program invocation call depth too deep")
}
InstructionError::MissingAccount => {
f.write_str("An account required by the instruction is missing")
}
InstructionError::ReentrancyNotAllowed => {
f.write_str("Cross-program invocation reentrancy not allowed for this instruction")
}
InstructionError::MaxSeedLengthExceeded => {
f.write_str("Length of the seed is too long for address generation")
}
InstructionError::InvalidSeeds => {
f.write_str("Provided seeds do not result in a valid address")
}
InstructionError::InvalidRealloc => f.write_str("Failed to reallocate account data"),
InstructionError::ComputationalBudgetExceeded => {
f.write_str("Computational budget exceeded")
}
InstructionError::PrivilegeEscalation => {
f.write_str("Cross-program invocation with unauthorized signer or writable account")
}
InstructionError::ProgramEnvironmentSetupFailure => {
f.write_str("Failed to create program execution environment")
}
InstructionError::ProgramFailedToComplete => f.write_str("Program failed to complete"),
InstructionError::ProgramFailedToCompile => f.write_str("Program failed to compile"),
InstructionError::Immutable => f.write_str("Account is immutable"),
InstructionError::IncorrectAuthority => f.write_str("Incorrect authority provided"),
InstructionError::BorshIoError => {
f.write_str("Failed to serialize or deserialize account data")
}
InstructionError::AccountNotRentExempt => {
f.write_str("An account does not have enough lamports to be rent-exempt")
}
InstructionError::InvalidAccountOwner => f.write_str("Invalid account owner"),
InstructionError::ArithmeticOverflow => f.write_str("Program arithmetic overflowed"),
InstructionError::UnsupportedSysvar => f.write_str("Unsupported sysvar"),
InstructionError::IllegalOwner => f.write_str("Provided owner is not allowed"),
InstructionError::MaxAccountsDataAllocationsExceeded => f.write_str(
"Accounts data allocations exceeded the maximum allowed per transaction",
),
InstructionError::MaxAccountsExceeded => f.write_str("Max accounts exceeded"),
InstructionError::MaxInstructionTraceLengthExceeded => {
f.write_str("Max instruction trace length exceeded")
}
InstructionError::BuiltinProgramsMustConsumeComputeUnits => {
f.write_str("Builtin programs must consume compute units")
}
}
}
}
#[cfg(feature = "num-traits")]
impl<T> From<T> for InstructionError
where
T: ToPrimitive,
{
fn from(error: T) -> Self {
let error = error.to_u64().unwrap_or(0xbad_c0de);
match error {
CUSTOM_ZERO => Self::Custom(0),
INVALID_ARGUMENT => Self::InvalidArgument,
INVALID_INSTRUCTION_DATA => Self::InvalidInstructionData,
INVALID_ACCOUNT_DATA => Self::InvalidAccountData,
ACCOUNT_DATA_TOO_SMALL => Self::AccountDataTooSmall,
INSUFFICIENT_FUNDS => Self::InsufficientFunds,
INCORRECT_PROGRAM_ID => Self::IncorrectProgramId,
MISSING_REQUIRED_SIGNATURES => Self::MissingRequiredSignature,
ACCOUNT_ALREADY_INITIALIZED => Self::AccountAlreadyInitialized,
UNINITIALIZED_ACCOUNT => Self::UninitializedAccount,
#[allow(deprecated)]
NOT_ENOUGH_ACCOUNT_KEYS => Self::NotEnoughAccountKeys,
ACCOUNT_BORROW_FAILED => Self::AccountBorrowFailed,
MAX_SEED_LENGTH_EXCEEDED => Self::MaxSeedLengthExceeded,
INVALID_SEEDS => Self::InvalidSeeds,
BORSH_IO_ERROR => Self::BorshIoError,
ACCOUNT_NOT_RENT_EXEMPT => Self::AccountNotRentExempt,
UNSUPPORTED_SYSVAR => Self::UnsupportedSysvar,
ILLEGAL_OWNER => Self::IllegalOwner,
MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED => Self::MaxAccountsDataAllocationsExceeded,
INVALID_ACCOUNT_DATA_REALLOC => Self::InvalidRealloc,
MAX_INSTRUCTION_TRACE_LENGTH_EXCEEDED => Self::MaxInstructionTraceLengthExceeded,
BUILTIN_PROGRAMS_MUST_CONSUME_COMPUTE_UNITS => {
Self::BuiltinProgramsMustConsumeComputeUnits
}
INVALID_ACCOUNT_OWNER => Self::InvalidAccountOwner,
ARITHMETIC_OVERFLOW => Self::ArithmeticOverflow,
IMMUTABLE => Self::Immutable,
INCORRECT_AUTHORITY => Self::IncorrectAuthority,
_ => {
if error >> solana_program_error::BUILTIN_BIT_SHIFT == 0 {
Self::Custom(error as u32)
} else {
Self::InvalidError
}
}
}
}
}
#[derive(Debug)]
pub enum LamportsError {
ArithmeticUnderflow,
ArithmeticOverflow,
}
impl core::error::Error for LamportsError {}
impl fmt::Display for LamportsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::ArithmeticUnderflow => f.write_str("Arithmetic underflowed"),
Self::ArithmeticOverflow => f.write_str("Arithmetic overflowed"),
}
}
}
impl From<LamportsError> for InstructionError {
fn from(error: LamportsError) -> Self {
match error {
LamportsError::ArithmeticOverflow => InstructionError::ArithmeticOverflow,
LamportsError::ArithmeticUnderflow => InstructionError::ArithmeticOverflow,
}
}
}
impl TryFrom<InstructionError> for ProgramError {
type Error = InstructionError;
fn try_from(error: InstructionError) -> Result<Self, Self::Error> {
match error {
Self::Error::Custom(err) => Ok(Self::Custom(err)),
Self::Error::InvalidArgument => Ok(Self::InvalidArgument),
Self::Error::InvalidInstructionData => Ok(Self::InvalidInstructionData),
Self::Error::InvalidAccountData => Ok(Self::InvalidAccountData),
Self::Error::AccountDataTooSmall => Ok(Self::AccountDataTooSmall),
Self::Error::InsufficientFunds => Ok(Self::InsufficientFunds),
Self::Error::IncorrectProgramId => Ok(Self::IncorrectProgramId),
Self::Error::MissingRequiredSignature => Ok(Self::MissingRequiredSignature),
Self::Error::AccountAlreadyInitialized => Ok(Self::AccountAlreadyInitialized),
Self::Error::UninitializedAccount => Ok(Self::UninitializedAccount),
#[allow(deprecated)]
Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
Self::Error::MissingAccount => Ok(Self::NotEnoughAccountKeys),
Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
Self::Error::InvalidSeeds => Ok(Self::InvalidSeeds),
Self::Error::BorshIoError => Ok(Self::BorshIoError),
Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
Self::Error::UnsupportedSysvar => Ok(Self::UnsupportedSysvar),
Self::Error::IllegalOwner => Ok(Self::IllegalOwner),
Self::Error::MaxAccountsDataAllocationsExceeded => {
Ok(Self::MaxAccountsDataAllocationsExceeded)
}
Self::Error::InvalidRealloc => Ok(Self::InvalidRealloc),
Self::Error::MaxInstructionTraceLengthExceeded => {
Ok(Self::MaxInstructionTraceLengthExceeded)
}
Self::Error::BuiltinProgramsMustConsumeComputeUnits => {
Ok(Self::BuiltinProgramsMustConsumeComputeUnits)
}
Self::Error::InvalidAccountOwner => Ok(Self::InvalidAccountOwner),
Self::Error::ArithmeticOverflow => Ok(Self::ArithmeticOverflow),
Self::Error::Immutable => Ok(Self::Immutable),
Self::Error::IncorrectAuthority => Ok(Self::IncorrectAuthority),
_ => Err(error),
}
}
}