From 810998a2affd66a9adc6e8351e1e39d458fc096a Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 8 Sep 2022 12:19:03 +0200 Subject: [PATCH] Add PerpLiqForceCancelOrders instruction --- programs/mango-v4/src/instructions/mod.rs | 2 + .../perp_liq_force_cancel_orders.rs | 88 +++++++++++++++++++ programs/mango-v4/src/lib.rs | 4 + 3 files changed, 94 insertions(+) create mode 100644 programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs diff --git a/programs/mango-v4/src/instructions/mod.rs b/programs/mango-v4/src/instructions/mod.rs index bc4cb064b..4aaae421b 100644 --- a/programs/mango-v4/src/instructions/mod.rs +++ b/programs/mango-v4/src/instructions/mod.rs @@ -21,6 +21,7 @@ pub use perp_create_market::*; pub use perp_deactivate_position::*; pub use perp_edit_market::*; pub use perp_liq_base_position::*; +pub use perp_liq_force_cancel_orders::*; pub use perp_place_order::*; pub use perp_settle_fees::*; pub use perp_settle_pnl::*; @@ -69,6 +70,7 @@ mod perp_create_market; mod perp_deactivate_position; mod perp_edit_market; mod perp_liq_base_position; +mod perp_liq_force_cancel_orders; mod perp_place_order; mod perp_settle_fees; mod perp_settle_pnl; diff --git a/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs b/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs new file mode 100644 index 000000000..e2a55387b --- /dev/null +++ b/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs @@ -0,0 +1,88 @@ +use anchor_lang::prelude::*; +use fixed::types::I80F48; + +use crate::error::*; +use crate::state::*; + +#[derive(Accounts)] +pub struct PerpLiqForceCancelOrders<'info> { + pub group: AccountLoader<'info, Group>, + + #[account(mut, has_one = group)] + pub account: AccountLoaderDynamic<'info, MangoAccount>, + + #[account( + mut, + has_one = group, + has_one = bids, + has_one = asks + )] + pub perp_market: AccountLoader<'info, PerpMarket>, + #[account(mut)] + pub asks: AccountLoader<'info, BookSide>, + #[account(mut)] + pub bids: AccountLoader<'info, BookSide>, +} + +pub fn perp_liq_force_cancel_orders( + ctx: Context, + limit: u8, +) -> Result<()> { + let mut account = ctx.accounts.account.load_mut()?; + + // + // Check liqee health if liquidation is allowed + // + let mut health_cache = { + let mut account = ctx.accounts.account.load_mut()?; + let retriever = + new_fixed_order_account_retriever(ctx.remaining_accounts, &account.borrow())?; + let health_cache = + new_health_cache(&account.borrow(), &retriever).context("create health cache")?; + + if account.being_liquidated() { + let init_health = health_cache.health(HealthType::Init); + if account + .fixed + .maybe_recover_from_being_liquidated(init_health) + { + msg!("Liqee init_health above zero"); + return Ok(()); + } + } else { + let maint_health = health_cache.health(HealthType::Maint); + require!( + maint_health < I80F48::ZERO, + MangoError::HealthMustBeNegative + ); + account.fixed.set_being_liquidated(true); + } + + health_cache + }; + + // + // Cancel orders + // + { + let mut perp_market = ctx.accounts.perp_market.load_mut()?; + let bids = ctx.accounts.bids.load_mut()?; + let asks = ctx.accounts.asks.load_mut()?; + let mut book = Book::new(bids, asks); + + book.cancel_all_orders(&mut account.borrow_mut(), &mut perp_market, limit, None)?; + + let perp_position = account.perp_position(perp_market.perp_market_index)?; + health_cache.recompute_perp_info(perp_position, &perp_market)?; + } + + // + // Health check at the end + // + let init_health = health_cache.health(HealthType::Init); + account + .fixed + .maybe_recover_from_being_liquidated(init_health); + + Ok(()) +} diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index 03273ff2b..979b87652 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -514,6 +514,10 @@ pub mod mango_v4 { instructions::perp_liq_base_position(ctx, max_base_transfer) } + pub fn perp_liq_force_cancel_orders(ctx: Context) -> Result<()> { + instructions::perp_liq_force_cancel_orders(ctx) + } + // TODO // perp_force_cancel_order