Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
crispheaney committed Oct 11, 2023
1 parent e5cdd49 commit a7e0f61
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 43 deletions.
58 changes: 32 additions & 26 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use crate::math::spot_swap::select_margin_type_for_swap;
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::fill_mode::FillMode;
use crate::state::fulfillment::{PerpFulfillmentMethod, SpotFulfillmentMethod};
use crate::state::margin_calculation::MarginContext;
use crate::state::oracle::{OraclePriceData, StrictOraclePrice};
Expand Down Expand Up @@ -852,6 +853,7 @@ pub fn fill_perp_order(
makers_and_referrer_stats: &UserStatsMap,
jit_maker_order_id: Option<u32>,
clock: &Clock,
fill_mode: FillMode,
) -> DriftResult<u64> {
let now = clock.unix_timestamp;
let slot = clock.slot;
Expand Down Expand Up @@ -1091,6 +1093,7 @@ pub fn fill_perp_order(
slot,
state.min_perp_auction_duration,
amm_is_available,
fill_mode,
)?;

if base_asset_amount != 0 {
Expand Down Expand Up @@ -1475,12 +1478,20 @@ fn fulfill_perp_order(
slot: u64,
min_auction_duration: u8,
amm_is_available: bool,
fill_mode: FillMode,
) -> DriftResult<(u64, u64)> {
let market_index = user.orders[user_order_index].market_index;

let user_order_position_decreasing =
determine_if_user_order_is_position_decreasing(user, market_index, user_order_index)?;

let limit_price = fill_mode.get_limit_price(
&user.orders[user_order_index],
valid_oracle_price,
slot,
perp_market_map.get_ref(&market_index)?.amm.order_tick_size,
)?;

let fulfillment_methods = {
let market = perp_market_map.get_ref(&market_index)?;
let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price;
Expand All @@ -1491,6 +1502,7 @@ fn fulfill_perp_order(
&market.amm,
reserve_price_before,
Some(oracle_price),
limit_price,
amm_is_available,
slot,
min_auction_duration,
Expand Down Expand Up @@ -1530,14 +1542,14 @@ fn fulfill_perp_order(
reserve_price_before,
now,
slot,
valid_oracle_price,
user_key,
filler_key,
filler,
filler_stats,
&mut referrer.as_deref_mut(),
&mut referrer_stats.as_deref_mut(),
fee_structure,
limit_price,
None,
*maker_price,
AMMLiquiditySplit::Shared,
Expand Down Expand Up @@ -1578,6 +1590,7 @@ fn fulfill_perp_order(
&mut referrer_stats.as_deref_mut(),
reserve_price_before,
valid_oracle_price,
limit_price,
now,
slot,
fee_structure,
Expand Down Expand Up @@ -1704,14 +1717,14 @@ pub fn fulfill_perp_order_with_amm(
reserve_price_before: u64,
now: i64,
slot: u64,
valid_oracle_price: Option<i64>,
user_key: &Pubkey,
filler_key: &Pubkey,
filler: &mut Option<&mut User>,
filler_stats: &mut Option<&mut UserStats>,
referrer: &mut Option<&mut User>,
referrer_stats: &mut Option<&mut UserStats>,
fee_structure: &FeeStructure,
limit_price: Option<u64>,
override_base_asset_amount: Option<u64>,
override_fill_price: Option<u64>,
liquidity_split: AMMLiquiditySplit,
Expand All @@ -1721,22 +1734,14 @@ pub fn fulfill_perp_order_with_amm(
// Determine the base asset amount the market can fill
let (base_asset_amount, limit_price, fill_price) = match override_base_asset_amount {
Some(override_base_asset_amount) => {
let limit_price = user.orders[order_index].get_limit_price(
valid_oracle_price,
None,
slot,
market.amm.order_tick_size,
)?;

(override_base_asset_amount, limit_price, override_fill_price)
}
None => {
let existing_base_asset_amount = user.perp_positions[position_index].base_asset_amount;
let (base_asset_amount, limit_price) = calculate_base_asset_amount_for_amm_to_fulfill(
&user.orders[order_index],
market,
valid_oracle_price,
slot,
limit_price,
override_fill_price,
existing_base_asset_amount,
)?;
Expand Down Expand Up @@ -1987,6 +1992,7 @@ pub fn fulfill_perp_order_with_match(
referrer_stats: &mut Option<&mut UserStats>,
reserve_price_before: u64,
valid_oracle_price: Option<i64>,
taker_limit_price: Option<u64>,
now: i64,
slot: u64,
fee_structure: &FeeStructure,
Expand All @@ -2003,20 +2009,20 @@ pub fn fulfill_perp_order_with_match(

let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price;
let taker_direction = taker.orders[taker_order_index].direction;
let amm_available_liquidity = calculate_amm_available_liquidity(&market.amm, &taker_direction)?;
let taker_fallback_price = get_fallback_price(
&taker_direction,
bid_price,
ask_price,
amm_available_liquidity,
oracle_price,
)?;
let taker_price = taker.orders[taker_order_index].force_get_limit_price(
Some(oracle_price),
Some(taker_fallback_price),
slot,
market.amm.order_tick_size,
)?;

let taker_price = if let Some(taker_limit_price) = taker_limit_price {
taker_limit_price
} else {
let amm_available_liquidity =
calculate_amm_available_liquidity(&market.amm, &taker_direction)?;
get_fallback_price(
&taker_direction,
bid_price,
ask_price,
amm_available_liquidity,
oracle_price,
)?
};

let taker_existing_position = taker
.get_perp_position(market.market_index)?
Expand Down Expand Up @@ -2094,14 +2100,14 @@ pub fn fulfill_perp_order_with_match(
reserve_price_before,
now,
slot,
valid_oracle_price,
taker_key,
filler_key,
filler,
filler_stats,
&mut None,
&mut None,
fee_structure,
taker_limit_price,
Some(jit_base_asset_amount),
Some(maker_price), // match the makers price
amm_liquidity_split,
Expand Down
2 changes: 2 additions & 0 deletions programs/drift/src/instructions/keeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::math::constants::QUOTE_SPOT_MARKET_INDEX;
use crate::math::insurance::if_shares_to_vault_amount;
use crate::math::orders::{estimate_price_from_side, find_bids_and_asks_from_users};
use crate::math::spot_withdraw::validate_spot_market_vault_amount;
use crate::state::fill_mode::FillMode;
use crate::state::fulfillment_params::drift::MatchFulfillmentParams;
use crate::state::fulfillment_params::phoenix::PhoenixFulfillmentParams;
use crate::state::fulfillment_params::serum::SerumFulfillmentParams;
Expand Down Expand Up @@ -107,6 +108,7 @@ fn fill_order(ctx: Context<FillOrder>, order_id: u32, market_index: u16) -> Resu
&makers_and_referrer_stats,
None,
clock,
FillMode::Fill,
)?;

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions programs/drift/src/instructions/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use crate::state::events::{
DepositDirection, DepositExplanation, DepositRecord, LPAction, LPRecord, NewUserRecord,
OrderActionExplanation, SwapRecord,
};
use crate::state::fill_mode::FillMode;
use crate::state::fulfillment_params::drift::MatchFulfillmentParams;
use crate::state::fulfillment_params::phoenix::PhoenixFulfillmentParams;
use crate::state::fulfillment_params::serum::SerumFulfillmentParams;
Expand Down Expand Up @@ -1225,6 +1226,7 @@ pub fn handle_place_and_take_perp_order<'info>(
&makers_and_referrer_stats,
None,
&Clock::get()?,
FillMode::PlaceAndTake,
)?;

let order_exists = load!(ctx.accounts.user)?
Expand Down Expand Up @@ -1322,6 +1324,7 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>(
&makers_and_referrer_stats,
Some(order_id),
clock,
FillMode::PlaceAndMake,
)?;

let order_exists = load!(ctx.accounts.user)?
Expand Down
8 changes: 3 additions & 5 deletions programs/drift/src/math/fulfillment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub fn determine_perp_fulfillment_methods(
amm: &AMM,
amm_reserve_price: u64,
valid_oracle_price: Option<i64>,
limit_price: Option<u64>,
amm_is_available: bool,
slot: u64,
min_auction_duration: u8,
Expand All @@ -26,15 +27,12 @@ pub fn determine_perp_fulfillment_methods(
&& valid_oracle_price.is_some()
&& is_amm_available_liquidity_source(taker_order, min_auction_duration, slot)?;

let taker_price =
taker_order.get_limit_price(valid_oracle_price, None, slot, amm.order_tick_size)?;

let maker_direction = taker_order.direction.opposite();

let (mut amm_bid_price, mut amm_ask_price) = amm.bid_ask_price(amm_reserve_price)?;

for (maker_key, maker_order_index, maker_price) in maker_orders_info.iter() {
let taker_crosses_maker = match taker_price {
let taker_crosses_maker = match limit_price {
Some(taker_price) => do_orders_cross(maker_direction, *maker_price, taker_price),
None => true,
};
Expand Down Expand Up @@ -75,7 +73,7 @@ pub fn determine_perp_fulfillment_methods(
PositionDirection::Short => amm_ask_price,
};

let taker_crosses_maker = match taker_price {
let taker_crosses_maker = match limit_price {
Some(taker_price) => do_orders_cross(maker_direction, amm_price, taker_price),
None => true,
};
Expand Down
21 changes: 9 additions & 12 deletions programs/drift/src/math/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,26 @@ mod tests;
pub fn calculate_base_asset_amount_for_amm_to_fulfill(
order: &Order,
market: &PerpMarket,
valid_oracle_price: Option<i64>,
slot: u64,
override_limit_price: Option<u64>,
limit_price: Option<u64>,
override_fill_price: Option<u64>,
existing_base_asset_amount: i64,
) -> DriftResult<(u64, Option<u64>)> {
let limit_price = if let Some(override_limit_price) = override_limit_price {
if let Some(limit_price) =
order.get_limit_price(valid_oracle_price, None, slot, market.amm.order_tick_size)?
{
let limit_price = if let Some(override_fill_price) = override_fill_price {
if let Some(limit_price) = limit_price {
validate!(
(limit_price >= override_limit_price && order.direction == PositionDirection::Long)
|| (limit_price <= override_limit_price
(limit_price >= override_fill_price && order.direction == PositionDirection::Long)
|| (limit_price <= override_fill_price
&& order.direction == PositionDirection::Short),
ErrorCode::InvalidAmmLimitPriceOverride,
"override_limit_price={} not better than order_limit_price={}",
override_limit_price,
override_fill_price,
limit_price
)?;
}

Some(override_limit_price)
Some(override_fill_price)
} else {
order.get_limit_price(valid_oracle_price, None, slot, market.amm.order_tick_size)?
limit_price
};

if order.must_be_triggered() && !order.triggered() {
Expand Down
41 changes: 41 additions & 0 deletions programs/drift/src/state/fill_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::error::DriftResult;
use crate::math::auction::calculate_auction_price;
use crate::math::casting::Cast;
use crate::math::safe_math::SafeMath;
use crate::state::user::Order;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FillMode {
Fill,
PlaceAndMake,
PlaceAndTake,
}

impl FillMode {
pub fn get_limit_price(
&self,
order: &Order,
valid_oracle_price: Option<i64>,
slot: u64,
tick_size: u64,
) -> DriftResult<Option<u64>> {
match self {
FillMode::Fill | FillMode::PlaceAndMake => {
order.get_limit_price(valid_oracle_price, None, slot, tick_size)
}
FillMode::PlaceAndTake => {
if order.has_auction() {
calculate_auction_price(
order,
slot.safe_add(order.auction_duration.cast()?)?,
tick_size,
valid_oracle_price,
)
.map(Some)
} else {
order.get_limit_price(valid_oracle_price, None, slot, tick_size)
}
}
}
}
}
1 change: 1 addition & 0 deletions programs/drift/src/state/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod events;
pub mod fill_mode;
pub mod fulfillment;
pub mod fulfillment_params;
pub mod insurance_fund_stake;
Expand Down

0 comments on commit a7e0f61

Please sign in to comment.