Skip to content

Commit

Permalink
program: dynamic liq fee (#601)
Browse files Browse the repository at this point in the history
* initial logic to scale initial weight

* add cargo test

* add initial sdk logic

* tweak field comments

* program: add twap to initial asset weight calc

* inital work for worst case to account for free collateral contribution

* add strict oracle price

* tests work

* used cache values from calc worst case token amounts

* rm comment

* use free collateral contribution in place_spot_order

* use strict quote in calculate_perp_position_value_and_pnl

* remove w bounds from pnl calc

* expand worst case tests

* test the twap logic in worst case calc

* some simplifications

* add some tests for scaled asset weight using twap

* make calc max spot order size work

* tweak place_spot_order on how it checks if spot order is risk decreasing

* always do margin check in place order

* log margin type in meets_place_order_margin_requirement

* fix a bug

* better logic for deciding if trigger order is risk increasing

* sdk: rework calculateWorstCaseTokenAmounts

* place order params keep track of risk increasing

* tweaks

* tweak some tests

* add some comments

* tweak some tests

* calculate_max_withdrawable_amount use spot_market.get_asset_weight

* fix ts tests

* get_asset_weight just takes oracle price

* calculateAssetWeight doesn't look at twap

* add strictOraclePrice

* add strictOraclePrice

* add some sdk tests for worst case token amount calc

* add MarginCalculation struct

* add get_margin_ratio to MarginCalculation

* make strict() modifier for MarginContext

* dont deconstruct margin calculation in liq ix

* apply max if fee

* make margin_requirement_with_buffer private

* if fee for spot liquidation still lets user outta liq territory

* rm comment

* add new max if fee calcs

* remove calculate_if_fee fn

* remove logic to track margin ratio

* tweak language for tracking mkt margin requirement

* add test for calculate_perp_if_fee

* calculate_spot_if_fee tests

* fix bug w tracked_market_margin_shortage

* change how margin is check in fills

* extra safety check in MarginCalculation

* make MarketIdentifier a struct

* add back isolated liability

* fix tests/liquidateSpotSocialLoss.ts (no if liq fee)

* fix sdk/src/user.ts

* fix tests/insuranceFundStake.ts

* prettify tests/insuranceFundStake.ts

* try fix liq perp tests

* yarn prettify:fix

* fix merge

* try fix insurance fund stake test

* CHANGELOG

---------

Co-authored-by: 0xbigz <[email protected]>
  • Loading branch information
crispheaney and 0xbigz committed Sep 15, 2023
1 parent 383574c commit ce80b36
Show file tree
Hide file tree
Showing 21 changed files with 2,174 additions and 1,252 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- program: add dynamic liquidation fee ([#601](https://github.com/drift-labs/protocol-v2/pull/601))

### Fixes

### Breaking
Expand Down
651 changes: 307 additions & 344 deletions programs/drift/src/controller/liquidation.rs

Large diffs are not rendered by default.

584 changes: 449 additions & 135 deletions programs/drift/src/controller/liquidation/tests.rs

Large diffs are not rendered by default.

28 changes: 16 additions & 12 deletions programs/drift/src/controller/lp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ use crate::math::constants::{
SPOT_BALANCE_PRECISION_U64, SPOT_CUMULATIVE_INTEREST_PRECISION, SPOT_WEIGHT_PRECISION,
};
use crate::math::margin::{
calculate_margin_requirement_and_total_collateral, calculate_perp_position_value_and_pnl,
meets_maintenance_margin_requirement, MarginRequirementType,
calculate_margin_requirement_and_total_collateral_and_liability_info,
calculate_perp_position_value_and_pnl, meets_maintenance_margin_requirement,
MarginRequirementType,
};
use crate::state::margin_calculation::{MarginCalculation, MarginContext};
use crate::state::oracle::{HistoricalOracleData, OracleSource};
use crate::state::oracle::{OraclePriceData, StrictOraclePrice};
use crate::state::oracle_map::OracleMap;
Expand Down Expand Up @@ -529,16 +531,18 @@ pub fn test_lp_settle_pnl() {
..State::default()
};

let (margin_requirement1, total_collateral1, _, _) =
calculate_margin_requirement_and_total_collateral(
&user,
&market_map,
MarginRequirementType::Initial,
&spot_market_map,
&mut oracle_map,
None,
)
.unwrap();
let MarginCalculation {
total_collateral: total_collateral1,
margin_requirement: margin_requirement1,
..
} = calculate_margin_requirement_and_total_collateral_and_liability_info(
&user,
&market_map,
&spot_market_map,
&mut oracle_map,
MarginContext::standard(MarginRequirementType::Initial),
)
.unwrap();

assert_eq!(total_collateral1, 49999988);
assert_eq!(margin_requirement1, 2099020); // $2+ for margin req
Expand Down
60 changes: 29 additions & 31 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ use crate::print_error;
use crate::state::events::{emit_stack, get_order_action_record, OrderActionRecord, OrderRecord};
use crate::state::events::{OrderAction, OrderActionExplanation};
use crate::state::fulfillment::{PerpFulfillmentMethod, SpotFulfillmentMethod};
use crate::state::margin_calculation::MarginContext;
use crate::state::oracle::{OraclePriceData, StrictOraclePrice};
use crate::state::oracle_map::OracleMap;
use crate::state::perp_market::{AMMLiquiditySplit, MarketStatus, PerpMarket};
Expand Down Expand Up @@ -1608,47 +1609,46 @@ fn fulfill_perp_order(
quote_asset_amount
)?;

let (taker_margin_requirement, taker_total_collateral, _, _) =
calculate_margin_requirement_and_total_collateral(
let taker_margin_calculation =
calculate_margin_requirement_and_total_collateral_and_liability_info(
user,
perp_market_map,
if user_order_position_decreasing {
spot_market_map,
oracle_map,
MarginContext::standard(if user_order_position_decreasing {
MarginRequirementType::Maintenance
} else {
MarginRequirementType::Fill
},
spot_market_map,
oracle_map,
None,
}),
)?;
if taker_total_collateral < taker_margin_requirement.cast()? {

if !taker_margin_calculation.meets_margin_requirement() {
msg!(
"taker breached fill requirements (margin requirement {}) (total_collateral {})",
taker_margin_requirement,
taker_total_collateral
taker_margin_calculation.margin_requirement,
taker_margin_calculation.total_collateral
);
return Err(ErrorCode::InsufficientCollateral);
}

for (maker_key, _) in makers_filled {
let maker = makers_and_referrer.get_ref(&maker_key)?;

let (maker_margin_requirement, maker_total_collateral, _, _) =
calculate_margin_requirement_and_total_collateral(
let maker_margin_calculation =
calculate_margin_requirement_and_total_collateral_and_liability_info(
&maker,
perp_market_map,
MarginRequirementType::Fill,
spot_market_map,
oracle_map,
None,
MarginContext::standard(MarginRequirementType::Fill),
)?;

if maker_total_collateral < maker_margin_requirement.cast()? {
if !maker_margin_calculation.meets_margin_requirement() {
msg!(
"maker ({}) breached fill requirements (margin requirement {}) (total_collateral {})",
maker_key,
maker_margin_requirement,
maker_total_collateral
maker_margin_calculation.margin_requirement,
maker_margin_calculation.total_collateral
);
return Err(ErrorCode::InsufficientCollateral);
}
Expand Down Expand Up @@ -3662,42 +3662,40 @@ fn fulfill_spot_order(
drop(base_market);
drop(quote_market);

let (taker_margin_requirement, taker_total_collateral, _, _) =
calculate_margin_requirement_and_total_collateral(
let taker_margin_calculation =
calculate_margin_requirement_and_total_collateral_and_liability_info(
user,
perp_market_map,
margin_type,
spot_market_map,
oracle_map,
None,
MarginContext::standard(margin_type),
)?;

if taker_total_collateral < taker_margin_requirement.cast()? {
if !taker_margin_calculation.meets_margin_requirement() {
msg!(
"taker breached maintenance requirements (margin requirement {}) (total_collateral {})",
taker_margin_requirement,
taker_total_collateral
taker_margin_calculation.margin_requirement,
taker_margin_calculation.total_collateral
);
return Err(ErrorCode::InsufficientCollateral);
}

if let Some(maker) = maker {
let (maker_margin_requirement, maker_total_collateral, _, _) =
calculate_margin_requirement_and_total_collateral(
let maker_margin_calculation =
calculate_margin_requirement_and_total_collateral_and_liability_info(
maker,
perp_market_map,
MarginRequirementType::Fill,
spot_market_map,
oracle_map,
None,
MarginContext::standard(MarginRequirementType::Fill),
)?;

if maker_total_collateral < maker_margin_requirement.cast()? {
if !maker_margin_calculation.meets_margin_requirement() {
msg!(
"maker ({}) breached maintenance requirements (margin requirement {}) (total_collateral {})",
maker_key.safe_unwrap()?,
maker_margin_requirement,
maker_total_collateral
maker_margin_calculation.margin_requirement,
maker_margin_calculation.total_collateral
);
return Err(ErrorCode::InsufficientCollateral);
}
Expand Down
Loading

0 comments on commit ce80b36

Please sign in to comment.