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
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Api, Coin, Decimal, Uint128};
use mars_utils::{
    error::ValidationError,
    helpers::{decimal_param_le_one, validate_native_denom},
};

use crate::{
    error::ContractResult,
    execute::{assert_hls_lqt_gt_max_ltv, assert_lqt_gt_max_ltv},
};

#[cw_serde]
pub struct HighLeverageStrategyParams {
    pub max_loan_to_value: Decimal,
    pub liquidation_threshold: Decimal,
}

#[cw_serde]
pub struct RoverSettings {
    pub whitelisted: bool,
    pub hls: HighLeverageStrategyParams,
}

#[cw_serde]
pub struct RedBankSettings {
    pub deposit_enabled: bool,
    pub borrow_enabled: bool,
    pub deposit_cap: Uint128,
}

#[cw_serde]
pub struct AssetParams {
    pub denom: String,
    pub rover: RoverSettings,
    pub red_bank: RedBankSettings,
    pub max_loan_to_value: Decimal,
    pub liquidation_threshold: Decimal,
    pub liquidation_bonus: Decimal,
}

impl AssetParams {
    pub fn validate(&self) -> Result<(), ValidationError> {
        validate_native_denom(&self.denom)?;

        decimal_param_le_one(self.max_loan_to_value, "max_loan_to_value")?;
        decimal_param_le_one(self.liquidation_threshold, "liquidation_threshold")?;
        assert_lqt_gt_max_ltv(self.max_loan_to_value, self.liquidation_threshold)?;

        decimal_param_le_one(self.liquidation_bonus, "liquidation_bonus")?;

        decimal_param_le_one(self.rover.hls.max_loan_to_value, "hls_max_loan_to_value")?;
        decimal_param_le_one(self.rover.hls.liquidation_threshold, "hls_liquidation_threshold")?;
        assert_hls_lqt_gt_max_ltv(
            self.rover.hls.max_loan_to_value,
            self.rover.hls.liquidation_threshold,
        )?;

        Ok(())
    }
}

#[cw_serde]
pub struct VaultConfigBase<T> {
    pub addr: T,
    pub deposit_cap: Coin,
    pub max_loan_to_value: Decimal,
    pub liquidation_threshold: Decimal,
    pub whitelisted: bool,
}

pub type VaultConfigUnchecked = VaultConfigBase<String>;
pub type VaultConfig = VaultConfigBase<Addr>;

impl From<VaultConfig> for VaultConfigUnchecked {
    fn from(v: VaultConfig) -> Self {
        VaultConfigUnchecked {
            addr: v.addr.to_string(),
            deposit_cap: v.deposit_cap,
            max_loan_to_value: v.max_loan_to_value,
            liquidation_threshold: v.liquidation_threshold,
            whitelisted: v.whitelisted,
        }
    }
}

impl VaultConfigUnchecked {
    pub fn check(&self, api: &dyn Api) -> ContractResult<VaultConfig> {
        decimal_param_le_one(self.max_loan_to_value, "max_loan_to_value")?;
        decimal_param_le_one(self.liquidation_threshold, "liquidation_threshold")?;
        assert_lqt_gt_max_ltv(self.max_loan_to_value, self.liquidation_threshold)?;

        Ok(VaultConfig {
            addr: api.addr_validate(&self.addr)?,
            deposit_cap: self.deposit_cap.clone(),
            max_loan_to_value: self.max_loan_to_value,
            liquidation_threshold: self.liquidation_threshold,
            whitelisted: self.whitelisted,
        })
    }
}

#[cw_serde]
pub enum AssetParamsUpdate {
    AddOrUpdate {
        params: AssetParams,
    },
}

#[cw_serde]
pub enum VaultConfigUpdate {
    AddOrUpdate {
        config: VaultConfigUnchecked,
    },
    Remove {
        addr: String,
    },
}

#[cw_serde]
pub enum RoverEmergencyUpdate {
    SetZeroMaxLtvOnVault(String),
    SetZeroDepositCapOnVault(String),
    DisallowCoin(String),
}

#[cw_serde]
pub enum RedBankEmergencyUpdate {
    DisableBorrowing(String),
}

#[cw_serde]
pub enum EmergencyUpdate {
    Rover(RoverEmergencyUpdate),
    RedBank(RedBankEmergencyUpdate),
}