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: new place_orders ix #499

Merged
merged 6 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
93 changes: 53 additions & 40 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::controller::spot_position::{
};
use crate::error::DriftResult;
use crate::error::ErrorCode;
use crate::instructions::OrderParams;
use crate::instructions::{OrderParams, PlaceOrderOptions};
use crate::load_mut;
use crate::math::amm_jit::calculate_amm_jit_liquidity;
use crate::math::auction::calculate_auction_prices;
Expand Down Expand Up @@ -91,6 +91,7 @@ pub fn place_perp_order(
oracle_map: &mut OracleMap,
clock: &Clock,
params: OrderParams,
options: PlaceOrderOptions,
) -> DriftResult {
let now = clock.unix_timestamp;
let slot = clock.slot;
Expand All @@ -107,15 +108,17 @@ pub fn place_perp_order(

validate!(!user.is_bankrupt(), ErrorCode::UserBankrupt)?;

expire_orders(
user,
&user_key,
perp_market_map,
spot_market_map,
oracle_map,
now,
slot,
)?;
if options.try_expire_orders {
expire_orders(
user,
&user_key,
perp_market_map,
spot_market_map,
oracle_map,
now,
slot,
)?;
}

let max_ts = match params.max_ts {
Some(max_ts) => max_ts,
Expand Down Expand Up @@ -291,17 +294,20 @@ pub fn place_perp_order(
<= worst_case_base_asset_amount_before.unsigned_abs()
&& order_risk_reducing;

// Order fails if it's risk increasing and it brings the user collateral below the margin requirement
let meets_initial_margin_requirement = meets_place_order_margin_requirement(
user,
perp_market_map,
spot_market_map,
oracle_map,
risk_decreasing,
)?;
// when orders are placed in bulk, only need to check margin on last place
if options.enforce_margin_check {
// Order fails if it's risk increasing and it brings the user collateral below the margin requirement
let meets_initial_margin_requirement = meets_place_order_margin_requirement(
user,
perp_market_map,
spot_market_map,
oracle_map,
risk_decreasing,
)?;

if !meets_initial_margin_requirement {
return Err(ErrorCode::InvalidOrderForInitialMarginReq);
if !meets_initial_margin_requirement {
return Err(ErrorCode::InvalidOrderForInitialMarginReq);
}
}

if force_reduce_only && !risk_decreasing {
Expand Down Expand Up @@ -740,6 +746,7 @@ pub fn modify_order(
oracle_map,
clock,
order_params,
PlaceOrderOptions::default(),
)?;
} else {
place_spot_order(
Expand All @@ -750,6 +757,7 @@ pub fn modify_order(
oracle_map,
clock,
order_params,
PlaceOrderOptions::default(),
)?;
}

Expand Down Expand Up @@ -2782,6 +2790,7 @@ pub fn place_spot_order(
oracle_map: &mut OracleMap,
clock: &Clock,
params: OrderParams,
options: PlaceOrderOptions,
) -> DriftResult {
let now = clock.unix_timestamp;
let slot = clock.slot;
Expand All @@ -2798,15 +2807,17 @@ pub fn place_spot_order(

validate!(!user.is_bankrupt(), ErrorCode::UserBankrupt)?;

expire_orders(
user,
&user_key,
perp_market_map,
spot_market_map,
oracle_map,
now,
slot,
)?;
if options.try_expire_orders {
expire_orders(
user,
&user_key,
perp_market_map,
spot_market_map,
oracle_map,
now,
slot,
)?;
}

let max_ts = match params.max_ts {
Some(max_ts) => max_ts,
Expand Down Expand Up @@ -2990,24 +3001,26 @@ pub fn place_spot_order(
<= worst_case_token_amount_before.unsigned_abs()
&& order_risk_decreasing;

let meets_initial_margin_requirement = meets_place_order_margin_requirement(
user,
perp_market_map,
spot_market_map,
oracle_map,
risk_decreasing,
)?;
if options.enforce_margin_check {
let meets_initial_margin_requirement = meets_place_order_margin_requirement(
user,
perp_market_map,
spot_market_map,
oracle_map,
risk_decreasing,
)?;

if !meets_initial_margin_requirement {
return Err(ErrorCode::InvalidOrderForInitialMarginReq);
if !meets_initial_margin_requirement {
return Err(ErrorCode::InvalidOrderForInitialMarginReq);
}
}

validate_spot_margin_trading(user, spot_market_map, oracle_map)?;

if force_reduce_only && !risk_decreasing {
return Err(ErrorCode::InvalidOrderNotRiskReducing);
}

validate_spot_margin_trading(user, spot_market_map, oracle_map)?;

let (taker, taker_order, maker, maker_order) =
get_taker_and_maker_for_order_record(&user_key, &new_order);

Expand Down
89 changes: 88 additions & 1 deletion programs/drift/src/instructions/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ pub fn handle_transfer_deposit(
Ok(())
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default, Copy)]
pub struct OrderParams {
pub order_type: OrderType,
pub market_type: MarketType,
Expand Down Expand Up @@ -756,6 +756,20 @@ impl Default for PostOnlyParam {
}
}

pub struct PlaceOrderOptions {
pub try_expire_orders: bool,
pub enforce_margin_check: bool,
}

impl Default for PlaceOrderOptions {
fn default() -> Self {
Self {
try_expire_orders: true,
enforce_margin_check: true,
}
}
}

#[access_control(
exchange_not_paused(&ctx.accounts.state)
)]
Expand Down Expand Up @@ -788,6 +802,7 @@ pub fn handle_place_perp_order(ctx: Context<PlaceOrder>, params: OrderParams) ->
&mut oracle_map,
clock,
params,
PlaceOrderOptions::default(),
)?;

Ok(())
Expand Down Expand Up @@ -1014,6 +1029,73 @@ pub fn handle_modify_order_by_user_order_id(
Ok(())
}

#[access_control(
exchange_not_paused(&ctx.accounts.state)
)]
pub fn handle_place_orders(ctx: Context<PlaceOrder>, params: Vec<OrderParams>) -> Result<()> {
let clock = &Clock::get()?;
let state = &ctx.accounts.state;

let AccountMaps {
perp_market_map,
spot_market_map,
mut oracle_map,
} = load_maps(
&mut ctx.remaining_accounts.iter().peekable(),
&MarketSet::new(),
&MarketSet::new(),
clock.slot,
Some(state.oracle_guard_rails),
)?;

validate!(
params.len() <= 32,
ErrorCode::DefaultError,
"max 32 order params"
)?;

let num_orders = params.len();
for (i, params) in params.iter().enumerate() {
validate!(
!params.immediate_or_cancel,
ErrorCode::InvalidOrderIOC,
"immediate_or_cancel order must be in place_and_make or place_and_take"
)?;

// only enforce margin on last order and only try to expire on first order
let options = PlaceOrderOptions {
enforce_margin_check: i == num_orders - 1,
try_expire_orders: i == 0,
};

if params.market_type == MarketType::Perp {
controller::orders::place_perp_order(
&ctx.accounts.state,
&ctx.accounts.user,
&perp_market_map,
&spot_market_map,
&mut oracle_map,
clock,
*params,
options,
)?;
} else {
controller::orders::place_spot_order(
&ctx.accounts.state,
&ctx.accounts.user,
&perp_market_map,
&spot_market_map,
&mut oracle_map,
clock,
*params,
options,
)?;
}
}

Ok(())
}

#[access_control(
fill_not_paused(&ctx.accounts.state)
)]
Expand Down Expand Up @@ -1063,6 +1145,7 @@ pub fn handle_place_and_take_perp_order<'info>(
&mut oracle_map,
&Clock::get()?,
params,
PlaceOrderOptions::default(),
)?;

let user = &mut ctx.accounts.user;
Expand Down Expand Up @@ -1151,6 +1234,7 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>(
&mut oracle_map,
clock,
params,
PlaceOrderOptions::default(),
)?;

let (order_id, authority) = {
Expand Down Expand Up @@ -1225,6 +1309,7 @@ pub fn handle_place_spot_order(ctx: Context<PlaceOrder>, params: OrderParams) ->
&mut oracle_map,
&Clock::get()?,
params,
PlaceOrderOptions::default(),
)?;

Ok(())
Expand Down Expand Up @@ -1313,6 +1398,7 @@ pub fn handle_place_and_take_spot_order<'info>(
&mut oracle_map,
&clock,
params,
PlaceOrderOptions::default(),
)?;

let user = &mut ctx.accounts.user;
Expand Down Expand Up @@ -1436,6 +1522,7 @@ pub fn handle_place_and_make_spot_order<'info>(
&mut oracle_map,
clock,
params,
PlaceOrderOptions::default(),
)?;

let order_id = load!(ctx.accounts.user)?.get_last_order_id();
Expand Down
4 changes: 4 additions & 0 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ pub mod drift {
)
}

pub fn place_orders(ctx: Context<PlaceOrder>, params: Vec<OrderParams>) -> Result<()> {
handle_place_orders(ctx, params)
}

pub fn begin_swap(
ctx: Context<Swap>,
in_market_index: u16,
Expand Down
Loading