pub mod interest_rate_models;
pub mod msg;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use cosmwasm_std::{Addr, Uint128};
use crate::asset::AssetType;
use crate::error::MarsError;
use crate::helpers::decimal_param_le_one;
use crate::math::decimal::Decimal;
use self::interest_rate_models::InterestRateModel;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Config {
pub owner: Addr,
pub address_provider_address: Addr,
pub ma_token_code_id: u64,
pub close_factor: Decimal,
}
impl Config {
pub fn validate(&self) -> Result<(), MarsError> {
decimal_param_le_one(&self.close_factor, "close_factor")?;
Ok(())
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct GlobalState {
pub market_count: u32,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Market {
pub index: u32,
pub ma_token_address: Addr,
pub asset_type: AssetType,
pub max_loan_to_value: Decimal,
pub liquidation_threshold: Decimal,
pub liquidation_bonus: Decimal,
pub reserve_factor: Decimal,
pub interest_rate_model: InterestRateModel,
pub borrow_index: Decimal,
pub liquidity_index: Decimal,
pub borrow_rate: Decimal,
pub liquidity_rate: Decimal,
pub indexes_last_updated: u64,
pub debt_total_scaled: Uint128,
pub active: bool,
pub deposit_enabled: bool,
pub borrow_enabled: bool,
}
impl Market {
pub fn validate(&self) -> Result<(), MarketError> {
decimal_param_le_one(&self.max_loan_to_value, "max_loan_to_value")?;
decimal_param_le_one(&self.liquidation_threshold, "liquidation_threshold")?;
decimal_param_le_one(&self.liquidation_bonus, "liquidation_bonus")?;
if self.liquidation_threshold <= self.max_loan_to_value {
return Err(MarketError::InvalidLiquidationThreshold {
liquidation_threshold: self.liquidation_threshold,
max_loan_to_value: self.max_loan_to_value,
});
}
Ok(())
}
}
impl Default for Market {
fn default() -> Self {
let dynamic_ir_model = interest_rate_models::InterestRateModel::Dynamic {
params: interest_rate_models::DynamicInterestRateModelParams {
min_borrow_rate: Decimal::zero(),
max_borrow_rate: Decimal::one(),
kp_1: Default::default(),
optimal_utilization_rate: Default::default(),
kp_augmentation_threshold: Default::default(),
kp_2: Default::default(),
update_threshold_txs: 1,
update_threshold_seconds: 0,
},
state: interest_rate_models::DynamicInterestRateModelState {
txs_since_last_borrow_rate_update: 0,
borrow_rate_last_updated: 0,
},
};
Market {
index: 0,
ma_token_address: crate::helpers::zero_address(),
liquidity_index: Decimal::one(),
borrow_index: Decimal::one(),
borrow_rate: Default::default(),
liquidity_rate: Default::default(),
max_loan_to_value: Default::default(),
reserve_factor: Default::default(),
indexes_last_updated: 0,
debt_total_scaled: Default::default(),
asset_type: AssetType::Native,
liquidation_threshold: Decimal::one(),
liquidation_bonus: Decimal::zero(),
interest_rate_model: dynamic_ir_model,
active: true,
deposit_enabled: true,
borrow_enabled: true,
}
}
}
#[derive(Error, Debug, PartialEq)]
pub enum MarketError {
#[error("{0}")]
Mars(#[from] MarsError),
#[error("liquidation_threshold should be greater than max_loan_to_value. liquidation_threshold: {liquidation_threshold:?}, max_loan_to_value: {max_loan_to_value:?}")]
InvalidLiquidationThreshold {
liquidation_threshold: Decimal,
max_loan_to_value: Decimal,
},
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct User {
pub borrowed_assets: Uint128,
pub collateral_assets: Uint128,
}
impl Default for User {
fn default() -> Self {
User {
borrowed_assets: Uint128::zero(),
collateral_assets: Uint128::zero(),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Debt {
pub amount_scaled: Uint128,
pub uncollateralized: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum UserHealthStatus {
NotBorrowing,
Borrowing(Decimal),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ConfigResponse {
pub owner: Addr,
pub address_provider_address: Addr,
pub ma_token_code_id: u64,
pub market_count: u32,
pub close_factor: Decimal,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct MarketsListResponse {
pub markets_list: Vec<MarketInfo>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct MarketInfo {
pub denom: String,
pub asset_label: String,
pub asset_reference: Vec<u8>,
pub asset_type: AssetType,
pub ma_token_address: Addr,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UserDebtResponse {
pub debts: Vec<UserAssetDebtResponse>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UserAssetDebtResponse {
pub denom: String,
pub asset_label: String,
pub asset_reference: Vec<u8>,
pub asset_type: AssetType,
pub amount_scaled: Uint128,
pub amount: Uint128,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UserCollateralResponse {
pub collateral: Vec<UserAssetCollateralResponse>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UserAssetCollateralResponse {
pub denom: String,
pub asset_label: String,
pub asset_reference: Vec<u8>,
pub asset_type: AssetType,
pub enabled: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UserPositionResponse {
pub total_collateral_in_uusd: Uint128,
pub total_debt_in_uusd: Uint128,
pub total_collateralized_debt_in_uusd: Uint128,
pub max_debt_in_uusd: Uint128,
pub weighted_liquidation_threshold_in_uusd: Uint128,
pub health_status: UserHealthStatus,
}