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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::{Config, InterestRateModel};
use codec::MaxEncodedLen;
use currency::Amount;
use frame_support::pallet_prelude::*;
use primitives::{CurrencyId, Liquidity, Rate, Ratio, Shortfall};
use scale_info::TypeInfo;

// TODO: `cargo doc` crashes on this type, remove the `hidden` macro
// when upgrading rustc in case that fixes it
/// Container for account liquidity information
#[doc(hidden)]
#[derive(Eq, PartialEq, Clone, RuntimeDebug)]
pub enum AccountLiquidity<T: Config> {
    Liquidity(Amount<T>),
    Shortfall(Amount<T>),
}

impl<T: Config> AccountLiquidity<T> {
    pub fn from_collateral_and_debt(
        collateral_value: Amount<T>,
        borrow_value: Amount<T>,
    ) -> Result<Self, DispatchError> {
        let account_liquidity = if collateral_value.gt(&borrow_value)? {
            AccountLiquidity::Liquidity(collateral_value.checked_sub(&borrow_value)?)
        } else {
            AccountLiquidity::Shortfall(borrow_value.checked_sub(&collateral_value)?)
        };
        Ok(account_liquidity)
    }

    pub fn currency(&self) -> CurrencyId {
        match &self {
            AccountLiquidity::Liquidity(x) | AccountLiquidity::Shortfall(x) => x.currency(),
        }
    }

    pub fn liquidity(&self) -> Amount<T> {
        if let AccountLiquidity::Liquidity(x) = &self {
            return x.clone();
        }
        Amount::<T>::zero(self.currency())
    }

    pub fn shortfall(&self) -> Amount<T> {
        if let AccountLiquidity::Shortfall(x) = &self {
            return x.clone();
        }
        Amount::<T>::zero(self.currency())
    }

    pub fn to_rpc_tuple(&self) -> Result<(Liquidity, Shortfall), DispatchError> {
        Ok((
            self.liquidity().to_unsigned_fixed_point()?,
            self.shortfall().to_unsigned_fixed_point()?,
        ))
    }
}

/// Container for borrow balance information
#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)]
pub struct BorrowSnapshot<Balance> {
    /// Principal Total balance (with accrued interest), after applying the most recent balance-changing action.
    /// In other words, this is the amount of underlying borrowed that is to be paid back eventually.
    pub principal: Balance,
    /// InterestIndex Global borrowIndex as of the most recent balance-changing action
    pub borrow_index: Rate,
}

/// Container for earned amount information
#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, Default, TypeInfo)]
pub struct EarnedSnapshot<Balance> {
    /// Total deposit interest, after applying the most recent balance-changing action
    pub total_earned_prior: Balance,
    /// Exchange rate, after applying the most recent balance-changing action
    pub exchange_rate_prior: Rate,
}

/// The current state of a market. For more information, see [Market].
#[derive(
    serde::Deserialize,
    serde::Serialize,
    Encode,
    Decode,
    Eq,
    PartialEq,
    Copy,
    Clone,
    RuntimeDebug,
    TypeInfo,
    MaxEncodedLen,
)]
pub enum MarketState {
    Active,
    Pending,
    // Unclear why the `Supervision` state is required at all, since it's not used anywhere.
    // Could just reuse the `Pending` state to temporarily halt a market.
    Supervision,
}

/// Market.
///
/// A large pool of liquidity where accounts can lend and borrow.
#[derive(
    serde::Deserialize,
    serde::Serialize,
    Encode,
    Decode,
    Eq,
    PartialEq,
    Copy,
    Clone,
    RuntimeDebug,
    TypeInfo,
    MaxEncodedLen,
)]
pub struct Market<Balance> {
    /// The secure collateral ratio
    pub collateral_factor: Ratio,
    /// The collateral ratio when a borrower can be liquidated. Higher than the `collateral_factor` and lower than
    /// 100%.
    pub liquidation_threshold: Ratio,
    /// Fraction of interest currently set aside for reserves
    pub reserve_factor: Ratio,
    /// The percent, ranging from 0% to 100%, of a liquidatable account's
    /// borrow that can be repaid in a single liquidate transaction.
    pub close_factor: Ratio,
    /// Liquidation incentive ratio
    pub liquidate_incentive: Rate,
    /// Liquidation share set aside for reserves
    pub liquidate_incentive_reserved_factor: Ratio,
    /// Current interest rate model being used
    pub rate_model: InterestRateModel,
    /// Current market state
    pub state: MarketState,
    /// Upper bound of supplying
    pub supply_cap: Balance,
    /// Upper bound of borrowing
    pub borrow_cap: Balance,
    /// LendToken asset id
    pub lend_token_id: CurrencyId,
}

#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, Default, MaxEncodedLen)]
pub struct RewardMarketState<BlockNumber, Balance> {
    pub index: Balance,
    /// total amount of staking asset user deposited
    pub block: BlockNumber,
}