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: limit order auctions #355

Merged
merged 40 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a2d3d65
new is_amm_available_liquidity_source
crispheaney Feb 10, 2023
aeea891
tweak how trigger orders work
crispheaney Feb 10, 2023
012e5a9
tweak get_limit_price to allow limit orders to have auction price
crispheaney Feb 10, 2023
ff3c8cb
allow limit order to pass auction params
crispheaney Feb 10, 2023
e65ff2b
do order validation
crispheaney Feb 10, 2023
34f9e4b
make the resting limit order logic based on auction being complete
crispheaney Feb 11, 2023
b310cbf
dlob trigger order matches on chain
crispheaney Feb 11, 2023
761c724
ts client reflects price changes
crispheaney Feb 11, 2023
a9f7492
fix ts dlob tests
crispheaney Feb 11, 2023
ff74fa9
add rust tests
crispheaney Feb 11, 2023
4f9c405
add failing test
crispheaney Feb 15, 2023
b533e34
prototype of updateRestingLimitOrders
crispheaney Feb 15, 2023
005a362
address pr feedback
crispheaney Feb 16, 2023
135eb86
program: tweak calculate_size_premium_liability_weight to have smalle…
0xbigz Feb 10, 2023
a82dd07
v2.16.0-beta.2
crispheaney Feb 10, 2023
df4be82
sdk: fix borrow limit calc (#356)
wphan Feb 10, 2023
0bc0823
update CHANGELOG.md
wphan Feb 10, 2023
cbf23b9
sdk: new squareRootBN implementation using bit shifting
crispheaney Feb 13, 2023
c1adcc1
sdk: change modify order params to be object (#353)
evanpipta Feb 13, 2023
9edb1f2
sdk: DLOB matching logic accounts for zero-price spot market orders n…
crispheaney Feb 14, 2023
e83fdb1
v2.16.0-beta.3
crispheaney Feb 14, 2023
1d1350c
sdk: add market lookup table (#359)
crispheaney Feb 14, 2023
22e2b70
v2.16.0
crispheaney Feb 14, 2023
ef7ac56
getMarketBids/Asks becomes getTakingBids/Asks
crispheaney Feb 16, 2023
6aa353b
remove updateRestingLimitOrder from getbestNode
crispheaney Feb 16, 2023
b246089
tests working
crispheaney Feb 18, 2023
f1355ce
update isFallbackAvailableLiquiditySource
crispheaney Feb 18, 2023
b62baf7
tweak is_maker_for_taker
crispheaney Feb 18, 2023
5fb214e
Merge branch 'master' into crispheaney/limit-order-auctions
crispheaney Feb 19, 2023
c08d0ac
tweaks
crispheaney Feb 19, 2023
e0a476a
fix updateRestingLimitOrders
crispheaney Feb 19, 2023
c2a528d
add test for updating resting limit ordres
crispheaney Feb 19, 2023
399fcf5
add tests for is_maker_for_taker
crispheaney Feb 19, 2023
e961604
fix broken ts test
crispheaney Feb 19, 2023
8c58197
Merge branch 'master' into crispheaney/limit-order-auctions
0xbigz Feb 20, 2023
194ca4f
tweak some syntax choices
crispheaney Feb 20, 2023
fefd6d8
simplify is_maker_for_taker
crispheaney Feb 20, 2023
04b7566
dont let auction prices be zero for market or limit orders
crispheaney Feb 20, 2023
5652856
tweak findJitAuctionNodesToFill
crispheaney Feb 20, 2023
68b198a
CHANGELOG
crispheaney Feb 20, 2023
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
95 changes: 52 additions & 43 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::cell::RefMut;
use std::cmp::max;
use std::num::NonZeroU64;
use std::ops::DerefMut;

Expand Down Expand Up @@ -29,7 +28,7 @@ use crate::get_struct_values;
use crate::get_then_update_id;
use crate::instructions::OrderParams;
use crate::load_mut;
use crate::math::auction::{calculate_auction_prices, is_auction_complete};
use crate::math::auction::{calculate_auction_prices, is_amm_available_liquidity_source};
use crate::math::casting::Cast;
use crate::math::constants::{
BASE_PRECISION_U64, FEE_POOL_TO_REVENUE_POOL_THRESHOLD, FIVE_MINUTE, ONE_HOUR, PERP_DECIMALS,
Expand Down Expand Up @@ -207,20 +206,19 @@ pub fn place_perp_order(
};

let oracle_price_data = oracle_map.get_price_data(&market.amm.oracle)?;
let (auction_start_price, auction_end_price) =
get_auction_prices(&params, oracle_price_data, market.amm.order_tick_size)?;
let (auction_start_price, auction_end_price, auction_duration) = get_auction_params(
&params,
oracle_price_data,
market.amm.order_tick_size,
state.min_perp_auction_duration,
)?;

validate!(
params.market_type == MarketType::Perp,
ErrorCode::InvalidOrderMarketType,
"must be perp order"
)?;

let auction_duration = max(
params.auction_duration.unwrap_or(0),
state.min_perp_auction_duration,
);

let new_order = Order {
status: OrderStatus::Open,
order_type: params.order_type,
Expand Down Expand Up @@ -371,13 +369,31 @@ pub fn place_perp_order(
Ok(())
}

fn get_auction_prices(
fn get_auction_params(
params: &OrderParams,
oracle_price_data: &OraclePriceData,
tick_size: u64,
) -> DriftResult<(i64, i64)> {
if !matches!(params.order_type, OrderType::Market | OrderType::Oracle) {
return Ok((0_i64, 0_i64));
min_auction_duration: u8,
) -> DriftResult<(i64, i64, u8)> {
if !matches!(
params.order_type,
OrderType::Market | OrderType::Oracle | OrderType::Limit
) {
return Ok((0_i64, 0_i64, 0_u8));
}

let auction_duration = params
.auction_duration
.unwrap_or(0)
.max(min_auction_duration);

if params.order_type == OrderType::Limit {
return match (params.auction_start_price, params.auction_end_price) {
(Some(auction_start_price), Some(auction_end_price)) => {
Ok((auction_start_price, auction_end_price, auction_duration))
}
_ => Ok((0_i64, 0_i64, 0_u8)),
};
}

let (auction_start_price, auction_end_price) =
Expand All @@ -395,6 +411,7 @@ fn get_auction_prices(
Ok((
standardize_price_i64(auction_start_price, tick_size.cast()?, params.direction)?,
standardize_price_i64(auction_end_price, tick_size.cast()?, params.direction)?,
auction_duration,
))
}

Expand Down Expand Up @@ -856,6 +873,7 @@ pub fn fill_perp_order(
valid_oracle_price,
now,
slot,
state.min_perp_auction_duration,
amm_is_available,
)?;

Expand Down Expand Up @@ -1076,11 +1094,12 @@ fn sanitize_maker_order<'a>(
let maker_order_price = *maker_order_price;

let maker_order = &maker.orders[maker_order_index];
if !is_maker_for_taker(maker_order, taker_order)? {
if !is_maker_for_taker(maker_order, taker_order, slot)? {
continue;
}

if !maker_order.is_resting_limit_order(slot)? || maker_order.is_jit_maker() {
// dont use maker if order is < 45 slots old and cross amm
if slot.safe_sub(maker_order.slot)? < 45 {
match maker_direction {
PositionDirection::Long => {
if maker_order_price >= amm_ask_price {
Expand Down Expand Up @@ -1258,6 +1277,7 @@ fn fulfill_perp_order(
valid_oracle_price: Option<i64>,
now: i64,
slot: u64,
min_auction_duration: u8,
amm_is_available: bool,
) -> DriftResult<(u64, bool, bool)> {
let market_index = user.orders[user_order_index].market_index;
Expand Down Expand Up @@ -1287,6 +1307,7 @@ fn fulfill_perp_order(
Some(oracle_price),
amm_is_available,
slot,
min_auction_duration,
)?
};

Expand Down Expand Up @@ -1347,6 +1368,7 @@ fn fulfill_perp_order(
valid_oracle_price,
now,
slot,
min_auction_duration,
fee_structure,
oracle_map,
&mut order_records,
Expand Down Expand Up @@ -1764,6 +1786,7 @@ pub fn fulfill_perp_order_with_match(
valid_oracle_price: Option<i64>,
now: i64,
slot: u64,
min_auction_duration: u8,
fee_structure: &FeeStructure,
oracle_map: &mut OracleMap,
order_records: &mut Vec<OrderActionRecord>,
Expand Down Expand Up @@ -1816,7 +1839,11 @@ pub fn fulfill_perp_order_with_match(
// if the auction isn't complete, cant fill against vamm yet
// use the vamm price to guard against bad fill for taker
if taker.orders[taker_order_index].is_limit_order()
&& !taker.orders[taker_order_index].is_auction_complete(slot)?
&& !is_amm_available_liquidity_source(
&taker.orders[taker_order_index],
min_auction_duration,
slot,
)?
{
taker_price = match taker_direction {
PositionDirection::Long => {
Expand Down Expand Up @@ -2298,14 +2325,6 @@ pub fn trigger_order(

let oracle_price = oracle_price_data.price;

let order_slot = user.orders[order_index].slot;
let auction_duration = user.orders[order_index].auction_duration;
validate!(
is_auction_complete(order_slot, auction_duration, slot)?,
ErrorCode::OrderDidNotSatisfyTriggerCondition,
"Auction duration must elapse before triggering"
)?;

let can_trigger = order_satisfies_trigger_condition(
&user.orders[order_index],
oracle_price.unsigned_abs().cast()?,
Expand All @@ -2328,6 +2347,7 @@ pub fn trigger_order(
user.orders[order_index].slot = slot;
let order_type = user.orders[order_index].order_type;
if let OrderType::TriggerMarket = order_type {
user.orders[order_index].auction_duration = state.min_perp_auction_duration;
let (auction_start_price, auction_end_price) =
calculate_auction_prices(oracle_price_data, direction, 0)?;
user.orders[order_index].auction_start_price = auction_start_price;
Expand Down Expand Up @@ -2712,8 +2732,12 @@ pub fn place_spot_order(
)
};

let (auction_start_price, auction_end_price) =
get_auction_prices(&params, &oracle_price_data, spot_market.order_tick_size)?;
let (auction_start_price, auction_end_price, auction_duration) = get_auction_params(
&params,
&oracle_price_data,
spot_market.order_tick_size,
state.default_spot_auction_duration,
)?;

validate!(spot_market.orders_enabled, ErrorCode::SpotOrdersDisabled)?;

Expand All @@ -2729,10 +2753,6 @@ pub fn place_spot_order(
"must be spot order"
)?;

let auction_duration = params
.auction_duration
.unwrap_or(state.default_spot_auction_duration);

let new_order = Order {
status: OrderStatus::Open,
order_type: params.order_type,
Expand Down Expand Up @@ -3153,11 +3173,7 @@ fn sanitize_spot_maker_order<'a>(

{
let maker_order = &maker.orders[maker_order_index];
if !is_maker_for_taker(maker_order, taker_order)? {
return Ok((None, None, None, None));
}

if !maker_order.is_resting_limit_order(slot)? {
if !is_maker_for_taker(maker_order, taker_order, slot)? {
return Ok((None, None, None, None));
}

Expand Down Expand Up @@ -4282,14 +4298,6 @@ pub fn trigger_spot_order(

let oracle_price = oracle_price_data.price;

let order_slot = user.orders[order_index].slot;
let auction_duration = user.orders[order_index].auction_duration;
validate!(
is_auction_complete(order_slot, auction_duration, slot)?,
ErrorCode::OrderDidNotSatisfyTriggerCondition,
"Auction duration must elapse before triggering"
)?;

let can_trigger = order_satisfies_trigger_condition(
&user.orders[order_index],
oracle_price.unsigned_abs().cast()?,
Expand All @@ -4311,6 +4319,7 @@ pub fn trigger_spot_order(
user.orders[order_index].slot = slot;
let order_type = user.orders[order_index].order_type;
if let OrderType::TriggerMarket = order_type {
user.orders[order_index].auction_duration = state.default_spot_auction_duration;
let (auction_start_price, auction_end_price) =
calculate_auction_prices(oracle_price_data, direction, 0)?;
user.orders[order_index].auction_start_price = auction_start_price;
Expand Down
12 changes: 12 additions & 0 deletions programs/drift/src/controller/orders/amm_jit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
0,
true,
)
.unwrap();
Expand Down Expand Up @@ -469,6 +470,7 @@ pub mod amm_jit {
Some(PRICE_PRECISION_I64),
now,
slot,
10,
true,
)
.unwrap();
Expand Down Expand Up @@ -651,6 +653,7 @@ pub mod amm_jit {
Some(PRICE_PRECISION_I64),
now,
slot,
10,
true,
)
.unwrap();
Expand Down Expand Up @@ -833,6 +836,7 @@ pub mod amm_jit {
Some(200 * PRICE_PRECISION_I64),
now,
slot,
10,
true,
)
.unwrap();
Expand Down Expand Up @@ -1023,6 +1027,7 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
0,
true,
)
.unwrap();
Expand Down Expand Up @@ -1221,6 +1226,7 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
0,
true,
)
.unwrap();
Expand Down Expand Up @@ -1419,6 +1425,7 @@ pub mod amm_jit {
Some(market.amm.historical_oracle_data.last_oracle_price),
now,
slot,
0,
true,
)
.unwrap();
Expand Down Expand Up @@ -1593,6 +1600,7 @@ pub mod amm_jit {
Some(1),
now,
slot,
10,
true,
)
.unwrap();
Expand Down Expand Up @@ -1778,6 +1786,7 @@ pub mod amm_jit {
Some(200 * PRICE_PRECISION_I64),
now,
slot,
10,
true,
)
.unwrap();
Expand Down Expand Up @@ -2014,6 +2023,7 @@ pub mod amm_jit {
Some(1),
now,
slot,
auction_duration,
true,
)
.unwrap();
Expand Down Expand Up @@ -2284,6 +2294,7 @@ pub mod amm_jit {
Some(200 * PRICE_PRECISION_I64),
now,
slot,
10,
true,
)
.unwrap();
Expand Down Expand Up @@ -2496,6 +2507,7 @@ pub mod amm_jit {
Some(1),
now,
slot,
0,
true,
)
.unwrap();
Expand Down
Loading