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: more leniency in allowing risk decreasing trades for perps #297

Merged
merged 5 commits into from
Dec 19, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
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(
Copy link
Member Author

Choose a reason for hiding this comment

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

when market if reduce only, we force all orders to be reduce_only. and we already check to cancel reduce only orders elsewhere, so this was redundant now

Copy link
Member

Choose a reason for hiding this comment

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

so even if a risk increasing limit order was placed prior to the market becoming reduce only, it will cancel still?

Copy link
Member Author

Choose a reason for hiding this comment

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

no it would still be able to increase the position

Copy link
Member Author

Choose a reason for hiding this comment

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

we can add this back else where

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