Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow purging of anyone's orders and positions in force-closed markets #1009

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2599,8 +2599,7 @@ impl TransactionBuilder {
}

pub fn append(&mut self, prepared_instructions: PreparedInstructions) {
self.instructions
.extend(prepared_instructions.instructions);
self.instructions.extend(prepared_instructions.instructions);
}
}

Expand Down
4 changes: 4 additions & 0 deletions programs/mango-v4/src/accounts_ix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub use perp_liq_base_or_positive_pnl::*;
pub use perp_liq_force_cancel_orders::*;
pub use perp_liq_negative_pnl_or_bankruptcy::*;
pub use perp_place_order::*;
pub use perp_purge_orders::*;
pub use perp_purge_position::*;
pub use perp_settle_fees::*;
pub use perp_settle_pnl::*;
pub use perp_update_funding::*;
Expand Down Expand Up @@ -125,6 +127,8 @@ mod perp_liq_base_or_positive_pnl;
mod perp_liq_force_cancel_orders;
mod perp_liq_negative_pnl_or_bankruptcy;
mod perp_place_order;
mod perp_purge_orders;
mod perp_purge_position;
mod perp_settle_fees;
mod perp_settle_pnl;
mod perp_update_funding;
Expand Down
27 changes: 27 additions & 0 deletions programs/mango-v4/src/accounts_ix/perp_purge_orders.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::state::{BookSide, Group, MangoAccountFixed, PerpMarket};
use anchor_lang::prelude::*;

#[derive(Accounts)]
pub struct PerpPurgeOrders<'info> {
#[account()]
pub group: AccountLoader<'info, Group>,

#[account(
mut,
has_one = group,
// owner is not checked on purpose
)]
pub account: AccountLoader<'info, MangoAccountFixed>,

#[account(
mut,
has_one = group,
has_one = bids,
has_one = asks,
)]
pub perp_market: AccountLoader<'info, PerpMarket>,
#[account(mut)]
pub bids: AccountLoader<'info, BookSide>,
#[account(mut)]
pub asks: AccountLoader<'info, BookSide>,
}
26 changes: 26 additions & 0 deletions programs/mango-v4/src/accounts_ix/perp_purge_position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use anchor_lang::prelude::*;

use crate::state::*;

#[derive(Accounts)]
pub struct PerpPurgePosition<'info> {
#[account()]
pub group: AccountLoader<'info, Group>,

#[account(
mut,
has_one = group,
// owner is not checked on purpose
)]
pub account: AccountLoader<'info, MangoAccountFixed>,

#[account(has_one = group)]
pub perp_market: AccountLoader<'info, PerpMarket>,

#[account(mut, has_one = group)]
pub settle_bank: AccountLoader<'info, Bank>,

/// CHECK: Oracle can have different account types
#[account(address = settle_bank.load()?.oracle)]
pub settle_oracle: UncheckedAccount<'info>,
}
4 changes: 4 additions & 0 deletions programs/mango-v4/src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub use perp_liq_base_or_positive_pnl::*;
pub use perp_liq_force_cancel_orders::*;
pub use perp_liq_negative_pnl_or_bankruptcy::*;
pub use perp_place_order::*;
pub use perp_purge_orders::*;
pub use perp_purge_position::*;
pub use perp_settle_fees::*;
pub use perp_settle_pnl::*;
pub use perp_update_funding::*;
Expand Down Expand Up @@ -106,6 +108,8 @@ mod perp_liq_base_or_positive_pnl;
mod perp_liq_force_cancel_orders;
mod perp_liq_negative_pnl_or_bankruptcy;
mod perp_place_order;
mod perp_purge_orders;
mod perp_purge_position;
mod perp_settle_fees;
mod perp_settle_pnl;
mod perp_update_funding;
Expand Down
25 changes: 25 additions & 0 deletions programs/mango-v4/src/instructions/perp_purge_orders.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use anchor_lang::prelude::*;

use crate::accounts_ix::*;
use crate::error::MangoError;
use crate::state::*;

pub fn perp_purge_orders(ctx: Context<PerpPurgeOrders>, limit: u8) -> Result<()> {
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
// only allow pruning orders when market is in force-close
require!(perp_market.is_force_close(), MangoError::SomeError);

let mut account = ctx.accounts.account.load_full_mut()?;
let mut book = Orderbook {
bids: ctx.accounts.bids.load_mut()?,
asks: ctx.accounts.asks.load_mut()?,
};

book.cancel_all_orders(
&mut account.borrow_mut(),
ctx.accounts.account.as_ref().key,
&mut perp_market,
limit,
None,
)
}
92 changes: 92 additions & 0 deletions programs/mango-v4/src/instructions/perp_purge_position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use anchor_lang::prelude::*;
use fixed::types::I80F48;

use crate::accounts_ix::*;
use crate::error::*;
use crate::logs::emit_perp_balances;
use crate::logs::emit_stack;
use crate::logs::TokenBalanceLog;
use crate::require_msg;
use crate::state::*;

pub fn perp_purge_position(ctx: Context<PerpPurgePosition>) -> Result<()> {
let perp_market = ctx.accounts.perp_market.load()?;
// only allow purging positions when market is in force-close
require!(perp_market.is_force_close(), MangoError::SomeError);

let mut settle_bank = ctx.accounts.settle_bank.load_mut()?;
// Verify that the bank is the quote currency bank
require!(
settle_bank.token_index == perp_market.settle_token_index,
MangoError::InvalidBank
);

let mut account = ctx.accounts.account.load_full_mut()?;
let perp_position = account.perp_position_mut(perp_market.perp_market_index)?;

// Base position needs to be zero'd out already and all orders closed
require_msg!(
perp_position.base_position_lots() == 0,
"perp position still has base lots"
);
require_msg!(
perp_position.bids_base_lots == 0 && perp_position.asks_base_lots == 0,
"perp position still has open orders"
);
require_msg!(
perp_position.taker_base_lots == 0 && perp_position.taker_quote_lots == 0,
"perp position still has events on event queue"
);

// Flush funding so that all remaining quote position is accounted for
perp_position.settle_funding(&perp_market);
let settlement = -perp_position.quote_position_native();

// only if there's negative pnl we settle directly with bank
// note: the positive pnl case is not implemented
if settlement != 0 {
require_msg!(
settlement > I80F48::ZERO,
"can only purge negative quote positions"
);

// Set perp quote to 0
perp_position.record_settle(settlement, &perp_market);
emit_perp_balances(
ctx.accounts.group.key(),
ctx.accounts.account.key(),
perp_position,
&perp_market,
);

// Update the accounts' perp_spot_transfer statistics.
let settlement_i64 = settlement.round_to_zero().to_num::<i64>();
perp_position.perp_spot_transfers += settlement_i64;
account.fixed.perp_spot_transfers += settlement_i64;

// Settle quote token balance
let token_position = account
.token_position_mut(perp_market.settle_token_index)?
.0;
let now_ts: u64 = Clock::get()?.unix_timestamp.try_into().unwrap();
settle_bank.withdraw_without_fee(token_position, settlement, now_ts)?;

emit_stack(TokenBalanceLog {
mango_group: ctx.accounts.group.key(),
mango_account: ctx.accounts.account.key(),
token_index: perp_market.settle_token_index,
indexed_position: token_position.indexed_position.to_bits(),
deposit_index: settle_bank.deposit_index.to_bits(),
borrow_index: settle_bank.borrow_index.to_bits(),
});
}

// clean up perp position to free up oracles for users and allow closing market
account.deactivate_perp_position_and_log(
perp_market.perp_market_index,
perp_market.settle_token_index,
ctx.accounts.account.key(),
)?;

Ok(())
}
12 changes: 12 additions & 0 deletions programs/mango-v4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,12 @@ pub mod mango_v4 {
Ok(())
}

pub fn perp_purge_position(ctx: Context<PerpPurgePosition>) -> Result<()> {
#[cfg(feature = "enable-gpl")]
instructions::perp_purge_position(ctx)?;
Ok(())
}

#[allow(clippy::too_many_arguments)]
pub fn perp_place_order(
ctx: Context<PerpPlaceOrder>,
Expand Down Expand Up @@ -1320,6 +1326,12 @@ pub mod mango_v4 {
Ok(())
}

pub fn perp_purge_orders(ctx: Context<PerpPurgeOrders>, limit: u8) -> Result<()> {
#[cfg(feature = "enable-gpl")]
instructions::perp_purge_orders(ctx, limit)?;
Ok(())
}

pub fn perp_consume_events(ctx: Context<PerpConsumeEvents>, limit: usize) -> Result<()> {
#[cfg(feature = "enable-gpl")]
instructions::perp_consume_events(ctx, limit)?;
Expand Down
Loading