group halt (#370)
* group halt Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * Fixes from review Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * format Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
93d33edb74
commit
5ef04d6d08
|
@ -69,6 +69,8 @@ pub enum MangoError {
|
|||
TokenInReduceOnlyMode,
|
||||
#[msg("market is in reduce only mode")]
|
||||
MarketInReduceOnlyMode,
|
||||
#[msg("group is halted")]
|
||||
GroupIsHalted,
|
||||
#[msg("the perp position has non-zero base lots")]
|
||||
PerpHasBaseLots,
|
||||
#[msg("there are open or unsettled serum3 orders")]
|
||||
|
|
|
@ -6,6 +6,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct AccountClose<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -7,6 +7,9 @@ use crate::util::fill_from_str;
|
|||
#[derive(Accounts)]
|
||||
#[instruction(account_num: u32, token_count: u8, serum3_count: u8, perp_count: u8, perp_oo_count: u8)]
|
||||
pub struct AccountCreate<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -6,6 +6,9 @@ use crate::util::fill_from_str;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct AccountEdit<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::error::MangoError;
|
||||
use crate::state::*;
|
||||
use crate::util::checked_math as cm;
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct AccountExpand<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -2,12 +2,14 @@ use anchor_lang::prelude::*;
|
|||
use solana_address_lookup_table_program as solana_alt;
|
||||
|
||||
use crate::address_lookup_table_program;
|
||||
use crate::error::MangoError;
|
||||
use crate::state::*;
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct AltExtend<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -9,6 +9,7 @@ pub struct AltSet<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::state::*;
|
||||
use crate::{error::MangoError, state::*};
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::{self, CloseAccount, Token, TokenAccount};
|
||||
|
||||
|
@ -6,9 +6,10 @@ use anchor_spl::token::{self, CloseAccount, Token, TokenAccount};
|
|||
pub struct GroupClose<'info> {
|
||||
#[account(
|
||||
mut,
|
||||
constraint = group.load()?.is_testing(),
|
||||
has_one = admin,
|
||||
has_one = insurance_vault,
|
||||
constraint = group.load()?.is_testing(),
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
close = sol_destination
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
|
|
@ -18,6 +18,7 @@ pub fn group_edit(
|
|||
ctx: Context<GroupEdit>,
|
||||
admin_opt: Option<Pubkey>,
|
||||
fast_listing_admin_opt: Option<Pubkey>,
|
||||
security_admin_opt: Option<Pubkey>,
|
||||
testing_opt: Option<u8>,
|
||||
version_opt: Option<u8>,
|
||||
) -> Result<()> {
|
||||
|
@ -31,6 +32,10 @@ pub fn group_edit(
|
|||
group.fast_listing_admin = fast_listing_admin;
|
||||
}
|
||||
|
||||
if let Some(security_admin) = security_admin_opt {
|
||||
group.security_admin = security_admin;
|
||||
}
|
||||
|
||||
if let Some(testing) = testing_opt {
|
||||
group.testing = testing;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::state::*;
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct GroupToggleHalt<'info> {
|
||||
#[account(
|
||||
mut,
|
||||
constraint = group.load()?.admin == admin.key() || group.load()?.security_admin == admin.key(),
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
}
|
||||
|
||||
pub fn group_toggle_halt(ctx: Context<GroupToggleHalt>, halted: bool) -> Result<()> {
|
||||
let mut group = ctx.accounts.group.load_mut()?;
|
||||
group.halted = if halted { 1 } else { 0 };
|
||||
Ok(())
|
||||
}
|
|
@ -10,6 +10,7 @@ pub use flash_loan::*;
|
|||
pub use group_close::*;
|
||||
pub use group_create::*;
|
||||
pub use group_edit::*;
|
||||
pub use group_toggle_halt::*;
|
||||
pub use health_region::*;
|
||||
pub use perp_cancel_all_orders::*;
|
||||
pub use perp_cancel_all_orders_by_side::*;
|
||||
|
@ -63,6 +64,7 @@ mod flash_loan;
|
|||
mod group_close;
|
||||
mod group_create;
|
||||
mod group_edit;
|
||||
mod group_toggle_halt;
|
||||
mod health_region;
|
||||
mod perp_cancel_all_orders;
|
||||
mod perp_cancel_all_orders_by_side;
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::state::{BookSide, Group, MangoAccountFixed, MangoAccountLoader, Order
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelAllOrders<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -7,6 +7,9 @@ use crate::state::{
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelAllOrdersBySide<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::state::{BookSide, Group, MangoAccountFixed, MangoAccountLoader, Order
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelOrder<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::state::{BookSide, Group, MangoAccountFixed, MangoAccountLoader, Order
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelOrderByClientOrderId<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::Token;
|
||||
|
||||
use crate::state::*;
|
||||
use crate::{error::MangoError, state::*};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCloseMarket<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_testing(),
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
has_one = admin,
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
|
|
@ -9,6 +9,9 @@ use crate::logs::{emit_perp_balances, FillLog};
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpConsumeEvents<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -13,7 +13,8 @@ use crate::logs::PerpMarketMetaDataLog;
|
|||
pub struct PerpCreateMarket<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
constraint = group.load()?.perps_supported()
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
constraint = group.load()?.perps_supported(),
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpDeactivatePosition<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::logs::PerpMarketMetaDataLog;
|
|||
#[derive(Accounts)]
|
||||
pub struct PerpEditMarket<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
has_one = admin
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token;
|
||||
use anchor_spl::token::Token;
|
||||
use anchor_spl::token::TokenAccount;
|
||||
use fixed::types::I80F48;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::health::*;
|
||||
use crate::state::*;
|
||||
use crate::util::checked_math as cm;
|
||||
|
||||
use crate::logs::{emit_perp_balances, PerpLiqBankruptcyLog, TokenBalanceLog};
|
||||
|
||||
// Remaining accounts:
|
||||
// - merged health accounts for liqor+liqee
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpLiqBankruptcy<'info> {
|
||||
#[account(
|
||||
has_one = insurance_vault,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
has_one = group
|
||||
// liqor_owner is checked at #1
|
||||
)]
|
||||
pub liqor: AccountLoader<'info, MangoAccountFixed>,
|
||||
pub liqor_owner: Signer<'info>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
has_one = group
|
||||
)]
|
||||
pub liqee: AccountLoader<'info, MangoAccountFixed>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
// address is checked at #2
|
||||
)]
|
||||
pub settle_bank: AccountLoader<'info, Bank>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
address = settle_bank.load()?.vault
|
||||
)]
|
||||
pub settle_vault: Account<'info, TokenAccount>,
|
||||
|
||||
/// CHECK: Oracle can have different account types
|
||||
#[account(address = settle_bank.load()?.oracle)]
|
||||
pub settle_oracle: UncheckedAccount<'info>,
|
||||
|
||||
// future: this would be an insurance fund vault specific to a
|
||||
// trustless token, separate from the shared one on the group
|
||||
#[account(mut)]
|
||||
pub insurance_vault: Account<'info, TokenAccount>,
|
||||
|
||||
pub token_program: Program<'info, Token>,
|
||||
}
|
||||
|
||||
impl<'info> PerpLiqBankruptcy<'info> {
|
||||
pub fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> {
|
||||
let program = self.token_program.to_account_info();
|
||||
let accounts = token::Transfer {
|
||||
from: self.insurance_vault.to_account_info(),
|
||||
to: self.settle_vault.to_account_info(),
|
||||
authority: self.group.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn perp_liq_bankruptcy(ctx: Context<PerpLiqBankruptcy>, max_liab_transfer: u64) -> Result<()> {
|
||||
let group = ctx.accounts.group.load()?;
|
||||
let group_pk = &ctx.accounts.group.key();
|
||||
|
||||
let mut liqor = ctx.accounts.liqor.load_full_mut()?;
|
||||
// account constraint #1
|
||||
require!(
|
||||
liqor
|
||||
.fixed
|
||||
.is_owner_or_delegate(ctx.accounts.liqor_owner.key()),
|
||||
MangoError::SomeError
|
||||
);
|
||||
require!(!liqor.fixed.being_liquidated(), MangoError::BeingLiquidated);
|
||||
|
||||
let mut liqee = ctx.accounts.liqee.load_full_mut()?;
|
||||
let mut liqee_health_cache = {
|
||||
let account_retriever = ScanningAccountRetriever::new(ctx.remaining_accounts, group_pk)?;
|
||||
new_health_cache(&liqee.borrow(), &account_retriever)
|
||||
.context("create liqee health cache")?
|
||||
};
|
||||
|
||||
// Check if liqee is bankrupt
|
||||
require!(
|
||||
!liqee_health_cache.has_liquidatable_assets(),
|
||||
MangoError::IsNotBankrupt
|
||||
);
|
||||
liqee.fixed.set_being_liquidated(true);
|
||||
|
||||
// Find bankrupt liab amount
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let settle_token_index = perp_market.settle_token_index;
|
||||
let liqee_perp_position = liqee.perp_position_mut(perp_market.perp_market_index)?;
|
||||
require_msg!(
|
||||
liqee_perp_position.base_position_lots() == 0,
|
||||
"liqee must have zero base position"
|
||||
);
|
||||
require!(
|
||||
!liqee_perp_position.has_open_orders(),
|
||||
MangoError::HasOpenPerpOrders
|
||||
);
|
||||
|
||||
let liqee_pnl = liqee_perp_position.quote_position_native();
|
||||
require_msg!(
|
||||
liqee_pnl.is_negative(),
|
||||
"liqee pnl must be negative, was {}",
|
||||
liqee_pnl
|
||||
);
|
||||
let liab_transfer = (-liqee_pnl).min(I80F48::from(max_liab_transfer));
|
||||
|
||||
// Preparation for covering it with the insurance fund
|
||||
let insurance_vault_amount = if perp_market.elligible_for_group_insurance_fund() {
|
||||
ctx.accounts.insurance_vault.amount
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let liquidation_fee_factor = cm!(I80F48::ONE + perp_market.liquidation_fee);
|
||||
|
||||
let insurance_transfer = cm!(liab_transfer * liquidation_fee_factor)
|
||||
.checked_ceil()
|
||||
.unwrap()
|
||||
.checked_to_num::<u64>()
|
||||
.unwrap()
|
||||
.min(insurance_vault_amount);
|
||||
|
||||
let insurance_transfer_i80f48 = I80F48::from(insurance_transfer);
|
||||
let insurance_fund_exhausted = insurance_transfer == insurance_vault_amount;
|
||||
let insurance_liab_transfer =
|
||||
cm!(insurance_transfer_i80f48 / liquidation_fee_factor).min(liab_transfer);
|
||||
|
||||
// Try using the insurance fund if possible
|
||||
if insurance_transfer > 0 {
|
||||
let mut settle_bank = ctx.accounts.settle_bank.load_mut()?;
|
||||
require_eq!(settle_bank.token_index, settle_token_index);
|
||||
require_keys_eq!(settle_bank.mint, ctx.accounts.insurance_vault.mint);
|
||||
|
||||
// move insurance assets into quote bank
|
||||
let group_seeds = group_seeds!(group);
|
||||
token::transfer(
|
||||
ctx.accounts.transfer_ctx().with_signer(&[group_seeds]),
|
||||
insurance_transfer,
|
||||
)?;
|
||||
|
||||
// credit the liqor with quote tokens
|
||||
let (liqor_quote, _, _) = liqor.ensure_token_position(settle_token_index)?;
|
||||
settle_bank.deposit(
|
||||
liqor_quote,
|
||||
insurance_transfer_i80f48,
|
||||
Clock::get()?.unix_timestamp.try_into().unwrap(),
|
||||
)?;
|
||||
|
||||
emit!(TokenBalanceLog {
|
||||
mango_group: ctx.accounts.group.key(),
|
||||
mango_account: ctx.accounts.liqor.key(),
|
||||
token_index: settle_token_index,
|
||||
indexed_position: liqor_quote.indexed_position.to_bits(),
|
||||
deposit_index: settle_bank.deposit_index.to_bits(),
|
||||
borrow_index: settle_bank.borrow_index.to_bits(),
|
||||
});
|
||||
|
||||
// transfer perp quote loss from the liqee to the liqor
|
||||
let liqor_perp_position = liqor
|
||||
.ensure_perp_position(perp_market.perp_market_index, settle_token_index)?
|
||||
.0;
|
||||
liqee_perp_position.record_settle(-insurance_liab_transfer);
|
||||
liqor_perp_position.record_liquidation_quote_change(-insurance_liab_transfer);
|
||||
|
||||
emit_perp_balances(
|
||||
ctx.accounts.group.key(),
|
||||
ctx.accounts.liqor.key(),
|
||||
perp_market.perp_market_index,
|
||||
liqor_perp_position,
|
||||
&perp_market,
|
||||
);
|
||||
}
|
||||
|
||||
// Socialize loss if the insurance fund is exhausted
|
||||
let remaining_liab = liab_transfer - insurance_liab_transfer;
|
||||
let mut socialized_loss = I80F48::ZERO;
|
||||
if insurance_fund_exhausted && remaining_liab.is_positive() {
|
||||
perp_market.socialize_loss(-remaining_liab)?;
|
||||
liqee_perp_position.record_settle(-remaining_liab);
|
||||
require_eq!(liqee_perp_position.quote_position_native(), 0);
|
||||
socialized_loss = remaining_liab;
|
||||
}
|
||||
|
||||
emit_perp_balances(
|
||||
ctx.accounts.group.key(),
|
||||
ctx.accounts.liqee.key(),
|
||||
perp_market.perp_market_index,
|
||||
liqee_perp_position,
|
||||
&perp_market,
|
||||
);
|
||||
|
||||
emit!(PerpLiqBankruptcyLog {
|
||||
mango_group: ctx.accounts.group.key(),
|
||||
liqee: ctx.accounts.liqee.key(),
|
||||
liqor: ctx.accounts.liqor.key(),
|
||||
perp_market_index: perp_market.perp_market_index,
|
||||
insurance_transfer: insurance_transfer_i80f48.to_bits(),
|
||||
socialized_loss: socialized_loss.to_bits()
|
||||
});
|
||||
|
||||
// Check liqee health again
|
||||
liqee_health_cache.recompute_perp_info(liqee_perp_position, &perp_market)?;
|
||||
let liqee_init_health = liqee_health_cache.health(HealthType::Init);
|
||||
liqee
|
||||
.fixed
|
||||
.maybe_recover_from_being_liquidated(liqee_init_health);
|
||||
|
||||
drop(perp_market);
|
||||
|
||||
// Check liqor's health
|
||||
if !liqor.fixed.is_in_health_region() {
|
||||
let account_retriever = ScanningAccountRetriever::new(ctx.remaining_accounts, group_pk)?;
|
||||
let liqor_health = compute_health(&liqor.borrow(), HealthType::Init, &account_retriever)
|
||||
.context("compute liqor health")?;
|
||||
require!(liqor_health >= 0, MangoError::HealthMustBePositive);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -11,6 +11,9 @@ use crate::logs::{emit_perp_balances, PerpLiqBasePositionLog};
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpLiqBasePosition<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group, has_one = oracle)]
|
||||
|
|
|
@ -7,6 +7,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpLiqForceCancelOrders<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -11,6 +11,9 @@ use crate::state::{
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpPlaceOrder<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -12,6 +12,9 @@ use crate::logs::{emit_perp_balances, PerpSettleFeesLog, TokenBalanceLog};
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpSettleFees<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group, has_one = oracle)]
|
||||
|
|
|
@ -11,6 +11,9 @@ use crate::state::{Group, MangoAccountFixed, MangoAccountLoader, PerpMarket};
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpSettlePnl<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::accounts_zerocopy::*;
|
||||
use crate::error::MangoError;
|
||||
use crate::state::{BookSide, Group, Orderbook, PerpMarket};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpUpdateFunding<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>, // Required for group metadata parsing
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -8,6 +8,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3CancelAllOrders<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -13,6 +13,9 @@ use crate::serum3_cpi::load_open_orders_ref;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3CancelOrder<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3CloseOpenOrders<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3CreateOpenOrders<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::Token;
|
||||
|
||||
use crate::state::*;
|
||||
use crate::{error::MangoError, state::*};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3DeregisterMarket<'info> {
|
||||
#[account(
|
||||
mut,
|
||||
constraint = group.load()?.is_testing(),
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_testing(),
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -14,6 +14,9 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3LiqForceCancelOrders<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
|
|
@ -135,6 +135,9 @@ pub enum Serum3Side {
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3PlaceOrder<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -13,6 +13,7 @@ pub struct Serum3RegisterMarket<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
constraint = group.load()?.serum3_supported()
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
|
|
@ -13,6 +13,9 @@ use crate::logs::{LoanOriginationFeeInstruction, WithdrawLoanOriginationFeeLog};
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Serum3SettleFunds<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::Token;
|
||||
|
||||
use crate::state::*;
|
||||
use crate::{error::MangoError, state::*};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct StubOracleClose<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_testing(),
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
constraint = group.load()?.is_testing(),
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -2,12 +2,13 @@ use anchor_lang::prelude::*;
|
|||
use anchor_spl::token::Mint;
|
||||
use fixed::types::I80F48;
|
||||
|
||||
use crate::state::*;
|
||||
use crate::{error::MangoError, state::*};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct StubOracleCreate<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use fixed::types::I80F48;
|
||||
|
||||
use crate::state::*;
|
||||
use crate::{error::MangoError, state::*};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct StubOracleSet<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::state::*;
|
|||
pub struct TokenAddBank<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
constraint = group.load()?.multiple_banks_supported()
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
|
|
@ -15,6 +15,9 @@ use crate::logs::{DepositLog, TokenBalanceLog};
|
|||
// Same as TokenDeposit, but without the owner signing
|
||||
#[derive(Accounts)]
|
||||
pub struct TokenDepositIntoExisting<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group)]
|
||||
|
@ -45,6 +48,9 @@ pub struct TokenDepositIntoExisting<'info> {
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct TokenDeposit<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group, has_one = owner)]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::{self, CloseAccount, Token, TokenAccount};
|
||||
|
||||
use crate::{accounts_zerocopy::LoadZeroCopyRef, state::*};
|
||||
use crate::{accounts_zerocopy::LoadZeroCopyRef, error::MangoError, state::*};
|
||||
use anchor_lang::AccountsClose;
|
||||
|
||||
/// In addition to these accounts, there must be remaining_accounts:
|
||||
|
@ -9,8 +9,9 @@ use anchor_lang::AccountsClose;
|
|||
#[derive(Accounts)]
|
||||
pub struct TokenDeregister<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_testing(),
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted,
|
||||
constraint = group.load()?.is_testing(),
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::logs::TokenMetaDataLog;
|
|||
#[derive(Accounts)]
|
||||
pub struct TokenEdit<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
has_one = admin
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::logs::{
|
|||
pub struct TokenLiqBankruptcy<'info> {
|
||||
#[account(
|
||||
has_one = insurance_vault,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@ use crate::util::checked_math as cm;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct TokenLiqWithToken<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -19,6 +19,7 @@ const FIRST_BANK_NUM: u32 = 0;
|
|||
pub struct TokenRegister<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub admin: Signer<'info>,
|
||||
|
|
|
@ -17,6 +17,7 @@ const FIRST_BANK_NUM: u32 = 0;
|
|||
pub struct TokenRegisterTrustless<'info> {
|
||||
#[account(
|
||||
has_one = fast_listing_admin,
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
pub fast_listing_admin: Signer<'info>,
|
||||
|
|
|
@ -26,6 +26,9 @@ pub mod compute_budget {
|
|||
/// or ComputeBudget instructions.
|
||||
#[derive(Accounts)]
|
||||
pub struct TokenUpdateIndexAndRate<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>, // Required for group metadata parsing
|
||||
|
||||
#[account(
|
||||
|
|
|
@ -15,6 +15,9 @@ use crate::util::checked_math as cm;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct TokenWithdraw<'info> {
|
||||
#[account(
|
||||
constraint = group.load()?.is_operational() @ MangoError::GroupIsHalted
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(mut, has_one = group, has_one = owner)]
|
||||
|
|
|
@ -45,6 +45,7 @@ pub mod mango_v4 {
|
|||
ctx: Context<GroupEdit>,
|
||||
admin_opt: Option<Pubkey>,
|
||||
fast_listing_admin_opt: Option<Pubkey>,
|
||||
security_admin_opt: Option<Pubkey>,
|
||||
testing_opt: Option<u8>,
|
||||
version_opt: Option<u8>,
|
||||
) -> Result<()> {
|
||||
|
@ -52,11 +53,16 @@ pub mod mango_v4 {
|
|||
ctx,
|
||||
admin_opt,
|
||||
fast_listing_admin_opt,
|
||||
security_admin_opt,
|
||||
testing_opt,
|
||||
version_opt,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn group_toggle_halt(ctx: Context<GroupToggleHalt>, halted: bool) -> Result<()> {
|
||||
instructions::group_toggle_halt(ctx, halted)
|
||||
}
|
||||
|
||||
pub fn group_close(ctx: Context<GroupClose>) -> Result<()> {
|
||||
instructions::group_close(ctx)
|
||||
}
|
||||
|
|
|
@ -31,15 +31,19 @@ pub struct Group {
|
|||
|
||||
pub version: u8,
|
||||
|
||||
pub padding2: [u8; 5],
|
||||
pub halted: u8,
|
||||
|
||||
pub padding2: [u8; 4],
|
||||
|
||||
pub address_lookup_tables: [Pubkey; 20],
|
||||
|
||||
pub reserved: [u8; 1920],
|
||||
pub security_admin: Pubkey,
|
||||
|
||||
pub reserved: [u8; 1888],
|
||||
}
|
||||
const_assert_eq!(
|
||||
size_of::<Group>(),
|
||||
32 * 5 + 4 + 4 + 1 + 1 + 6 + 20 * 32 + 1920
|
||||
32 + 4 + 32 * 2 + 4 + 32 * 2 + 4 + 4 + 20 * 32 + 32 + 1888
|
||||
);
|
||||
const_assert_eq!(size_of::<Group>(), 2736);
|
||||
const_assert_eq!(size_of::<Group>() % 8, 0);
|
||||
|
@ -60,6 +64,10 @@ impl Group {
|
|||
pub fn perps_supported(&self) -> bool {
|
||||
self.is_testing() || self.version > 1
|
||||
}
|
||||
|
||||
pub fn is_operational(&self) -> bool {
|
||||
self.halted == 0
|
||||
}
|
||||
}
|
||||
|
||||
// note: using creator instead of admin, since admin can be changed
|
||||
|
|
|
@ -129,6 +129,7 @@ export class MangoClient {
|
|||
group: Group,
|
||||
admin?: PublicKey,
|
||||
fastListingAdmin?: PublicKey,
|
||||
securityAdmin?: PublicKey,
|
||||
testing?: number,
|
||||
version?: number,
|
||||
): Promise<TransactionSignature> {
|
||||
|
@ -136,6 +137,7 @@ export class MangoClient {
|
|||
.groupEdit(
|
||||
admin ?? null,
|
||||
fastListingAdmin ?? null,
|
||||
securityAdmin ?? null,
|
||||
testing ?? null,
|
||||
version ?? null,
|
||||
)
|
||||
|
@ -146,6 +148,19 @@ export class MangoClient {
|
|||
.rpc();
|
||||
}
|
||||
|
||||
public async groupToggleHalt(
|
||||
group: Group,
|
||||
halt: boolean,
|
||||
): Promise<TransactionSignature> {
|
||||
return await this.program.methods
|
||||
.groupToggleHalt(halt)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
})
|
||||
.rpc();
|
||||
}
|
||||
|
||||
public async groupClose(group: Group): Promise<TransactionSignature> {
|
||||
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
||||
return await this.program.methods
|
||||
|
|
|
@ -121,6 +121,12 @@ export type MangoV4 = {
|
|||
"option": "publicKey"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "securityAdminOpt",
|
||||
"type": {
|
||||
"option": "publicKey"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "testingOpt",
|
||||
"type": {
|
||||
|
@ -135,6 +141,27 @@ export type MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "groupToggleHalt",
|
||||
"accounts": [
|
||||
{
|
||||
"name": "group",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"isMut": false,
|
||||
"isSigner": true
|
||||
}
|
||||
],
|
||||
"args": [
|
||||
{
|
||||
"name": "halted",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "groupClose",
|
||||
"accounts": [
|
||||
|
@ -3364,18 +3391,13 @@ export type MangoV4 = {
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "perpLiqBankruptcy",
|
||||
"name": "perpLiqQuoteAndBankruptcy",
|
||||
"accounts": [
|
||||
{
|
||||
"name": "group",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "perpMarket",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"isMut": true,
|
||||
|
@ -3391,6 +3413,16 @@ export type MangoV4 = {
|
|||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "perpMarket",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "oracle",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "settleBank",
|
||||
"isMut": true,
|
||||
|
@ -3850,12 +3882,16 @@ export type MangoV4 = {
|
|||
"name": "version",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "halted",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding2",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
5
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -3868,12 +3904,16 @@ export type MangoV4 = {
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "securityAdmin",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1920
|
||||
1888
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -4778,6 +4818,13 @@ export type MangoV4 = {
|
|||
{
|
||||
"name": "marketIndex",
|
||||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "hasZeroFunds",
|
||||
"docs": [
|
||||
"The open orders account has no free or reserved funds"
|
||||
],
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -7042,6 +7089,16 @@ export type MangoV4 = {
|
|||
"name": "socializedLoss",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "startingLiabDepositIndex",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "endingLiabDepositIndex",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7307,6 +7364,56 @@ export type MangoV4 = {
|
|||
"name": "socializedLoss",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "startingLongFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "startingShortFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "endingLongFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "endingShortFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PerpLiqQuoteAndBankruptcyLog",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "perpMarketIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "settlement",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7536,6 +7643,36 @@ export type MangoV4 = {
|
|||
"code": 6031,
|
||||
"name": "MarketInReduceOnlyMode",
|
||||
"msg": "market is in reduce only mode"
|
||||
},
|
||||
{
|
||||
"code": 6032,
|
||||
"name": "GroupIsHalted",
|
||||
"msg": "group is halted"
|
||||
},
|
||||
{
|
||||
"code": 6033,
|
||||
"name": "PerpHasBaseLots",
|
||||
"msg": "the perp position has non-zero base lots"
|
||||
},
|
||||
{
|
||||
"code": 6034,
|
||||
"name": "HasOpenOrUnsettledSerum3Orders",
|
||||
"msg": "there are open or unsettled serum3 orders"
|
||||
},
|
||||
{
|
||||
"code": 6035,
|
||||
"name": "HasLiquidatableTokenPosition",
|
||||
"msg": "has liquidatable token position"
|
||||
},
|
||||
{
|
||||
"code": 6036,
|
||||
"name": "HasLiquidatablePerpBasePosition",
|
||||
"msg": "has liquidatable perp base position"
|
||||
},
|
||||
{
|
||||
"code": 6037,
|
||||
"name": "HasLiquidatableTrustedPerpPnl",
|
||||
"msg": "has liquidatable trusted perp pnl"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -7663,6 +7800,12 @@ export const IDL: MangoV4 = {
|
|||
"option": "publicKey"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "securityAdminOpt",
|
||||
"type": {
|
||||
"option": "publicKey"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "testingOpt",
|
||||
"type": {
|
||||
|
@ -7677,6 +7820,27 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "groupToggleHalt",
|
||||
"accounts": [
|
||||
{
|
||||
"name": "group",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"isMut": false,
|
||||
"isSigner": true
|
||||
}
|
||||
],
|
||||
"args": [
|
||||
{
|
||||
"name": "halted",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "groupClose",
|
||||
"accounts": [
|
||||
|
@ -10906,18 +11070,13 @@ export const IDL: MangoV4 = {
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "perpLiqBankruptcy",
|
||||
"name": "perpLiqQuoteAndBankruptcy",
|
||||
"accounts": [
|
||||
{
|
||||
"name": "group",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "perpMarket",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"isMut": true,
|
||||
|
@ -10933,6 +11092,16 @@ export const IDL: MangoV4 = {
|
|||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "perpMarket",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "oracle",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "settleBank",
|
||||
"isMut": true,
|
||||
|
@ -11392,12 +11561,16 @@ export const IDL: MangoV4 = {
|
|||
"name": "version",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "halted",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding2",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
5
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -11410,12 +11583,16 @@ export const IDL: MangoV4 = {
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "securityAdmin",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1920
|
||||
1888
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -12320,6 +12497,13 @@ export const IDL: MangoV4 = {
|
|||
{
|
||||
"name": "marketIndex",
|
||||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "hasZeroFunds",
|
||||
"docs": [
|
||||
"The open orders account has no free or reserved funds"
|
||||
],
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -14584,6 +14768,16 @@ export const IDL: MangoV4 = {
|
|||
"name": "socializedLoss",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "startingLiabDepositIndex",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "endingLiabDepositIndex",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -14849,6 +15043,56 @@ export const IDL: MangoV4 = {
|
|||
"name": "socializedLoss",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "startingLongFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "startingShortFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "endingLongFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "endingShortFunding",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PerpLiqQuoteAndBankruptcyLog",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "perpMarketIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "settlement",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -15078,6 +15322,36 @@ export const IDL: MangoV4 = {
|
|||
"code": 6031,
|
||||
"name": "MarketInReduceOnlyMode",
|
||||
"msg": "market is in reduce only mode"
|
||||
},
|
||||
{
|
||||
"code": 6032,
|
||||
"name": "GroupIsHalted",
|
||||
"msg": "group is halted"
|
||||
},
|
||||
{
|
||||
"code": 6033,
|
||||
"name": "PerpHasBaseLots",
|
||||
"msg": "the perp position has non-zero base lots"
|
||||
},
|
||||
{
|
||||
"code": 6034,
|
||||
"name": "HasOpenOrUnsettledSerum3Orders",
|
||||
"msg": "there are open or unsettled serum3 orders"
|
||||
},
|
||||
{
|
||||
"code": 6035,
|
||||
"name": "HasLiquidatableTokenPosition",
|
||||
"msg": "has liquidatable token position"
|
||||
},
|
||||
{
|
||||
"code": 6036,
|
||||
"name": "HasLiquidatablePerpBasePosition",
|
||||
"msg": "has liquidatable perp base position"
|
||||
},
|
||||
{
|
||||
"code": 6037,
|
||||
"name": "HasLiquidatableTrustedPerpPnl",
|
||||
"msg": "has liquidatable trusted perp pnl"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue