Don't incentivise using asset tokens with high liquidation fee during liquidation (#536)

* Don't incentivise using non-usdc coins to liquidate tokens

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* fix tests

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* fix tests

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* review: add back test comment

---------

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
Co-authored-by: Christian Kamm <mail@ckamm.de>
This commit is contained in:
microwavedcola1 2023-04-13 12:43:31 +02:00 committed by GitHub
parent 61a4f62ea4
commit 2dca3003df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 22 deletions

View File

@ -115,16 +115,13 @@ pub(crate) fn liquidation_action(
// Liquidation fees work by giving the liqor more assets than the oracle price would
// indicate. Specifically we choose
// assets =
// liabs * liab_oracle_price/asset_oracle_price * (1 + liab_liq_fee + asset_liq_fee)
// Which means that we use a increased liab oracle price and reduced asset oracle price for
// the conversion.
// It would be more fully correct to use (1+liab_liq_fee)*(1+asset_liq_fee), but for small
// fee amounts that is nearly identical.
// liabs * liab_oracle_price/asset_oracle_price * (1 + liab_liq_fee)
// Which means that we use a increased liab oracle price for the conversion.
// For simplicity we write
// 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 = I80F48::ONE + asset_bank.liquidation_fee + liab_bank.liquidation_fee;
let fee_factor = I80F48::ONE + liab_bank.liquidation_fee;
let liab_oracle_price_adjusted = liab_oracle_price * fee_factor;
let init_asset_weight = asset_bank.init_asset_weight;

View File

@ -184,7 +184,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> {
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
(-350.0f64 + (1000.0 / 20.0 / 1.02)).round() as i64
);
let liqee = get_mango_account(solana, account).await;
assert!(liqee.being_liquidated());
@ -206,7 +206,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> {
.await
.unwrap();
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);
let borrow1_after_liq = -350.0f64 + (1000.0 / 20.0 / 1.02) + (20.0 / 20.0 / 1.02);
assert_eq!(
account_position(solana, account, borrow_token1.bank).await,
borrow1_after_liq.round() as i64

View File

@ -331,10 +331,10 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
.await
.unwrap();
// the we only have 20 collateral2, and can trade them for 20 / 1.04 = 19.2 borrow2
// the we only have 20 collateral2, and can trade them for 20 / 1.02 = 19.6 borrow2
assert_eq!(
account_position(solana, account, borrow_token2.bank).await,
-50 + 19
-50 + 20
);
assert!(account_position_closed(solana, account, collateral_token2.bank).await,);
let liqee = get_mango_account(solana, account).await;
@ -360,11 +360,11 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
.await
.unwrap();
// the asset cost for 50-19=31 borrow2 is 31 * 1.04 = 32.24
// the asset cost for 50-19=31 borrow2 is 31 * 1.02 = 31.62
assert!(account_position_closed(solana, account, borrow_token2.bank).await);
assert_eq!(
account_position(solana, account, collateral_token1.bank).await,
1000 - 32
1000 - 31
);
let liqee = get_mango_account(solana, account).await;
assert!(liqee.being_liquidated());
@ -388,14 +388,14 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
.await
.unwrap();
// the asset cost for 10 borrow1 is 10 * 2 * 1.04 = 20.8
// the asset cost for 10 borrow1 is 10 * 2 * 1.02 = 20.4
assert_eq!(
account_position(solana, account, borrow_token1.bank).await,
-350 + 10
);
assert_eq!(
account_position(solana, account, collateral_token1.bank).await,
1000 - 32 - 21
1000 - 31 - 20
);
let liqee = get_mango_account(solana, account).await;
assert!(liqee.being_liquidated());
@ -420,16 +420,16 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
.unwrap();
// health after borrow2 liquidation was (1000-32) * 0.6 - 350 * 2 * 1.4 = -399.2
// borrow1 needed 399.2 / (1.4*2 - 0.6*2*1.04) = 257.2
// asset cost = 257.2 * 2 * 1.04 = 535
// borrow1 needed 399.2 / (1.4*2 - 0.6*2*1.02) = 253.29
// asset cost = 253.29 * 2 * 1.02 = 516.7
// loan orignation fee = 1
assert_eq!(
account_position(solana, account, borrow_token1.bank).await,
-350 + 257
-350 + 253
);
assert_eq!(
account_position(solana, account, collateral_token1.bank).await,
1000 - 32 - 535 - 1
1000 - 31 - 516 - 1
);
let liqee = get_mango_account(solana, account).await;
assert!(!liqee.being_liquidated());
@ -474,12 +474,11 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
.await
.unwrap();
// Liqee's remaining collateral got dusted, only borrows remain
// but the borrow amount is so tiny, that being_liquidated is already switched off
// Liqee's remaining collateral got dusted, only borrows remain: the account is bankrupt
let liqee = get_mango_account(solana, account).await;
assert_eq!(liqee.active_token_positions().count(), 1);
assert!(account_position_f64(solana, account, borrow_token1.bank).await > -1.0);
assert!(!liqee.being_liquidated());
assert!(account_position_f64(solana, account, borrow_token1.bank).await > -2.74);
assert!(liqee.being_liquidated());
Ok(())
}

View File

@ -339,6 +339,10 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> {
)
.await
.unwrap();
<<<<<<< HEAD
=======
>>>>>>> dev
// No change
{
let perp_market = solana.get_account::<PerpMarket>(perp_market).await;