Stability Pool
Inspired by Liquity's Stability Pool (https://docs.liquity.org/faq/stability-pool-and-liquidations)
The Stability Pool (SP) is the second line of defense in Positions contract liquidations. It acts as a pool of liquidity that can be used to repay insolvent positions in return for discounted collateral assets. When a position is liquidated, the pool repays its debt in exchange for assets sent by the Positions contract after successful repayments. In contrast to Liquity's pro rata model, this SP is First In First Out when it comes to rewarding liquidations to pool liquidity providers. Due to how the Liquidation Queue calculates liquidations, there will always be something for the SP to liquidate, meaning its advantageous for the first bidder at every liquidation and not just the one's the Liq Queue can't fulfill. This has the added benefit of filtering through spam deposits before large liquidatiosn. Pro-rata distributions, like the Liq Queue and Liquity's SP are better than FIFO at attracting large capital, but FIFO has direct incentives for competitive replenishes which is better for a pool that isn't prioritized but needs quick refills if the situation calls for it. We want this step of the liquidation mechanism to be reactive when low while not taking too much potential capital from the Liq Queue which will likely liquidate collateral for lower premiums a majority of the time, which is better for user solvency.
Key Points:
Any user funds in the Stability Pool will be used to repay said user's positions if liquidated. Meaning depositing in the SP doesn't increase liquidation risk for the user.
Unstaked deposits are still used to liquidate but accrue no incentives.
Withdrawals that would leave less than the minmum deposit amount will withdraw the remaining bid.
InstantiateMsg
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
pub owner: Option<String>,
pub asset_pool: Option<AssetPool>,
pub incentive_rate: Option<Decimal>,
pub max_incentives: Option<Uint128>,
pub minimum_deposit_amount: Uint128,
pub osmosis_proxy: String,
pub positions_contract: String,
pub oracle_contract: String,
pub mbrn_denom: String,
}
pub struct AssetPool {
pub credit_asset: Asset,
pub liq_premium: Decimal,
pub deposits: Vec<Deposit>
}
pub struct Asset {
pub info: AssetInfo,
pub amount: Uint128,
}
*asset_pool
AssetPool
Initial Asset Pool for the contract
*owner
String
Owner of the contract, defaults to info.sender
*incentive_rate
Decimal
Base MBRN incentive rate
*max_incentives
Uint128
Maximum MBRN the Pool can mint for incentives
*minimum_deposit_amount
Uint128
Minimum deposit amount
osmosis_proxy
String
Osmosis Proxy contract address
positions_contract
String
CDP contract
oracle_contract
String
Oracle contract
mbrn_denom
String
MBRN denom
* = optional
ExecuteMsg
UpdateConfig
UpdateConfig
Update Config if info.sender is config.owner
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
UpdateConfig(UpdateConfig),
}
pub struct UpdateConfig {
owner: Option<String>,
incentive_rate: Option<Decimal>,
max_incentives: Option<Uint128>,
minimum_deposit_amount: Option<Uint128>,
unstaking_period: Option<u64>,
osmosis_proxy: Option<String>,
positions_contract: Option<String>,
pub oracle_contract: Option<String>,
mbrn_denom: Option<String>,
}
Deposit
Deposit
Deposit accepted credit assets to corresponding Asset Pools
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Deposit {
user: Option<String>
}
}
*user
String
Address with claim over the deposit(s)
* = optional
Withdraw
Withdraw
Withdraw caller owned deposits from corresponding Asset Pools
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Withdraw {
amount: Uint128
}
}
amount
Uint128
Amount to be withdrawn
Restake
Restake
Restake unstak(ed/ing) assets
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Restake {
restake_amount: Decimal,
}
}
restake_amount
Decimal
Amount to restake
Liquidate
Liquidate
Use Asset Pool assets to repay for a Position and earn discounted assets
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Liquidate {
liq_amount: Decimal
}
}
liq_amount
Decimal
Amount to be repaid
ClaimRewards
ClaimRewards
Claim all discounted assets received from liquidations for the calling address
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
ClaimRewards { }
}
Distribute
Distribute
Called by the Positions contract. Distributes liquidated funds to the users whose Deposits were used to repay the debt.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Distribute { //Distributes liquidated funds to users
distribution_assets: Vec<Asset>,
distribution_asset_ratios: Vec<Decimal>,
distribute_for: Uint128,
}
}
distribution_assets
Vec<Asset>
Assets to be distributed to users
distribution-asset-ratios
Vec<Decimal>
Ratios of distribution assets
credit_price
Decimal
Redemption price of credit_asset
Repay
Repay
Allows the Positions contract to use user funds to repay for themselves
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Repay {
user_info: UserInfo,
repayment: Asset,
}
}
pub struct UserInfo {
pub position_id: Uint128,
pub position_owner: String,
}
user_info
UserInfo
User's Position info
repayment
Asset
Asset to repay
QueryMsg
Config
Config
Returns the current Config fields
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
Config {}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Config {
pub owner: Addr, //Positions contract address
pub incentive_rate: Decimal,
pub max_incentives: Uint128,
pub unstaking_period: u64, // in days
pub mbrn_denom: String,
pub osmosis_proxy: Addr,
pub positions_contract: Addr,
pub oracle_contract: Addr,
}
CheckLiquidatible
CheckLiquidatible
Returns the amount of said asset that isn't liquidatible (i.e. leftover)
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
CheckLiquidatible {
amount: Decimal
}
}
pub struct LiquidatibleResponse {
pub leftover: Decimal,
}
amount
Decimal
Amount to check for
UserClaims
UserClaims
Returns the user
's claimable assets
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
UserClaims {
user: String
}
}
pub struct ClaimsResponse {
pub claims: Vec<Coin>,
}
user
String
The user whose claims to check
AssetPool
AssetPool
Returns Asset Pool info
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
AssetPool {
user: Option<String>,
deposit_limit: Option<u32>,
start_after: Option<u32>,
}
}
pub struct PoolResponse {
pub credit_asset: Asset,
pub liq_premium: Decimal,
pub deposits: Vec<Deposit>
}
*user
String
User's deposits to return
*deposit_limit
u32
Deposit limit
*start_after
u32
Start after Deposit count
UnclaimedIncentives
UnclaimedIncentives
Returns unclaimed incentives for a user in an AssetPool
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
UnclaimedIncentives {
user: String,
}
}
//Returns Uint128
user
String
User address
CapitalAheadOfDeposit
CapitalAheadOfDeposit
Returns capital ahead of each user Deposit in an AssetPool
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
CapitalAheadOfDeposit {
user: String,
}
}
pub struct DepositPositionResponse {
pub deposit: Deposit,
pub capital_ahead: Decimal,
}
pub struct Deposit {
pub user: Addr,
pub amount: Decimal,
pub deposit_time: u64,
pub last_accrued: u64,
pub unstake_time: Option<u64>,
}
user
String
User address
Last updated