casper_types/system/mint/
error.rs

1//! Home of the Mint contract's [`enum@Error`] type.
2
3use alloc::vec::Vec;
4use core::{
5    convert::{TryFrom, TryInto},
6    fmt::{self, Display, Formatter},
7};
8
9use crate::{
10    bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH},
11    CLType, CLTyped,
12};
13
14/// Errors which can occur while executing the Mint contract.
15#[derive(Debug, Copy, Clone, PartialEq, Eq)]
16#[repr(u8)]
17#[non_exhaustive]
18pub enum Error {
19    /// Insufficient funds to complete the transfer.
20    /// ```
21    /// # use casper_types::system::mint::Error;
22    /// assert_eq!(0, Error::InsufficientFunds as u8);
23    /// ```
24    InsufficientFunds = 0,
25    /// Source purse not found.
26    /// ```
27    /// # use casper_types::system::mint::Error;
28    /// assert_eq!(1, Error::SourceNotFound as u8);
29    /// ```
30    SourceNotFound = 1,
31    /// Destination purse not found.
32    /// ```
33    /// # use casper_types::system::mint::Error;
34    /// assert_eq!(2, Error::DestNotFound as u8);
35    /// ```
36    DestNotFound = 2,
37    /// The given [`URef`](crate::URef) does not reference the account holder's purse, or such a
38    /// `URef` does not have the required [`AccessRights`](crate::AccessRights).
39    /// ```
40    /// # use casper_types::system::mint::Error;
41    /// assert_eq!(3, Error::InvalidURef as u8);
42    /// ```
43    InvalidURef = 3,
44    /// The source purse is not writeable (see [`URef::is_writeable`](crate::URef::is_writeable)),
45    /// or the destination purse is not addable (see
46    /// [`URef::is_addable`](crate::URef::is_addable)).
47    /// ```
48    /// # use casper_types::system::mint::Error;
49    /// assert_eq!(4, Error::InvalidAccessRights as u8);
50    /// ```
51    InvalidAccessRights = 4,
52    /// Tried to create a new purse with a non-zero initial balance.
53    /// ```
54    /// # use casper_types::system::mint::Error;
55    /// assert_eq!(5, Error::InvalidNonEmptyPurseCreation as u8);
56    /// ```
57    InvalidNonEmptyPurseCreation = 5,
58    /// Failed to read from local or global storage.
59    /// ```
60    /// # use casper_types::system::mint::Error;
61    /// assert_eq!(6, Error::Storage as u8);
62    /// ```
63    Storage = 6,
64    /// Purse not found while trying to get balance.
65    /// ```
66    /// # use casper_types::system::mint::Error;
67    /// assert_eq!(7, Error::PurseNotFound as u8);
68    /// ```
69    PurseNotFound = 7,
70    /// Unable to obtain a key by its name.
71    /// ```
72    /// # use casper_types::system::mint::Error;
73    /// assert_eq!(8, Error::MissingKey as u8);
74    /// ```
75    MissingKey = 8,
76    /// Total supply not found.
77    /// ```
78    /// # use casper_types::system::mint::Error;
79    /// assert_eq!(9, Error::TotalSupplyNotFound as u8);
80    /// ```
81    TotalSupplyNotFound = 9,
82    /// Failed to record transfer.
83    /// ```
84    /// # use casper_types::system::mint::Error;
85    /// assert_eq!(10, Error::RecordTransferFailure as u8);
86    /// ```
87    RecordTransferFailure = 10,
88    /// Invalid attempt to reduce total supply.
89    /// ```
90    /// # use casper_types::system::mint::Error;
91    /// assert_eq!(11, Error::InvalidTotalSupplyReductionAttempt as u8);
92    /// ```
93    InvalidTotalSupplyReductionAttempt = 11,
94    /// Failed to create new uref.
95    /// ```
96    /// # use casper_types::system::mint::Error;
97    /// assert_eq!(12, Error::NewURef as u8);
98    /// ```
99    NewURef = 12,
100    /// Failed to put key.
101    /// ```
102    /// # use casper_types::system::mint::Error;
103    /// assert_eq!(13, Error::PutKey as u8);
104    /// ```
105    PutKey = 13,
106    /// Failed to write to dictionary.
107    /// ```
108    /// # use casper_types::system::mint::Error;
109    /// assert_eq!(14, Error::WriteDictionary as u8);
110    /// ```
111    WriteDictionary = 14,
112    /// Failed to create a [`crate::CLValue`].
113    /// ```
114    /// # use casper_types::system::mint::Error;
115    /// assert_eq!(15, Error::CLValue as u8);
116    /// ```
117    CLValue = 15,
118    /// Failed to serialize data.
119    /// ```
120    /// # use casper_types::system::mint::Error;
121    /// assert_eq!(16, Error::Serialize as u8);
122    /// ```
123    Serialize = 16,
124    /// Source and target purse [`crate::URef`]s are equal.
125    /// ```
126    /// # use casper_types::system::mint::Error;
127    /// assert_eq!(17, Error::EqualSourceAndTarget as u8);
128    /// ```
129    EqualSourceAndTarget = 17,
130    /// An arithmetic overflow has occurred.
131    /// ```
132    /// # use casper_types::system::mint::Error;
133    /// assert_eq!(18, Error::ArithmeticOverflow as u8);
134    /// ```
135    ArithmeticOverflow = 18,
136
137    // NOTE: These variants below will be removed once support for WASM system contracts will be
138    // dropped.
139    #[doc(hidden)]
140    GasLimit = 19,
141
142    /// Raised when an entry point is called from invalid account context.
143    InvalidContext = 20,
144
145    /// Session code tried to transfer more CSPR than user approved.
146    /// ```
147    /// # use casper_types::system::mint::Error;
148    /// assert_eq!(21, Error::UnapprovedSpendingAmount as u8);
149    UnapprovedSpendingAmount = 21,
150
151    /// Failed to transfer tokens on a private chain.
152    /// ```
153    /// # use casper_types::system::mint::Error;
154    /// assert_eq!(22, Error::DisabledUnrestrictedTransfers as u8);
155    DisabledUnrestrictedTransfers = 22,
156
157    /// Attempt to access a record using forged permissions.
158    /// ```
159    /// # use casper_types::system::mint::Error;
160    /// assert_eq!(23, Error::ForgedReference as u8);
161    ForgedReference = 23,
162    /// Available balance can never be greater than total balance.
163    /// ```
164    /// # use casper_types::system::mint::Error;
165    /// assert_eq!(24, Error::InconsistentBalances as u8);
166    InconsistentBalances = 24,
167    /// Unable to get the system registry.
168    /// ```
169    /// # use casper_types::system::mint::Error;
170    /// assert_eq!(25, Error::UnableToGetSystemRegistry as u8);
171    UnableToGetSystemRegistry = 25,
172
173    #[cfg(test)]
174    #[doc(hidden)]
175    Sentinel,
176}
177
178/// Used for testing; this should be guaranteed to be the maximum valid value of [`Error`] enum.
179#[cfg(test)]
180const MAX_ERROR_VALUE: u8 = Error::Sentinel as u8;
181
182impl CLTyped for Error {
183    fn cl_type() -> CLType {
184        CLType::U8
185    }
186}
187
188// This error type is not intended to be used by third party crates.
189#[doc(hidden)]
190pub struct TryFromU8ForError(());
191
192// This conversion is not intended to be used by third party crates.
193#[doc(hidden)]
194impl TryFrom<u8> for Error {
195    type Error = TryFromU8ForError;
196
197    fn try_from(value: u8) -> Result<Self, Self::Error> {
198        match value {
199            d if d == Error::InsufficientFunds as u8 => Ok(Error::InsufficientFunds),
200            d if d == Error::SourceNotFound as u8 => Ok(Error::SourceNotFound),
201            d if d == Error::DestNotFound as u8 => Ok(Error::DestNotFound),
202            d if d == Error::InvalidURef as u8 => Ok(Error::InvalidURef),
203            d if d == Error::InvalidAccessRights as u8 => Ok(Error::InvalidAccessRights),
204            d if d == Error::InvalidNonEmptyPurseCreation as u8 => {
205                Ok(Error::InvalidNonEmptyPurseCreation)
206            }
207            d if d == Error::Storage as u8 => Ok(Error::Storage),
208            d if d == Error::PurseNotFound as u8 => Ok(Error::PurseNotFound),
209            d if d == Error::MissingKey as u8 => Ok(Error::MissingKey),
210            d if d == Error::TotalSupplyNotFound as u8 => Ok(Error::TotalSupplyNotFound),
211            d if d == Error::RecordTransferFailure as u8 => Ok(Error::RecordTransferFailure),
212            d if d == Error::InvalidTotalSupplyReductionAttempt as u8 => {
213                Ok(Error::InvalidTotalSupplyReductionAttempt)
214            }
215            d if d == Error::NewURef as u8 => Ok(Error::NewURef),
216            d if d == Error::PutKey as u8 => Ok(Error::PutKey),
217            d if d == Error::WriteDictionary as u8 => Ok(Error::WriteDictionary),
218            d if d == Error::CLValue as u8 => Ok(Error::CLValue),
219            d if d == Error::Serialize as u8 => Ok(Error::Serialize),
220            d if d == Error::EqualSourceAndTarget as u8 => Ok(Error::EqualSourceAndTarget),
221            d if d == Error::ArithmeticOverflow as u8 => Ok(Error::ArithmeticOverflow),
222            d if d == Error::GasLimit as u8 => Ok(Error::GasLimit),
223            d if d == Error::InvalidContext as u8 => Ok(Error::InvalidContext),
224            d if d == Error::UnapprovedSpendingAmount as u8 => Ok(Error::UnapprovedSpendingAmount),
225            d if d == Error::DisabledUnrestrictedTransfers as u8 => {
226                Ok(Error::DisabledUnrestrictedTransfers)
227            }
228            d if d == Error::ForgedReference as u8 => Ok(Error::ForgedReference),
229            d if d == Error::InconsistentBalances as u8 => Ok(Error::InconsistentBalances),
230            d if d == Error::UnableToGetSystemRegistry as u8 => {
231                Ok(Error::UnableToGetSystemRegistry)
232            }
233            _ => Err(TryFromU8ForError(())),
234        }
235    }
236}
237
238impl ToBytes for Error {
239    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
240        let value = *self as u8;
241        value.to_bytes()
242    }
243
244    fn serialized_length(&self) -> usize {
245        U8_SERIALIZED_LENGTH
246    }
247}
248
249impl FromBytes for Error {
250    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
251        let (value, rem): (u8, _) = FromBytes::from_bytes(bytes)?;
252        let error: Error = value
253            .try_into()
254            // In case an Error variant is unable to be determined it would return an
255            // Error::Formatting as if its unable to be correctly deserialized.
256            .map_err(|_| bytesrepr::Error::Formatting)?;
257        Ok((error, rem))
258    }
259}
260
261impl Display for Error {
262    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
263        match self {
264            Error::InsufficientFunds => formatter.write_str("Insufficient funds"),
265            Error::SourceNotFound => formatter.write_str("Source not found"),
266            Error::DestNotFound => formatter.write_str("Destination not found"),
267            Error::InvalidURef => formatter.write_str("Invalid URef"),
268            Error::InvalidAccessRights => formatter.write_str("Invalid AccessRights"),
269            Error::InvalidNonEmptyPurseCreation => {
270                formatter.write_str("Invalid non-empty purse creation")
271            }
272            Error::Storage => formatter.write_str("Storage error"),
273            Error::PurseNotFound => formatter.write_str("Purse not found"),
274            Error::MissingKey => formatter.write_str("Missing key"),
275            Error::TotalSupplyNotFound => formatter.write_str("Total supply not found"),
276            Error::RecordTransferFailure => formatter.write_str("Failed to record transfer"),
277            Error::InvalidTotalSupplyReductionAttempt => {
278                formatter.write_str("Invalid attempt to reduce total supply")
279            }
280            Error::NewURef => formatter.write_str("Failed to create new uref"),
281            Error::PutKey => formatter.write_str("Failed to put key"),
282            Error::WriteDictionary => formatter.write_str("Failed to write dictionary"),
283            Error::CLValue => formatter.write_str("Failed to create a CLValue"),
284            Error::Serialize => formatter.write_str("Failed to serialize data"),
285            Error::EqualSourceAndTarget => formatter.write_str("Invalid target purse"),
286            Error::ArithmeticOverflow => formatter.write_str("Arithmetic overflow has occurred"),
287            Error::GasLimit => formatter.write_str("GasLimit"),
288            Error::InvalidContext => formatter.write_str("Invalid context"),
289            Error::UnapprovedSpendingAmount => formatter.write_str("Unapproved spending amount"),
290            Error::DisabledUnrestrictedTransfers => {
291                formatter.write_str("Disabled unrestricted transfers")
292            }
293            Error::ForgedReference => formatter.write_str("Forged reference"),
294            Error::InconsistentBalances => {
295                formatter.write_str("Available balance can never be greater than total balance")
296            }
297            Error::UnableToGetSystemRegistry => {
298                formatter.write_str("Unable to get the system registry")
299            }
300            #[cfg(test)]
301            Error::Sentinel => formatter.write_str("Sentinel error"),
302        }
303    }
304}
305
306#[cfg(test)]
307mod tests {
308    use super::{Error, TryFromU8ForError, MAX_ERROR_VALUE};
309
310    #[test]
311    fn error_round_trips() {
312        for i in 0..=u8::MAX {
313            match Error::try_from(i) {
314                Ok(error) if i < MAX_ERROR_VALUE => assert_eq!(error as u8, i),
315                Ok(error) => panic!(
316                    "value of variant {:?} ({}) exceeds MAX_ERROR_VALUE ({})",
317                    error, i, MAX_ERROR_VALUE
318                ),
319                Err(TryFromU8ForError(())) if i >= MAX_ERROR_VALUE => (),
320                Err(TryFromU8ForError(())) => {
321                    panic!("missing conversion from u8 to error value: {}", i)
322                }
323            }
324        }
325    }
326}