The Liquidation Lifecycle
Liquidation Bots
Presently, only Imperial's liquidation bots can liquidate Positions on Imperial but there are plans to drop this requirement shortly. All who liquidate earn fees from liquidation, and once security audits are complete, this restriction will be lifted so that this practice can be decentralized.
The current bot aims to recycle a Position within 5 minutes of it becoming eligible for liquidation.
Reasons for Liquidation
There are presently two reasons for liquidation, having made too much profit and having such overwhelming losses that your effective_collateral is so low that your effective leverage is beyond the allowable limits set by your Position.
Too much profit?
Discussed further in the Concepts section on the Liquidation Engine, each Position is granted a max_size set on that Position, dynamically set by a combination of fields on the Custody, Pool, and current long/short ratios. If the total value (loan + collateral + profit) of the Position pierces this max_size value, then the Position may be liquidated and profits and collateral paid back to the owner.
Fees are still paid to the liquidator bot and to Imperial, but not to the Pool.
Too much leverage?
If your leverage drops below allowed limits set by your Position as given by long/short conditions at the time of creation and the max_leverage settings on the Pool and Custody, then you become eligible for liquidation. Liquidation rewards are paid out of your collateral remaining to the liquidator bot, to the Pool, and to Imperial.
Liquidation Endpoint
There is but a single endpoint for liquidation called liquidate_position with the following accounts:
#[derive(Accounts)]
pub struct LiquidatePosition<'info> {
#[account(mut, associated_token::mint = collateral_custody.mint, associated_token::authority = liquidator)]
pub liquidator_token: Box<Account<'info, TokenAccount>>,
#[account(mut, associated_token::mint = collateral_custody.mint, associated_token::authority = position.owner)]
pub user_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut, seeds = [b"insurance", collateral_custody.key().as_ref(), collateral_custody.mint.as_ref()], bump, token::mint = collateral_custody.mint, token::authority = collateral_custody)]
pub insurance_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut, associated_token::mint = collateral_custody.mint, associated_token::authority = collateral_custody)]
pub custody_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut, associated_token::mint = collateral_custody.mint, associated_token::authority = state)]
pub protocol_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut, has_one=position_payer, has_one=pool, has_one=collateral_custody, seeds=[b"position", pool.key().as_ref(), collateral_custody.mint.key().as_ref(), position.owner.key().as_ref(), position.time_window.as_ref(), position.side.to_le_bytes().as_ref()], bump)]
pub position: Box<Account<'info, Position>>,
#[account(mut)]
pub position_payer: AccountInfo<'info>,
#[account(mut)]
pub liquidator: Signer<'info>,
#[account(mut, has_one=state, seeds=[b"pool", pool.name.as_bytes().as_ref(), pool.state.key().as_ref(), pool.lp_mint.key().as_ref()], bump)]
pub pool: Box<Account<'info, Pool>>,
#[account(mut, has_one = custody_token_account, has_one=pool, seeds=[b"custody", pool.key().as_ref(), collateral_custody.mint.key().as_ref()], bump)]
pub collateral_custody: Box<Account<'info, Custody>>,
#[account(owner = ORACLE_ID)]
pub oracle: Box<Account<'info, OracleAccount>>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
#[account(seeds=[b"state"], bump)]
pub state: Box<Account<'info, State>>,
pub clock: Sysvar<'info, Clock>,
}
This will close the Position out and make the correct payments to the different parties in a single transaction. For more on how the Liquidation Engine functions specifically from an accounting and math perspective, please see the relevant article in the Concepts section.
Last updated