osmosis-labs / isotonic

Smart Contracts for the Lendex Protocol
MIT License
1 stars 0 forks source link

Liquidate via AMM #92

Closed uint closed 2 years ago

uint commented 2 years ago

Ideally, we wait for #101 to be complete before tackling this since it's going to provide us with SwapWithdrawFrom.

Desc

Right now, a liquidator has to manually choose to liquidate a particular debt and cover the whole thing. They pay for some of the debt, they receive some of the debtor's collateral for doing that.

We're changing that. Now whenever liquidation is triggered and debt <= credit_line, the following needs to happen:

Suggested solution

// credit_agency::state::Config
struct Config {
    ...
    /// The liquidation fee to be payed out to all lenders in the debt market
    liquidation_fee: Decimal,
    /// The liquidation triggering fee to be payed out to the person who "clicked the button"
    liquidation_initiation_fee: Decimal,
    /// When trading on the AMM during liquidation, how much slippage from oracle prices are we willing to accept?
    liquidation_slippage: Decimal,
}
// credit_agency::msg::ExecuteMsg
enum ExecuteMsg {
    ...
    /// Anyone can trigger this.
    Liquidate {
        /// The account to liquidate
        account: String,
        /// The collateral denom to use
        collateral: Token,
        /// How much of the loan are we trying to repay
        amount_to_repay: Coin,
    },
}

Liquidation logic:

// assert that given account actually has more debt then credit
let total_credit_line = query::total_credit_line(deps.as_ref(), account.to_string())?;
let total_credit_line = total_credit_line.validate(&Token::Native(cfg.common_token))?;
if total_credit_line.debt <= total_credit_line.credit_line {
    return Err(ContractError::LiquidationNotAllowed {});
}

let charge = amount_to_repay * (1 + cfg.liquidation_fee + cfg.liquidation_initiation_fee);

// TODO: currently these queries don't include fees - should they? should markets be queryable for
// trading both ways? it would improve this approximation
let expected_rate = collateral_market.query(price) * (1 / debt_market.query(price));
let sell_limit = amount_to_repay / expected_rate * (1 + cfg.liquidation_slippage);

simulated_credit_line = credit_line.credit_line - (sell_limit * collateral_ratio);
simulated_debt = credit_line.debt - amount_to_repay;
if simulated_debt > simulated_credit_line {
    return Error("This wouldn't stop the poor fellow from being underwater, friend");
}

collateral_market.execute(SwapWithdrawFrom {account, sell_limit, buy: charge});
debt_market.execute(RepayTo {account, amount: amount_to_repay.amount});
// figure out how to now give fees to people who are supposed to get them - probably needs some new endpoints on the debt market

Background

BirgitPohl commented 2 years ago

Blocked because: We don't yet have cosmos integration point to osmosis blockchain. Help from @ethanfrey We would like to know the status. Any updates?

ethanfrey commented 2 years ago

Yes, this is blocked, it will be some time before system tests can cover this

uint commented 2 years ago

No longer blocked since we have https://github.com/confio/osmosis-bindings. TWAP to arrive in the future.