use num_enum::{FromPrimitive, IntoPrimitive};
use solana_program::program_error::ProgramError;
use thiserror::Error;
pub type DexResult<T = ()> = Result<T, DexError>;
#[derive(Debug)]
pub struct AssertionError {
pub line: u16,
pub file_id: SourceFileId,
}
impl From<AssertionError> for u32 {
fn from(err: AssertionError) -> u32 {
(err.line as u32) + ((err.file_id as u8 as u32) << 24)
}
}
impl From<AssertionError> for DexError {
fn from(err: AssertionError) -> DexError {
let err: u32 = err.into();
DexError::ProgramError(ProgramError::Custom(err.into()))
}
}
#[derive(Error, Debug, PartialEq, Eq)]
pub enum DexError {
#[error(transparent)]
ProgramError(#[from] ProgramError),
#[error("{0:?}")]
ErrorCode(#[from] DexErrorCode),
}
#[derive(Debug, IntoPrimitive, FromPrimitive, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum DexErrorCode {
InvalidMarketFlags = 0,
InvalidAskFlags,
InvalidBidFlags,
InvalidQueueLength,
OwnerAccountNotProvided,
ConsumeEventsQueueFailure,
WrongCoinVault,
WrongPcVault,
WrongCoinMint,
WrongPcMint,
CoinVaultProgramId = 10,
PcVaultProgramId,
CoinMintProgramId,
PcMintProgramId,
WrongCoinMintSize,
WrongPcMintSize,
WrongCoinVaultSize,
WrongPcVaultSize,
UninitializedVault,
UninitializedMint,
CoinMintUninitialized = 20,
PcMintUninitialized,
WrongMint,
WrongVaultOwner,
VaultHasDelegate,
AlreadyInitialized,
WrongAccountDataAlignment,
WrongAccountDataPaddingLength,
WrongAccountHeadPadding,
WrongAccountTailPadding,
RequestQueueEmpty = 30,
EventQueueTooSmall,
SlabTooSmall,
BadVaultSignerNonce,
InsufficientFunds,
SplAccountProgramId,
SplAccountLen,
WrongFeeDiscountAccountOwner,
WrongFeeDiscountMint,
CoinPayerProgramId,
PcPayerProgramId = 40,
ClientIdNotFound,
TooManyOpenOrders,
FakeErrorSoWeDontChangeNumbers,
BorrowError,
WrongOrdersAccount,
WrongBidsAccount,
WrongAsksAccount,
WrongRequestQueueAccount,
WrongEventQueueAccount,
RequestQueueFull = 50,
EventQueueFull,
MarketIsDisabled,
WrongSigner,
TransferFailed,
ClientOrderIdIsZero,
WrongRentSysvarAccount,
RentNotProvided,
OrdersNotRentExempt,
OrderNotFound,
OrderNotYours,
WouldSelfTrade,
InvalidOpenOrdersAuthority,
Unknown = 1000,
#[num_enum(default)]
AssertionError,
}
#[repr(u8)]
#[derive(Error, Debug)]
pub enum SourceFileId {
#[error("src/state.rs")]
State = 1,
#[error("src/matching.rs")]
Matching = 2,
#[error("src/critbit.rs")]
Critbit = 3,
}
#[macro_export]
macro_rules! declare_check_assert_macros {
($source_file_id:expr) => {
macro_rules! assertion_error {
() => {{
let file_id: SourceFileId = $source_file_id;
$crate::error::AssertionError {
line: line!() as u16,
file_id,
}
}};
}
#[allow(unused_macros)]
macro_rules! check_assert {
($val:expr) => {{
if $val {
Ok(())
} else {
Err(assertion_error!())
}
}};
}
#[allow(unused_macros)]
macro_rules! check_assert_eq {
($a:expr, $b:expr) => {{
if $a == $b {
Ok(())
} else {
Err(assertion_error!())
}
}};
}
#[allow(unused_macros)]
macro_rules! check_unreachable {
() => {{
Err(assertion_error!())
}};
}
};
}
impl std::fmt::Display for DexErrorCode {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
<Self as std::fmt::Debug>::fmt(self, fmt)
}
}
impl std::error::Error for DexErrorCode {}
impl std::convert::From<DexError> for ProgramError {
fn from(e: DexError) -> ProgramError {
match e {
DexError::ProgramError(e) => e,
DexError::ErrorCode(c) => ProgramError::Custom(c.into()),
}
}
}
impl std::convert::From<std::cell::BorrowError> for DexError {
fn from(_: std::cell::BorrowError) -> Self {
DexError::ErrorCode(DexErrorCode::BorrowError)
}
}