1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
//! Home of the Proof of Stake contract's [`Error`] type.

use core::result;

/// Errors which can occur while executing the Proof of Stake contract.
#[derive(Debug, PartialEq)]
// TODO: Split this up into user errors vs. system errors.
#[repr(u8)]
pub enum Error {
    // ===== User errors =====
    /// The given validator is not bonded.
    NotBonded = 0,
    /// There are too many bonding or unbonding attempts already enqueued to allow more.
    TooManyEventsInQueue,
    /// At least one validator must remain bonded.
    CannotUnbondLastValidator,
    /// Failed to bond or unbond as this would have resulted in exceeding the maximum allowed
    /// difference between the largest and smallest stakes.
    SpreadTooHigh,
    /// The given validator already has a bond or unbond attempt enqueued.
    MultipleRequests,
    /// Attempted to bond with a stake which was too small.
    BondTooSmall,
    /// Attempted to bond with a stake which was too large.
    BondTooLarge,
    /// Attempted to unbond an amount which was too large.
    UnbondTooLarge,
    /// While bonding, the transfer from source purse to the Proof of Stake internal purse failed.
    BondTransferFailed,
    /// While unbonding, the transfer from the Proof of Stake internal purse to the destination
    /// purse failed.
    UnbondTransferFailed,
    // ===== System errors =====
    /// Internal error: a [`BlockTime`](crate::BlockTime) was unexpectedly out of sequence.
    TimeWentBackwards,
    /// Internal error: stakes were unexpectedly empty.
    StakesNotFound,
    /// Internal error: the PoS contract's payment purse wasn't found.
    PaymentPurseNotFound,
    /// Internal error: the PoS contract's payment purse key was the wrong type.
    PaymentPurseKeyUnexpectedType,
    /// Internal error: couldn't retrieve the balance for the PoS contract's payment purse.
    PaymentPurseBalanceNotFound,
    /// Internal error: the PoS contract's bonding purse wasn't found.
    BondingPurseNotFound,
    /// Internal error: the PoS contract's bonding purse key was the wrong type.
    BondingPurseKeyUnexpectedType,
    /// Internal error: the PoS contract's refund purse key was the wrong type.
    RefundPurseKeyUnexpectedType,
    /// Internal error: the PoS contract's rewards purse wasn't found.
    RewardsPurseNotFound,
    /// Internal error: the PoS contract's rewards purse key was the wrong type.
    RewardsPurseKeyUnexpectedType,
    // TODO: Put these in their own enum, and wrap them separately in `BondingError` and
    //       `UnbondingError`.
    /// Internal error: failed to deserialize the stake's key.
    StakesKeyDeserializationFailed,
    /// Internal error: failed to deserialize the stake's balance.
    StakesDeserializationFailed,
    /// The invoked PoS function can only be called by system contracts, but was called by a user
    /// contract.
    SystemFunctionCalledByUserAccount,
    /// Internal error: while finalizing payment, the amount spent exceeded the amount available.
    InsufficientPaymentForAmountSpent,
    /// Internal error: while finalizing payment, failed to pay the validators (the transfer from
    /// the PoS contract's payment purse to rewards purse failed).
    FailedTransferToRewardsPurse,
    /// Internal error: while finalizing payment, failed to refund the caller's purse (the transfer
    /// from the PoS contract's payment purse to refund purse or account's main purse failed).
    FailedTransferToAccountPurse,
    /// PoS contract's "set_refund_purse" method can only be called by the payment code of a
    /// deploy, but was called by the session code.
    SetRefundPurseCalledOutsidePayment,
}

/// An alias for `Result<T, pos::Error>`.
pub type Result<T> = result::Result<T, Error>;

// This error type is not intended to be used by third party crates.
#[doc(hidden)]
pub enum PurseLookupError {
    KeyNotFound,
    KeyUnexpectedType,
}

// This error type is not intended to be used by third party crates.
#[doc(hidden)]
impl PurseLookupError {
    pub fn bonding(err: PurseLookupError) -> Error {
        match err {
            PurseLookupError::KeyNotFound => Error::BondingPurseNotFound,
            PurseLookupError::KeyUnexpectedType => Error::BondingPurseKeyUnexpectedType,
        }
    }

    pub fn payment(err: PurseLookupError) -> Error {
        match err {
            PurseLookupError::KeyNotFound => Error::PaymentPurseNotFound,
            PurseLookupError::KeyUnexpectedType => Error::PaymentPurseKeyUnexpectedType,
        }
    }

    pub fn rewards(err: PurseLookupError) -> Error {
        match err {
            PurseLookupError::KeyNotFound => Error::RewardsPurseNotFound,
            PurseLookupError::KeyUnexpectedType => Error::RewardsPurseKeyUnexpectedType,
        }
    }
}