Skip to content

Commit

Permalink
program: allow amm to fill instantly (drift-labs#1258)
Browse files Browse the repository at this point in the history
* program: add-amm-availability-enum

* passing tests

* add init skip duration logic

* amm skip auction duration check for prelaunch oracle

* cargo fmt --

* add state check for pause

* add protected maker mode for user

* improve naming

* filter protected makers in get_maker_orders_info

* add helper function for amm fill check

* Revert "filter protected makers in get_maker_orders_info"

This reverts commit e1a9e1a.

* Revert "add protected maker mode for user"

This reverts commit c59e2b2.

* wip - cache amm imbalance math

* add support for cached amm imbalance

* use cached amm_lp_allowed_to_jit_make, simplier criteria for user skip

* add PerpOperation AmmImmediateFill

* user skip check on sub_account_id stats

* add sufficient_slippage for user skip_duration

* simplify number_of_sub_accounts_created check

* some optimizations

* fix test

* add logs and test

* cargo fmt --

* CHANGELOG

---------

Co-authored-by: Chris Heaney <[email protected]>
  • Loading branch information
0xbigz and crispheaney authored Nov 3, 2024
1 parent 149bf50 commit 50f67cf
Show file tree
Hide file tree
Showing 19 changed files with 408 additions and 98 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- sdk: init referrerMap ([#1295](https://github.com/drift-labs/protocol-v2/pull/1295))
- program: allow disable high leverage mode after 1 hour ([#1289](https://github.com/drift-labs/protocol-v2/pull/1289))
- sdk: driftClient unsub from delisted markets by default ([#1298](https://github.com/drift-labs/protocol-v2/pull/1298))
- program: allow amm to fill immediately ([#1258](https://github.com/drift-labs/protocol-v2/pull/1258))

### Fixes

Expand Down
83 changes: 66 additions & 17 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ use crate::controller::spot_position::{
};
use crate::error::DriftResult;
use crate::error::ErrorCode;
use crate::get_struct_values;
use crate::get_then_update_id;
use crate::load_mut;
use crate::math::amm::calculate_amm_available_liquidity;
use crate::math::amm_jit::calculate_amm_jit_liquidity;
use crate::math::auction::{calculate_auction_params_for_trigger_order, calculate_auction_prices};
use crate::math::casting::Cast;
Expand All @@ -35,23 +34,17 @@ use crate::math::fulfillment::{
determine_perp_fulfillment_methods, determine_spot_fulfillment_methods,
};
use crate::math::liquidation::validate_user_not_being_liquidated;
use crate::math::lp::calculate_lp_shares_to_burn_for_risk_reduction;
use crate::math::matching::{
are_orders_same_market_but_different_sides, calculate_fill_for_matched_orders,
calculate_filler_multiplier_for_matched_orders, do_orders_cross, is_maker_for_taker,
};
use crate::math::oracle::{is_oracle_valid_for_action, DriftAction, OracleValidity};
use crate::math::safe_math::SafeMath;
use crate::math::spot_balance::{get_signed_token_amount, get_token_amount};
use crate::math::{amm, fees, margin::*, orders::*};
use crate::state::order_params::{
ModifyOrderParams, ModifyOrderPolicy, OrderParams, PlaceOrderOptions, PostOnlyParam, RFQMatch,
};
use crate::{controller, ID};

use crate::math::amm::calculate_amm_available_liquidity;
use crate::math::lp::calculate_lp_shares_to_burn_for_risk_reduction;
use crate::math::safe_unwrap::SafeUnwrap;
use crate::math::spot_balance::{get_signed_token_amount, get_token_amount};
use crate::math::spot_swap::select_margin_type_for_swap;
use crate::math::{amm, fees, margin::*, orders::*};
use crate::print_error;
use crate::state::events::{
emit_stack, get_order_action_record, LPAction, LPRecord, OrderActionRecord, OrderRecord,
Expand All @@ -62,8 +55,11 @@ use crate::state::fulfillment::{PerpFulfillmentMethod, SpotFulfillmentMethod};
use crate::state::margin_calculation::{MarginCalculation, MarginContext};
use crate::state::oracle::{OraclePriceData, StrictOraclePrice};
use crate::state::oracle_map::OracleMap;
use crate::state::order_params::{
ModifyOrderParams, ModifyOrderPolicy, OrderParams, PlaceOrderOptions, PostOnlyParam, RFQMatch,
};
use crate::state::paused_operations::{PerpOperation, SpotOperation};
use crate::state::perp_market::{AMMLiquiditySplit, MarketStatus, PerpMarket};
use crate::state::perp_market::{AMMAvailability, AMMLiquiditySplit, MarketStatus, PerpMarket};
use crate::state::perp_market_map::PerpMarketMap;
use crate::state::rfq_user::{RFQOrderId, RFQUser};
use crate::state::spot_fulfillment_params::{ExternalSpotFill, SpotFulfillmentParams};
Expand All @@ -82,6 +78,9 @@ use crate::validation;
use crate::validation::order::{
validate_order, validate_order_for_force_reduce_only, validate_spot_order,
};
use crate::{controller, ID};
use crate::{get_struct_values, PERCENTAGE_PRECISION};
use crate::{get_then_update_id, PERCENTAGE_PRECISION_I64};

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -1079,12 +1078,23 @@ pub fn fill_perp_order(
.position(|order| order.order_id == order_id)
.ok_or_else(print_error!(ErrorCode::OrderDoesNotExist))?;

let (order_status, market_index, order_market_type, order_direction) = get_struct_values!(
let (
order_status,
market_index,
order_market_type,
order_price,
order_oracle_price_offset,
order_direction,
order_auction_duration,
) = get_struct_values!(
user.orders[order_index],
status,
market_index,
market_type,
direction
price,
oracle_price_offset,
direction,
auction_duration
);

validate!(
Expand Down Expand Up @@ -1152,6 +1162,9 @@ pub fn fill_perp_order(
let oracle_price: i64;
let oracle_twap_5min: i64;
let perp_market_index: u16;
let user_can_skip_duration: bool;
let amm_can_skip_duration: bool;
let amm_lp_allowed_to_jit_make: bool;

let mut amm_is_available = !state.amm_paused()? && !fill_mode.is_rfq();
{
Expand All @@ -1176,6 +1189,27 @@ pub fn fill_perp_order(
amm_is_available &= !market.is_operation_paused(PerpOperation::AmmFill);
amm_is_available &= !market.has_too_much_drawdown()?;

let amm_wants_to_jit_make = market.amm.amm_wants_to_jit_make(order_direction)?;
amm_lp_allowed_to_jit_make = market
.amm
.amm_lp_allowed_to_jit_make(amm_wants_to_jit_make)?;
amm_can_skip_duration =
market.can_skip_auction_duration(&state, amm_lp_allowed_to_jit_make)?;

user_can_skip_duration = if amm_can_skip_duration && amm_is_available {
user.can_skip_auction_duration(
user_stats,
order_auction_duration > 0,
fill_mode.is_ioc(),
order_direction,
order_price,
order_oracle_price_offset,
oracle_price_data.price,
)?
} else {
false
};

reserve_price_before = market.amm.reserve_price()?;
oracle_price = oracle_price_data.price;
oracle_twap_5min = market
Expand Down Expand Up @@ -1320,6 +1354,16 @@ pub fn fill_perp_order(
return Ok((0, 0));
}

let amm_availability = if amm_is_available {
if amm_can_skip_duration && user_can_skip_duration {
AMMAvailability::Immediate
} else {
AMMAvailability::AfterMinDuration
}
} else {
AMMAvailability::Unavailable
};

let (base_asset_amount, quote_asset_amount) = fulfill_perp_order(
user,
order_index,
Expand All @@ -1341,8 +1385,9 @@ pub fn fill_perp_order(
now,
slot,
state.min_perp_auction_duration,
amm_is_available,
amm_availability,
fill_mode,
Some(amm_lp_allowed_to_jit_make),
)?;

if base_asset_amount != 0 {
Expand Down Expand Up @@ -1735,8 +1780,9 @@ fn fulfill_perp_order(
now: i64,
slot: u64,
min_auction_duration: u8,
amm_is_available: bool,
amm_availability: AMMAvailability,
fill_mode: FillMode,
amm_lp_allowed_to_jit_make: Option<bool>,
) -> DriftResult<(u64, u64)> {
let market_index = user.orders[user_order_index].market_index;

Expand Down Expand Up @@ -1764,7 +1810,7 @@ fn fulfill_perp_order(
reserve_price_before,
Some(oracle_price),
limit_price,
amm_is_available,
amm_availability,
slot,
min_auction_duration,
fill_mode,
Expand Down Expand Up @@ -1878,6 +1924,7 @@ fn fulfill_perp_order(
fee_structure,
oracle_map,
fill_mode.is_liquidation(),
None,
)?;

if maker_fill_base_asset_amount != 0 {
Expand Down Expand Up @@ -2424,6 +2471,7 @@ pub fn fulfill_perp_order_with_match(
fee_structure: &FeeStructure,
oracle_map: &mut OracleMap,
is_liquidation: bool,
amm_lp_allowed_to_jit_make: Option<bool>,
) -> DriftResult<(u64, u64, u64)> {
if !are_orders_same_market_but_different_sides(
&maker.orders[maker_order_index],
Expand Down Expand Up @@ -2512,6 +2560,7 @@ pub fn fulfill_perp_order_with_match(
taker_base_asset_amount,
maker_base_asset_amount,
taker.orders[taker_order_index].has_limit_price(slot)?,
amm_lp_allowed_to_jit_make,
)?;

if jit_base_asset_amount > 0 {
Expand Down
42 changes: 28 additions & 14 deletions programs/drift/src/controller/orders/amm_jit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,9 @@ pub mod amm_jit {
now,
slot,
0,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -487,8 +488,9 @@ pub mod amm_jit {
now,
slot,
10,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -684,8 +686,9 @@ pub mod amm_jit {
now,
slot,
10,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -880,8 +883,9 @@ pub mod amm_jit {
now,
slot,
10,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -1078,8 +1082,9 @@ pub mod amm_jit {
now,
slot,
0,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -1285,8 +1290,9 @@ pub mod amm_jit {
now,
slot,
0,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -1490,8 +1496,9 @@ pub mod amm_jit {
now,
slot,
0,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -1718,8 +1725,9 @@ pub mod amm_jit {
now,
slot,
0,
false,
crate::state::perp_market::AMMAvailability::Unavailable,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -1917,8 +1925,9 @@ pub mod amm_jit {
now,
slot,
0,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -2104,8 +2113,9 @@ pub mod amm_jit {
now,
slot,
10,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -2303,8 +2313,9 @@ pub mod amm_jit {
now,
slot,
10,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -2553,8 +2564,9 @@ pub mod amm_jit {
now,
slot,
auction_duration,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -2836,8 +2848,9 @@ pub mod amm_jit {
now,
slot,
10,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down Expand Up @@ -3064,8 +3077,9 @@ pub mod amm_jit {
now,
slot,
0,
true,
crate::state::perp_market::AMMAvailability::AfterMinDuration,
FillMode::Fill,
None,
)
.unwrap();

Expand Down
Loading

0 comments on commit 50f67cf

Please sign in to comment.