Skip to content

Commit

Permalink
program: more leniency in allowing risk decreasing trades for perps (#…
Browse files Browse the repository at this point in the history
…297)

* program: more leniency in allowing risk decreasing trades for perps

* remove unused param

* skip maker maintenance check if maker wasn't filled

* update CHANGELOG.md
  • Loading branch information
crispheaney authored Dec 19, 2022
1 parent e362fc2 commit 0f800e3
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 94 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixes

program: more leniency in allowing risk decreasing trades for perps ([#297](https://github.com/drift-labs/protocol-v2/pull/297))
program: fix is_user_being_liquidated in deposit

### Breaking
Expand Down
134 changes: 57 additions & 77 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,12 +692,10 @@ pub fn fill_perp_order(
let oracle_reserve_price_spread_pct_before: i64;
let is_oracle_valid: bool;
let oracle_price: i64;
let market_is_reduce_only: bool;
let mut amm_is_available = state.exchange_status != ExchangeStatus::AmmPaused;

{
let market = &mut perp_market_map.get_ref_mut(&market_index)?;
market_is_reduce_only = market.is_reduce_only()?;
amm_is_available &= market.status != MarketStatus::AmmPaused;
validation::perp_market::validate_perp_market(market)?;
validate!(
Expand Down Expand Up @@ -829,7 +827,6 @@ pub fn fill_perp_order(
valid_oracle_price,
now,
slot,
market_is_reduce_only,
amm_is_available,
)?;

Expand Down Expand Up @@ -1227,38 +1224,22 @@ fn fulfill_perp_order(
valid_oracle_price: Option<i64>,
now: i64,
slot: u64,
market_is_reduce_only: bool,
amm_is_available: bool,
) -> DriftResult<(u64, bool, bool)> {
let market_index = user.orders[user_order_index].market_index;

let position_index = get_position_index(&user.perp_positions, market_index)?;
let order_direction = user.orders[user_order_index].direction;
let position_base_asset_amount_before = user.perp_positions[position_index].base_asset_amount;
let risk_decreasing = is_order_risk_decreasing(
&order_direction,
user.orders[user_order_index]
.get_base_asset_amount_unfilled(Some(position_base_asset_amount_before))?,
position_base_asset_amount_before.cast()?,
)?;

if !risk_decreasing && market_is_reduce_only {
cancel_risk_increasing_order(
user,
user_order_index,
user_key,
filler,
filler_key,
perp_market_map,
spot_market_map,
oracle_map,
fee_structure,
now,
slot,
)?;
let user_position_index = get_position_index(&user.perp_positions, market_index)?;
let position_base_asset_amount_before =
user.perp_positions[user_position_index].base_asset_amount;
let user_order_risk_decreasing =
determine_if_user_order_is_risk_decreasing(user, market_index, user_order_index)?;

return Ok((0, false, true));
}
let maker_order_risk_decreasing =
if let (Some(maker), Some(maker_order_index)) = (maker.as_ref(), maker_order_index) {
determine_if_user_order_is_risk_decreasing(maker, market_index, maker_order_index)?
} else {
false
};

let fulfillment_methods = {
let market = perp_market_map.get_ref(&market_index)?;
Expand All @@ -1285,6 +1266,7 @@ fn fulfill_perp_order(
let mut base_asset_amount = 0_u64;
let mut quote_asset_amount = 0_u64;
let mut order_records: Vec<OrderActionRecord> = vec![];
let mut maker_filled = false;
for fulfillment_method in fulfillment_methods.iter() {
if user.orders[user_order_index].status != OrderStatus::Open {
break;
Expand Down Expand Up @@ -1340,6 +1322,10 @@ fn fulfill_perp_order(
)?,
};

if fulfillment_method == &PerpFulfillmentMethod::Match && fill_base_asset_amount != 0 {
maker_filled = true;
}

base_asset_amount = base_asset_amount.safe_add(fill_base_asset_amount)?;
quote_asset_amount = quote_asset_amount.safe_add(fill_quote_asset_amount)?;
market
Expand All @@ -1352,11 +1338,16 @@ fn fulfill_perp_order(
}

let perp_market = perp_market_map.get_ref(&market_index)?;
let initial_margin_ratio = perp_market.margin_ratio_initial;
let maintenance_margin_ratio = perp_market.margin_ratio_maintenance;
let maintenance_margin_buffer = initial_margin_ratio
.safe_sub(maintenance_margin_ratio)?
.safe_div(2)?;
let taker_maintenance_margin_buffer = calculate_maintenance_buffer_ratio(
perp_market.margin_ratio_initial,
perp_market.margin_ratio_maintenance,
user_order_risk_decreasing,
)?;
let maker_maintenance_margin_buffer = calculate_maintenance_buffer_ratio(
perp_market.margin_ratio_initial,
perp_market.margin_ratio_maintenance,
maker_order_risk_decreasing,
)?;
drop(perp_market);

let (_, taker_total_collateral, taker_margin_requirement_plus_buffer, _) =
Expand All @@ -1366,7 +1357,7 @@ fn fulfill_perp_order(
MarginRequirementType::Maintenance,
spot_market_map,
oracle_map,
Some(maintenance_margin_buffer.cast()?),
Some(taker_maintenance_margin_buffer.cast()?),
)?;
if taker_total_collateral < taker_margin_requirement_plus_buffer.cast()? {
msg!(
Expand All @@ -1377,15 +1368,15 @@ fn fulfill_perp_order(
return Err(ErrorCode::InsufficientCollateral);
}

if let Some(maker) = maker {
if let (Some(maker), true) = (maker, maker_filled) {
let (_, maker_total_collateral, maker_margin_requirement_plus_buffer, _) =
calculate_margin_requirement_and_total_collateral(
maker,
perp_market_map,
MarginRequirementType::Maintenance,
spot_market_map,
oracle_map,
Some(maintenance_margin_buffer.cast()?),
Some(maker_maintenance_margin_buffer.cast()?),
)?;

if maker_total_collateral < maker_margin_requirement_plus_buffer.cast()? {
Expand All @@ -1398,7 +1389,8 @@ fn fulfill_perp_order(
}
}

let position_base_asset_amount_after = user.perp_positions[position_index].base_asset_amount;
let position_base_asset_amount_after =
user.perp_positions[user_position_index].base_asset_amount;
let risk_increasing = position_base_asset_amount_before == 0
|| position_base_asset_amount_before.signum() != position_base_asset_amount_after.signum()
|| position_base_asset_amount_before.abs() < position_base_asset_amount_after.abs();
Expand All @@ -1408,46 +1400,34 @@ fn fulfill_perp_order(
Ok((base_asset_amount, risk_increasing, updated_user_state))
}

fn cancel_risk_increasing_order(
user: &mut User,
user_order_index: usize,
user_key: &Pubkey,
filler: &mut Option<&mut User>,
filler_key: &Pubkey,
perp_market_map: &PerpMarketMap,
spot_market_map: &SpotMarketMap,
oracle_map: &mut OracleMap,
fee_structure: &FeeStructure,
now: i64,
slot: u64,
) -> DriftResult {
let market_index = user.orders[user_order_index].market_index;
let filler_reward = {
let mut market = perp_market_map.get_ref_mut(&market_index)?;
pay_keeper_flat_reward_for_perps(
user,
filler.as_deref_mut(),
market.deref_mut(),
fee_structure.flat_filler_fee,
)?
};
fn determine_if_user_order_is_risk_decreasing(
user: &User,
market_index: u16,
order_index: usize,
) -> DriftResult<bool> {
let position_index = get_position_index(&user.perp_positions, market_index)?;
let order_direction = user.orders[order_index].direction;
let position_base_asset_amount_before = user.perp_positions[position_index].base_asset_amount;
is_order_risk_decreasing(
&order_direction,
user.orders[order_index]
.get_base_asset_amount_unfilled(Some(position_base_asset_amount_before))?,
position_base_asset_amount_before.cast()?,
)
}

cancel_order(
user_order_index,
user,
user_key,
perp_market_map,
spot_market_map,
oracle_map,
now,
slot,
OrderActionExplanation::RiskingIncreasingOrder,
Some(filler_key),
filler_reward,
false,
)?;
fn calculate_maintenance_buffer_ratio(
initial_margin_ratio: u32,
maintenance_margin_ratio: u32,
order_is_risk_decreasing: bool,
) -> DriftResult<u32> {
if order_is_risk_decreasing {
return Ok(0);
}

Ok(())
initial_margin_ratio
.safe_sub(maintenance_margin_ratio)?
.safe_div(2)
}

pub fn fulfill_perp_order_with_amm(
Expand Down
12 changes: 0 additions & 12 deletions programs/drift/src/controller/orders/amm_jit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -470,7 +469,6 @@ pub mod amm_jit {
Some(PRICE_PRECISION_I64),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -653,7 +651,6 @@ pub mod amm_jit {
Some(PRICE_PRECISION_I64),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -836,7 +833,6 @@ pub mod amm_jit {
Some(200 * PRICE_PRECISION_I64),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -1027,7 +1023,6 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -1226,7 +1221,6 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -1425,7 +1419,6 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -1600,7 +1593,6 @@ pub mod amm_jit {
Some(1),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -1786,7 +1778,6 @@ pub mod amm_jit {
Some(200 * PRICE_PRECISION_I64),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -2023,7 +2014,6 @@ pub mod amm_jit {
Some(1),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -2294,7 +2284,6 @@ pub mod amm_jit {
Some(200 * PRICE_PRECISION_I64),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -2507,7 +2496,6 @@ pub mod amm_jit {
Some(1),
now,
slot,
false,
true,
)
.unwrap();
Expand Down
5 changes: 0 additions & 5 deletions programs/drift/src/controller/orders/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2457,7 +2457,6 @@ pub mod fulfill_order {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -2669,7 +2668,6 @@ pub mod fulfill_order {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -2859,7 +2857,6 @@ pub mod fulfill_order {
None,
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -3020,7 +3017,6 @@ pub mod fulfill_order {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
false,
true,
)
.unwrap();
Expand Down Expand Up @@ -3411,7 +3407,6 @@ pub mod fulfill_order {
None,
now,
slot,
false,
true,
)
.unwrap();
Expand Down

0 comments on commit 0f800e3

Please sign in to comment.