Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

program: add buffer to calculating max perp if fee #635

Merged
merged 3 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 130 additions & 1 deletion programs/drift/src/controller/liquidation/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1929,8 +1929,137 @@ pub mod liquidate_perp {
.unwrap();

let market_after = perp_market_map.get_ref(&0).unwrap();
// .5% * 100 * .95 =$0.475
assert_eq!(market_after.amm.total_liquidation_fee, 475000);
}

#[test]
pub fn successful_liquidation_portion_of_if_fee() {
let now = 0_i64;
let slot = 0_u64;

let mut oracle_price = get_hardcoded_pyth_price(23244136, 6);
let oracle_price_key =
Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap();
let pyth_program = crate::ids::pyth_program::id();
create_account_info!(
oracle_price,
&oracle_price_key,
&pyth_program,
oracle_account_info
);
let mut oracle_map = OracleMap::load_one(&oracle_account_info, slot, None).unwrap();

let mut market = PerpMarket {
amm: AMM {
base_asset_reserve: 100 * AMM_RESERVE_PRECISION,
quote_asset_reserve: 100 * AMM_RESERVE_PRECISION,
bid_base_asset_reserve: 101 * AMM_RESERVE_PRECISION,
bid_quote_asset_reserve: 99 * AMM_RESERVE_PRECISION,
ask_base_asset_reserve: 99 * AMM_RESERVE_PRECISION,
ask_quote_asset_reserve: 101 * AMM_RESERVE_PRECISION,
sqrt_k: 100 * AMM_RESERVE_PRECISION,
peg_multiplier: 100 * PEG_PRECISION,
max_slippage_ratio: 50,
max_fill_reserve_fraction: 100,
order_step_size: 10000000,
quote_asset_amount: 50 * QUOTE_PRECISION_I128,
base_asset_amount_with_amm: BASE_PRECISION_I128,
oracle: oracle_price_key,
historical_oracle_data: HistoricalOracleData::default_price(oracle_price.agg.price),
funding_period: 3600,
..AMM::default()
},
margin_ratio_initial: 1000,
margin_ratio_maintenance: 500,
number_of_users_with_base: 1,
number_of_users: 1,
status: MarketStatus::Initialized,
liquidator_fee: LIQUIDATION_FEE_PRECISION / 100,
if_liquidation_fee: LIQUIDATION_FEE_PRECISION / 100,
..PerpMarket::default()
};
create_anchor_account_info!(market, PerpMarket, market_account_info);
let perp_market_map = PerpMarketMap::load_one(&market_account_info, true).unwrap();

let mut spot_market = SpotMarket {
market_index: 0,
oracle_source: OracleSource::QuoteAsset,
cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION,
decimals: 6,
initial_asset_weight: SPOT_WEIGHT_PRECISION,
historical_oracle_data: HistoricalOracleData {
last_oracle_price_twap: PRICE_PRECISION_I64,
last_oracle_price_twap_5min: PRICE_PRECISION_I64,
..HistoricalOracleData::default()
},
..SpotMarket::default()
};
create_anchor_account_info!(spot_market, SpotMarket, spot_market_account_info);
let spot_market_map = SpotMarketMap::load_one(&spot_market_account_info, true).unwrap();

let mut user = User {
perp_positions: get_positions(PerpPosition {
market_index: 0,
base_asset_amount: -299400000000,
quote_asset_amount: 6959294318,
quote_entry_amount: 6959294318,
quote_break_even_amount: 6959294318,
..PerpPosition::default()
}),
spot_positions: get_spot_positions(SpotPosition {
market_index: 0,
balance_type: SpotBalanceType::Deposit,
scaled_balance: 113838792 * 1000,
..SpotPosition::default()
}),
..User::default()
};

let mut liquidator = User {
spot_positions: get_spot_positions(SpotPosition {
market_index: 0,
balance_type: SpotBalanceType::Deposit,
scaled_balance: 50000 * SPOT_BALANCE_PRECISION_U64,
..SpotPosition::default()
}),
..User::default()
};

let user_key = Pubkey::default();
let liquidator_key = Pubkey::default();

let mut user_stats = UserStats::default();
let mut liquidator_stats = UserStats::default();
let state = State {
liquidation_margin_buffer_ratio: 200,
initial_pct_to_liquidate: LIQUIDATION_PCT_PRECISION as u16,
liquidation_duration: 150,
..Default::default()
};
liquidate_perp(
0,
300 * BASE_PRECISION_U64,
None,
&mut user,
&user_key,
&mut user_stats,
&mut liquidator,
&liquidator_key,
&mut liquidator_stats,
&perp_market_map,
&spot_market_map,
&mut oracle_map,
slot,
now,
&state,
)
.unwrap();

let market_after = perp_market_map.get_ref(&0).unwrap();
assert!(!user.is_being_liquidated());
// .5% * 100 =$0.5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix comment (with description?)

assert_eq!(market_after.amm.total_liquidation_fee, QUOTE_PRECISION / 2);
assert_eq!(market_after.amm.total_liquidation_fee, 41787043);
}
}

Expand Down
22 changes: 13 additions & 9 deletions programs/drift/src/math/liquidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,15 +379,19 @@ pub fn calculate_perp_if_fee(
.safe_div(PRICE_PRECISION)?;

// margin ratio - liquidator fee - (margin shortage / (user base asset amount * price))
let implied_if_fee = margin_ratio.saturating_sub(liquidator_fee).saturating_sub(
margin_shortage
.safe_mul(BASE_PRECISION)?
.safe_div(user_base_asset_amount.cast()?)?
.safe_mul(PRICE_PRECISION)?
.safe_div(price)?
.cast::<u32>()
.unwrap_or(u32::MAX),
);
let implied_if_fee = margin_ratio
.saturating_sub(liquidator_fee)
.saturating_sub(
margin_shortage
.safe_mul(BASE_PRECISION)?
.safe_div(user_base_asset_amount.cast()?)?
.safe_mul(PRICE_PRECISION)?
.safe_div(price)?
.cast::<u32>()
.unwrap_or(u32::MAX),
)
.safe_mul(19)?
.safe_div(20)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you leave comment describing the reason for 5% off

  • update CHANGELOG


Ok(max_if_liquidation_fee.min(implied_if_fee))
}
Expand Down
4 changes: 2 additions & 2 deletions programs/drift/src/math/liquidation/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ mod calculate_perp_if_fee {
)
.unwrap();

assert_eq!(fee, LIQUIDATION_FEE_PRECISION / 50); // 2%
assert_eq!(fee, 19000); // 2%
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix comment (with description?)


let tiny_margin_shortage = QUOTE_PRECISION;
let fee = calculate_perp_if_fee(
Expand All @@ -574,7 +574,7 @@ mod calculate_perp_if_fee {
)
.unwrap();

assert_eq!(fee, 39000); // 3.9%
assert_eq!(fee, 37050); // 3.9%
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix comment (with description?)


let huge_margin_shortage = 1000 * QUOTE_PRECISION;
let fee = calculate_perp_if_fee(
Expand Down
Loading