andromeda_std/
error.rs

1use cosmwasm_std::{Addr, OverflowError, StdError};
2use cw20_base::ContractError as Cw20ContractError;
3use cw721_base::ContractError as Cw721ContractError;
4use cw_asset::AssetError;
5use cw_utils::{Expiration, ParseReplyError, PaymentError};
6use hex::FromHexError;
7use std::convert::From;
8use std::str::{ParseBoolError, Utf8Error};
9use std::string::FromUtf8Error;
10use thiserror::Error;
11
12#[derive(Error, Debug, PartialEq)]
13pub enum ContractError {
14    #[error("{0}")]
15    Std(#[from] StdError),
16
17    #[error("{0}")]
18    Hex(#[from] FromHexError),
19
20    #[error("{0}")]
21    Payment(#[from] PaymentError),
22
23    #[error("{0}")]
24    ParseReplyError(#[from] ParseReplyError),
25
26    #[error("Unauthorized")]
27    Unauthorized {},
28
29    #[error("UnpublishedCodeID")]
30    UnpublishedCodeID {},
31
32    #[error("UnpublishedVersion")]
33    UnpublishedVersion {},
34
35    #[error("ContractLocked")]
36    ContractLocked {},
37
38    #[error("UnidentifiedMsgID")]
39    UnidentifiedMsgID {},
40
41    #[error("UnmetCondition")]
42    UnmetCondition {},
43
44    #[error("InvalidOrigin")]
45    InvalidOrigin {},
46
47    #[error("InvalidSender")]
48    InvalidSender {},
49
50    #[error("RewardTooLow")]
51    RewardTooLow {},
52
53    #[error("IncompleteUnbondingPeriod")]
54    IncompleteUnbondingPeriod {},
55
56    #[error("LockedNFT")]
57    LockedNFT {},
58
59    #[error("UserNotFound")]
60    UserNotFound {},
61
62    #[error("ProcessNotFound")]
63    ProcessNotFound {},
64
65    #[error("only unordered channels are supported")]
66    OrderedChannel {},
67
68    #[error("invalid IBC channel version - got ({actual}), expected ({expected})")]
69    InvalidVersion { actual: String, expected: String },
70
71    #[error("CrossChainComponentsCurrentlyDisabled")]
72    CrossChainComponentsCurrentlyDisabled {},
73
74    #[error("tokenId list has different length than tokenUri list")]
75    TokenInfoLenMissmatch {},
76
77    #[error("ICS 721 channels may not be closed")]
78    CantCloseChannel {},
79
80    #[error("Paused")]
81    Paused {},
82
83    #[error("EmptyOptional")]
84    EmptyOptional {},
85
86    #[error("EmptyOptional")]
87    EmptyClassId {},
88
89    #[error("NoTokens")]
90    NoTokens {},
91
92    #[error("UnrecognisedReplyId")]
93    UnrecognisedReplyId {},
94
95    #[error("ImbalancedTokenInfo")]
96    ImbalancedTokenInfo {},
97
98    #[error("UnsupportedNFT")]
99    UnsupportedNFT {},
100
101    #[error("UnsupportedReturnType")]
102    UnsupportedReturnType {},
103
104    #[error("UnsupportedProtocol")]
105    UnsupportedProtocol {},
106
107    #[error("AlreadyUnbonded")]
108    AlreadyUnbonded {},
109
110    #[error("NFTNotFound")]
111    NFTNotFound {},
112
113    #[error("PriceNotSet")]
114    PriceNotSet {},
115
116    #[error("InvalidPrimitive")]
117    InvalidPrimitive {},
118
119    #[error("StillBonded")]
120    StillBonded {},
121
122    #[error("ParseBoolError")]
123    ParseBoolError {},
124
125    #[error("NoResponseElementNeeded")]
126    NoResponseElementNeeded {},
127
128    #[error("ResponseElementRequired")]
129    ResponseElementRequired {},
130
131    #[error("InsufficientBondedTime")]
132    InsufficientBondedTime {},
133
134    #[error("LockTimeTooShort")]
135    LockTimeTooShort {},
136
137    #[error("LockTimeTooLong")]
138    LockTimeTooLong {},
139
140    #[error("InvalidWeight")]
141    InvalidWeight {},
142
143    #[error("NoResults")]
144    NoResults {},
145
146    #[error("NotEnoughTokens")]
147    NotEnoughTokens {},
148
149    #[error("MissingParameters")]
150    MissingParameters {},
151
152    #[error("OnlyOneSourceAllowed")]
153    OnlyOneSourceAllowed {},
154
155    #[error("IllegalTokenName")]
156    IllegalTokenName {},
157
158    #[error("IllegalTokenSymbol")]
159    IllegalTokenSymbol {},
160
161    #[error("Refilling")]
162    Refilling {},
163
164    #[error("WithdrawalLimitExceeded")]
165    WithdrawalLimitExceeded {},
166
167    #[error("CoinNotFound")]
168    CoinNotFound {},
169
170    #[error("NotInRefillMode")]
171    NotInRefillMode {},
172
173    #[error("NotEnoughResults")]
174    NotEnoughResults {},
175
176    #[error("ReachedRecipientLimit")]
177    ReachedRecipientLimit {},
178
179    #[error("MinterBlacklisted")]
180    MinterBlacklisted {},
181
182    #[error("EmptyRecipientsList")]
183    EmptyRecipientsList {},
184
185    #[error("AmountExceededHundredPrecent")]
186    AmountExceededHundredPrecent {},
187
188    #[error("InvalidAddress")]
189    InvalidAddress {},
190
191    #[error("ExpirationInPast")]
192    ExpirationInPast {},
193
194    #[error("ExecuteError")]
195    ExecuteError {},
196
197    #[error("UnspecifiedWithdrawalFrequency")]
198    UnspecifiedWithdrawalFrequency {},
199
200    #[error("ExpirationNotSpecified")]
201    ExpirationNotSpecified {},
202
203    #[error("CannotOverwriteHeldFunds")]
204    CannotOverwriteHeldFunds {},
205
206    #[error("ContractAddressNotInAddressList")]
207    ContractAddressNotInAddressList {},
208
209    #[error("ModuleNotUnique")]
210    ModuleNotUnique {},
211
212    #[error("InvalidRate")]
213    InvalidRate {},
214
215    #[error("InsufficientFunds")]
216    InsufficientFunds {},
217
218    #[error("NoPendingPayments")]
219    NoPendingPayments {},
220
221    #[error("NoReceivingAddress")]
222    NoReceivingAddress {},
223
224    #[error("TemporarilyDisabled")]
225    TemporarilyDisabled {},
226
227    #[error("AccountNotFound")]
228    AccountNotFound {},
229
230    #[error("ModuleDiscriptionTooLong: {msg}")]
231    ModuleDiscriptionTooLong { msg: String },
232
233    #[error("SymbolInUse")]
234    SymbolInUse {},
235
236    #[error("ExceedsMaxAllowedCoins")]
237    ExceedsMaxAllowedCoins {},
238
239    #[error("NoLockedFunds")]
240    NoLockedFunds {},
241
242    #[error("FundsAreLocked")]
243    FundsAreLocked {},
244
245    #[error("InvalidTokenNameLength: {msg}")]
246    InvalidTokenNameLength { msg: String },
247
248    #[error("TokenIsArchived")]
249    TokenIsArchived {},
250
251    #[error("AuctionDoesNotExist")]
252    AuctionDoesNotExist {},
253
254    #[error("SaleDoesNotExist")]
255    SaleDoesNotExist {},
256
257    #[error("AuctionNotStarted")]
258    AuctionNotStarted {},
259
260    #[error("AuctionEnded")]
261    AuctionEnded {},
262
263    #[error("SaleNotStarted")]
264    SaleNotStarted {},
265
266    #[error("SaleEnded")]
267    SaleEnded {},
268
269    #[error("SaleNotOpen")]
270    SaleNotOpen {},
271
272    #[error("SaleExpired")]
273    SaleExpired {},
274
275    #[error("SaleExecuted")]
276    SaleExecuted {},
277
278    #[error("SaleCancelled")]
279    SaleCancelled {},
280
281    #[error("NoTargetADOs")]
282    NoTargetADOs {},
283
284    #[error("TokenOwnerCannotBid")]
285    TokenOwnerCannotBid {},
286
287    #[error("TokenOwnerCannotBuy")]
288    TokenOwnerCannotBuy {},
289
290    #[error("BidSmallerThanHighestBid")]
291    BidSmallerThanHighestBid {},
292
293    #[error("Overflow")]
294    Overflow {},
295
296    #[error("Underflow")]
297    Underflow {},
298
299    #[error("CannotWithdrawHighestBid")]
300    CannotWithdrawHighestBid {},
301
302    #[error("WithdrawalIsEmpty")]
303    WithdrawalIsEmpty {},
304
305    #[error("AuctionAlreadyStarted")]
306    AuctionAlreadyStarted {},
307
308    #[error("StartTimeAfterEndTime")]
309    StartTimeAfterEndTime {},
310
311    #[error("Start time in past. Current time: {current_time}. Current block: {current_block}")]
312    StartTimeInThePast {
313        current_time: u64,
314        current_block: u64,
315    },
316
317    #[error("OutOfNFTs")]
318    OutOfNFTs {},
319
320    #[error("HighestBidderCannotOutBid")]
321    HighestBidderCannotOutBid {},
322
323    #[error("InvalidFunds: {msg}")]
324    InvalidFunds { msg: String },
325
326    #[error("InvalidADOVersion: {msg:?}")]
327    InvalidADOVersion { msg: Option<String> },
328
329    #[error("InvalidCodeID: {msg:?}")]
330    InvalidCodeID { msg: Option<String> },
331
332    #[error("InvalidADOType: {msg:?}")]
333    InvalidADOType { msg: Option<String> },
334
335    #[error("AuctionRewardAlreadyClaimed")]
336    AuctionAlreadyClaimed {},
337
338    #[error("SaleAlreadyConducted")]
339    SaleAlreadyConducted {},
340
341    #[error("AuctionNotEnded")]
342    AuctionNotEnded {},
343
344    #[error("AuctionCancelled")]
345    AuctionCancelled {},
346
347    #[error("ExpirationMustNotBeNever")]
348    ExpirationMustNotBeNever {},
349
350    #[error("ExpirationsMustBeOfSameType")]
351    ExpirationsMustBeOfSameType {},
352
353    #[error("MoreThanOneCoin")]
354    MoreThanOneCoin {},
355
356    #[error("InvalidReplyId")]
357    InvalidReplyId {},
358
359    #[error("ParsingError: {err}")]
360    ParsingError { err: String },
361
362    #[error("MissingRequiredMessageData")]
363    MissingRequiredMessageData {},
364
365    #[error("Cannot migrate from different contract type: {previous_contract}")]
366    CannotMigrate { previous_contract: String },
367
368    #[error("NestedAndromedaMsg")]
369    NestedAndromedaMsg {},
370
371    #[error("UnexpectedExternalRate")]
372    UnexpectedExternalRate {},
373
374    #[error("DuplicateCoinDenoms")]
375    DuplicateCoinDenoms {},
376
377    #[error("DuplicateRecipient")]
378    DuplicateRecipient {},
379
380    #[error("DuplicateContract")]
381    DuplicateContract {},
382
383    // BEGIN CW20 ERRORS
384    #[error("Cannot set to own account")]
385    CannotSetOwnAccount {},
386
387    #[error("Invalid zero amount")]
388    InvalidZeroAmount {},
389
390    #[error("Allowance is expired")]
391    Expired {},
392
393    #[error("No allowance for this account")]
394    NoAllowance {},
395
396    #[error("Minting cannot exceed the cap")]
397    CannotExceedCap {},
398
399    #[error("Logo binary data exceeds 5KB limit")]
400    LogoTooBig {},
401
402    #[error("Invalid xml preamble for SVG")]
403    InvalidXmlPreamble {},
404
405    #[error("Invalid png header")]
406    InvalidPngHeader {},
407
408    #[error("Instantiate2 Address Mistmatch: expected: {expected}, received: {received}")]
409    Instantiate2AddressMismatch { expected: Addr, received: Addr },
410
411    #[error("Duplicate initial balance addresses")]
412    DuplicateInitialBalanceAddresses {},
413
414    // END CW20 ERRORS
415    #[error("Invalid Module, {msg:?}")]
416    InvalidModule { msg: Option<String> },
417
418    #[error("UnsupportedOperation")]
419    UnsupportedOperation {},
420
421    #[error("IncompatibleModules: {msg}")]
422    IncompatibleModules { msg: String },
423
424    #[error("ModuleDoesNotExist")]
425    ModuleDoesNotExist {},
426
427    #[error("token_id already claimed")]
428    Claimed {},
429
430    #[error("Approval not found for: {spender}")]
431    ApprovalNotFound { spender: String },
432
433    #[error("BidAlreadyPlaced")]
434    BidAlreadyPlaced {},
435
436    #[error("BidLowerThanCurrent")]
437    BidLowerThanCurrent {},
438
439    #[error("BidNotExpired")]
440    BidNotExpired {},
441
442    #[error("TransferAgreementExists")]
443    TransferAgreementExists {},
444
445    #[error("CannotDoubleWrapToken")]
446    CannotDoubleWrapToken {},
447
448    #[error("UnwrappingDisabled")]
449    UnwrappingDisabled {},
450
451    #[error("TokenNotWrappedByThisContract")]
452    TokenNotWrappedByThisContract {},
453
454    #[error("InvalidMetadata")]
455    InvalidMetadata {},
456
457    #[error("InvalidRecipientType: {msg}")]
458    InvalidRecipientType { msg: String },
459
460    #[error("InvalidTokensToWithdraw: {msg}")]
461    InvalidTokensToWithdraw { msg: String },
462
463    #[error("ModuleImmutable")]
464    ModuleImmutable {},
465
466    #[error("GeneratorNotSpecified")]
467    GeneratorNotSpecified {},
468
469    #[error("TooManyAppComponents")]
470    TooManyAppComponents {},
471
472    #[error("InvalidLtvRatio: {msg}")]
473    InvalidLtvRatio { msg: String },
474
475    #[error("Name already taken")]
476    NameAlreadyTaken {},
477
478    #[error("No Ongoing Sale")]
479    NoOngoingSale {},
480
481    #[error("Purchase limit reached")]
482    PurchaseLimitReached {},
483
484    #[error("Sale not ended")]
485    SaleNotEnded {},
486
487    #[error("Min sales exceeded")]
488    MinSalesExceeded {},
489
490    #[error("Limit must not be zero")]
491    LimitMustNotBeZero {},
492
493    #[error("Sale has already started")]
494    SaleStarted {},
495
496    #[error("No purchases")]
497    NoPurchases {},
498
499    #[error("Cannot mint after sale conducted")]
500    CannotMintAfterSaleConducted {},
501
502    #[error("Not implemented: {msg:?}")]
503    NotImplemented { msg: Option<String> },
504
505    #[error("Invalid Strategy: {strategy}")]
506    InvalidStrategy { strategy: String },
507
508    #[error("Invalid Query")]
509    InvalidQuery {},
510
511    #[error("Invalid Withdrawal: {msg:?}")]
512    InvalidWithdrawal { msg: Option<String> },
513
514    #[error("Airdrop stage {stage} expired at {expiration}")]
515    StageExpired { stage: u8, expiration: Expiration },
516
517    #[error("Airdrop stage {stage} not expired yet")]
518    StageNotExpired { stage: u8, expiration: Expiration },
519
520    #[error("Wrong Length")]
521    WrongLength {},
522
523    #[error("Verification Failed")]
524    VerificationFailed {},
525
526    #[error("Invalid Asset: {asset}")]
527    InvalidAsset { asset: String },
528
529    #[error("Asset Error")]
530    AssetError {},
531
532    #[error("Invalid cycle duration")]
533    InvalidCycleDuration {},
534
535    #[error("Reward increase must be less than 1")]
536    InvalidRewardIncrease {},
537
538    #[error("Max of {max} for reward tokens is exceeded")]
539    MaxRewardTokensExceeded { max: u32 },
540
541    #[error("Primitive Does Not Exist: {msg}")]
542    PrimitiveDoesNotExist { msg: String },
543
544    #[error("Token already being distributed")]
545    TokenAlreadyBeingDistributed {},
546
547    #[error("Deposit window closed")]
548    DepositWindowClosed {},
549
550    #[error("No saved auction contract")]
551    NoSavedBootstrapContract {},
552
553    #[error("Phase ongoing")]
554    PhaseOngoing {},
555
556    #[error("Claims already allowed")]
557    ClaimsAlreadyAllowed {},
558
559    #[error("ClaimsNotAllowed")]
560    ClaimsNotAllowed {},
561
562    #[error("Lockdrop already claimed")]
563    LockdropAlreadyClaimed {},
564
565    #[error("No lockup to claim rewards for")]
566    NoLockup {},
567
568    #[error("Invalid deposit/withdraw window")]
569    InvalidWindow {},
570
571    #[error("Duplicate tokens")]
572    DuplicateTokens {},
573
574    #[error("All tokens purchased")]
575    AllTokensPurchased {},
576
577    #[error("Token not available")]
578    TokenNotAvailable {},
579
580    #[error("Invalid expiration")]
581    InvalidExpiration {},
582
583    #[error("Invalid start time")]
584    InvalidStartTime {},
585
586    #[error("Too many mint messages, limit is {limit}")]
587    TooManyMintMessages { limit: u32 },
588
589    #[error("App contract not specified")]
590    AppContractNotSpecified {},
591
592    #[error("VFS contract not specified")]
593    VFSContractNotSpecified {},
594
595    #[error("JsonError")]
596    JsonError {},
597
598    #[error("Invalid component: {name}")]
599    InvalidComponent { name: String },
600
601    #[error("Multi-batch not supported")]
602    MultiBatchNotSupported {},
603
604    #[error("Unexpected number of bytes. Expected: {expected}, actual: {actual}")]
605    UnexpectedNumberOfBytes { expected: u8, actual: usize },
606
607    #[error("Not an assigned operator, {msg:?}")]
608    NotAssignedOperator { msg: Option<String> },
609
610    #[error("Invalid Expiration Time")]
611    InvalidExpirationTime {},
612
613    #[error("Invalid Pathname, {error:?}")]
614    InvalidPathname { error: Option<String> },
615
616    #[error("Invalid Username, {error:?}")]
617    InvalidUsername { error: Option<String> },
618
619    #[error("Invalid Packet, {error:?}")]
620    InvalidPacket { error: Option<String> },
621
622    #[error("Invalid Denom Trace: {denom}")]
623    InvalidDenomTrace { denom: String },
624
625    #[error("Invalid Denom Trace Path: {path} - {denom}")]
626    InvalidDenomTracePath { path: String, denom: String },
627
628    #[error("Invalid Transfer Port: {port}")]
629    InvalidTransferPort { port: String },
630
631    #[error("Invalid Modules: {msg}")]
632    InvalidModules { msg: String },
633
634    #[error("Invalid time: {msg}")]
635    InvalidTimestamp { msg: String },
636}
637
638impl From<Cw20ContractError> for ContractError {
639    fn from(err: Cw20ContractError) -> Self {
640        match err {
641            Cw20ContractError::Std(std) => ContractError::Std(std),
642            Cw20ContractError::Expired {} => ContractError::Expired {},
643            Cw20ContractError::LogoTooBig {} => ContractError::LogoTooBig {},
644            Cw20ContractError::NoAllowance {} => ContractError::NoAllowance {},
645            Cw20ContractError::Unauthorized {} => ContractError::Unauthorized {},
646            Cw20ContractError::CannotExceedCap {} => ContractError::CannotExceedCap {},
647            Cw20ContractError::InvalidPngHeader {} => ContractError::InvalidPngHeader {},
648            Cw20ContractError::InvalidXmlPreamble {} => ContractError::InvalidXmlPreamble {},
649            Cw20ContractError::CannotSetOwnAccount {} => ContractError::CannotSetOwnAccount {},
650            Cw20ContractError::DuplicateInitialBalanceAddresses {} => {
651                ContractError::DuplicateInitialBalanceAddresses {}
652            }
653            Cw20ContractError::InvalidExpiration {} => ContractError::InvalidExpiration {},
654            _ => panic!("Unsupported cw20 error: {err:?}"),
655        }
656    }
657}
658
659impl From<ParseBoolError> for ContractError {
660    fn from(_err: ParseBoolError) -> Self {
661        ContractError::ParseBoolError {}
662    }
663}
664
665impl From<Cw721ContractError> for ContractError {
666    fn from(err: Cw721ContractError) -> Self {
667        match err {
668            Cw721ContractError::Std(std) => ContractError::Std(std),
669            Cw721ContractError::Expired {} => ContractError::Expired {},
670            Cw721ContractError::Ownership(_) => ContractError::Unauthorized {},
671            Cw721ContractError::Claimed {} => ContractError::Claimed {},
672            Cw721ContractError::ApprovalNotFound { spender } => {
673                ContractError::ApprovalNotFound { spender }
674            }
675            Cw721ContractError::Version(_) => ContractError::InvalidADOVersion { msg: None },
676        }
677    }
678}
679
680impl From<FromUtf8Error> for ContractError {
681    fn from(err: FromUtf8Error) -> Self {
682        ContractError::Std(StdError::from(err))
683    }
684}
685
686impl From<Utf8Error> for ContractError {
687    fn from(err: Utf8Error) -> Self {
688        ContractError::Std(StdError::from(err))
689    }
690}
691
692impl From<OverflowError> for ContractError {
693    fn from(_err: OverflowError) -> Self {
694        ContractError::Overflow {}
695    }
696}
697
698impl From<AssetError> for ContractError {
699    fn from(_err: AssetError) -> Self {
700        ContractError::AssetError {}
701    }
702}
703
704/// Enum that can never be constructed. Used as an error type where we
705/// can not error.
706#[derive(Error, Debug)]
707pub enum Never {}
708
709pub fn from_semver(err: semver::Error) -> StdError {
710    StdError::generic_err(format!("Semver: {err}"))
711}