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 #[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 #[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#[derive(Error, Debug)]
707pub enum Never {}
708
709pub fn from_semver(err: semver::Error) -> StdError {
710 StdError::generic_err(format!("Semver: {err}"))
711}