const ANCHOR_ERROR_BASE: u32 = 6000;
macro_rules! define_kvault_errors {
(
$(
$(#[doc = $doc:expr])*
$variant:ident = $offset:literal => $msg:expr
),*
$(,)?
) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum KvaultError {
$(
$(#[doc = $doc])*
$variant = ANCHOR_ERROR_BASE + $offset,
)*
}
impl KvaultError {
pub const fn error_code(self) -> u32 {
self as u32
}
pub const fn message(self) -> &'static str {
match self {
$(Self::$variant => $msg,)*
}
}
pub const fn from_error_code(code: u32) -> Option<Self> {
match code {
$(x if x == ANCHOR_ERROR_BASE + $offset => Some(Self::$variant),)*
_ => None,
}
}
}
impl core::fmt::Display for KvaultError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.message())
}
}
impl TryFrom<u32> for KvaultError {
type Error = u32;
fn try_from(code: u32) -> Result<Self, Self::Error> {
Self::from_error_code(code).ok_or(code)
}
}
};
}
define_kvault_errors! {
DepositAmountsZero = 1000 => "Cannot deposit zero tokens",
SharesIssuedAmountDoesNotMatch = 1001 => "Post check failed on share issued",
MathOverflow = 1002 => "Math operation overflowed",
IntegerOverflow = 1003 => "Integer conversion overflowed",
WithdrawAmountBelowMinimum = 1004 => "Withdrawn amount is below minimum",
TooMuchLiquidityToWithdraw = 1005 => "TooMuchLiquidityToWithdraw",
ReserveAlreadyExists = 1006 => "ReserveAlreadyExists",
ReserveNotPartOfAllocations = 1007 => "ReserveNotPartOfAllocations",
CouldNotDeserializeAccountAsReserve = 1008 => "CouldNotDeserializeAccountAsReserve",
ReserveNotProvidedInTheAccounts = 1009 => "ReserveNotProvidedInTheAccounts",
ReserveAccountAndKeyMismatch = 1010 => "ReserveAccountAndKeyMismatch",
OutOfRangeOfReserveIndex = 1011 => "OutOfRangeOfReserveIndex",
CannotFindReserveInAllocations = 1012 => "OutOfRangeOfReserveIndex",
InvestAmountBelowMinimum = 1013 => "Invested amount is below minimum",
AdminAuthorityIncorrect = 1014 => "AdminAuthorityIncorrect",
BaseVaultAuthorityIncorrect = 1015 => "BaseVaultAuthorityIncorrect",
BaseVaultAuthorityBumpIncorrect = 1016 => "BaseVaultAuthorityBumpIncorrect",
TokenMintIncorrect = 1017 => "TokenMintIncorrect",
TokenMintDecimalsIncorrect = 1018 => "TokenMintDecimalsIncorrect",
TokenVaultIncorrect = 1019 => "TokenVaultIncorrect",
SharesMintDecimalsIncorrect = 1020 => "SharesMintDecimalsIncorrect",
SharesMintIncorrect = 1021 => "SharesMintIncorrect",
InitialAccountingIncorrect = 1022 => "InitialAccountingIncorrect",
ReserveIsStale = 1023 => "Reserve is stale and must be refreshed before any operation",
NotEnoughLiquidityDisinvestedToSendToUser = 1024 => "Not enough liquidity disinvested to send to user",
BPSValueTooBig = 1025 => "BPS value is greater than 10000",
DepositAmountBelowMinimum = 1026 => "Deposited amount is below minimum",
ReserveSpaceExhausted = 1027 => "Vault have no space for new reserves",
CannotWithdrawFromEmptyVault = 1028 => "Cannot withdraw from empty vault",
TokensDepositedAmountDoesNotMatch = 1029 => "TokensDepositedAmountDoesNotMatch",
AmountToWithdrawDoesNotMatch = 1030 => "Amount to withdraw does not match",
LiquidityToWithdrawDoesNotMatch = 1031 => "Liquidity to withdraw does not match",
UserReceivedAmountDoesNotMatch = 1032 => "User received amount does not match",
SharesBurnedAmountDoesNotMatch = 1033 => "Shares burned amount does not match",
DisinvestedLiquidityAmountDoesNotMatch = 1034 => "Disinvested liquidity amount does not match",
SharesMintedAmountDoesNotMatch = 1035 => "SharesMintedAmountDoesNotMatch",
AUMDecreasedAfterInvest = 1036 => "AUM decreased after invest",
AUMBelowPendingFees = 1037 => "AUM is below pending fees",
DepositAmountsZeroShares = 1038 => "Deposit amount results in 0 shares",
WithdrawResultsInZeroShares = 1039 => "Withdraw amount results in 0 shares",
CannotWithdrawZeroShares = 1040 => "Cannot withdraw zero shares",
ManagementFeeGreaterThanMaxAllowed = 1041 => "Management fee is greater than maximum allowed",
VaultAUMZero = 1042 => "Vault assets under management are empty",
MissingReserveForBatchRefresh = 1043 => "Missing reserve for batch refresh",
MinWithdrawAmountTooBig = 1044 => "Min withdraw amount is too big",
InvestTooSoon = 1045 => "Invest is called too soon after last invest",
WrongAdminOrAllocationAdmin = 1046 => "Wrong admin or allocation admin",
ReserveHasNonZeroAllocationOrCTokens = 1047 => "Reserve has non-zero allocation or ctokens so cannot be removed",
DepositAmountGreaterThanRequestedAmount = 1048 => "Deposit amount is greater than requested amount",
WithdrawAmountLessThanWithdrawalPenalty = 1049 => "Withdraw amount is less than withdrawal penalty",
CannotWithdrawZeroLamports = 1050 => "Cannot withdraw 0 lamports",
NoUpgradeAuthority = 1051 => "Cannot initialize global config because there is no upgrade authority to the program",
WithdrawalFeeBPSGreaterThanMaxAllowed = 1052 => "Withdrawal fee BPS is greater than maximum allowed",
WithdrawalFeeLamportsGreaterThanMaxAllowed = 1053 => "Withdrawal fee lamports is greater than maximum allowed",
ReserveNotWhitelisted = 1054 => "Reserve is not whitelisted",
InvalidBoolLikeValue = 1055 => "Invalid bool-like value passed in (should be 0 or 1)",
AUMDecreasedMoreThanExpected = 1056 => "AUM decreased more than expected during redeem in kind",
RewardTopupAmountZero = 1057 => "Reward topup amount is zero",
RewardTopupAmountNotExpected = 1058 => "Reward topup is not as expected after transfer",
RewardWithdrawAmountZero = 1059 => "Reward withdraw amount is zero",
RewardWithdrawAmountNotExpected = 1060 => "Reward withdraw is not as expected after transfer",
RewardsStaleForFeeUpdate = 1061 => "Rewards are stale - must be refreshed before updating fees",
VaultDepositCapReached = 1062 => "Vault deposit cap reached",
MaxInvestAmountMustBeGreaterThanZero = 1063 => "max_amount must be greater than 0",
}
impl std::error::Error for KvaultError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn verify_error_codes() {
assert_eq!(KvaultError::DepositAmountsZero.error_code(), 7000);
assert_eq!(KvaultError::MathOverflow.error_code(), 7002);
assert_eq!(KvaultError::AUMDecreasedMoreThanExpected.error_code(), 7056);
assert_eq!(KvaultError::RewardsStaleForFeeUpdate.error_code(), 7061);
assert_eq!(KvaultError::VaultDepositCapReached.error_code(), 7062);
assert_eq!(
KvaultError::MaxInvestAmountMustBeGreaterThanZero.error_code(),
7063
);
assert_eq!(
KvaultError::from_error_code(7000),
Some(KvaultError::DepositAmountsZero)
);
assert_eq!(
KvaultError::from_error_code(7056),
Some(KvaultError::AUMDecreasedMoreThanExpected)
);
assert_eq!(KvaultError::from_error_code(5000), None);
assert_eq!(KvaultError::from_error_code(9999), None);
assert_eq!(
KvaultError::MathOverflow.to_string(),
"Math operation overflowed"
);
assert_eq!(KvaultError::try_from(7002), Ok(KvaultError::MathOverflow));
assert_eq!(KvaultError::try_from(9999), Err(9999));
}
}