Allow serum/perp order force cancelling on frozen accounts (#374)
This commit is contained in:
parent
4f0b4da26d
commit
5227daa0b8
|
@ -71,24 +71,8 @@ pub fn perp_liq_base_position(
|
|||
let liqee_init_health = liqee_health_cache.health(HealthType::Init);
|
||||
liqee_health_cache.require_after_phase1_liquidation()?;
|
||||
|
||||
// Once maint_health falls below 0, we want to start liquidating,
|
||||
// we want to allow liquidation to continue until init_health is positive,
|
||||
// to prevent constant oscillation between the two states
|
||||
if liqee.being_liquidated() {
|
||||
if liqee
|
||||
.fixed
|
||||
.maybe_recover_from_being_liquidated(liqee_init_health)
|
||||
{
|
||||
msg!("Liqee init_health above zero");
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
let maint_health = liqee_health_cache.health(HealthType::Maint);
|
||||
require!(
|
||||
maint_health < I80F48::ZERO,
|
||||
MangoError::HealthMustBeNegative
|
||||
);
|
||||
liqee.fixed.set_being_liquidated(true);
|
||||
if !liqee.check_liquidatable(&liqee_health_cache)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use fixed::types::I80F48;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::health::*;
|
||||
|
@ -47,22 +46,20 @@ pub fn perp_liq_force_cancel_orders(
|
|||
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(());
|
||||
{
|
||||
let result = account.check_liquidatable(&health_cache);
|
||||
if account.fixed.is_operational() {
|
||||
if !result? {
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
// Frozen accounts can always have their orders cancelled
|
||||
if let Err(Error::AnchorError(ref inner)) = result {
|
||||
if inner.error_code_number != MangoError::HealthMustBeNegative as u32 {
|
||||
result?;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let maint_health = health_cache.health(HealthType::Maint);
|
||||
require!(
|
||||
maint_health < I80F48::ZERO,
|
||||
MangoError::HealthMustBeNegative
|
||||
);
|
||||
account.fixed.set_being_liquidated(true);
|
||||
}
|
||||
|
||||
health_cache
|
||||
|
|
|
@ -118,24 +118,8 @@ pub fn perp_liq_quote_and_bankruptcy(
|
|||
let liqee_settle_health = liqee_health_cache.perp_settle_health();
|
||||
liqee_health_cache.require_after_phase2_liquidation()?;
|
||||
|
||||
// Once maint_health falls below 0, we want to start liquidating,
|
||||
// we want to allow liquidation to continue until init_health is positive,
|
||||
// to prevent constant oscillation between the two states
|
||||
if liqee.being_liquidated() {
|
||||
if liqee
|
||||
.fixed
|
||||
.maybe_recover_from_being_liquidated(liqee_init_health)
|
||||
{
|
||||
msg!("Liqee init_health above zero");
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
let maint_health = liqee_health_cache.health(HealthType::Maint);
|
||||
require!(
|
||||
maint_health < I80F48::ZERO,
|
||||
MangoError::HealthMustBeNegative
|
||||
);
|
||||
liqee.fixed.set_being_liquidated(true);
|
||||
if !liqee.check_liquidatable(&liqee_health_cache)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// check positions exist/create them, done early for nicer error messages
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::{Token, TokenAccount};
|
||||
use fixed::types::I80F48;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::health::*;
|
||||
|
@ -126,22 +125,21 @@ pub fn serum3_liq_force_cancel_orders(
|
|||
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(());
|
||||
{
|
||||
let result = account.check_liquidatable(&health_cache);
|
||||
if account.fixed.is_operational() {
|
||||
if !result? {
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
// Frozen accounts can always have their orders cancelled
|
||||
if let Err(Error::AnchorError(ref inner)) = result {
|
||||
if inner.error_code_number != MangoError::HealthMustBeNegative as u32 {
|
||||
// propagate all unexpected errors
|
||||
result?;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let maint_health = health_cache.health(HealthType::Maint);
|
||||
require!(
|
||||
maint_health < I80F48::ZERO,
|
||||
MangoError::HealthMustBeNegative
|
||||
);
|
||||
account.fixed.set_being_liquidated(true);
|
||||
}
|
||||
|
||||
health_cache
|
||||
|
|
|
@ -69,21 +69,8 @@ pub fn token_liq_with_token(
|
|||
let init_health = liqee_health_cache.health(HealthType::Init);
|
||||
liqee_health_cache.require_after_phase1_liquidation()?;
|
||||
|
||||
// Once maint_health falls below 0, we want to start liquidating,
|
||||
// we want to allow liquidation to continue until init_health is positive,
|
||||
// to prevent constant oscillation between the two states
|
||||
if liqee.being_liquidated() {
|
||||
if liqee.fixed.maybe_recover_from_being_liquidated(init_health) {
|
||||
msg!("Liqee init_health above zero");
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
let maint_health = liqee_health_cache.health(HealthType::Maint);
|
||||
require!(
|
||||
maint_health < I80F48::ZERO,
|
||||
MangoError::HealthMustBeNegative
|
||||
);
|
||||
liqee.fixed.set_being_liquidated(true);
|
||||
if !liqee.check_liquidatable(&liqee_health_cache)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -968,6 +968,30 @@ impl<
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn check_liquidatable(&mut self, health_cache: &HealthCache) -> Result<bool> {
|
||||
// Once maint_health falls below 0, we want to start liquidating,
|
||||
// we want to allow liquidation to continue until init_health is positive,
|
||||
// to prevent constant oscillation between the two states
|
||||
if self.being_liquidated() {
|
||||
let init_health = health_cache.health(HealthType::Init);
|
||||
if self
|
||||
.fixed_mut()
|
||||
.maybe_recover_from_being_liquidated(init_health)
|
||||
{
|
||||
msg!("Liqee init_health above zero");
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
let maint_health = health_cache.health(HealthType::Maint);
|
||||
require!(
|
||||
maint_health < I80F48::ZERO,
|
||||
MangoError::HealthMustBeNegative
|
||||
);
|
||||
self.fixed_mut().set_being_liquidated(true);
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
// writes length of tokens vec at appropriate offset so that borsh can infer the vector length
|
||||
// length used is that present in the header
|
||||
fn write_token_length(&mut self) {
|
||||
|
|
Loading…
Reference in New Issue