liquidation: Add flag to disable asset liquidation (#867)
This can be used to remove the oracle dependency for tokens with zero maint asset weight that are not borrowable.
This commit is contained in:
parent
712a2e3bd6
commit
d9a9c7d664
|
@ -370,11 +370,11 @@ impl<'a> LiquidateHelper<'a> {
|
||||||
.filter_map(|(ti, effective)| {
|
.filter_map(|(ti, effective)| {
|
||||||
// check constraints for liquidatable assets, see also has_possible_spot_liquidations()
|
// check constraints for liquidatable assets, see also has_possible_spot_liquidations()
|
||||||
let tokens = ti.balance_spot.min(effective.spot_and_perp);
|
let tokens = ti.balance_spot.min(effective.spot_and_perp);
|
||||||
let is_valid_asset = tokens >= 1;
|
let is_valid_asset = tokens >= 1 && ti.allow_asset_liquidation;
|
||||||
let quote_value = tokens * ti.prices.oracle;
|
let quote_value = tokens * ti.prices.oracle;
|
||||||
// prefer to liquidate tokens with asset weight that have >$1 liquidatable
|
// prefer to liquidate tokens with asset weight that have >$1 liquidatable
|
||||||
let is_preferred =
|
let is_preferred =
|
||||||
ti.init_asset_weight > 0 && quote_value > I80F48::from(1_000_000);
|
ti.maint_asset_weight > 0 && quote_value > I80F48::from(1_000_000);
|
||||||
is_valid_asset.then_some((ti.token_index, is_preferred, quote_value))
|
is_valid_asset.then_some((ti.token_index, is_preferred, quote_value))
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
|
@ -631,6 +631,10 @@
|
||||||
{
|
{
|
||||||
"name": "platformLiquidationFee",
|
"name": "platformLiquidationFee",
|
||||||
"type": "f32"
|
"type": "f32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidation",
|
||||||
|
"type": "bool"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1041,6 +1045,12 @@
|
||||||
"type": {
|
"type": {
|
||||||
"option": "f32"
|
"option": "f32"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidationOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "bool"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -7373,12 +7383,20 @@
|
||||||
"name": "forceClose",
|
"name": "forceClose",
|
||||||
"type": "u8"
|
"type": "u8"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidation",
|
||||||
|
"docs": [
|
||||||
|
"If set to 1, deposits cannot be liquidated when an account is liquidatable.",
|
||||||
|
"That means bankrupt accounts may still have assets of this type deposited."
|
||||||
|
],
|
||||||
|
"type": "u8"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": [
|
||||||
"u8",
|
"u8",
|
||||||
6
|
5
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -14028,6 +14046,11 @@
|
||||||
"code": 6068,
|
"code": 6068,
|
||||||
"name": "MissingFeedForCLMMOracle",
|
"name": "MissingFeedForCLMMOracle",
|
||||||
"msg": "Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)"
|
"msg": "Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": 6069,
|
||||||
|
"name": "TokenAssetLiquidationDisabled",
|
||||||
|
"msg": "the asset does not allow liquidation"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -143,6 +143,8 @@ pub enum MangoError {
|
||||||
InvalidFeedForCLMMOracle,
|
InvalidFeedForCLMMOracle,
|
||||||
#[msg("Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)")]
|
#[msg("Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)")]
|
||||||
MissingFeedForCLMMOracle,
|
MissingFeedForCLMMOracle,
|
||||||
|
#[msg("the asset does not allow liquidation")]
|
||||||
|
TokenAssetLiquidationDisabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MangoError {
|
impl MangoError {
|
||||||
|
|
|
@ -175,6 +175,8 @@ pub struct TokenInfo {
|
||||||
/// Includes TokenPosition and free Serum3OpenOrders balances.
|
/// Includes TokenPosition and free Serum3OpenOrders balances.
|
||||||
/// Does not include perp upnl or Serum3 reserved amounts.
|
/// Does not include perp upnl or Serum3 reserved amounts.
|
||||||
pub balance_spot: I80F48,
|
pub balance_spot: I80F48,
|
||||||
|
|
||||||
|
pub allow_asset_liquidation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporary value used during health computations
|
/// Temporary value used during health computations
|
||||||
|
@ -907,6 +909,7 @@ impl HealthCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Liquidatable spot assets mean: actual token deposits and also a positive effective token balance
|
/// Liquidatable spot assets mean: actual token deposits and also a positive effective token balance
|
||||||
|
/// and is available for asset liquidation
|
||||||
pub fn has_liq_spot_assets(&self) -> bool {
|
pub fn has_liq_spot_assets(&self) -> bool {
|
||||||
let health_token_balances = self.effective_token_balances(HealthType::LiquidationEnd);
|
let health_token_balances = self.effective_token_balances(HealthType::LiquidationEnd);
|
||||||
self.token_infos
|
self.token_infos
|
||||||
|
@ -914,11 +917,11 @@ impl HealthCache {
|
||||||
.zip(health_token_balances.iter())
|
.zip(health_token_balances.iter())
|
||||||
.any(|(ti, b)| {
|
.any(|(ti, b)| {
|
||||||
// need 1 native token to use token_liq_with_token
|
// need 1 native token to use token_liq_with_token
|
||||||
ti.balance_spot >= 1 && b.spot_and_perp >= 1
|
ti.balance_spot >= 1 && b.spot_and_perp >= 1 && ti.allow_asset_liquidation
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Liquidatable spot borrows mean: actual toen borrows plus a negative effective token balance
|
/// Liquidatable spot borrows mean: actual token borrows plus a negative effective token balance
|
||||||
pub fn has_liq_spot_borrows(&self) -> bool {
|
pub fn has_liq_spot_borrows(&self) -> bool {
|
||||||
let health_token_balances = self.effective_token_balances(HealthType::LiquidationEnd);
|
let health_token_balances = self.effective_token_balances(HealthType::LiquidationEnd);
|
||||||
self.token_infos
|
self.token_infos
|
||||||
|
@ -932,7 +935,9 @@ impl HealthCache {
|
||||||
let health_token_balances = self.effective_token_balances(HealthType::LiquidationEnd);
|
let health_token_balances = self.effective_token_balances(HealthType::LiquidationEnd);
|
||||||
let all_iter = || self.token_infos.iter().zip(health_token_balances.iter());
|
let all_iter = || self.token_infos.iter().zip(health_token_balances.iter());
|
||||||
all_iter().any(|(ti, b)| ti.balance_spot < 0 && b.spot_and_perp < 0)
|
all_iter().any(|(ti, b)| ti.balance_spot < 0 && b.spot_and_perp < 0)
|
||||||
&& all_iter().any(|(ti, b)| ti.balance_spot >= 1 && b.spot_and_perp >= 1)
|
&& all_iter().any(|(ti, b)| {
|
||||||
|
ti.balance_spot >= 1 && b.spot_and_perp >= 1 && ti.allow_asset_liquidation
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_serum3_open_orders_funds(&self) -> bool {
|
pub fn has_serum3_open_orders_funds(&self) -> bool {
|
||||||
|
@ -1286,6 +1291,7 @@ fn new_health_cache_impl(
|
||||||
init_scaled_liab_weight: bank.scaled_init_liab_weight(liab_price),
|
init_scaled_liab_weight: bank.scaled_init_liab_weight(liab_price),
|
||||||
prices,
|
prices,
|
||||||
balance_spot: native,
|
balance_spot: native,
|
||||||
|
allow_asset_liquidation: bank.allows_asset_liquidation(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -682,6 +682,7 @@ mod tests {
|
||||||
init_scaled_liab_weight: I80F48::from_num(1.0 + x),
|
init_scaled_liab_weight: I80F48::from_num(1.0 + x),
|
||||||
prices: Prices::new_single_price(I80F48::from_num(price)),
|
prices: Prices::new_single_price(I80F48::from_num(price)),
|
||||||
balance_spot: I80F48::ZERO,
|
balance_spot: I80F48::ZERO,
|
||||||
|
allow_asset_liquidation: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ pub fn token_edit(
|
||||||
deposit_limit_opt: Option<u64>,
|
deposit_limit_opt: Option<u64>,
|
||||||
zero_util_rate: Option<f32>,
|
zero_util_rate: Option<f32>,
|
||||||
platform_liquidation_fee: Option<f32>,
|
platform_liquidation_fee: Option<f32>,
|
||||||
|
disable_asset_liquidation_opt: Option<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let group = ctx.accounts.group.load()?;
|
let group = ctx.accounts.group.load()?;
|
||||||
|
|
||||||
|
@ -484,6 +485,16 @@ pub fn token_edit(
|
||||||
bank.platform_liquidation_fee = I80F48::from_num(platform_liquidation_fee);
|
bank.platform_liquidation_fee = I80F48::from_num(platform_liquidation_fee);
|
||||||
require_group_admin = true;
|
require_group_admin = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(disable_asset_liquidation) = disable_asset_liquidation_opt {
|
||||||
|
msg!(
|
||||||
|
"Asset liquidation disabled old {:?}, new {:?}",
|
||||||
|
bank.disable_asset_liquidation,
|
||||||
|
disable_asset_liquidation
|
||||||
|
);
|
||||||
|
bank.disable_asset_liquidation = u8::from(disable_asset_liquidation);
|
||||||
|
require_group_admin = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// account constraint #1
|
// account constraint #1
|
||||||
|
|
|
@ -112,6 +112,10 @@ pub(crate) fn liquidation_action(
|
||||||
liqee.token_position_and_raw_index(asset_token_index)?;
|
liqee.token_position_and_raw_index(asset_token_index)?;
|
||||||
let liqee_asset_native = liqee_asset_position.native(asset_bank);
|
let liqee_asset_native = liqee_asset_position.native(asset_bank);
|
||||||
require_gt!(liqee_asset_native, 0);
|
require_gt!(liqee_asset_native, 0);
|
||||||
|
require!(
|
||||||
|
asset_bank.allows_asset_liquidation(),
|
||||||
|
MangoError::TokenAssetLiquidationDisabled
|
||||||
|
);
|
||||||
|
|
||||||
let (liqee_liab_position, liqee_liab_raw_index) =
|
let (liqee_liab_position, liqee_liab_raw_index) =
|
||||||
liqee.token_position_and_raw_index(liab_token_index)?;
|
liqee.token_position_and_raw_index(liab_token_index)?;
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub fn token_register(
|
||||||
deposit_limit: u64,
|
deposit_limit: u64,
|
||||||
zero_util_rate: f32,
|
zero_util_rate: f32,
|
||||||
platform_liquidation_fee: f32,
|
platform_liquidation_fee: f32,
|
||||||
|
disable_asset_liquidation: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Require token 0 to be in the insurance token
|
// Require token 0 to be in the insurance token
|
||||||
if token_index == INSURANCE_TOKEN_INDEX {
|
if token_index == INSURANCE_TOKEN_INDEX {
|
||||||
|
@ -109,6 +110,7 @@ pub fn token_register(
|
||||||
deposit_weight_scale_start_quote,
|
deposit_weight_scale_start_quote,
|
||||||
reduce_only,
|
reduce_only,
|
||||||
force_close: 0,
|
force_close: 0,
|
||||||
|
disable_asset_liquidation: u8::from(disable_asset_liquidation),
|
||||||
padding: Default::default(),
|
padding: Default::default(),
|
||||||
fees_withdrawn: 0,
|
fees_withdrawn: 0,
|
||||||
token_conditional_swap_taker_fee_rate,
|
token_conditional_swap_taker_fee_rate,
|
||||||
|
|
|
@ -90,6 +90,7 @@ pub fn token_register_trustless(
|
||||||
deposit_weight_scale_start_quote: 5_000_000_000.0, // $5k
|
deposit_weight_scale_start_quote: 5_000_000_000.0, // $5k
|
||||||
reduce_only: 2, // deposit-only
|
reduce_only: 2, // deposit-only
|
||||||
force_close: 0,
|
force_close: 0,
|
||||||
|
disable_asset_liquidation: 1,
|
||||||
padding: Default::default(),
|
padding: Default::default(),
|
||||||
fees_withdrawn: 0,
|
fees_withdrawn: 0,
|
||||||
token_conditional_swap_taker_fee_rate: 0.0,
|
token_conditional_swap_taker_fee_rate: 0.0,
|
||||||
|
|
|
@ -157,6 +157,7 @@ pub mod mango_v4 {
|
||||||
deposit_limit: u64,
|
deposit_limit: u64,
|
||||||
zero_util_rate: f32,
|
zero_util_rate: f32,
|
||||||
platform_liquidation_fee: f32,
|
platform_liquidation_fee: f32,
|
||||||
|
disable_asset_liquidation: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
#[cfg(feature = "enable-gpl")]
|
#[cfg(feature = "enable-gpl")]
|
||||||
instructions::token_register(
|
instructions::token_register(
|
||||||
|
@ -190,6 +191,7 @@ pub mod mango_v4 {
|
||||||
deposit_limit,
|
deposit_limit,
|
||||||
zero_util_rate,
|
zero_util_rate,
|
||||||
platform_liquidation_fee,
|
platform_liquidation_fee,
|
||||||
|
disable_asset_liquidation,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -245,6 +247,7 @@ pub mod mango_v4 {
|
||||||
deposit_limit_opt: Option<u64>,
|
deposit_limit_opt: Option<u64>,
|
||||||
zero_util_rate_opt: Option<f32>,
|
zero_util_rate_opt: Option<f32>,
|
||||||
platform_liquidation_fee_opt: Option<f32>,
|
platform_liquidation_fee_opt: Option<f32>,
|
||||||
|
disable_asset_liquidation_opt: Option<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
#[cfg(feature = "enable-gpl")]
|
#[cfg(feature = "enable-gpl")]
|
||||||
instructions::token_edit(
|
instructions::token_edit(
|
||||||
|
@ -287,6 +290,7 @@ pub mod mango_v4 {
|
||||||
deposit_limit_opt,
|
deposit_limit_opt,
|
||||||
zero_util_rate_opt,
|
zero_util_rate_opt,
|
||||||
platform_liquidation_fee_opt,
|
platform_liquidation_fee_opt,
|
||||||
|
disable_asset_liquidation_opt,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,8 +158,12 @@ pub struct Bank {
|
||||||
pub reduce_only: u8,
|
pub reduce_only: u8,
|
||||||
pub force_close: u8,
|
pub force_close: u8,
|
||||||
|
|
||||||
|
/// If set to 1, deposits cannot be liquidated when an account is liquidatable.
|
||||||
|
/// That means bankrupt accounts may still have assets of this type deposited.
|
||||||
|
pub disable_asset_liquidation: u8,
|
||||||
|
|
||||||
#[derivative(Debug = "ignore")]
|
#[derivative(Debug = "ignore")]
|
||||||
pub padding: [u8; 6],
|
pub padding: [u8; 5],
|
||||||
|
|
||||||
// Do separate bookkeping for how many tokens were withdrawn
|
// Do separate bookkeping for how many tokens were withdrawn
|
||||||
// This ensures that collected_fees_native is strictly increasing for stats gathering purposes
|
// This ensures that collected_fees_native is strictly increasing for stats gathering purposes
|
||||||
|
@ -346,7 +350,8 @@ impl Bank {
|
||||||
deposit_weight_scale_start_quote: existing_bank.deposit_weight_scale_start_quote,
|
deposit_weight_scale_start_quote: existing_bank.deposit_weight_scale_start_quote,
|
||||||
reduce_only: existing_bank.reduce_only,
|
reduce_only: existing_bank.reduce_only,
|
||||||
force_close: existing_bank.force_close,
|
force_close: existing_bank.force_close,
|
||||||
padding: [0; 6],
|
disable_asset_liquidation: existing_bank.disable_asset_liquidation,
|
||||||
|
padding: [0; 5],
|
||||||
token_conditional_swap_taker_fee_rate: existing_bank
|
token_conditional_swap_taker_fee_rate: existing_bank
|
||||||
.token_conditional_swap_taker_fee_rate,
|
.token_conditional_swap_taker_fee_rate,
|
||||||
token_conditional_swap_maker_fee_rate: existing_bank
|
token_conditional_swap_maker_fee_rate: existing_bank
|
||||||
|
@ -396,6 +401,10 @@ impl Bank {
|
||||||
require_gte!(self.maint_weight_shift_liab_target, 0.0);
|
require_gte!(self.maint_weight_shift_liab_target, 0.0);
|
||||||
require_gte!(self.zero_util_rate, I80F48::ZERO);
|
require_gte!(self.zero_util_rate, I80F48::ZERO);
|
||||||
require_gte!(self.platform_liquidation_fee, 0.0);
|
require_gte!(self.platform_liquidation_fee, 0.0);
|
||||||
|
if !self.allows_asset_liquidation() {
|
||||||
|
require!(self.are_borrows_reduce_only(), MangoError::SomeError);
|
||||||
|
require_eq!(self.maint_asset_weight, I80F48::ZERO);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,6 +426,10 @@ impl Bank {
|
||||||
self.force_close == 1
|
self.force_close == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn allows_asset_liquidation(&self) -> bool {
|
||||||
|
self.disable_asset_liquidation == 0
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn native_borrows(&self) -> I80F48 {
|
pub fn native_borrows(&self) -> I80F48 {
|
||||||
self.borrow_index * self.indexed_borrows
|
self.borrow_index * self.indexed_borrows
|
||||||
|
|
|
@ -324,6 +324,66 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
||||||
//
|
//
|
||||||
set_bank_stub_oracle_price(solana, group, borrow_token1, admin, 2.0).await;
|
set_bank_stub_oracle_price(solana, group, borrow_token1, admin, 2.0).await;
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: can't liquidate if token has no asset weight
|
||||||
|
//
|
||||||
|
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
TokenEdit {
|
||||||
|
group,
|
||||||
|
admin,
|
||||||
|
mint: collateral_token2.mint.pubkey,
|
||||||
|
fallback_oracle: Pubkey::default(),
|
||||||
|
options: mango_v4::instruction::TokenEdit {
|
||||||
|
maint_asset_weight_opt: Some(0.0),
|
||||||
|
init_asset_weight_opt: Some(0.0),
|
||||||
|
disable_asset_liquidation_opt: Some(true),
|
||||||
|
reduce_only_opt: Some(1),
|
||||||
|
..token_edit_instruction_default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let res = send_tx(
|
||||||
|
solana,
|
||||||
|
TokenLiqWithTokenInstruction {
|
||||||
|
liqee: account,
|
||||||
|
liqor: vault_account,
|
||||||
|
liqor_owner: owner,
|
||||||
|
asset_token_index: collateral_token2.index,
|
||||||
|
liab_token_index: borrow_token2.index,
|
||||||
|
asset_bank_index: 0,
|
||||||
|
liab_bank_index: 0,
|
||||||
|
max_liab_transfer: I80F48::from_num(10000.0),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_mango_error(
|
||||||
|
&res,
|
||||||
|
MangoError::TokenAssetLiquidationDisabled.into(),
|
||||||
|
"liquidation disabled".to_string(),
|
||||||
|
);
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
TokenEdit {
|
||||||
|
group,
|
||||||
|
admin,
|
||||||
|
mint: collateral_token2.mint.pubkey,
|
||||||
|
fallback_oracle: Pubkey::default(),
|
||||||
|
options: mango_v4::instruction::TokenEdit {
|
||||||
|
maint_asset_weight_opt: Some(0.8),
|
||||||
|
init_asset_weight_opt: Some(0.6),
|
||||||
|
disable_asset_liquidation_opt: Some(false),
|
||||||
|
reduce_only_opt: Some(0),
|
||||||
|
..token_edit_instruction_default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
//
|
//
|
||||||
// TEST: liquidate borrow2 against too little collateral2
|
// TEST: liquidate borrow2 against too little collateral2
|
||||||
//
|
//
|
||||||
|
|
|
@ -1077,6 +1077,7 @@ impl ClientInstruction for TokenRegisterInstruction {
|
||||||
deposit_limit: 0,
|
deposit_limit: 0,
|
||||||
zero_util_rate: 0.0,
|
zero_util_rate: 0.0,
|
||||||
platform_liquidation_fee: self.platform_liquidation_fee,
|
platform_liquidation_fee: self.platform_liquidation_fee,
|
||||||
|
disable_asset_liquidation: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let bank = Pubkey::find_program_address(
|
let bank = Pubkey::find_program_address(
|
||||||
|
@ -1324,6 +1325,7 @@ pub fn token_edit_instruction_default() -> mango_v4::instruction::TokenEdit {
|
||||||
deposit_limit_opt: None,
|
deposit_limit_opt: None,
|
||||||
zero_util_rate_opt: None,
|
zero_util_rate_opt: None,
|
||||||
platform_liquidation_fee_opt: None,
|
platform_liquidation_fee_opt: None,
|
||||||
|
disable_asset_liquidation_opt: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ export class Bank implements BankForHealth {
|
||||||
depositWeightScaleStartQuote: number;
|
depositWeightScaleStartQuote: number;
|
||||||
reduceOnly: number;
|
reduceOnly: number;
|
||||||
forceClose: number;
|
forceClose: number;
|
||||||
|
disableAssetLiquidation: number;
|
||||||
feesWithdrawn: BN;
|
feesWithdrawn: BN;
|
||||||
tokenConditionalSwapTakerFeeRate: number;
|
tokenConditionalSwapTakerFeeRate: number;
|
||||||
tokenConditionalSwapMakerFeeRate: number;
|
tokenConditionalSwapMakerFeeRate: number;
|
||||||
|
@ -211,6 +212,7 @@ export class Bank implements BankForHealth {
|
||||||
obj.zeroUtilRate,
|
obj.zeroUtilRate,
|
||||||
obj.platformLiquidationFee,
|
obj.platformLiquidationFee,
|
||||||
obj.collectedLiquidationFees,
|
obj.collectedLiquidationFees,
|
||||||
|
obj.disableAssetLiquidation == 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +278,7 @@ export class Bank implements BankForHealth {
|
||||||
zeroUtilRate: I80F48Dto,
|
zeroUtilRate: I80F48Dto,
|
||||||
platformLiquidationFee: I80F48Dto,
|
platformLiquidationFee: I80F48Dto,
|
||||||
collectedLiquidationFees: I80F48Dto,
|
collectedLiquidationFees: I80F48Dto,
|
||||||
|
public allowAssetLiquidation: boolean,
|
||||||
) {
|
) {
|
||||||
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
|
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
|
||||||
this.oracleConfig = {
|
this.oracleConfig = {
|
||||||
|
|
|
@ -461,6 +461,7 @@ export class MangoClient {
|
||||||
params.depositLimit,
|
params.depositLimit,
|
||||||
params.zeroUtilRate,
|
params.zeroUtilRate,
|
||||||
params.platformLiquidationFee,
|
params.platformLiquidationFee,
|
||||||
|
params.disableAssetLiquidation,
|
||||||
)
|
)
|
||||||
.accounts({
|
.accounts({
|
||||||
group: group.publicKey,
|
group: group.publicKey,
|
||||||
|
@ -548,6 +549,7 @@ export class MangoClient {
|
||||||
params.depositLimit,
|
params.depositLimit,
|
||||||
params.zeroUtilRate,
|
params.zeroUtilRate,
|
||||||
params.platformLiquidationFee,
|
params.platformLiquidationFee,
|
||||||
|
params.disableAssetLiquidation,
|
||||||
)
|
)
|
||||||
.accounts({
|
.accounts({
|
||||||
group: group.publicKey,
|
group: group.publicKey,
|
||||||
|
|
|
@ -30,6 +30,7 @@ export interface TokenRegisterParams {
|
||||||
depositLimit: BN;
|
depositLimit: BN;
|
||||||
zeroUtilRate: number;
|
zeroUtilRate: number;
|
||||||
platformLiquidationFee: number;
|
platformLiquidationFee: number;
|
||||||
|
disableAssetLiquidation: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
||||||
|
@ -70,6 +71,7 @@ export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
||||||
depositLimit: new BN(0),
|
depositLimit: new BN(0),
|
||||||
zeroUtilRate: 0.0,
|
zeroUtilRate: 0.0,
|
||||||
platformLiquidationFee: 0.0,
|
platformLiquidationFee: 0.0,
|
||||||
|
disableAssetLiquidation: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface TokenEditParams {
|
export interface TokenEditParams {
|
||||||
|
@ -111,6 +113,7 @@ export interface TokenEditParams {
|
||||||
depositLimit: BN | null;
|
depositLimit: BN | null;
|
||||||
zeroUtilRate: number | null;
|
zeroUtilRate: number | null;
|
||||||
platformLiquidationFee: number | null;
|
platformLiquidationFee: number | null;
|
||||||
|
disableAssetLiquidation: boolean | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NullTokenEditParams: TokenEditParams = {
|
export const NullTokenEditParams: TokenEditParams = {
|
||||||
|
@ -152,6 +155,7 @@ export const NullTokenEditParams: TokenEditParams = {
|
||||||
depositLimit: null,
|
depositLimit: null,
|
||||||
zeroUtilRate: null,
|
zeroUtilRate: null,
|
||||||
platformLiquidationFee: null,
|
platformLiquidationFee: null,
|
||||||
|
disableAssetLiquidation: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface PerpEditParams {
|
export interface PerpEditParams {
|
||||||
|
|
|
@ -631,6 +631,10 @@ export type MangoV4 = {
|
||||||
{
|
{
|
||||||
"name": "platformLiquidationFee",
|
"name": "platformLiquidationFee",
|
||||||
"type": "f32"
|
"type": "f32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidation",
|
||||||
|
"type": "bool"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1041,6 +1045,12 @@ export type MangoV4 = {
|
||||||
"type": {
|
"type": {
|
||||||
"option": "f32"
|
"option": "f32"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidationOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "bool"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -7373,12 +7383,20 @@ export type MangoV4 = {
|
||||||
"name": "forceClose",
|
"name": "forceClose",
|
||||||
"type": "u8"
|
"type": "u8"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidation",
|
||||||
|
"docs": [
|
||||||
|
"If set to 1, deposits cannot be liquidated when an account is liquidatable.",
|
||||||
|
"That means bankrupt accounts may still have assets of this type deposited."
|
||||||
|
],
|
||||||
|
"type": "u8"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": [
|
||||||
"u8",
|
"u8",
|
||||||
6
|
5
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -14028,6 +14046,11 @@ export type MangoV4 = {
|
||||||
"code": 6068,
|
"code": 6068,
|
||||||
"name": "MissingFeedForCLMMOracle",
|
"name": "MissingFeedForCLMMOracle",
|
||||||
"msg": "Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)"
|
"msg": "Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": 6069,
|
||||||
|
"name": "TokenAssetLiquidationDisabled",
|
||||||
|
"msg": "the asset does not allow liquidation"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -14665,6 +14688,10 @@ export const IDL: MangoV4 = {
|
||||||
{
|
{
|
||||||
"name": "platformLiquidationFee",
|
"name": "platformLiquidationFee",
|
||||||
"type": "f32"
|
"type": "f32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidation",
|
||||||
|
"type": "bool"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -15075,6 +15102,12 @@ export const IDL: MangoV4 = {
|
||||||
"type": {
|
"type": {
|
||||||
"option": "f32"
|
"option": "f32"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidationOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "bool"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -21407,12 +21440,20 @@ export const IDL: MangoV4 = {
|
||||||
"name": "forceClose",
|
"name": "forceClose",
|
||||||
"type": "u8"
|
"type": "u8"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "disableAssetLiquidation",
|
||||||
|
"docs": [
|
||||||
|
"If set to 1, deposits cannot be liquidated when an account is liquidatable.",
|
||||||
|
"That means bankrupt accounts may still have assets of this type deposited."
|
||||||
|
],
|
||||||
|
"type": "u8"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": [
|
||||||
"u8",
|
"u8",
|
||||||
6
|
5
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -28062,6 +28103,11 @@ export const IDL: MangoV4 = {
|
||||||
"code": 6068,
|
"code": 6068,
|
||||||
"name": "MissingFeedForCLMMOracle",
|
"name": "MissingFeedForCLMMOracle",
|
||||||
"msg": "Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)"
|
"msg": "Pyth USDC/USD or SOL/USD feed not found (required by CLMM oracle)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": 6069,
|
||||||
|
"name": "TokenAssetLiquidationDisabled",
|
||||||
|
"msg": "the asset does not allow liquidation"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue