Add a token-token platform liquidation fee (#849)
The liqor liquidation fee and platform liquidation fee for the asset and liab token are both payed by the liqee. The platform liquidation fee is added to the Bank's collected_fees_native and tracked in collected_liquidation_fees.
This commit is contained in:
parent
511814ca97
commit
8383109f0d
177
mango_v4.json
177
mango_v4.json
|
@ -627,6 +627,10 @@
|
|||
{
|
||||
"name": "zeroUtilRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFee",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1031,6 +1035,12 @@
|
|||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFeeOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7193,6 +7203,12 @@
|
|||
},
|
||||
{
|
||||
"name": "collectedFeesNative",
|
||||
"docs": [
|
||||
"Fees collected over the lifetime of the bank",
|
||||
"",
|
||||
"See fees_withdrawn for how much of the fees was withdrawn.",
|
||||
"See collected_liquidation_fees for the (included) subtotal for liquidation related fees."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7235,6 +7251,15 @@
|
|||
},
|
||||
{
|
||||
"name": "liquidationFee",
|
||||
"docs": [
|
||||
"Liquidation fee that goes to the liqor.",
|
||||
"",
|
||||
"Liquidation always involves two tokens, and the sum of the two configured fees is used.",
|
||||
"",
|
||||
"A fraction of the price, like 0.05 for a 5% fee during liquidation.",
|
||||
"",
|
||||
"See also platform_liquidation_fee."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7458,12 +7483,32 @@
|
|||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFee",
|
||||
"docs": [
|
||||
"Additional to liquidation_fee, but goes to the group owner instead of the liqor"
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "collectedLiquidationFees",
|
||||
"docs": [
|
||||
"Fees that were collected during liquidation (in native tokens)",
|
||||
"",
|
||||
"See also collected_fees_native and fees_withdrawn."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1952
|
||||
1920
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -11962,6 +12007,71 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenLiqWithTokenLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferFromLiqee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferToLiqor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetLiquidationFee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTransfer",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "bankruptcy",
|
||||
"type": "bool",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Serum3OpenOrdersBalanceLog",
|
||||
"fields": [
|
||||
|
@ -12838,6 +12948,71 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenForceCloseBorrowsWithTokenLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferFromLiqee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferToLiqor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetLiquidationFee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTransfer",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "feeFactor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenConditionalSwapCreateLog",
|
||||
"fields": [
|
||||
|
|
|
@ -52,6 +52,7 @@ pub fn token_edit(
|
|||
set_fallback_oracle: bool,
|
||||
deposit_limit_opt: Option<u64>,
|
||||
zero_util_rate: Option<f32>,
|
||||
platform_liquidation_fee: Option<f32>,
|
||||
) -> Result<()> {
|
||||
let group = ctx.accounts.group.load()?;
|
||||
|
||||
|
@ -473,6 +474,16 @@ pub fn token_edit(
|
|||
bank.zero_util_rate = I80F48::from_num(zero_util_rate);
|
||||
require_group_admin = true;
|
||||
}
|
||||
|
||||
if let Some(platform_liquidation_fee) = platform_liquidation_fee {
|
||||
msg!(
|
||||
"Platform liquidation fee old {:?}, new {:?}",
|
||||
bank.platform_liquidation_fee,
|
||||
platform_liquidation_fee
|
||||
);
|
||||
bank.platform_liquidation_fee = I80F48::from_num(platform_liquidation_fee);
|
||||
require_group_admin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// account constraint #1
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::accounts_ix::*;
|
||||
use crate::error::*;
|
||||
use crate::health::*;
|
||||
use crate::logs::{emit_stack, TokenBalanceLog, TokenForceCloseBorrowsWithTokenLog};
|
||||
use crate::logs::{emit_stack, TokenBalanceLog, TokenForceCloseBorrowsWithTokenLogV2};
|
||||
use crate::state::*;
|
||||
use anchor_lang::prelude::*;
|
||||
use fixed::types::I80F48;
|
||||
|
@ -62,12 +62,18 @@ pub fn token_force_close_borrows_with_token(
|
|||
MangoError::TokenInReduceOnlyMode
|
||||
);
|
||||
|
||||
let fee_factor_liqor =
|
||||
(I80F48::ONE + liab_bank.liquidation_fee) * (I80F48::ONE + asset_bank.liquidation_fee);
|
||||
let fee_factor_total =
|
||||
(I80F48::ONE + liab_bank.liquidation_fee + liab_bank.platform_liquidation_fee)
|
||||
* (I80F48::ONE + asset_bank.liquidation_fee + asset_bank.platform_liquidation_fee);
|
||||
|
||||
// account constraint #3
|
||||
// only allow combination of asset and liab token,
|
||||
// where liqee's health would be guaranteed to not decrease
|
||||
require_gte!(
|
||||
liab_bank.init_liab_weight,
|
||||
asset_bank.init_liab_weight * (I80F48::ONE + liab_bank.liquidation_fee),
|
||||
asset_bank.init_liab_weight * fee_factor_total,
|
||||
MangoError::SomeError
|
||||
);
|
||||
|
||||
|
@ -95,10 +101,13 @@ pub fn token_force_close_borrows_with_token(
|
|||
.max(I80F48::ZERO);
|
||||
|
||||
// The amount of asset native tokens we will give up for them
|
||||
let fee_factor =
|
||||
(I80F48::ONE + liab_bank.liquidation_fee) * (I80F48::ONE + asset_bank.liquidation_fee);
|
||||
let liab_oracle_price_adjusted = liab_oracle_price * fee_factor;
|
||||
let asset_transfer = liab_transfer * liab_oracle_price_adjusted / asset_oracle_price;
|
||||
let asset_transfer_base = liab_transfer * liab_oracle_price / asset_oracle_price;
|
||||
let asset_transfer_to_liqor = asset_transfer_base * fee_factor_liqor;
|
||||
let asset_transfer_from_liqee = asset_transfer_base * fee_factor_total;
|
||||
|
||||
let asset_liquidation_fee = asset_transfer_from_liqee - asset_transfer_to_liqor;
|
||||
asset_bank.collected_fees_native += asset_liquidation_fee;
|
||||
asset_bank.collected_liquidation_fees += asset_liquidation_fee;
|
||||
|
||||
// Apply the balance changes to the liqor and liqee accounts
|
||||
let liqee_liab_active =
|
||||
|
@ -113,13 +122,13 @@ pub fn token_force_close_borrows_with_token(
|
|||
let (liqor_asset_position, liqor_asset_raw_index, _) =
|
||||
liqor.ensure_token_position(asset_token_index)?;
|
||||
let liqor_asset_active =
|
||||
asset_bank.deposit(liqor_asset_position, asset_transfer, now_ts)?;
|
||||
asset_bank.deposit(liqor_asset_position, asset_transfer_to_liqor, now_ts)?;
|
||||
let liqor_asset_indexed_position = liqor_asset_position.indexed_position;
|
||||
|
||||
let liqee_asset_position = liqee.token_position_mut_by_raw_index(liqee_asset_raw_index);
|
||||
let liqee_asset_active = asset_bank.withdraw_without_fee_with_dusting(
|
||||
liqee_asset_position,
|
||||
asset_transfer,
|
||||
asset_transfer_from_liqee,
|
||||
now_ts,
|
||||
)?;
|
||||
let liqee_asset_indexed_position = liqee_asset_position.indexed_position;
|
||||
|
@ -128,7 +137,7 @@ pub fn token_force_close_borrows_with_token(
|
|||
msg!(
|
||||
"Force closed {} liab for {} asset",
|
||||
liab_transfer,
|
||||
asset_transfer
|
||||
asset_transfer_from_liqee,
|
||||
);
|
||||
|
||||
// liqee asset
|
||||
|
@ -168,17 +177,19 @@ pub fn token_force_close_borrows_with_token(
|
|||
borrow_index: liab_bank.borrow_index.to_bits(),
|
||||
});
|
||||
|
||||
emit_stack(TokenForceCloseBorrowsWithTokenLog {
|
||||
emit_stack(TokenForceCloseBorrowsWithTokenLogV2 {
|
||||
mango_group: liqee.fixed.group,
|
||||
liqee: liqee_key,
|
||||
liqor: liqor_key,
|
||||
asset_token_index: asset_token_index,
|
||||
liab_token_index: liab_token_index,
|
||||
asset_transfer: asset_transfer.to_bits(),
|
||||
asset_transfer_from_liqee: asset_transfer_from_liqee.to_bits(),
|
||||
asset_transfer_to_liqor: asset_transfer_to_liqor.to_bits(),
|
||||
asset_liquidation_fee: asset_liquidation_fee.to_bits(),
|
||||
liab_transfer: liab_transfer.to_bits(),
|
||||
asset_price: asset_oracle_price.to_bits(),
|
||||
liab_price: liab_oracle_price.to_bits(),
|
||||
fee_factor: fee_factor.to_bits(),
|
||||
fee_factor: fee_factor_total.to_bits(),
|
||||
});
|
||||
|
||||
// liqor should never have a borrow
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::accounts_ix::*;
|
|||
use crate::error::*;
|
||||
use crate::health::*;
|
||||
use crate::logs::{
|
||||
emit_stack, LoanOriginationFeeInstruction, TokenBalanceLog, TokenLiqWithTokenLog,
|
||||
emit_stack, LoanOriginationFeeInstruction, TokenBalanceLog, TokenLiqWithTokenLogV2,
|
||||
WithdrawLoanLog,
|
||||
};
|
||||
use crate::state::*;
|
||||
|
@ -132,9 +132,12 @@ pub(crate) fn liquidation_action(
|
|||
// assets = liabs * liab_oracle_price / asset_oracle_price * fee_factor
|
||||
// assets = liabs * liab_oracle_price_adjusted / asset_oracle_price
|
||||
// = liabs * lopa / aop
|
||||
let fee_factor =
|
||||
let fee_factor_liqor =
|
||||
(I80F48::ONE + liab_bank.liquidation_fee) * (I80F48::ONE + asset_bank.liquidation_fee);
|
||||
let liab_oracle_price_adjusted = liab_oracle_price * fee_factor;
|
||||
let fee_factor_total =
|
||||
(I80F48::ONE + liab_bank.liquidation_fee + liab_bank.platform_liquidation_fee)
|
||||
* (I80F48::ONE + asset_bank.liquidation_fee + asset_bank.platform_liquidation_fee);
|
||||
let liab_oracle_price_adjusted = liab_oracle_price * fee_factor_total;
|
||||
|
||||
let init_asset_weight = asset_bank.init_asset_weight;
|
||||
let init_liab_weight = liab_bank.init_liab_weight;
|
||||
|
@ -218,7 +221,13 @@ pub(crate) fn liquidation_action(
|
|||
.max(I80F48::ZERO);
|
||||
|
||||
// The amount of asset native tokens we will give up for them
|
||||
let asset_transfer = liab_transfer * liab_oracle_price_adjusted / asset_oracle_price;
|
||||
let asset_transfer_base = liab_transfer * liab_oracle_price / asset_oracle_price;
|
||||
let asset_transfer_to_liqor = asset_transfer_base * fee_factor_liqor;
|
||||
let asset_transfer_from_liqee = asset_transfer_base * fee_factor_total;
|
||||
|
||||
let asset_liquidation_fee = asset_transfer_from_liqee - asset_transfer_to_liqor;
|
||||
asset_bank.collected_fees_native += asset_liquidation_fee;
|
||||
asset_bank.collected_liquidation_fees += asset_liquidation_fee;
|
||||
|
||||
// During liquidation, we mustn't leave small positive balances in the liqee. Those
|
||||
// could break bankruptcy-detection. Thus we dust them even if the token position
|
||||
|
@ -239,13 +248,14 @@ pub(crate) fn liquidation_action(
|
|||
|
||||
let (liqor_asset_position, liqor_asset_raw_index, _) =
|
||||
liqor.ensure_token_position(asset_token_index)?;
|
||||
let liqor_asset_active = asset_bank.deposit(liqor_asset_position, asset_transfer, now_ts)?;
|
||||
let liqor_asset_active =
|
||||
asset_bank.deposit(liqor_asset_position, asset_transfer_to_liqor, now_ts)?;
|
||||
let liqor_asset_indexed_position = liqor_asset_position.indexed_position;
|
||||
|
||||
let liqee_asset_position = liqee.token_position_mut_by_raw_index(liqee_asset_raw_index);
|
||||
let liqee_asset_active = asset_bank.withdraw_without_fee_with_dusting(
|
||||
liqee_asset_position,
|
||||
asset_transfer,
|
||||
asset_transfer_from_liqee,
|
||||
now_ts,
|
||||
)?;
|
||||
let liqee_asset_indexed_position = liqee_asset_position.indexed_position;
|
||||
|
@ -260,7 +270,7 @@ pub(crate) fn liquidation_action(
|
|||
msg!(
|
||||
"liquidated {} liab for {} asset",
|
||||
liab_transfer,
|
||||
asset_transfer
|
||||
asset_transfer_from_liqee,
|
||||
);
|
||||
|
||||
// liqee asset
|
||||
|
@ -335,13 +345,15 @@ pub(crate) fn liquidation_action(
|
|||
.fixed
|
||||
.maybe_recover_from_being_liquidated(liqee_liq_end_health);
|
||||
|
||||
emit_stack(TokenLiqWithTokenLog {
|
||||
emit_stack(TokenLiqWithTokenLogV2 {
|
||||
mango_group: liqee.fixed.group,
|
||||
liqee: liqee_key,
|
||||
liqor: liqor_key,
|
||||
asset_token_index,
|
||||
liab_token_index,
|
||||
asset_transfer: asset_transfer.to_bits(),
|
||||
asset_transfer_from_liqee: asset_transfer_from_liqee.to_bits(),
|
||||
asset_transfer_to_liqor: asset_transfer_to_liqor.to_bits(),
|
||||
asset_liquidation_fee: asset_liquidation_fee.to_bits(),
|
||||
liab_transfer: liab_transfer.to_bits(),
|
||||
asset_price: asset_oracle_price.to_bits(),
|
||||
liab_price: liab_oracle_price.to_bits(),
|
||||
|
|
|
@ -43,6 +43,7 @@ pub fn token_register(
|
|||
group_insurance_fund: bool,
|
||||
deposit_limit: u64,
|
||||
zero_util_rate: f32,
|
||||
platform_liquidation_fee: f32,
|
||||
) -> Result<()> {
|
||||
// Require token 0 to be in the insurance token
|
||||
if token_index == INSURANCE_TOKEN_INDEX {
|
||||
|
@ -124,7 +125,9 @@ pub fn token_register(
|
|||
fallback_oracle: ctx.accounts.fallback_oracle.key(),
|
||||
deposit_limit,
|
||||
zero_util_rate: I80F48::from_num(zero_util_rate),
|
||||
reserved: [0; 1952],
|
||||
platform_liquidation_fee: I80F48::from_num(platform_liquidation_fee),
|
||||
collected_liquidation_fees: I80F48::ZERO,
|
||||
reserved: [0; 1920],
|
||||
};
|
||||
|
||||
let oracle_ref = &AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?;
|
||||
|
|
|
@ -71,7 +71,8 @@ pub fn token_register_trustless(
|
|||
init_asset_weight: I80F48::from_num(0),
|
||||
maint_liab_weight: I80F48::from_num(1.4), // 2.5x
|
||||
init_liab_weight: I80F48::from_num(1.8), // 1.25x
|
||||
liquidation_fee: I80F48::from_num(0.2),
|
||||
liquidation_fee: I80F48::from_num(0.05),
|
||||
platform_liquidation_fee: I80F48::from_num(0.05),
|
||||
dust: I80F48::ZERO,
|
||||
flash_loan_token_account_initial: u64::MAX,
|
||||
flash_loan_approved_amount: 0,
|
||||
|
@ -105,7 +106,8 @@ pub fn token_register_trustless(
|
|||
fallback_oracle: ctx.accounts.fallback_oracle.key(),
|
||||
deposit_limit: 0,
|
||||
zero_util_rate: I80F48::ZERO,
|
||||
reserved: [0; 1952],
|
||||
collected_liquidation_fees: I80F48::ZERO,
|
||||
reserved: [0; 1920],
|
||||
};
|
||||
let oracle_ref = &AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?;
|
||||
if let Ok(oracle_price) = bank.oracle_price(&OracleAccountInfos::from_reader(oracle_ref), None)
|
||||
|
|
|
@ -156,6 +156,7 @@ pub mod mango_v4 {
|
|||
group_insurance_fund: bool,
|
||||
deposit_limit: u64,
|
||||
zero_util_rate: f32,
|
||||
platform_liquidation_fee: f32,
|
||||
) -> Result<()> {
|
||||
#[cfg(feature = "enable-gpl")]
|
||||
instructions::token_register(
|
||||
|
@ -188,6 +189,7 @@ pub mod mango_v4 {
|
|||
group_insurance_fund,
|
||||
deposit_limit,
|
||||
zero_util_rate,
|
||||
platform_liquidation_fee,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -242,6 +244,7 @@ pub mod mango_v4 {
|
|||
set_fallback_oracle: bool,
|
||||
deposit_limit_opt: Option<u64>,
|
||||
zero_util_rate_opt: Option<f32>,
|
||||
platform_liquidation_fee_opt: Option<f32>,
|
||||
) -> Result<()> {
|
||||
#[cfg(feature = "enable-gpl")]
|
||||
instructions::token_edit(
|
||||
|
@ -283,6 +286,7 @@ pub mod mango_v4 {
|
|||
set_fallback_oracle,
|
||||
deposit_limit_opt,
|
||||
zero_util_rate_opt,
|
||||
platform_liquidation_fee_opt,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -344,6 +344,22 @@ pub struct TokenLiqWithTokenLog {
|
|||
pub bankruptcy: bool,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct TokenLiqWithTokenLogV2 {
|
||||
pub mango_group: Pubkey,
|
||||
pub liqee: Pubkey,
|
||||
pub liqor: Pubkey,
|
||||
pub asset_token_index: u16,
|
||||
pub liab_token_index: u16,
|
||||
pub asset_transfer_from_liqee: i128, // I80F48
|
||||
pub asset_transfer_to_liqor: i128, // I80F48
|
||||
pub asset_liquidation_fee: i128, // I80F48
|
||||
pub liab_transfer: i128, // I80F48
|
||||
pub asset_price: i128, // I80F48
|
||||
pub liab_price: i128, // I80F48
|
||||
pub bankruptcy: bool,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct Serum3OpenOrdersBalanceLog {
|
||||
pub mango_group: Pubkey,
|
||||
|
@ -594,6 +610,23 @@ pub struct TokenForceCloseBorrowsWithTokenLog {
|
|||
pub fee_factor: i128,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct TokenForceCloseBorrowsWithTokenLogV2 {
|
||||
pub mango_group: Pubkey,
|
||||
pub liqor: Pubkey,
|
||||
pub liqee: Pubkey,
|
||||
pub asset_token_index: u16,
|
||||
pub liab_token_index: u16,
|
||||
pub asset_transfer_from_liqee: i128, // I80F48
|
||||
pub asset_transfer_to_liqor: i128, // I80F48
|
||||
pub asset_liquidation_fee: i128, // I80F48
|
||||
pub liab_transfer: i128, // I80F48
|
||||
pub asset_price: i128, // I80F48
|
||||
pub liab_price: i128, // I80F48
|
||||
/// including liqor and platform liquidation fees
|
||||
pub fee_factor: i128, // I80F48
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct TokenConditionalSwapCreateLog {
|
||||
pub mango_group: Pubkey,
|
||||
|
|
|
@ -79,8 +79,12 @@ pub struct Bank {
|
|||
/// which is >=1.
|
||||
pub max_rate: I80F48,
|
||||
|
||||
// TODO: add ix/logic to regular send this to DAO
|
||||
/// Fees collected over the lifetime of the bank
|
||||
///
|
||||
/// See fees_withdrawn for how much of the fees was withdrawn.
|
||||
/// See collected_liquidation_fees for the (included) subtotal for liquidation related fees.
|
||||
pub collected_fees_native: I80F48,
|
||||
|
||||
pub loan_origination_fee_rate: I80F48,
|
||||
pub loan_fee_rate: I80F48,
|
||||
|
||||
|
@ -92,9 +96,13 @@ pub struct Bank {
|
|||
pub maint_liab_weight: I80F48,
|
||||
pub init_liab_weight: I80F48,
|
||||
|
||||
// a fraction of the price, like 0.05 for a 5% fee during liquidation
|
||||
//
|
||||
// Liquidation always involves two tokens, and the sum of the two configured fees is used.
|
||||
/// Liquidation fee that goes to the liqor.
|
||||
///
|
||||
/// Liquidation always involves two tokens, and the sum of the two configured fees is used.
|
||||
///
|
||||
/// A fraction of the price, like 0.05 for a 5% fee during liquidation.
|
||||
///
|
||||
/// See also platform_liquidation_fee.
|
||||
pub liquidation_fee: I80F48,
|
||||
|
||||
// Collection of all fractions-of-native-tokens that got rounded away
|
||||
|
@ -201,8 +209,16 @@ pub struct Bank {
|
|||
/// See util0, rate0, util1, rate1, max_rate
|
||||
pub zero_util_rate: I80F48,
|
||||
|
||||
/// Additional to liquidation_fee, but goes to the group owner instead of the liqor
|
||||
pub platform_liquidation_fee: I80F48,
|
||||
|
||||
/// Fees that were collected during liquidation (in native tokens)
|
||||
///
|
||||
/// See also collected_fees_native and fees_withdrawn.
|
||||
pub collected_liquidation_fees: I80F48,
|
||||
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub reserved: [u8; 1952],
|
||||
pub reserved: [u8; 1920],
|
||||
}
|
||||
const_assert_eq!(
|
||||
size_of::<Bank>(),
|
||||
|
@ -239,8 +255,8 @@ const_assert_eq!(
|
|||
+ 16 * 3
|
||||
+ 32
|
||||
+ 8
|
||||
+ 16
|
||||
+ 1952
|
||||
+ 16 * 3
|
||||
+ 1920
|
||||
);
|
||||
const_assert_eq!(size_of::<Bank>(), 3064);
|
||||
const_assert_eq!(size_of::<Bank>() % 8, 0);
|
||||
|
@ -283,6 +299,7 @@ impl Bank {
|
|||
indexed_deposits: I80F48::ZERO,
|
||||
indexed_borrows: I80F48::ZERO,
|
||||
collected_fees_native: I80F48::ZERO,
|
||||
collected_liquidation_fees: I80F48::ZERO,
|
||||
fees_withdrawn: 0,
|
||||
dust: I80F48::ZERO,
|
||||
flash_loan_approved_amount: 0,
|
||||
|
@ -345,7 +362,8 @@ impl Bank {
|
|||
fallback_oracle: existing_bank.oracle,
|
||||
deposit_limit: existing_bank.deposit_limit,
|
||||
zero_util_rate: existing_bank.zero_util_rate,
|
||||
reserved: [0; 1952],
|
||||
platform_liquidation_fee: existing_bank.platform_liquidation_fee,
|
||||
reserved: [0; 1920],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,6 +395,7 @@ impl Bank {
|
|||
require_gte!(self.maint_weight_shift_asset_target, 0.0);
|
||||
require_gte!(self.maint_weight_shift_liab_target, 0.0);
|
||||
require_gte!(self.zero_util_rate, I80F48::ZERO);
|
||||
require_gte!(self.platform_liquidation_fee, 0.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,25 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
|||
let collateral_token1 = &tokens[2];
|
||||
let collateral_token2 = &tokens[3];
|
||||
|
||||
for token in &tokens[0..4] {
|
||||
send_tx(
|
||||
solana,
|
||||
TokenEdit {
|
||||
group,
|
||||
admin,
|
||||
mint: token.mint.pubkey,
|
||||
fallback_oracle: Pubkey::default(),
|
||||
options: mango_v4::instruction::TokenEdit {
|
||||
liquidation_fee_opt: Some(0.01),
|
||||
platform_liquidation_fee_opt: Some(0.01),
|
||||
..token_edit_instruction_default()
|
||||
},
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// deposit some funds, to the vaults aren't empty
|
||||
let vault_account = send_tx(
|
||||
solana,
|
||||
|
@ -325,13 +344,42 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
// the we only have 20 collateral2, and can trade them for 20 / (1.02 * 1.02) = 19.22 borrow2
|
||||
// (liq fee is 2% for both sides)
|
||||
// the liqee's 20 collateral2 are traded for 20 / (1.02 * 1.02) = 19.22 borrow2
|
||||
// (liq fee is 1% liqor + 1% platform for both sides)
|
||||
assert_eq!(
|
||||
account_position(solana, account, borrow_token2.bank).await,
|
||||
-50 + 19
|
||||
);
|
||||
assert_eq!(
|
||||
account_position(solana, vault_account, borrow_token2.bank).await,
|
||||
100000 - 19
|
||||
);
|
||||
|
||||
// All liqee collateral2 is gone
|
||||
assert!(account_position_closed(solana, account, collateral_token2.bank).await,);
|
||||
|
||||
// The liqee pays for the 20 collateral at a price of 1.02*1.02. The liqor gets 1.01*1.01,
|
||||
// so the platform fee is
|
||||
let platform_fee = 20.0 * (1.0 - 1.01 * 1.01 / (1.02 * 1.02));
|
||||
assert!(assert_equal_f64_f64(
|
||||
account_position_f64(solana, vault_account, collateral_token2.bank).await,
|
||||
100000.0 + 20.0 - platform_fee,
|
||||
0.001,
|
||||
));
|
||||
|
||||
// Verify platform liq fee tracking
|
||||
let colbank = solana.get_account::<Bank>(collateral_token2.bank).await;
|
||||
assert!(assert_equal_fixed_f64(
|
||||
colbank.collected_fees_native,
|
||||
platform_fee,
|
||||
0.001
|
||||
));
|
||||
assert!(assert_equal_fixed_f64(
|
||||
colbank.collected_liquidation_fees,
|
||||
platform_fee,
|
||||
0.001
|
||||
));
|
||||
|
||||
let liqee = get_mango_account(solana, account).await;
|
||||
assert!(liqee.being_liquidated());
|
||||
|
||||
|
|
|
@ -1012,6 +1012,7 @@ pub struct TokenRegisterInstruction {
|
|||
pub maint_liab_weight: f32,
|
||||
pub init_liab_weight: f32,
|
||||
pub liquidation_fee: f32,
|
||||
pub platform_liquidation_fee: f32,
|
||||
|
||||
pub min_vault_to_deposits_ratio: f64,
|
||||
pub net_borrow_limit_per_window_quote: i64,
|
||||
|
@ -1075,6 +1076,7 @@ impl ClientInstruction for TokenRegisterInstruction {
|
|||
group_insurance_fund: true,
|
||||
deposit_limit: 0,
|
||||
zero_util_rate: 0.0,
|
||||
platform_liquidation_fee: self.platform_liquidation_fee,
|
||||
};
|
||||
|
||||
let bank = Pubkey::find_program_address(
|
||||
|
@ -1321,6 +1323,7 @@ pub fn token_edit_instruction_default() -> mango_v4::instruction::TokenEdit {
|
|||
set_fallback_oracle: false,
|
||||
deposit_limit_opt: None,
|
||||
zero_util_rate_opt: None,
|
||||
platform_liquidation_fee_opt: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ impl<'a> GroupWithTokensConfig {
|
|||
min_vault_to_deposits_ratio: 0.2,
|
||||
net_borrow_limit_per_window_quote: 1_000_000_000_000,
|
||||
net_borrow_limit_window_size_ts: 24 * 60 * 60,
|
||||
platform_liquidation_fee: 0.0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
|
|
@ -81,6 +81,8 @@ export class Bank implements BankForHealth {
|
|||
public maintWeightShiftAssetTarget: I80F48;
|
||||
public maintWeightShiftLiabTarget: I80F48;
|
||||
public zeroUtilRate: I80F48;
|
||||
public platformLiquidationFee: I80F48;
|
||||
public collectedLiquidationFees: I80F48;
|
||||
|
||||
static from(
|
||||
publicKey: PublicKey,
|
||||
|
@ -142,6 +144,8 @@ export class Bank implements BankForHealth {
|
|||
maintWeightShiftLiabTarget: I80F48Dto;
|
||||
depositLimit: BN;
|
||||
zeroUtilRate: I80F48Dto;
|
||||
platformLiquidationFee: I80F48Dto;
|
||||
collectedLiquidationFees: I80F48Dto;
|
||||
},
|
||||
): Bank {
|
||||
return new Bank(
|
||||
|
@ -203,6 +207,8 @@ export class Bank implements BankForHealth {
|
|||
obj.maintWeightShiftLiabTarget,
|
||||
obj.depositLimit,
|
||||
obj.zeroUtilRate,
|
||||
obj.platformLiquidationFee,
|
||||
obj.collectedLiquidationFees,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -265,6 +271,8 @@ export class Bank implements BankForHealth {
|
|||
maintWeightShiftLiabTarget: I80F48Dto,
|
||||
public depositLimit: BN,
|
||||
zeroUtilRate: I80F48Dto,
|
||||
platformLiquidationFee: I80F48Dto,
|
||||
collectedLiquidationFees: I80F48Dto,
|
||||
) {
|
||||
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
|
||||
this.oracleConfig = {
|
||||
|
@ -295,6 +303,8 @@ export class Bank implements BankForHealth {
|
|||
this.maintWeightShiftAssetTarget = I80F48.from(maintWeightShiftAssetTarget);
|
||||
this.maintWeightShiftLiabTarget = I80F48.from(maintWeightShiftLiabTarget);
|
||||
this.zeroUtilRate = I80F48.from(zeroUtilRate);
|
||||
this.platformLiquidationFee = I80F48.from(platformLiquidationFee);
|
||||
this.collectedLiquidationFees = I80F48.from(collectedLiquidationFees);
|
||||
this._price = undefined;
|
||||
this._uiPrice = undefined;
|
||||
this._oracleLastUpdatedSlot = undefined;
|
||||
|
|
|
@ -459,6 +459,7 @@ export class MangoClient {
|
|||
params.groupInsuranceFund,
|
||||
params.depositLimit,
|
||||
params.zeroUtilRate,
|
||||
params.platformLiquidationFee,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
|
@ -544,6 +545,7 @@ export class MangoClient {
|
|||
params.setFallbackOracle ?? false,
|
||||
params.depositLimit,
|
||||
params.zeroUtilRate,
|
||||
params.platformLiquidationFee,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
|
|
|
@ -29,6 +29,7 @@ export interface TokenRegisterParams {
|
|||
interestTargetUtilization: number;
|
||||
depositLimit: BN;
|
||||
zeroUtilRate: number;
|
||||
platformLiquidationFee: number;
|
||||
}
|
||||
|
||||
export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
||||
|
@ -68,6 +69,7 @@ export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
|||
interestTargetUtilization: 0.5,
|
||||
depositLimit: new BN(0),
|
||||
zeroUtilRate: 0.0,
|
||||
platformLiquidationFee: 0.0,
|
||||
};
|
||||
|
||||
export interface TokenEditParams {
|
||||
|
@ -108,6 +110,7 @@ export interface TokenEditParams {
|
|||
setFallbackOracle: boolean | null;
|
||||
depositLimit: BN | null;
|
||||
zeroUtilRate: number | null;
|
||||
platformLiquidationFee: number | null;
|
||||
}
|
||||
|
||||
export const NullTokenEditParams: TokenEditParams = {
|
||||
|
@ -148,6 +151,7 @@ export const NullTokenEditParams: TokenEditParams = {
|
|||
setFallbackOracle: null,
|
||||
depositLimit: null,
|
||||
zeroUtilRate: null,
|
||||
platformLiquidationFee: null,
|
||||
};
|
||||
|
||||
export interface PerpEditParams {
|
||||
|
|
|
@ -627,6 +627,10 @@ export type MangoV4 = {
|
|||
{
|
||||
"name": "zeroUtilRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFee",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1031,6 +1035,12 @@ export type MangoV4 = {
|
|||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFeeOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7193,6 +7203,12 @@ export type MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "collectedFeesNative",
|
||||
"docs": [
|
||||
"Fees collected over the lifetime of the bank",
|
||||
"",
|
||||
"See fees_withdrawn for how much of the fees was withdrawn.",
|
||||
"See collected_liquidation_fees for the (included) subtotal for liquidation related fees."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7235,6 +7251,15 @@ export type MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "liquidationFee",
|
||||
"docs": [
|
||||
"Liquidation fee that goes to the liqor.",
|
||||
"",
|
||||
"Liquidation always involves two tokens, and the sum of the two configured fees is used.",
|
||||
"",
|
||||
"A fraction of the price, like 0.05 for a 5% fee during liquidation.",
|
||||
"",
|
||||
"See also platform_liquidation_fee."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7458,12 +7483,32 @@ export type MangoV4 = {
|
|||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFee",
|
||||
"docs": [
|
||||
"Additional to liquidation_fee, but goes to the group owner instead of the liqor"
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "collectedLiquidationFees",
|
||||
"docs": [
|
||||
"Fees that were collected during liquidation (in native tokens)",
|
||||
"",
|
||||
"See also collected_fees_native and fees_withdrawn."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1952
|
||||
1920
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -11962,6 +12007,71 @@ export type MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenLiqWithTokenLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferFromLiqee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferToLiqor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetLiquidationFee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTransfer",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "bankruptcy",
|
||||
"type": "bool",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Serum3OpenOrdersBalanceLog",
|
||||
"fields": [
|
||||
|
@ -12838,6 +12948,71 @@ export type MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenForceCloseBorrowsWithTokenLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferFromLiqee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferToLiqor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetLiquidationFee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTransfer",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "feeFactor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenConditionalSwapCreateLog",
|
||||
"fields": [
|
||||
|
@ -14387,6 +14562,10 @@ export const IDL: MangoV4 = {
|
|||
{
|
||||
"name": "zeroUtilRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFee",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -14791,6 +14970,12 @@ export const IDL: MangoV4 = {
|
|||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFeeOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -20953,6 +21138,12 @@ export const IDL: MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "collectedFeesNative",
|
||||
"docs": [
|
||||
"Fees collected over the lifetime of the bank",
|
||||
"",
|
||||
"See fees_withdrawn for how much of the fees was withdrawn.",
|
||||
"See collected_liquidation_fees for the (included) subtotal for liquidation related fees."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -20995,6 +21186,15 @@ export const IDL: MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "liquidationFee",
|
||||
"docs": [
|
||||
"Liquidation fee that goes to the liqor.",
|
||||
"",
|
||||
"Liquidation always involves two tokens, and the sum of the two configured fees is used.",
|
||||
"",
|
||||
"A fraction of the price, like 0.05 for a 5% fee during liquidation.",
|
||||
"",
|
||||
"See also platform_liquidation_fee."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -21218,12 +21418,32 @@ export const IDL: MangoV4 = {
|
|||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "platformLiquidationFee",
|
||||
"docs": [
|
||||
"Additional to liquidation_fee, but goes to the group owner instead of the liqor"
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "collectedLiquidationFees",
|
||||
"docs": [
|
||||
"Fees that were collected during liquidation (in native tokens)",
|
||||
"",
|
||||
"See also collected_fees_native and fees_withdrawn."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1952
|
||||
1920
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -25722,6 +25942,71 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenLiqWithTokenLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferFromLiqee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferToLiqor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetLiquidationFee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTransfer",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "bankruptcy",
|
||||
"type": "bool",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Serum3OpenOrdersBalanceLog",
|
||||
"fields": [
|
||||
|
@ -26598,6 +26883,71 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenForceCloseBorrowsWithTokenLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqor",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liqee",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferFromLiqee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetTransferToLiqor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetLiquidationFee",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabTransfer",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "assetPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "liabPrice",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "feeFactor",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenConditionalSwapCreateLog",
|
||||
"fields": [
|
||||
|
|
|
@ -134,7 +134,7 @@ export async function getPriceImpactForLiqor(
|
|||
// Max liab of a particular token that would be liquidated to bring health above 0
|
||||
mangoAccountsWithHealth.reduce((sum, a) => {
|
||||
// How much would health increase for every unit liab moved to liqor
|
||||
// liabprice * (liabweight - (1+fee)*assetweight)
|
||||
// liabprice * (liabweight - (1+liabfees)*(1+assetfees)*assetweight)
|
||||
// Choose the most valuable asset the user has
|
||||
const assetBank = Array.from(group.banksMapByTokenIndex.values())
|
||||
.flat()
|
||||
|
@ -152,12 +152,16 @@ export async function getPriceImpactForLiqor(
|
|||
? prev
|
||||
: curr,
|
||||
);
|
||||
const tokenLiabHealthContrib = bank.price.mul(
|
||||
bank.initLiabWeight.sub(
|
||||
const feeFactor = ONE_I80F48()
|
||||
.add(bank.liquidationFee)
|
||||
.add(bank.platformLiquidationFee)
|
||||
.mul(
|
||||
ONE_I80F48()
|
||||
.add(bank.liquidationFee)
|
||||
.mul(assetBank.initAssetWeight),
|
||||
),
|
||||
.add(assetBank.liquidationFee)
|
||||
.add(assetBank.platformLiquidationFee),
|
||||
);
|
||||
const tokenLiabHealthContrib = bank.price.mul(
|
||||
bank.initLiabWeight.sub(feeFactor.mul(assetBank.initAssetWeight)),
|
||||
);
|
||||
// Abs liab/borrow
|
||||
const maxTokenLiab = a.account
|
||||
|
|
Loading…
Reference in New Issue