@@ -32,6 +32,27 @@ pub fn jit<'info>(ctx: Context<'_, '_, 'info, 'info, Jit<'info>>, params: JitPar
3232 let market_index = taker_order. market_index ;
3333 let taker_direction = taker_order. direction ;
3434
35+ let slots_left = taker_order
36+ . slot
37+ . safe_add ( taker_order. auction_duration . cast ( ) ?) ?
38+ . cast :: < i64 > ( ) ?
39+ . safe_sub ( slot. cast ( ) ?) ?;
40+ msg ! (
41+ "slot = {} auction duration = {} slots_left = {}" ,
42+ slot,
43+ taker_order. auction_duration,
44+ slots_left
45+ ) ;
46+
47+ msg ! (
48+ "taker order type {:?} auction start {} auction end {} limit price {} oracle price offset {}" ,
49+ taker_order. order_type,
50+ taker_order. auction_start_price,
51+ taker_order. auction_end_price,
52+ taker_order. price,
53+ taker_order. oracle_price_offset
54+ ) ;
55+
3556 let remaining_accounts_iter = & mut ctx. remaining_accounts . iter ( ) . peekable ( ) ;
3657 let AccountMaps {
3758 perp_market_map,
@@ -45,20 +66,45 @@ pub fn jit<'info>(ctx: Context<'_, '_, 'info, 'info, Jit<'info>>, params: JitPar
4566 None ,
4667 ) ?;
4768
48- let ( oracle_price, tick_size) = if market_type == DriftMarketType :: Perp {
69+ let ( oracle_price, tick_size, min_order_size ) = if market_type == DriftMarketType :: Perp {
4970 let perp_market = perp_market_map. get_ref ( & market_index) ?;
5071 let oracle_price = oracle_map. get_price_data ( & perp_market. amm . oracle ) ?. price ;
5172
52- ( oracle_price, perp_market. amm . order_tick_size )
73+ (
74+ oracle_price,
75+ perp_market. amm . order_tick_size ,
76+ perp_market. amm . min_order_size ,
77+ )
5378 } else {
5479 let spot_market = spot_market_map. get_ref ( & market_index) ?;
5580 let oracle_price = oracle_map. get_price_data ( & spot_market. oracle ) ?. price ;
5681
57- ( oracle_price, spot_market. order_tick_size )
82+ (
83+ oracle_price,
84+ spot_market. order_tick_size ,
85+ spot_market. min_order_size ,
86+ )
5887 } ;
5988
6089 let taker_price =
61- taker_order. force_get_limit_price ( Some ( oracle_price) , None , slot, tick_size) ?;
90+ match taker_order. get_limit_price ( Some ( oracle_price) , None , slot, tick_size) ? {
91+ Some ( price) => price,
92+ None if market_type == DriftMarketType :: Perp => {
93+ msg ! ( "taker order didnt have price. deriving fallback" ) ;
94+ // if the order doesn't have a price, drift users amm price for taker price
95+ let perp_market = perp_market_map. get_ref ( & market_index) ?;
96+ let reserve_price = perp_market. amm . reserve_price ( ) ?;
97+ match taker_direction {
98+ PositionDirection :: Long => perp_market. amm . ask_price ( reserve_price) ?,
99+ PositionDirection :: Short => perp_market. amm . bid_price ( reserve_price) ?,
100+ }
101+ }
102+ None => {
103+ // Shouldnt be possible for spot
104+ msg ! ( "taker order didnt have price" ) ;
105+ return Err ( ErrorCode :: TakerOrderNotFound . into ( ) ) ;
106+ }
107+ } ;
62108
63109 let maker_direction = taker_direction. opposite ( ) ;
64110 let maker_worst_price = params. get_worst_price ( oracle_price, taker_direction) ?;
@@ -84,9 +130,41 @@ pub fn jit<'info>(ctx: Context<'_, '_, 'info, 'info, Jit<'info>>, params: JitPar
84130 }
85131 }
86132 }
87- let maker_price = taker_price;
88133
89- let taker_base_asset_amount_unfilled = taker_order. get_base_asset_amount_unfilled ( None ) ?;
134+ let maker_price = if market_type == DriftMarketType :: Perp {
135+ let perp_market = perp_market_map. get_ref ( & market_index) ?;
136+ let reserve_price = perp_market. amm . reserve_price ( ) ?;
137+
138+ let maker_price = match maker_direction {
139+ PositionDirection :: Long => {
140+ let amm_bid_price = perp_market. amm . bid_price ( reserve_price) ?;
141+
142+ // if amm price is better than maker, use amm price to ensure fill
143+ if taker_price <= amm_bid_price {
144+ amm_bid_price. min ( maker_worst_price)
145+ } else {
146+ taker_price
147+ }
148+ }
149+ PositionDirection :: Short => {
150+ let amm_ask_price = perp_market. amm . ask_price ( reserve_price) ?;
151+
152+ if taker_price >= amm_ask_price {
153+ amm_ask_price. max ( maker_worst_price)
154+ } else {
155+ taker_price
156+ }
157+ }
158+ } ;
159+
160+ maker_price
161+ } else {
162+ taker_price
163+ } ;
164+
165+ let taker_base_asset_amount_unfilled = taker_order
166+ . get_base_asset_amount_unfilled ( None ) ?
167+ . max ( min_order_size) ;
90168 let maker_existing_position = if market_type == DriftMarketType :: Perp {
91169 let perp_market = perp_market_map. get_ref ( & market_index) ?;
92170 let perp_position = maker. get_perp_position ( market_index) ;
@@ -111,6 +189,7 @@ pub fn jit<'info>(ctx: Context<'_, '_, 'info, 'info, Jit<'info>>, params: JitPar
111189 maker_direction,
112190 taker_base_asset_amount_unfilled,
113191 maker_existing_position,
192+ min_order_size,
114193 ) {
115194 Ok ( size) => size,
116195 Err ( e) => {
@@ -144,7 +223,36 @@ pub fn jit<'info>(ctx: Context<'_, '_, 'info, 'info, Jit<'info>>, params: JitPar
144223 drop ( taker) ;
145224 drop ( maker) ;
146225
147- place_and_make ( ctx, params. taker_order_id , order_params) ?;
226+ place_and_make ( & ctx, params. taker_order_id , order_params) ?;
227+
228+ let taker = ctx. accounts . taker . load ( ) ?;
229+
230+ let taker_base_asset_amount_unfilled_after = match taker. get_order ( params. taker_order_id ) {
231+ Some ( order) => order. get_base_asset_amount_unfilled ( None ) ?,
232+ None => 0 ,
233+ } ;
234+
235+ if taker_base_asset_amount_unfilled_after == taker_base_asset_amount_unfilled {
236+ // taker order failed to fill
237+ msg ! (
238+ "taker price = {} maker price = {} oracle price = {}" ,
239+ taker_price,
240+ maker_price,
241+ oracle_price
242+ ) ;
243+ msg ! ( "jit params {:?}" , params) ;
244+ if market_type == DriftMarketType :: Perp {
245+ let perp_market = perp_market_map. get_ref ( & market_index) ?;
246+ let reserve_price = perp_market. amm . reserve_price ( ) ?;
247+ let ( bid_price, ask_price) = perp_market. amm . bid_ask_price ( reserve_price) ?;
248+ msg ! (
249+ "vamm bid price = {} vamm ask price = {}" ,
250+ bid_price,
251+ ask_price
252+ ) ;
253+ }
254+ return Err ( ErrorCode :: NoFill . into ( ) ) ;
255+ }
148256
149257 Ok ( ( ) )
150258}
@@ -213,15 +321,17 @@ fn check_position_limits(
213321 maker_direction : PositionDirection ,
214322 taker_base_asset_amount_unfilled : u64 ,
215323 maker_existing_position : i64 ,
324+ min_order_size : u64 ,
216325) -> Result < u64 > {
217326 if maker_direction == PositionDirection :: Long {
218327 let size = params. max_position . safe_sub ( maker_existing_position) ?;
219328
220- if size <= 0 {
329+ if size <= min_order_size . cast ( ) ? {
221330 msg ! (
222- "maker existing position {} >= max position {}" ,
331+ "maker existing position {} >= max position {} + min order size {} " ,
223332 maker_existing_position,
224- params. max_position
333+ params. max_position,
334+ min_order_size
225335 ) ;
226336 return Err ( ErrorCode :: PositionLimitBreached . into ( ) ) ;
227337 }
@@ -230,11 +340,12 @@ fn check_position_limits(
230340 } else {
231341 let size = maker_existing_position. safe_sub ( params. min_position ) ?;
232342
233- if size <= 0 {
343+ if size <= min_order_size . cast ( ) ? {
234344 msg ! (
235- "maker existing position {} <= min position {}" ,
345+ "maker existing position {} <= min position {} + min order size {} " ,
236346 maker_existing_position,
237- params. min_position
347+ params. min_position,
348+ min_order_size
238349 ) ;
239350 return Err ( ErrorCode :: PositionLimitBreached . into ( ) ) ;
240351 }
@@ -256,55 +367,55 @@ mod tests {
256367 } ;
257368
258369 // same direction, doesn't breach
259- let result = check_position_limits ( params, PositionDirection :: Long , 10 , 40 ) ;
370+ let result = check_position_limits ( params, PositionDirection :: Long , 10 , 40 , 0 ) ;
260371 assert ! ( result. is_ok( ) ) ;
261372 assert_eq ! ( result. unwrap( ) , 10 ) ;
262- let result = check_position_limits ( params, PositionDirection :: Short , 10 , -40 ) ;
373+ let result = check_position_limits ( params, PositionDirection :: Short , 10 , -40 , 0 ) ;
263374 assert ! ( result. is_ok( ) ) ;
264375 assert_eq ! ( result. unwrap( ) , 10 ) ;
265376
266377 // same direction, whole order breaches, only takes enough to hit limit
267- let result = check_position_limits ( params, PositionDirection :: Long , 100 , 40 ) ;
378+ let result = check_position_limits ( params, PositionDirection :: Long , 100 , 40 , 0 ) ;
268379 assert ! ( result. is_ok( ) ) ;
269380 assert_eq ! ( result. unwrap( ) , 60 ) ;
270- let result = check_position_limits ( params, PositionDirection :: Short , 100 , -40 ) ;
381+ let result = check_position_limits ( params, PositionDirection :: Short , 100 , -40 , 0 ) ;
271382 assert ! ( result. is_ok( ) ) ;
272383 assert_eq ! ( result. unwrap( ) , 60 ) ;
273384
274385 // opposite direction, doesn't breach
275- let result = check_position_limits ( params, PositionDirection :: Long , 10 , -40 ) ;
386+ let result = check_position_limits ( params, PositionDirection :: Long , 10 , -40 , 0 ) ;
276387 assert ! ( result. is_ok( ) ) ;
277388 assert_eq ! ( result. unwrap( ) , 10 ) ;
278- let result = check_position_limits ( params, PositionDirection :: Short , 10 , 40 ) ;
389+ let result = check_position_limits ( params, PositionDirection :: Short , 10 , 40 , 0 ) ;
279390 assert ! ( result. is_ok( ) ) ;
280391 assert_eq ! ( result. unwrap( ) , 10 ) ;
281392
282393 // opposite direction, whole order breaches, only takes enough to take flipped limit
283- let result = check_position_limits ( params, PositionDirection :: Long , 200 , -40 ) ;
394+ let result = check_position_limits ( params, PositionDirection :: Long , 200 , -40 , 0 ) ;
284395 assert ! ( result. is_ok( ) ) ;
285396 assert_eq ! ( result. unwrap( ) , 140 ) ;
286- let result = check_position_limits ( params, PositionDirection :: Short , 200 , 40 ) ;
397+ let result = check_position_limits ( params, PositionDirection :: Short , 200 , 40 , 0 ) ;
287398 assert ! ( result. is_ok( ) ) ;
288399 assert_eq ! ( result. unwrap( ) , 140 ) ;
289400
290401 // opposite direction, maker already breached, allows reducing
291- let result = check_position_limits ( params, PositionDirection :: Long , 200 , -150 ) ;
402+ let result = check_position_limits ( params, PositionDirection :: Long , 200 , -150 , 0 ) ;
292403 assert ! ( result. is_ok( ) ) ;
293404 assert_eq ! ( result. unwrap( ) , 200 ) ;
294- let result = check_position_limits ( params, PositionDirection :: Short , 200 , 150 ) ;
405+ let result = check_position_limits ( params, PositionDirection :: Short , 200 , 150 , 0 ) ;
295406 assert ! ( result. is_ok( ) ) ;
296407 assert_eq ! ( result. unwrap( ) , 200 ) ;
297408
298409 // same direction, maker already breached, errors
299- let result = check_position_limits ( params, PositionDirection :: Long , 200 , 150 ) ;
410+ let result = check_position_limits ( params, PositionDirection :: Long , 200 , 150 , 0 ) ;
300411 assert ! ( result. is_err( ) ) ;
301- let result = check_position_limits ( params, PositionDirection :: Short , 200 , -150 ) ;
412+ let result = check_position_limits ( params, PositionDirection :: Short , 200 , -150 , 0 ) ;
302413 assert ! ( result. is_err( ) ) ;
303414 }
304415}
305416
306417fn place_and_make < ' info > (
307- ctx : Context < ' _ , ' _ , ' _ , ' info , Jit < ' info > > ,
418+ ctx : & Context < ' _ , ' _ , ' _ , ' info , Jit < ' info > > ,
308419 taker_order_id : u32 ,
309420 order_params : OrderParams ,
310421) -> Result < ( ) > {
0 commit comments