devol_accounts_kit/
errors.rs

1use std::fmt::{Debug};
2use strum_macros::{EnumIter, FromRepr};
3use thiserror::Error;
4
5#[repr(u16)]
6#[derive(Copy, Clone, Debug, Error, EnumIter, FromRepr, PartialEq)]
7pub enum ContractError {
8    #[error("No errors")]
9    NoError                     = 0x0000,
10    #[error("Incorrect account size")]
11    AccountSize                 = 0x0001,
12    #[error("The smart contract is not the owner of this account")]
13    AccountOwner                = 0x0002,
14    #[error("The `isWritable` attribute does not match the expected one passed in the transaction")]
15    AccountWritableAttribute    = 0x0003,
16    #[error("Account type is different from expected (determined by tag)")]
17    WrongAccountTag             = 0x0004,
18    #[error("The account version is higher than expected by the smart contract")]
19    AccountVersionTooHigh       = 0x0005,
20    #[error("The administrator must upgrade this account")]
21    AccountVersionTooLow        = 0x0006,
22    #[error("The account is not part of the tree of accounts descended from the root account")]
23    RootAddress                 = 0x0007,
24    #[error("An attempt to resize the account was unsuccessful")]
25    IncreaseSize                = 0x0008,
26    #[error("Incorrect instruction data length")]
27    InstructionDataLength       = 0x0009,
28    #[error("For an account with this tag, no actions are provided for this transaction or the tag is invalid")]
29    UnknownAccountTag           = 0x000A,
30    #[error("Error sending lamports from the signer's account to the target account")]
31    LamportTransfer             = 0x000B,
32    #[error("Incorrect size, version, writable attribute, etc., only for legacy checks")]
33    AccountLegacyError          = 0x000C,
34    #[error("Incorrect number of accounts passed to the transaction")]
35    AccountsQuantity            = 0x000D,
36    #[error("A specific account is missing")]
37    AccountIsMissing            = 0x000E,
38    #[error("There is a discrepancy between the order of the accounts passed to the Oracle instruction and the saved settings. Accounts must be transferred in the same order as the settings for them are specified.")]
39    MismatchOraclesOrder        = 0x000F,
40    #[error("The derived PDA does not match the expected account. This may indicate an issue with the seed(s) used for its generation or incorrect account usage.")]
41    InvalidPDA                  = 0x0010,
42    #[error("The operation could not be completed due to insufficient funds in the involved account(s). This error is raised when an account lacks the necessary lamports to perform actions such as account creation, transaction fees, or lamport transfers.")]
43    InsufficientFunds           = 0x0011,
44    #[error("Error while creating a new account")]
45    CreateAccount               = 0x0012,
46    #[error("Such an Oracle does not exist (probably the number is greater than or equal to ORACLES_DATA_COUNT)")]
47    SuchOracleDoesNotExists     = 0x0013,
48    #[error("Such an Instrument does not exist")]
49    SuchInstrumentDoesNotExists = 0x0014,
50    #[error("Used outdated instruction data format")]
51    InstructionDataVersion      = 0x0015,
52    #[error("Operations halted nearing expiration (e.g., maintenance, lockout)")]
53    TradeCloseBeforeExpire      = 0x0016,
54    #[error("Trade not possible; the option period has ended, next period yet to start (check option schedule)")]
55    OptionPeriodClosed          = 0x0017,
56    #[error("Option order exceeds 0.5% of liquidity pool (reduce order size)")]
57    NotionalValueTooHigh        = 0x0018,
58    #[error("Actual trade cost exceeds set maximum limit (adjust limit or price)")]
59    CostLimitExceeded           = 0x0019,
60    #[error("Transaction exceeds daily trading limit; register as Power Trader to remove this restriction")]
61    DailyLimitExceeded          = 0x001A,
62    #[error("New pool cannot start without initial funding; deposit funds to launch")]
63    PoolFundingRequired         = 0x001B,
64    #[error("Cannot determine asset price via oracles; trading halted (oracle not configured or data refresh issue)")]
65    AssetPriceUnavailable       = 0x001C,
66    #[error("Failed to read current time in smart contract; operation cannot proceed")]
67    TimeReadError               = 0x001D,
68    #[error("Error during calculations (type conversion, division by zero, floating point overflow, etc.)")]
69    ComputationError            = 0x001E,
70    #[error("Incorrect oracle number (number too large or negative); oracle does not exist")]
71    InvalidOracleNumber         = 0x001F,
72    #[error("Transaction must be executed by platform administrator only, but current signer is not authorized")]
73    AdminOnlyTransaction        = 0x0020,
74    #[error("Transaction requires the account to be a signer, but it is not")]
75    AccountNotSigner            = 0x0021,
76    #[error("Operation on client account attempted by incorrect client (wrong account sequence, missing, or another client's account)")]
77    UnauthorizedClientOperation = 0x0022,
78    #[error("No record of the targeted pool in client's account")]
79    PoolRecordNotFound          = 0x0023,
80    #[error("Significant price variance between oracles exceeds allowable range, preventing trade execution")]
81    PriceDiscrepancyError       = 0x0024,
82    #[error("Required oracle for price calculation is not provided in the function call")]
83    MandatoryOracleMissing      = 0x0025,
84    #[error("Invalid account ID")]
85    InvalidAccountId            = 0x0026,
86    #[error("Invalid mint ID")]
87    InvalidMintId               = 0x0027,
88    #[error("Operation with worker account cannot proceed due to incorrect state")]
89    WorkerInvalidState          = 0x0028,
90    #[error("Task cannot start before the current date; adjust task start time")]
91    TaskStartBeforeCurrentDate  = 0x0029,
92    #[error("Cannot assign new task as the maximum number of workers for the instrument has been reached")]
93    MaxWorkersExceeded          = 0x002A,
94    #[error("Specified fee payer for account opening does not match any valid options")]
95    InvalidFeePayerOption       = 0x002B,
96    #[error("Cannot finalize pool as it is not active")]
97    InactivePoolCannotFinalize  = 0x002C,
98    #[error("Cannot finalize pool as the designated time for finalization has not yet been reached")]
99    PoolFinalizeTimeNotReached  = 0x002D,
100    #[error("Provided PDA does not match expected for account creation")]
101    IncorrectExpectedPDA        = 0x002E,
102    #[error("Failed to transfer lamports to newly created account for rent exemption")]
103    LamportsTransferFailed      = 0x002F,
104    #[error("Created account size does not match the expected size")]
105    CreatedAccountSizeMismatch  = 0x0030,
106    #[error("Attempting to execute a trade with zero volume is not allowed")]
107    ZeroVolumeTradeAttempt      = 0x0031,
108    #[error("Trade operation attempted outside allowed activity hours or while pool is inactive")]
109    TradeOutsideActivePeriod    = 0x0032,
110    #[error("Cannot participate in more than 128 pools simultaneously as LP")]
111    MaxPoolsParticipationReached= 0x0033,
112    #[error("Attempt to sell more pool tokens than owned")]
113    PoolTokenSaleExceedsHoldings= 0x0034,
114    #[error("Trade exceeds maximum allowed deposit in pool, cannot proceed")]
115    DepositExceedsPoolLimit     = 0x0035,
116    #[error("Worker account in transaction does not match the one specified in instruction")]
117    WorkerAccountMismatch       = 0x0036,
118    #[error("Specified pool index exceeds maximum limit or is not valid")]
119    PoolIndexOutOfRange         = 0x0037,
120    #[error("Cannot proceed; settlement price not set or pool yet to be finalized")]
121    SettlementPriceUnavailable  = 0x0038,
122    #[error("Attempt to claim payoff before pool expiration is not allowed")]
123    EarlyPayoffAttempt          = 0x0039,
124    #[error("Invalid access to pool data for the client or worker account")]
125    InvalidPoolAccess           = 0x003A,
126    #[error("Worker state is not valid for task assignment; must be in 'Assigned' state")]
127    WorkerInvalidStateForTask   = 0x003B,
128    #[error("Worker's task duration cannot be zero; set a valid duration")]
129    WorkerDurationZero          = 0x003C,
130    #[error("Worker's initial offering price cannot be below ID; ensure correct price setup")]
131    WorkerInitPxBelowID         = 0x003D,
132    #[error("Worker's width factor cannot exceed ID; adjust width factor")]
133    WorkerWidthFactorExceedsID  = 0x003E,
134    #[error("Worker's fee rate is out of acceptable bounds; ensure fee rate is within limits")]
135    WorkerFeeRateOutOfBounds    = 0x003F,
136    #[error("Worker's fee ratio is out of acceptable bounds; adjust fee ratio to fit within limits")]
137    WorkerFeeRatioOutOfBounds   = 0x0040,
138    #[error("Worker's inventories ratio is out of acceptable bounds; ensure inventories ratio is within limits")]
139    WorkerInvRatioOutOfBounds   = 0x0041,
140    #[error("Transaction must be executed by KYC administrator only, but current signer is not authorized")]
141    KycAdminOnlyTransaction     = 0x0042,
142    #[error("Token account owner does not match expected SPL Token program")]
143    TokenOwnerMismatch          = 0x0043,
144    #[error("Token account's mint does not match the specified mint account")]
145    TokenMintMismatch           = 0x0044,
146    #[error("Account is not initialized")]
147    AccountUninitialized        = 0x0045,
148    #[error("Token account's public key does not match the expected")]
149    TokenPkMismatch             = 0x0046,
150    #[error("Program token account does not match the specified program account")]
151    ProgramTokenAccMismatch     = 0x0047,
152    #[error("Token transfer failed")]
153    TransferFailed              = 0x0048,
154    #[error("Token transfer execution failed")]
155    TransferExecutionFailed     = 0x0049,
156    #[error("Insufficient balance for withdrawal")]
157    InsufficientBalance         = 0x004A,
158    #[error("Attempted to invoke a non-existent smart contract instruction; check the instruction number")]
159    InvalidInstruction          = 0x004B,
160    #[error("Migration is not implemented for this account or version, please check SDK")]
161    MigrationNotImplemented     = 0x004C,
162    #[error("Current version of the migrating account doesn't match, please check SDK")]
163    InvalidOldMigrationVersion  = 0x004D,
164    #[error("New version of the migrating account doesn't match, please check SDK")]
165    InvalidNewMigrationVersion  = 0x004E,
166    #[error("Migration is not successful, please check SDK")]
167    MigrationFailed             = 0x004F,
168    #[error("Invalid strike id in the basket, must be less than BUCKETS_COUNT")]
169    InvalidBasketStrikeId       = 0x0050,
170    #[error("Trading basket length is greater than Pool Log can save")]
171    BasketLengthIsTooBig        = 0x0051,
172
173    #[error("Test abort")]
174    TestAbort                   = 0xFFFE,
175    // ↑ *** Add new errors above *** ↑
176    #[error("Unknown error code, please update SDK version to get detailed message")]
177    UnknownError          = 0xFFFF,
178
179}
180
181#[repr(u8)]
182#[derive(Copy, Clone, Debug, EnumIter, FromRepr, PartialEq)]
183pub enum AccountTag {
184    // Equals to the account tags (WORKER_ACCOUNT_TAG, ROOT_ACCOUNT_TAG etc.)
185    Root                = 0x00,
186    Mints               = 0x01,
187    Instruments         = 0x02,
188    AllWorkers          = 0x03,
189    PoolsTrace          = 0x04,
190    TasksTrace          = 0x05,
191    PoolsLog            = 0x06,
192    Worker              = 0x07,
193    Client              = 0x08,
194    PayoffLog           = 0x09,
195    MintLog             = 0x0A,
196    TasksLog            = 0x0B,
197    TradeLog            = 0x0C,
198    Oracle              = 0x0D,
199    // Other accounts
200    Admin               = 0x0E,   // Connected admin wallet
201    SystemProgram       = 0x0F,   // PublicKey(0)
202    Target              = 0x10,   // For the case when the target account will be determined at runtime
203    ExternalOracle      = 0x11,
204    Wallet              = 0x12,   // Connected wallet account
205    KycAdmin            = 0x13,   // Connected KYC admin wallet
206    ClientToken         = 0x14,
207    ProgramToken        = 0x15,
208    Buffer              = 0x16,
209    // ↑ *** Add new account tags above *** ↑
210    AccountDecodeError  = 0xFF, // Unknown account code
211}
212
213impl AccountTag {
214    pub fn from_u8(value: u8) -> Self {
215        let tag = Self::from_repr(value);
216        if let Some(tag) = tag {
217            tag
218        } else {
219            Self::AccountDecodeError
220        }
221    }
222}
223
224impl ContractError {
225    pub fn from_u16(value: u16) -> Self {
226        let error_code = Self::from_repr(value);
227        if let Some(error_code) = error_code {
228            error_code
229        } else {
230            Self::UnknownError
231        }
232    }
233}
234
235#[cfg(test)]
236mod tests {
237    use crate::dvl_error::DvlError;
238    use crate::errors::{AccountTag, ContractError};
239
240    #[test]
241    fn test_display_error() {
242        let error = DvlError::new_with_account(AccountTag::MintLog, ContractError::AccountSize);
243        assert_eq!(format!("{}", error), "Error: Incorrect account size, Account: MintLog");
244    }
245}