#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProgramError {
Custom(u32),
InvalidArgument,
InvalidInstructionData,
InvalidAccountData,
AccountDataTooSmall,
InsufficientFunds,
IncorrectProgramId,
MissingRequiredSignature,
AccountAlreadyInitialized,
UninitializedAccount,
NotEnoughAccountKeys,
AccountBorrowFailed,
MaxSeedLengthExceeded,
InvalidSeeds,
BorshIoError,
AccountNotRentExempt,
UnsupportedSysvar,
IllegalOwner,
MaxAccountsDataAllocationsExceeded,
InvalidRealloc,
MaxInstructionTraceLengthExceeded,
BuiltinProgramsMustConsumeComputeUnits,
InvalidAccountOwner,
ArithmeticOverflow,
Immutable,
IncorrectAuthority,
}
impl From<ProgramError> for u64 {
fn from(err: ProgramError) -> u64 {
match err {
ProgramError::Custom(0) => CUSTOM_ZERO,
ProgramError::Custom(code) => code as u64,
ProgramError::InvalidArgument => to_builtin(0),
ProgramError::InvalidInstructionData => to_builtin(1),
ProgramError::InvalidAccountData => to_builtin(2),
ProgramError::AccountDataTooSmall => to_builtin(3),
ProgramError::InsufficientFunds => to_builtin(4),
ProgramError::IncorrectProgramId => to_builtin(5),
ProgramError::MissingRequiredSignature => to_builtin(6),
ProgramError::AccountAlreadyInitialized => to_builtin(7),
ProgramError::UninitializedAccount => to_builtin(8),
ProgramError::NotEnoughAccountKeys => to_builtin(9),
ProgramError::AccountBorrowFailed => to_builtin(10),
ProgramError::MaxSeedLengthExceeded => to_builtin(11),
ProgramError::InvalidSeeds => to_builtin(12),
ProgramError::BorshIoError => to_builtin(13),
ProgramError::AccountNotRentExempt => to_builtin(14),
ProgramError::UnsupportedSysvar => to_builtin(15),
ProgramError::IllegalOwner => to_builtin(16),
ProgramError::MaxAccountsDataAllocationsExceeded => to_builtin(17),
ProgramError::InvalidRealloc => to_builtin(18),
ProgramError::MaxInstructionTraceLengthExceeded => to_builtin(19),
ProgramError::BuiltinProgramsMustConsumeComputeUnits => to_builtin(20),
ProgramError::InvalidAccountOwner => to_builtin(21),
ProgramError::ArithmeticOverflow => to_builtin(22),
ProgramError::Immutable => to_builtin(23),
ProgramError::IncorrectAuthority => to_builtin(24),
}
}
}
impl From<u64> for ProgramError {
fn from(code: u64) -> Self {
if code == CUSTOM_ZERO {
return ProgramError::Custom(0);
}
let builtin = code >> BUILTIN_BIT_SHIFT;
if code & BUILTIN_LOW_MASK == 0 && builtin >= 2 {
match builtin - 2 {
0 => return ProgramError::InvalidArgument,
1 => return ProgramError::InvalidInstructionData,
2 => return ProgramError::InvalidAccountData,
3 => return ProgramError::AccountDataTooSmall,
4 => return ProgramError::InsufficientFunds,
5 => return ProgramError::IncorrectProgramId,
6 => return ProgramError::MissingRequiredSignature,
7 => return ProgramError::AccountAlreadyInitialized,
8 => return ProgramError::UninitializedAccount,
9 => return ProgramError::NotEnoughAccountKeys,
10 => return ProgramError::AccountBorrowFailed,
11 => return ProgramError::MaxSeedLengthExceeded,
12 => return ProgramError::InvalidSeeds,
13 => return ProgramError::BorshIoError,
14 => return ProgramError::AccountNotRentExempt,
15 => return ProgramError::UnsupportedSysvar,
16 => return ProgramError::IllegalOwner,
17 => return ProgramError::MaxAccountsDataAllocationsExceeded,
18 => return ProgramError::InvalidRealloc,
19 => return ProgramError::MaxInstructionTraceLengthExceeded,
20 => return ProgramError::BuiltinProgramsMustConsumeComputeUnits,
21 => return ProgramError::InvalidAccountOwner,
22 => return ProgramError::ArithmeticOverflow,
23 => return ProgramError::Immutable,
24 => return ProgramError::IncorrectAuthority,
_ => {}
}
}
ProgramError::Custom(code as u32)
}
}
const BUILTIN_BIT_SHIFT: usize = 32;
const CUSTOM_ZERO: u64 = 1_u64 << BUILTIN_BIT_SHIFT;
const BUILTIN_LOW_MASK: u64 = (1_u64 << BUILTIN_BIT_SHIFT) - 1;
#[inline(always)]
const fn to_builtin(index: u64) -> u64 {
(index + 2) << BUILTIN_BIT_SHIFT
}
impl core::fmt::Display for ProgramError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ProgramError::Custom(code) => write!(f, "Custom({code})"),
ProgramError::InvalidArgument => write!(f, "InvalidArgument"),
ProgramError::InvalidInstructionData => write!(f, "InvalidInstructionData"),
ProgramError::InvalidAccountData => write!(f, "InvalidAccountData"),
ProgramError::AccountDataTooSmall => write!(f, "AccountDataTooSmall"),
ProgramError::InsufficientFunds => write!(f, "InsufficientFunds"),
ProgramError::IncorrectProgramId => write!(f, "IncorrectProgramId"),
ProgramError::MissingRequiredSignature => write!(f, "MissingRequiredSignature"),
ProgramError::AccountAlreadyInitialized => write!(f, "AccountAlreadyInitialized"),
ProgramError::UninitializedAccount => write!(f, "UninitializedAccount"),
ProgramError::NotEnoughAccountKeys => write!(f, "NotEnoughAccountKeys"),
ProgramError::AccountBorrowFailed => write!(f, "AccountBorrowFailed"),
ProgramError::MaxSeedLengthExceeded => write!(f, "MaxSeedLengthExceeded"),
ProgramError::InvalidSeeds => write!(f, "InvalidSeeds"),
ProgramError::BorshIoError => write!(f, "BorshIoError"),
ProgramError::AccountNotRentExempt => write!(f, "AccountNotRentExempt"),
ProgramError::UnsupportedSysvar => write!(f, "UnsupportedSysvar"),
ProgramError::IllegalOwner => write!(f, "IllegalOwner"),
ProgramError::MaxAccountsDataAllocationsExceeded => {
write!(f, "MaxAccountsDataAllocationsExceeded")
}
ProgramError::InvalidRealloc => write!(f, "InvalidRealloc"),
ProgramError::MaxInstructionTraceLengthExceeded => {
write!(f, "MaxInstructionTraceLengthExceeded")
}
ProgramError::BuiltinProgramsMustConsumeComputeUnits => {
write!(f, "BuiltinProgramsMustConsumeComputeUnits")
}
ProgramError::InvalidAccountOwner => write!(f, "InvalidAccountOwner"),
ProgramError::ArithmeticOverflow => write!(f, "ArithmeticOverflow"),
ProgramError::Immutable => write!(f, "Immutable"),
ProgramError::IncorrectAuthority => write!(f, "IncorrectAuthority"),
}
}
}