Merge pull request #99 from blockworks-foundation/ckamm/deactivate-token-positions
Deactivate token positions for liquidation and serum instructions
This commit is contained in:
commit
420132cf89
|
@ -87,8 +87,7 @@ pub fn liq_token_bankruptcy(
|
|||
|
||||
let liab_bank = bank_ais[0].load::<Bank>()?;
|
||||
let liab_deposit_index = liab_bank.deposit_index;
|
||||
let (liqee_liab, liqee_raw_token_index, _) =
|
||||
liqee.tokens.get_mut_or_create(liab_token_index)?;
|
||||
let (liqee_liab, liqee_raw_token_index) = liqee.tokens.get_mut(liab_token_index)?;
|
||||
let mut remaining_liab_loss = -liqee_liab.native(&liab_bank);
|
||||
require_gt!(remaining_liab_loss, I80F48::ZERO);
|
||||
drop(liab_bank);
|
||||
|
|
|
@ -72,13 +72,14 @@ pub fn liq_token_with_token(
|
|||
account_retriever.banks_mut_and_oracles(asset_token_index, liab_token_index)?;
|
||||
let (liab_bank, liab_price) = opt_liab_bank_and_price.unwrap();
|
||||
|
||||
let liqee_assets_native = liqee
|
||||
.tokens
|
||||
.get(asset_bank.token_index)?
|
||||
.native(&asset_bank);
|
||||
// The main complication here is that we can't keep the liqee_asset_position and liqee_liab_position
|
||||
// borrows alive at the same time. Possibly adding get_mut_pair() would be helpful.
|
||||
let (liqee_asset_position, liqee_asset_raw_index) = liqee.tokens.get(asset_token_index)?;
|
||||
let liqee_assets_native = liqee_asset_position.native(&asset_bank);
|
||||
require!(liqee_assets_native.is_positive(), MangoError::SomeError);
|
||||
|
||||
let liqee_liab_native = liqee.tokens.get(liab_bank.token_index)?.native(&liab_bank);
|
||||
let (liqee_liab_position, liqee_liab_raw_index) = liqee.tokens.get(liab_token_index)?;
|
||||
let liqee_liab_native = liqee_liab_position.native(&liab_bank);
|
||||
require!(liqee_liab_native.is_negative(), MangoError::SomeError);
|
||||
|
||||
// TODO why sum of both tokens liquidation fees? Add comment
|
||||
|
@ -116,18 +117,24 @@ pub fn liq_token_with_token(
|
|||
let asset_transfer = cm!(liab_transfer * liab_price_adjusted / asset_price);
|
||||
|
||||
// Apply the balance changes to the liqor and liqee accounts
|
||||
liab_bank.deposit(liqee.tokens.get_mut(liab_token_index)?, liab_transfer)?;
|
||||
liab_bank.withdraw_with_fee(
|
||||
liqor.tokens.get_mut_or_create(liab_token_index)?.0,
|
||||
liab_transfer,
|
||||
)?;
|
||||
let liqee_liab_position = liqee.tokens.get_mut_raw(liqee_liab_raw_index);
|
||||
let liqee_liab_active = liab_bank.deposit(liqee_liab_position, liab_transfer)?;
|
||||
let liqee_liab_position_indexed = liqee_liab_position.indexed_position;
|
||||
|
||||
asset_bank.deposit(
|
||||
liqor.tokens.get_mut_or_create(asset_token_index)?.0,
|
||||
asset_transfer,
|
||||
)?;
|
||||
asset_bank
|
||||
.withdraw_without_fee(liqee.tokens.get_mut(asset_token_index)?, asset_transfer)?;
|
||||
let (liqor_liab_position, liqor_liab_raw_index, _) =
|
||||
liqor.tokens.get_mut_or_create(liab_token_index)?;
|
||||
let liqor_liab_active = liab_bank.withdraw_with_fee(liqor_liab_position, liab_transfer)?;
|
||||
let liqor_liab_position_indexed = liqor_liab_position.indexed_position;
|
||||
|
||||
let (liqor_asset_position, liqor_asset_raw_index, _) =
|
||||
liqor.tokens.get_mut_or_create(asset_token_index)?;
|
||||
let liqor_asset_active = asset_bank.deposit(liqor_asset_position, asset_transfer)?;
|
||||
let liqor_asset_position_indexed = liqor_asset_position.indexed_position;
|
||||
|
||||
let liqee_asset_position = liqee.tokens.get_mut_raw(liqee_asset_raw_index);
|
||||
let liqee_asset_active =
|
||||
asset_bank.withdraw_without_fee(liqee_asset_position, asset_transfer)?;
|
||||
let liqee_asset_position_indexed = liqee_asset_position.indexed_position;
|
||||
|
||||
// Update the health cache
|
||||
liqee_health_cache.adjust_token_balance(liab_token_index, liab_transfer)?;
|
||||
|
@ -155,11 +162,7 @@ pub fn liq_token_with_token(
|
|||
emit!(TokenBalanceLog {
|
||||
mango_account: ctx.accounts.liqee.key(),
|
||||
token_index: asset_token_index,
|
||||
indexed_position: liqee
|
||||
.tokens
|
||||
.get_mut(asset_token_index)?
|
||||
.indexed_position
|
||||
.to_bits(),
|
||||
indexed_position: liqee_asset_position_indexed.to_bits(),
|
||||
deposit_index: asset_bank.deposit_index.to_bits(),
|
||||
borrow_index: asset_bank.borrow_index.to_bits(),
|
||||
price: asset_price.to_bits(),
|
||||
|
@ -168,11 +171,7 @@ pub fn liq_token_with_token(
|
|||
emit!(TokenBalanceLog {
|
||||
mango_account: ctx.accounts.liqee.key(),
|
||||
token_index: liab_token_index,
|
||||
indexed_position: liqee
|
||||
.tokens
|
||||
.get_mut(liab_token_index)?
|
||||
.indexed_position
|
||||
.to_bits(),
|
||||
indexed_position: liqee_liab_position_indexed.to_bits(),
|
||||
deposit_index: liab_bank.deposit_index.to_bits(),
|
||||
borrow_index: liab_bank.borrow_index.to_bits(),
|
||||
price: liab_price.to_bits(),
|
||||
|
@ -181,11 +180,7 @@ pub fn liq_token_with_token(
|
|||
emit!(TokenBalanceLog {
|
||||
mango_account: ctx.accounts.liqor.key(),
|
||||
token_index: asset_token_index,
|
||||
indexed_position: liqor
|
||||
.tokens
|
||||
.get_mut(asset_token_index)?
|
||||
.indexed_position
|
||||
.to_bits(),
|
||||
indexed_position: liqor_asset_position_indexed.to_bits(),
|
||||
deposit_index: asset_bank.deposit_index.to_bits(),
|
||||
borrow_index: asset_bank.borrow_index.to_bits(),
|
||||
price: asset_price.to_bits(),
|
||||
|
@ -194,15 +189,25 @@ pub fn liq_token_with_token(
|
|||
emit!(TokenBalanceLog {
|
||||
mango_account: ctx.accounts.liqor.key(),
|
||||
token_index: liab_token_index,
|
||||
indexed_position: liqor
|
||||
.tokens
|
||||
.get_mut(liab_token_index)?
|
||||
.indexed_position
|
||||
.to_bits(),
|
||||
indexed_position: liqor_liab_position_indexed.to_bits(),
|
||||
deposit_index: liab_bank.deposit_index.to_bits(),
|
||||
borrow_index: liab_bank.borrow_index.to_bits(),
|
||||
price: liab_price.to_bits(),
|
||||
});
|
||||
|
||||
// Since we use a scanning account retriever, it's safe to deactivate inactive token positions
|
||||
if !liqee_asset_active {
|
||||
liqee.tokens.deactivate(liqee_asset_raw_index);
|
||||
}
|
||||
if !liqee_liab_active {
|
||||
liqee.tokens.deactivate(liqee_liab_raw_index);
|
||||
}
|
||||
if !liqor_asset_active {
|
||||
liqor.tokens.deactivate(liqor_asset_raw_index);
|
||||
}
|
||||
if !liqor_liab_active {
|
||||
liqor.tokens.deactivate(liqor_liab_raw_index)
|
||||
}
|
||||
}
|
||||
|
||||
// Check liqee health again
|
||||
|
@ -221,7 +226,5 @@ pub fn liq_token_with_token(
|
|||
let liqor_health = compute_health(&liqor, HealthType::Init, &account_retriever)?;
|
||||
require!(liqor_health >= 0, MangoError::HealthMustBePositive);
|
||||
|
||||
// TOOD: this must deactivate token accounts if the deposit/withdraw calls above call for it
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::{Token, TokenAccount};
|
||||
use fixed::types::I80F48;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::instructions::apply_vault_difference;
|
||||
use crate::state::*;
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
@ -139,23 +139,19 @@ pub fn serum3_liq_force_cancel_orders(
|
|||
let after_quote_vault = ctx.accounts.quote_vault.amount;
|
||||
|
||||
// Charge the difference in vault balances to the user's account
|
||||
{
|
||||
let mut account = ctx.accounts.account.load_mut()?;
|
||||
|
||||
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
|
||||
let base_position = account.tokens.get_mut(base_bank.token_index)?;
|
||||
base_bank.deposit(
|
||||
base_position,
|
||||
I80F48::from(after_base_vault) - I80F48::from(before_base_vault),
|
||||
)?;
|
||||
|
||||
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
|
||||
let quote_position = account.tokens.get_mut(quote_bank.token_index)?;
|
||||
quote_bank.deposit(
|
||||
quote_position,
|
||||
I80F48::from(after_quote_vault) - I80F48::from(before_quote_vault),
|
||||
)?;
|
||||
}
|
||||
let mut account = ctx.accounts.account.load_mut()?;
|
||||
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
|
||||
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
|
||||
apply_vault_difference(
|
||||
&mut account,
|
||||
&mut base_bank,
|
||||
after_base_vault,
|
||||
before_base_vault,
|
||||
&mut quote_bank,
|
||||
after_quote_vault,
|
||||
before_quote_vault,
|
||||
)?
|
||||
.deactivate_inactive_token_accounts(&mut account);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -260,25 +260,31 @@ pub fn serum3_place_order(
|
|||
let after_quote_vault = ctx.accounts.quote_vault.amount;
|
||||
|
||||
// Charge the difference in vault balances to the user's account
|
||||
apply_vault_difference(
|
||||
ctx.accounts.account.load_mut()?,
|
||||
ctx.accounts.base_bank.load_mut()?,
|
||||
after_base_vault,
|
||||
before_base_vault,
|
||||
ctx.accounts.quote_bank.load_mut()?,
|
||||
after_quote_vault,
|
||||
before_quote_vault,
|
||||
)?;
|
||||
let mut account = ctx.accounts.account.load_mut()?;
|
||||
let vault_difference_result = {
|
||||
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
|
||||
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
|
||||
apply_vault_difference(
|
||||
&mut account,
|
||||
&mut base_bank,
|
||||
after_base_vault,
|
||||
before_base_vault,
|
||||
&mut quote_bank,
|
||||
after_quote_vault,
|
||||
before_quote_vault,
|
||||
)?
|
||||
};
|
||||
|
||||
//
|
||||
// Health check
|
||||
//
|
||||
let account = ctx.accounts.account.load()?;
|
||||
let retriever = new_fixed_order_account_retriever(ctx.remaining_accounts, &account)?;
|
||||
let health = compute_health(&account, HealthType::Init, &retriever)?;
|
||||
msg!("health: {}", health);
|
||||
require!(health >= 0, MangoError::HealthMustBePositive);
|
||||
|
||||
vault_difference_result.deactivate_inactive_token_accounts(&mut account);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -305,28 +311,51 @@ pub fn inc_maybe_loan(
|
|||
}
|
||||
}
|
||||
|
||||
pub struct VaultDifferenceResult {
|
||||
base_raw_index: usize,
|
||||
base_active: bool,
|
||||
quote_raw_index: usize,
|
||||
quote_active: bool,
|
||||
}
|
||||
|
||||
impl VaultDifferenceResult {
|
||||
pub fn deactivate_inactive_token_accounts(&self, account: &mut MangoAccount) {
|
||||
if !self.base_active {
|
||||
account.tokens.deactivate(self.base_raw_index);
|
||||
}
|
||||
if !self.quote_active {
|
||||
account.tokens.deactivate(self.quote_raw_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_vault_difference(
|
||||
mut account: std::cell::RefMut<MangoAccount>,
|
||||
mut base_bank: std::cell::RefMut<Bank>,
|
||||
account: &mut MangoAccount,
|
||||
base_bank: &mut Bank,
|
||||
after_base_vault: u64,
|
||||
before_base_vault: u64,
|
||||
mut quote_bank: std::cell::RefMut<Bank>,
|
||||
quote_bank: &mut Bank,
|
||||
after_quote_vault: u64,
|
||||
before_quote_vault: u64,
|
||||
) -> Result<()> {
|
||||
) -> Result<VaultDifferenceResult> {
|
||||
// TODO: Applying the loan origination fee here may be too early: it should only be
|
||||
// charged if an order executes and the loan materializes? Otherwise MMs that place
|
||||
// an order without having the funds will be charged for each place_order!
|
||||
|
||||
let base_position = account.tokens.get_mut(base_bank.token_index)?;
|
||||
let (base_position, base_raw_index) = account.tokens.get_mut(base_bank.token_index)?;
|
||||
let base_change = I80F48::from(after_base_vault) - I80F48::from(before_base_vault);
|
||||
base_bank.change_with_fee(base_position, base_change)?;
|
||||
let base_active = base_bank.change_with_fee(base_position, base_change)?;
|
||||
|
||||
let quote_position = account.tokens.get_mut(quote_bank.token_index)?;
|
||||
let (quote_position, quote_raw_index) = account.tokens.get_mut(quote_bank.token_index)?;
|
||||
let quote_change = I80F48::from(after_quote_vault) - I80F48::from(before_quote_vault);
|
||||
quote_bank.change_with_fee(quote_position, quote_change)?;
|
||||
let quote_active = quote_bank.change_with_fee(quote_position, quote_change)?;
|
||||
|
||||
Ok(())
|
||||
Ok(VaultDifferenceResult {
|
||||
base_raw_index,
|
||||
base_active,
|
||||
quote_raw_index,
|
||||
quote_active,
|
||||
})
|
||||
}
|
||||
|
||||
fn cpi_place_order(ctx: &Serum3PlaceOrder, order: NewOrderInstructionV3) -> Result<()> {
|
||||
|
|
|
@ -149,17 +149,19 @@ pub fn serum3_settle_funds(ctx: Context<Serum3SettleFunds>) -> Result<()> {
|
|||
let after_quote_vault = ctx.accounts.quote_vault.amount;
|
||||
|
||||
// Charge the difference in vault balances to the user's account
|
||||
let base_bank = ctx.accounts.base_bank.load_mut()?;
|
||||
let quote_bank = ctx.accounts.quote_bank.load_mut()?;
|
||||
let mut account = ctx.accounts.account.load_mut()?;
|
||||
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
|
||||
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
|
||||
apply_vault_difference(
|
||||
ctx.accounts.account.load_mut()?,
|
||||
base_bank,
|
||||
&mut account,
|
||||
&mut base_bank,
|
||||
after_base_vault,
|
||||
before_base_vault,
|
||||
quote_bank,
|
||||
&mut quote_bank,
|
||||
after_quote_vault,
|
||||
before_quote_vault,
|
||||
)?;
|
||||
)?
|
||||
.deactivate_inactive_token_accounts(&mut account);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -185,7 +187,7 @@ pub fn charge_maybe_fees(
|
|||
serum3_account.previous_native_coin_reserved = after_oo.native_coin_reserved();
|
||||
|
||||
// loan origination fees
|
||||
let coin_token_account = account.tokens.get_mut(coin_bank.token_index)?;
|
||||
let coin_token_account = account.tokens.get_mut(coin_bank.token_index)?.0;
|
||||
let coin_token_native = coin_token_account.native(&coin_bank);
|
||||
|
||||
if coin_token_native.is_negative() {
|
||||
|
@ -195,7 +197,7 @@ pub fn charge_maybe_fees(
|
|||
// charge the loan origination fee
|
||||
coin_bank
|
||||
.borrow_mut()
|
||||
.charge_loan_origination_fee(coin_token_account, actualized_loan)?;
|
||||
.withdraw_loan_origination_fee(coin_token_account, actualized_loan)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +211,7 @@ pub fn charge_maybe_fees(
|
|||
serum3_account.previous_native_pc_reserved = after_oo.native_pc_reserved();
|
||||
|
||||
// loan origination fees
|
||||
let pc_token_account = account.tokens.get_mut(pc_bank.token_index)?;
|
||||
let pc_token_account = account.tokens.get_mut(pc_bank.token_index)?.0;
|
||||
let pc_token_native = pc_token_account.native(&pc_bank);
|
||||
|
||||
if pc_token_native.is_negative() {
|
||||
|
@ -219,7 +221,7 @@ pub fn charge_maybe_fees(
|
|||
// charge the loan origination fee
|
||||
pc_bank
|
||||
.borrow_mut()
|
||||
.charge_loan_origination_fee(pc_token_account, actualized_loan)?;
|
||||
.withdraw_loan_origination_fee(pc_token_account, actualized_loan)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -320,7 +320,9 @@ impl Bank {
|
|||
}
|
||||
|
||||
if with_loan_origination_fee {
|
||||
self.charge_loan_origination_fee(position, native_amount)?;
|
||||
let loan_origination_fee = cm!(self.loan_origination_fee_rate * native_amount);
|
||||
self.collected_fees_native = cm!(self.collected_fees_native + loan_origination_fee);
|
||||
native_amount = cm!(native_amount + loan_origination_fee);
|
||||
}
|
||||
|
||||
// add to borrows
|
||||
|
@ -331,21 +333,17 @@ impl Bank {
|
|||
Ok(true)
|
||||
}
|
||||
|
||||
// charge only loan origination fee, assuming borrow has already happened
|
||||
pub fn charge_loan_origination_fee(
|
||||
// withdraw the loan origination fee for a borrow that happenend earlier
|
||||
pub fn withdraw_loan_origination_fee(
|
||||
&mut self,
|
||||
position: &mut TokenPosition,
|
||||
already_borrowed_native_amount: I80F48,
|
||||
) -> Result<()> {
|
||||
) -> Result<bool> {
|
||||
let loan_origination_fee =
|
||||
cm!(self.loan_origination_fee_rate * already_borrowed_native_amount);
|
||||
self.collected_fees_native = cm!(self.collected_fees_native + loan_origination_fee);
|
||||
|
||||
let indexed_change = cm!(loan_origination_fee / self.borrow_index);
|
||||
self.indexed_borrows = cm!(self.indexed_borrows + indexed_change);
|
||||
position.indexed_position = cm!(position.indexed_position - indexed_change);
|
||||
|
||||
Ok(())
|
||||
self.withdraw_internal(position, loan_origination_fee, false)
|
||||
}
|
||||
|
||||
/// Change a position without applying the loan origination fee
|
||||
|
|
|
@ -121,17 +121,25 @@ impl MangoAccountTokenPositions {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, token_index: TokenIndex) -> Result<&TokenPosition> {
|
||||
/// Returns
|
||||
/// - the position
|
||||
/// - the raw index into the token positions list (for use with get_raw/deactivate)
|
||||
pub fn get(&self, token_index: TokenIndex) -> Result<(&TokenPosition, usize)> {
|
||||
self.values
|
||||
.iter()
|
||||
.find(|p| p.is_active_for_token(token_index))
|
||||
.enumerate()
|
||||
.find_map(|(raw_index, p)| p.is_active_for_token(token_index).then(|| (p, raw_index)))
|
||||
.ok_or_else(|| error!(MangoError::SomeError)) // TODO: not found error
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, token_index: TokenIndex) -> Result<&mut TokenPosition> {
|
||||
/// Returns
|
||||
/// - the position
|
||||
/// - the raw index into the token positions list (for use with get_raw/deactivate)
|
||||
pub fn get_mut(&mut self, token_index: TokenIndex) -> Result<(&mut TokenPosition, usize)> {
|
||||
self.values
|
||||
.iter_mut()
|
||||
.find(|p| p.is_active_for_token(token_index))
|
||||
.enumerate()
|
||||
.find_map(|(raw_index, p)| p.is_active_for_token(token_index).then(|| (p, raw_index)))
|
||||
.ok_or_else(|| error!(MangoError::SomeError)) // TODO: not found error
|
||||
}
|
||||
|
||||
|
|
|
@ -205,10 +205,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
account_position(solana, account, collateral_token1.bank).await,
|
||||
0
|
||||
);
|
||||
assert!(account_position_closed(solana, account, collateral_token1.bank).await);
|
||||
assert_eq!(
|
||||
account_position(solana, account, borrow_token1.bank).await,
|
||||
(-350.0f64 + (1000.0 / 20.0 / 1.04)).round() as i64
|
||||
|
@ -233,10 +230,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
account_position(solana, account, collateral_token2.bank).await,
|
||||
0
|
||||
);
|
||||
assert!(account_position_closed(solana, account, collateral_token2.bank).await,);
|
||||
let borrow1_after_liq = -350.0f64 + (1000.0 / 20.0 / 1.04) + (20.0 / 20.0 / 1.04);
|
||||
assert_eq!(
|
||||
account_position(solana, account, borrow_token1.bank).await,
|
||||
|
@ -518,10 +512,7 @@ async fn test_bankrupt_tokens_insurance_fund() -> Result<(), TransportError> {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
account_position(solana, account, collateral_token1.bank).await,
|
||||
0
|
||||
);
|
||||
assert!(account_position_closed(solana, account, collateral_token1.bank).await);
|
||||
let liqee: MangoAccount = solana.get_account(account).await;
|
||||
assert!(liqee.being_liquidated());
|
||||
assert!(!liqee.is_bankrupt());
|
||||
|
@ -542,10 +533,7 @@ async fn test_bankrupt_tokens_insurance_fund() -> Result<(), TransportError> {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
account_position(solana, account, collateral_token2.bank).await,
|
||||
0
|
||||
);
|
||||
assert!(account_position_closed(solana, account, collateral_token2.bank).await,);
|
||||
let liqee: MangoAccount = solana.get_account(account).await;
|
||||
assert!(liqee.being_liquidated());
|
||||
assert!(liqee.is_bankrupt());
|
||||
|
|
|
@ -387,10 +387,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
|||
account_position(solana, account, borrow_token2.bank).await,
|
||||
-50 + 19
|
||||
);
|
||||
assert_eq!(
|
||||
account_position(solana, account, collateral_token2.bank).await,
|
||||
0
|
||||
);
|
||||
assert!(account_position_closed(solana, account, collateral_token2.bank).await,);
|
||||
let liqee: MangoAccount = solana.get_account(account).await;
|
||||
assert!(liqee.being_liquidated());
|
||||
assert!(!liqee.is_bankrupt());
|
||||
|
@ -416,10 +413,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
|||
.unwrap();
|
||||
|
||||
// the asset cost for 50-19=31 borrow2 is 31 * 1.04 = 32.24
|
||||
assert_eq!(
|
||||
account_position(solana, account, borrow_token2.bank).await,
|
||||
0
|
||||
);
|
||||
assert!(account_position_closed(solana, account, borrow_token2.bank).await);
|
||||
assert_eq!(
|
||||
account_position(solana, account, collateral_token1.bank).await,
|
||||
1000 - 32
|
||||
|
|
Loading…
Reference in New Issue