From d95326c0a49bc2d874f2c740475ec93b27ce317e Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 30 Jan 2023 22:09:49 -0500 Subject: [PATCH 01/29] init --- programs/drift/src/controller/orders.rs | 386 +++++++++++++++------- programs/drift/src/error.rs | 20 ++ programs/drift/src/instructions/keeper.rs | 19 +- programs/drift/src/instructions/user.rs | 40 +-- programs/drift/src/math/fulfillment.rs | 51 ++- programs/drift/src/state/fulfillment.rs | 4 +- programs/drift/src/state/mod.rs | 1 + programs/drift/src/state/user_map.rs | 286 ++++++++++++++++ sdk/src/events/fetchLogs.ts | 5 +- sdk/src/idl/drift.json | 51 +++ 10 files changed, 681 insertions(+), 182 deletions(-) create mode 100644 programs/drift/src/state/user_map.rs diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 8b1664427..9ef66da9c 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1,14 +1,14 @@ use std::cell::RefMut; use std::cmp::max; +use std::collections::BTreeMap; use std::num::NonZeroU64; -use std::ops::DerefMut; +use std::ops::{Deref, DerefMut}; use anchor_lang::prelude::*; use serum_dex::instruction::{NewOrderInstructionV3, SelfTradeBehavior}; use serum_dex::matching::Side; use solana_program::msg; -use crate::controller; use crate::controller::funding::settle_funding_payment; use crate::controller::position; use crate::controller::position::{ @@ -55,6 +55,7 @@ use crate::math::serum::{ use crate::math::spot_balance::{get_signed_token_amount, get_token_amount}; use crate::math::stats::calculate_new_twap; use crate::math::{amm, fees, margin::*, orders::*}; +use crate::{controller, load}; use crate::math::amm::calculate_amm_available_liquidity; use crate::math::safe_unwrap::SafeUnwrap; @@ -76,6 +77,7 @@ use crate::state::user::{ AssetType, Order, OrderStatus, OrderTriggerCondition, OrderType, UserStats, }; use crate::state::user::{MarketType, User}; +use crate::state::user_map::{UserMap, UserStatsMap}; use crate::validate; use crate::validation; use crate::validation::order::{validate_order, validate_spot_order}; @@ -617,11 +619,8 @@ pub fn fill_perp_order( oracle_map: &mut OracleMap, filler: &AccountLoader, filler_stats: &AccountLoader, - maker: Option<&AccountLoader>, - maker_stats: Option<&AccountLoader>, - _maker_order_id: Option, - referrer: Option<&AccountLoader>, - referrer_stats: Option<&AccountLoader>, + makers_and_referrer: &mut UserMap, + makers_and_referrer_stats: &mut UserStatsMap, clock: &Clock, ) -> DriftResult<(u64, bool)> { let now = clock.unix_timestamp; @@ -738,7 +737,7 @@ pub fn fill_perp_order( }; let is_filler_taker = user_key == filler_key; - let is_filler_maker = maker.map_or(false, |maker| maker.key() == filler_key); + let is_filler_maker = makers_and_referrer.0.contains_key(&filler_key); let (mut filler, mut filler_stats) = if !is_filler_maker && !is_filler_taker { let filler = load_mut!(filler)?; if filler.authority != user.authority { @@ -750,27 +749,27 @@ pub fn fill_perp_order( (None, None) }; - let (mut maker, mut maker_stats, maker_key, maker_order_price_and_indexes) = - sanitize_maker_order( - perp_market_map, - spot_market_map, - oracle_map, - maker, - maker_stats, - &user_key, - &user.authority, - &user.orders[order_index], - &mut filler.as_deref_mut(), - &filler_key, - state.perp_fee_structure.flat_filler_fee, - oracle_price, - reserve_price_before, - now, - slot, - )?; + let maker_order_info = sanitize_maker_order2( + perp_market_map, + spot_market_map, + oracle_map, + makers_and_referrer, + &user_key, + &user.orders[order_index], + &mut filler.as_deref_mut(), + &filler_key, + state.perp_fee_structure.flat_filler_fee, + oracle_price, + reserve_price_before, + now, + slot, + )?; - let (mut referrer, mut referrer_stats) = - sanitize_referrer(referrer, referrer_stats, user_stats)?; + let referrer_key = if !user_stats.referrer.eq(&Pubkey::default()) { + Some(user_stats.referrer) + } else { + None + }; let should_expire_order = should_expire_order(user, order_index, now)?; @@ -820,15 +819,13 @@ pub fn fill_perp_order( order_index, &user_key, user_stats, - &mut maker.as_deref_mut(), - &mut maker_stats.as_deref_mut(), - maker_order_price_and_indexes, - maker_key.as_ref(), + makers_and_referrer, + makers_and_referrer_stats, + maker_order_info, &mut filler.as_deref_mut(), &filler_key, &mut filler_stats.as_deref_mut(), - &mut referrer.as_deref_mut(), - &mut referrer_stats.as_deref_mut(), + referrer_key, spot_market_map, perp_market_map, oracle_map, @@ -1167,6 +1164,148 @@ fn sanitize_maker_order<'a>( )) } +#[allow(clippy::type_complexity)] +fn sanitize_maker_order2<'a>( + perp_market_map: &PerpMarketMap, + spot_market_map: &SpotMarketMap, + oracle_map: &mut OracleMap, + makers_and_referrer: &mut UserMap, + taker_key: &Pubkey, + taker_order: &Order, + filler: &mut Option<&mut User>, + filler_key: &Pubkey, + filler_reward: u64, + oracle_price: i64, + reserve_price: u64, + now: i64, + slot: u64, +) -> DriftResult> { + let market = perp_market_map.get_ref(&taker_order.market_index)?; + + let (amm_bid_price, amm_ask_price) = market.amm.bid_ask_price(reserve_price)?; + + let maker_direction = taker_order.direction.opposite(); + + let mut maker_order_info = vec![]; + for (maker_key, user_account_loader) in makers_and_referrer.0.iter_mut() { + if maker_key == taker_key { + continue; + } + + let mut maker = load_mut!(&user_account_loader)?; + + if maker.is_being_liquidated() || maker.is_bankrupt() { + return continue; + } + + let maker_order_price_and_indexes = find_maker_orders( + &maker, + &maker_direction, + &MarketType::Perp, + taker_order.market_index, + Some(oracle_price), + slot, + market.amm.order_tick_size, + )?; + + for (maker_order_index, maker_order_price) in maker_order_price_and_indexes.iter() { + let maker_order_index = *maker_order_index; + let maker_order_price = *maker_order_price; + + let maker_order = &maker.orders[maker_order_index]; + if !is_maker_for_taker(maker_order, taker_order)? { + continue; + } + + if !maker_order.is_resting_limit_order(slot)? { + match maker_direction { + PositionDirection::Long => { + if maker_order_price >= amm_ask_price { + msg!("maker order {} crosses the amm price", maker_order.order_id); + continue; + } + } + PositionDirection::Short => { + if maker_order_price <= amm_bid_price { + msg!("maker order {} crosses the amm price", maker_order.order_id); + continue; + } + } + } + } + + if !are_orders_same_market_but_different_sides(maker_order, taker_order) { + continue; + } + + let breaches_oracle_price_limits = { + limit_price_breaches_oracle_price_bands( + maker_order_price, + maker_order.direction, + oracle_price, + market.margin_ratio_initial, + market.margin_ratio_maintenance, + )? + }; + + let should_expire_order = should_expire_order(&maker, maker_order_index, now)?; + + let existing_base_asset_amount = maker + .get_perp_position(maker.orders[maker_order_index].market_index)? + .base_asset_amount; + let should_cancel_reduce_only_order = should_cancel_reduce_only_order( + &maker.orders[maker_order_index], + existing_base_asset_amount, + )?; + + if breaches_oracle_price_limits + || should_expire_order + || should_cancel_reduce_only_order + { + let filler_reward = { + let mut market = perp_market_map + .get_ref_mut(&maker.orders[maker_order_index].market_index)?; + pay_keeper_flat_reward_for_perps( + &mut maker, + filler.as_deref_mut(), + market.deref_mut(), + filler_reward, + )? + }; + + let explanation = if breaches_oracle_price_limits { + OrderActionExplanation::OraclePriceBreachedLimitPrice + } else if should_expire_order { + OrderActionExplanation::OrderExpired + } else { + OrderActionExplanation::ReduceOnlyOrderIncreasedPosition + }; + + cancel_order( + maker_order_index, + maker.deref_mut(), + &maker_key, + perp_market_map, + spot_market_map, + oracle_map, + now, + slot, + explanation, + Some(filler_key), + filler_reward, + false, + )?; + + continue; + } + + maker_order_info.push((*maker_key, maker_order_index, maker_order_price)); + } + } + + Ok(maker_order_info) +} + #[inline(always)] fn sort_maker_orders( maker_order_price_and_indexes: &mut [(usize, u64)], @@ -1222,15 +1361,13 @@ fn fulfill_perp_order( user_order_index: usize, user_key: &Pubkey, user_stats: &mut UserStats, - maker: &mut Option<&mut User>, - maker_stats: &mut Option<&mut UserStats>, - maker_order_price_and_indexes: Option>, - maker_key: Option<&Pubkey>, + makers_and_referrer: &mut UserMap, + makers_and_referrer_stats: &mut UserStatsMap, + maker_order_info: Vec<(Pubkey, usize, u64)>, filler: &mut Option<&mut User>, filler_key: &Pubkey, filler_stats: &mut Option<&mut UserStats>, - referrer: &mut Option<&mut User>, - referrer_stats: &mut Option<&mut UserStats>, + referrer_key: Option, spot_market_map: &SpotMarketMap, perp_market_map: &PerpMarketMap, oracle_map: &mut OracleMap, @@ -1249,20 +1386,13 @@ fn fulfill_perp_order( let user_order_risk_decreasing = determine_if_user_order_is_risk_decreasing(user, market_index, user_order_index)?; - let maker_base_asset_amount_before = if let Some(maker) = maker { - let maker_position_index = get_position_index(&maker.perp_positions, market_index)?; - maker.perp_positions[maker_position_index].base_asset_amount - } else { - 0 - }; - let fulfillment_methods = { let market = perp_market_map.get_ref(&market_index)?; let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price; determine_perp_fulfillment_methods( &user.orders[user_order_index], - &maker_order_price_and_indexes.as_ref(), + &maker_order_info, &market.amm, reserve_price_before, Some(oracle_price), @@ -1278,7 +1408,7 @@ fn fulfill_perp_order( let mut base_asset_amount = 0_u64; let mut quote_asset_amount = 0_u64; let mut order_records: Vec = vec![]; - let mut maker_filled = false; + let mut makers_filled: BTreeMap = BTreeMap::new(); for fulfillment_method in fulfillment_methods.iter() { if user.orders[user_order_index].status != OrderStatus::Open { break; @@ -1287,56 +1417,93 @@ fn fulfill_perp_order( let user_order_direction = user.orders[user_order_index].direction; let (fill_base_asset_amount, fill_quote_asset_amount) = match fulfillment_method { - PerpFulfillmentMethod::AMM(maker_price) => fulfill_perp_order_with_amm( - user, - user_stats, - user_order_index, - market.deref_mut(), - oracle_map, - reserve_price_before, - now, - slot, - valid_oracle_price, - user_key, - filler_key, - filler, - filler_stats, - referrer, - referrer_stats, - fee_structure, - &mut order_records, - None, - *maker_price, - true, - )?, - PerpFulfillmentMethod::Match(maker_order_index) => fulfill_perp_order_with_match( - market.deref_mut(), - user, - user_stats, - user_order_index, - user_key, - maker.as_deref_mut().safe_unwrap()?, - maker_stats, - *maker_order_index, - maker_key.safe_unwrap()?, - filler, - filler_stats, - filler_key, - referrer, - referrer_stats, - reserve_price_before, - valid_oracle_price, - now, - slot, - fee_structure, - oracle_map, - &mut order_records, - )?, - }; + PerpFulfillmentMethod::AMM(maker_price) => { + let (mut referrer, mut referrer_stats) = if let Some(referrer_key) = referrer_key { + let referrer = makers_and_referrer.get_ref_mut(&referrer_key)?; + let referrer_stats = + makers_and_referrer_stats.get_ref_mut(&referrer.authority)?; - if let PerpFulfillmentMethod::Match(_) = fulfillment_method { - maker_filled = fill_base_asset_amount != 0; - } + (Some(referrer), Some(referrer_stats)) + } else { + (None, None) + }; + + let (fill_base_asset_amount, fill_quote_asset_amount) = + fulfill_perp_order_with_amm( + user, + user_stats, + user_order_index, + market.deref_mut(), + oracle_map, + 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, + &mut order_records, + None, + *maker_price, + true, + )?; + + (fill_base_asset_amount, fill_quote_asset_amount) + } + PerpFulfillmentMethod::Match(maker_key, maker_order_index) => { + let mut maker = makers_and_referrer.get_ref_mut(maker_key)?; + let mut maker_stats = if maker.authority == user.authority { + None + } else { + Some(makers_and_referrer_stats.get_ref_mut(&maker.authority)?) + }; + + let (mut referrer, mut referrer_stats) = if let Some(referrer_key) = referrer_key { + let referrer = makers_and_referrer.get_ref_mut(&referrer_key)?; + let referrer_stats = + makers_and_referrer_stats.get_ref_mut(&referrer.authority)?; + + (Some(referrer), Some(referrer_stats)) + } else { + (None, None) + }; + + let (fill_base_asset_amount, fill_quote_asset_amount) = + fulfill_perp_order_with_match( + market.deref_mut(), + user, + user_stats, + user_order_index, + user_key, + &mut maker, + &mut maker_stats.as_deref_mut(), + *maker_order_index, + &maker_key, + filler, + filler_stats, + filler_key, + &mut referrer.as_deref_mut(), + &mut referrer_stats.as_deref_mut(), + reserve_price_before, + valid_oracle_price, + now, + slot, + fee_structure, + oracle_map, + &mut order_records, + )?; + + if fill_base_asset_amount != 0 { + makers_filled.insert(*maker_key, true); + } + + (fill_base_asset_amount, fill_quote_asset_amount) + } + }; base_asset_amount = base_asset_amount.safe_add(fill_base_asset_amount)?; quote_asset_amount = quote_asset_amount.safe_add(fill_quote_asset_amount)?; @@ -1349,19 +1516,6 @@ fn fulfill_perp_order( emit!(order_record) } - let maker_risk_reducing = if let Some(maker) = maker { - match get_position_index(&maker.perp_positions, market_index) { - Ok(maker_position_index) => { - let maker_base_asset_amount_after = - maker.perp_positions[maker_position_index].base_asset_amount; - maker_base_asset_amount_before.abs() > maker_base_asset_amount_after.abs() - } - Err(_) => true, - } - } else { - false - }; - let perp_market = perp_market_map.get_ref(&market_index)?; let taker_maintenance_margin_buffer = calculate_maintenance_buffer_ratio( perp_market.margin_ratio_initial, @@ -1371,7 +1525,7 @@ fn fulfill_perp_order( let maker_maintenance_margin_buffer = calculate_maintenance_buffer_ratio( perp_market.margin_ratio_initial, perp_market.margin_ratio_maintenance, - maker_risk_reducing, + false, )?; drop(perp_market); @@ -1393,10 +1547,12 @@ fn fulfill_perp_order( return Err(ErrorCode::InsufficientCollateral); } - if let (Some(maker), true) = (maker, maker_filled) { + for (maker_key, _) in makers_filled { + let maker = makers_and_referrer.get_ref_mut(&maker_key)?; + let (_, maker_total_collateral, maker_margin_requirement_plus_buffer, _) = calculate_margin_requirement_and_total_collateral( - maker, + &maker, perp_market_map, MarginRequirementType::Maintenance, spot_market_map, @@ -1407,7 +1563,7 @@ fn fulfill_perp_order( if maker_total_collateral < maker_margin_requirement_plus_buffer.cast()? { msg!( "maker ({}) breached maintenance requirements (margin requirement plus buffer {}) (total_collateral {})", - maker_key.safe_unwrap()?, + maker_key, maker_margin_requirement_plus_buffer, maker_total_collateral ); diff --git a/programs/drift/src/error.rs b/programs/drift/src/error.rs index 229627162..241ac2c33 100644 --- a/programs/drift/src/error.rs +++ b/programs/drift/src/error.rs @@ -457,6 +457,26 @@ pub enum ErrorCode { MaxNumberOfUsers, #[msg("InvalidOracleForSettlePnl")] InvalidOracleForSettlePnl, + #[msg("CouldNotLoadUserData")] + CouldNotLoadUserData, + #[msg("UserWrongMutability")] + UserWrongMutability, + #[msg("InvalidUserAccount")] + InvalidUserAccount, + #[msg("CouldNotLoadUserData")] + CouldNotLoadUserStatsData, + #[msg("UserWrongMutability")] + UserStatsWrongMutability, + #[msg("InvalidUserAccount")] + InvalidUserStatsAccount, + #[msg("UserNotFound")] + UserNotFound, + #[msg("UnableToLoadUserAccount")] + UnableToLoadUserAccount, + #[msg("UserStatsNotFound")] + UserStatsNotFound, + #[msg("UnableToLoadUserStatsAccount")] + UnableToLoadUserStatsAccount, } #[macro_export] diff --git a/programs/drift/src/instructions/keeper.rs b/programs/drift/src/instructions/keeper.rs index e78c1d218..9189b86b7 100644 --- a/programs/drift/src/instructions/keeper.rs +++ b/programs/drift/src/instructions/keeper.rs @@ -24,6 +24,7 @@ use crate::state::spot_market_map::{ }; use crate::state::state::State; use crate::state::user::{MarketType, User, UserStats}; +use crate::state::user_map::{UserMap, UserStatsMap}; use crate::validate; use crate::{controller, load, math}; @@ -85,15 +86,8 @@ fn fill_order( Some(state.oracle_guard_rails), )?; - let (maker, maker_stats) = match maker_order_id { - Some(_) => { - let (user, user_stats) = get_maker_and_maker_stats(remaining_accounts_iter)?; - (Some(user), Some(user_stats)) - } - None => (None, None), - }; - - let (referrer, referrer_stats) = get_referrer_and_referrer_stats(remaining_accounts_iter)?; + let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, None)?; + let mut makers_and_referrer_stats = UserStatsMap::load(remaining_accounts_iter, None)?; controller::repeg::update_amm( market_index, @@ -113,11 +107,8 @@ fn fill_order( &mut oracle_map, &ctx.accounts.filler, &ctx.accounts.filler_stats, - maker.as_ref(), - maker_stats.as_ref(), - maker_order_id, - referrer.as_ref(), - referrer_stats.as_ref(), + &mut makers_and_referrer, + &mut makers_and_referrer_stats, clock, )?; diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index c60b96685..18f85f3f3 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -1,4 +1,5 @@ use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize}; +use anchor_spl::token::accessor::authority; use anchor_spl::token::{Token, TokenAccount}; use crate::controller::orders::cancel_orders; @@ -39,6 +40,7 @@ use crate::state::traits::Size; use crate::state::user::{ MarketType, OrderTriggerCondition, OrderType, User, UserStats, UserStatus, }; +use crate::state::user_map::{UserMap, UserStatsMap}; use crate::validate; use crate::validation::user::validate_user_deletion; use crate::validation::whitelist::validate_whitelist_token; @@ -874,15 +876,8 @@ pub fn handle_place_and_take_perp_order<'info>( return Err(print_error!(ErrorCode::InvalidOrderPostOnly)().into()); } - let (maker, maker_stats) = match maker_order_id { - Some(_) => { - let (user, user_stats) = get_maker_and_maker_stats(remaining_accounts_iter)?; - (Some(user), Some(user_stats)) - } - None => (None, None), - }; - - let (referrer, referrer_stats) = get_referrer_and_referrer_stats(remaining_accounts_iter)?; + let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, None)?; + let mut makers_and_referrer_stats = UserStatsMap::load(remaining_accounts_iter, None)?; let is_immediate_or_cancel = params.immediate_or_cancel; @@ -917,11 +912,8 @@ pub fn handle_place_and_take_perp_order<'info>( &mut oracle_map, &user.clone(), &ctx.accounts.user_stats.clone(), - maker.as_ref(), - maker_stats.as_ref(), - maker_order_id, - referrer.as_ref(), - referrer_stats.as_ref(), + &mut makers_and_referrer, + &mut makers_and_referrer_stats, &Clock::get()?, )?; @@ -968,8 +960,6 @@ pub fn handle_place_and_make_perp_order<'info>( Some(state.oracle_guard_rails), )?; - let (referrer, referrer_stats) = get_referrer_and_referrer_stats(remaining_accounts_iter)?; - if !params.immediate_or_cancel || !params.post_only || params.order_type != OrderType::Limit { msg!("place_and_make must use IOC post only limit order"); return Err(print_error!(ErrorCode::InvalidOrderIOCPostOnly)().into()); @@ -993,7 +983,16 @@ pub fn handle_place_and_make_perp_order<'info>( params, )?; - let order_id = load!(ctx.accounts.user)?.get_last_order_id(); + let (order_id, authority) = { + let user = load!(ctx.accounts.user)?; + (user.get_last_order_id(), user.authority) + }; + + let jit_maker = (ctx.accounts.user.key(), ctx.accounts.user.clone(), order_id); + let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, Some(jit_maker))?; + let jit_maker_stats = (authority, ctx.accounts.user_stats.clone()); + let mut makers_and_referrer_stats = + UserStatsMap::load(remaining_accounts_iter, Some(jit_maker_stats))?; controller::orders::fill_perp_order( taker_order_id, @@ -1005,11 +1004,8 @@ pub fn handle_place_and_make_perp_order<'info>( &mut oracle_map, &ctx.accounts.user.clone(), &ctx.accounts.user_stats.clone(), - Some(&ctx.accounts.user), - Some(&ctx.accounts.user_stats), - Some(order_id), - referrer.as_ref(), - referrer_stats.as_ref(), + &mut makers_and_referrer, + &mut makers_and_referrer_stats, clock, )?; diff --git a/programs/drift/src/math/fulfillment.rs b/programs/drift/src/math/fulfillment.rs index aa8c357f7..e661c9f69 100644 --- a/programs/drift/src/math/fulfillment.rs +++ b/programs/drift/src/math/fulfillment.rs @@ -5,13 +5,14 @@ use crate::math::matching::do_orders_cross; use crate::state::fulfillment::{PerpFulfillmentMethod, SpotFulfillmentMethod}; use crate::state::perp_market::AMM; use crate::state::user::Order; +use solana_program::pubkey::Pubkey; #[cfg(test)] mod tests; pub fn determine_perp_fulfillment_methods( taker_order: &Order, - maker_order_price_and_indexes: &Option<&Vec<(usize, u64)>>, + maker_order_info: &Vec<(Pubkey, usize, u64)>, amm: &AMM, amm_reserve_price: u64, valid_oracle_price: Option, @@ -31,38 +32,36 @@ pub fn determine_perp_fulfillment_methods( let (mut amm_bid_price, mut amm_ask_price) = amm.bid_ask_price(amm_reserve_price)?; - if let Some(maker_order_price_and_indexes) = maker_order_price_and_indexes { - for (maker_order_index, maker_price) in maker_order_price_and_indexes.iter() { - let taker_crosses_maker = match taker_price { - Some(taker_price) => do_orders_cross(maker_direction, *maker_price, taker_price), - None => true, - }; + for (maker_key, maker_order_index, maker_price) in maker_order_info.iter() { + let taker_crosses_maker = match taker_price { + Some(taker_price) => do_orders_cross(maker_direction, *maker_price, taker_price), + None => true, + }; - if !taker_crosses_maker { - break; - } + if !taker_crosses_maker { + break; + } - if can_fill_with_amm { - let maker_better_than_amm = match taker_order.direction { - PositionDirection::Long => *maker_price <= amm_ask_price, - PositionDirection::Short => *maker_price >= amm_bid_price, - }; + if can_fill_with_amm { + let maker_better_than_amm = match taker_order.direction { + PositionDirection::Long => *maker_price <= amm_ask_price, + PositionDirection::Short => *maker_price >= amm_bid_price, + }; - if !maker_better_than_amm { - fulfillment_methods.push(PerpFulfillmentMethod::AMM(Some(*maker_price))); + if !maker_better_than_amm { + fulfillment_methods.push(PerpFulfillmentMethod::AMM(Some(*maker_price))); - match taker_order.direction { - PositionDirection::Long => amm_ask_price = *maker_price, - PositionDirection::Short => amm_bid_price = *maker_price, - }; - } + match taker_order.direction { + PositionDirection::Long => amm_ask_price = *maker_price, + PositionDirection::Short => amm_bid_price = *maker_price, + }; } + } - fulfillment_methods.push(PerpFulfillmentMethod::Match(*maker_order_index)); + fulfillment_methods.push(PerpFulfillmentMethod::Match(*maker_key, *maker_order_index)); - if fulfillment_methods.len() > 6 { - break; - } + if fulfillment_methods.len() > 6 { + break; } } diff --git a/programs/drift/src/state/fulfillment.rs b/programs/drift/src/state/fulfillment.rs index 03b90fa35..c2598448e 100644 --- a/programs/drift/src/state/fulfillment.rs +++ b/programs/drift/src/state/fulfillment.rs @@ -1,7 +1,9 @@ +use solana_program::pubkey::Pubkey; + #[derive(Debug, PartialEq, Eq)] pub enum PerpFulfillmentMethod { AMM(Option), - Match(usize), + Match(Pubkey, usize), } #[derive(Debug)] diff --git a/programs/drift/src/state/mod.rs b/programs/drift/src/state/mod.rs index cf0d42fe3..45de3e818 100644 --- a/programs/drift/src/state/mod.rs +++ b/programs/drift/src/state/mod.rs @@ -12,3 +12,4 @@ pub mod spot_market_map; pub mod state; pub mod traits; pub mod user; +pub mod user_map; diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs new file mode 100644 index 000000000..0e413745c --- /dev/null +++ b/programs/drift/src/state/user_map.rs @@ -0,0 +1,286 @@ +use crate::error::{DriftResult, ErrorCode}; +use crate::math::safe_unwrap::SafeUnwrap; +use crate::state::traits::Size; +use crate::state::user::{User, UserStats}; +use anchor_lang::prelude::AccountLoader; +use anchor_lang::Discriminator; +use arrayref::array_ref; +use solana_program::account_info::AccountInfo; +use solana_program::msg; +use solana_program::pubkey::Pubkey; +use std::cell::RefMut; +use std::collections::BTreeMap; +use std::iter::Peekable; +use std::panic::Location; +use std::slice::Iter; + +pub struct UserMap<'a, 'b>( + pub BTreeMap>, + pub Option<(Pubkey, AccountLoader<'b, User>, u32)>, +); + +impl<'a, 'b> UserMap<'a, 'b> { + // #[track_caller] + // #[inline(always)] + // pub fn get_ref(&self, market_index: &u16) -> DriftResult> { + // let loader = match self.0.get(market_index) { + // Some(loader) => loader, + // None => { + // let caller = Location::caller(); + // msg!( + // "Could not find perp market {} at {}:{}", + // market_index, + // caller.file(), + // caller.line() + // ); + // return Err(ErrorCode::PerpMarketNotFound); + // } + // }; + // + // match loader.load() { + // Ok(perp_market) => Ok(perp_market), + // Err(e) => { + // let caller = Location::caller(); + // msg!("{:?}", e); + // msg!( + // "Could not load perp market {} at {}:{}", + // market_index, + // caller.file(), + // caller.line() + // ); + // Err(ErrorCode::UnableToLoadPerpMarketAccount) + // } + // } + // } + // + #[track_caller] + #[inline(always)] + pub fn get_ref_mut(&self, user: &Pubkey) -> DriftResult> { + if let Some((jit_user, loader, _)) = &self.1 { + if jit_user == user { + return match loader.load_mut() { + Ok(user) => Ok(user), + Err(e) => { + let caller = Location::caller(); + msg!("{:?}", e); + msg!( + "Could not user {} at {}:{}", + user, + caller.file(), + caller.line() + ); + Err(ErrorCode::UnableToLoadUserAccount) + } + }; + } + } + + let loader = match self.0.get(user) { + Some(loader) => loader, + None => { + let caller = Location::caller(); + msg!( + "Could not find user {} at {}:{}", + user, + caller.file(), + caller.line() + ); + return Err(ErrorCode::PerpMarketNotFound); + } + }; + + match loader.load_mut() { + Ok(user) => Ok(user), + Err(e) => { + let caller = Location::caller(); + msg!("{:?}", e); + msg!( + "Could not load user {} at {}:{}", + user, + caller.file(), + caller.line() + ); + Err(ErrorCode::UnableToLoadUserAccount) + } + } + } + + pub fn load<'c>( + account_info_iter: &'c mut Peekable>>, + jit_maker: Option<(Pubkey, AccountLoader<'b, User>, u32)>, + ) -> DriftResult> { + let mut user_map = UserMap(BTreeMap::new(), jit_maker); + + let user_discriminator: [u8; 8] = User::discriminator(); + while let Some(account_info) = account_info_iter.peek() { + let user_key = account_info.key; + + let data = account_info + .try_borrow_data() + .or(Err(ErrorCode::CouldNotLoadUserData))?; + + let expected_data_len = User::SIZE; + if data.len() < expected_data_len { + break; + } + + let account_discriminator = array_ref![data, 0, 8]; + if account_discriminator != &user_discriminator { + break; + } + + let user_account_info = account_info_iter.next().safe_unwrap()?; + + let is_writable = user_account_info.is_writable; + if !is_writable { + return Err(ErrorCode::UserWrongMutability); + } + + let user_account_loader: AccountLoader = + AccountLoader::try_from(user_account_info) + .or(Err(ErrorCode::InvalidUserAccount))?; + + user_map.0.insert(*user_key, user_account_loader); + } + + Ok(user_map) + } +} + +pub struct UserStatsMap<'a, 'b>( + pub BTreeMap>, + pub Option<(Pubkey, AccountLoader<'b, UserStats>)>, +); + +impl<'a> UserStatsMap<'a, '_> { + // #[track_caller] + // #[inline(always)] + // pub fn get_ref(&self, market_index: &u16) -> DriftResult> { + // let loader = match self.0.get(market_index) { + // Some(loader) => loader, + // None => { + // let caller = Location::caller(); + // msg!( + // "Could not find perp market {} at {}:{}", + // market_index, + // caller.file(), + // caller.line() + // ); + // return Err(ErrorCode::PerpMarketNotFound); + // } + // }; + // + // match loader.load() { + // Ok(perp_market) => Ok(perp_market), + // Err(e) => { + // let caller = Location::caller(); + // msg!("{:?}", e); + // msg!( + // "Could not load perp market {} at {}:{}", + // market_index, + // caller.file(), + // caller.line() + // ); + // Err(ErrorCode::UnableToLoadPerpMarketAccount) + // } + // } + // } + // + #[track_caller] + #[inline(always)] + pub fn get_ref_mut(&self, authority: &Pubkey) -> DriftResult> { + if let Some((jit_authority, loader)) = &self.1 { + if jit_authority == authority { + return match loader.load_mut() { + Ok(perp_market) => Ok(perp_market), + Err(e) => { + let caller = Location::caller(); + msg!("{:?}", e); + msg!( + "Could not user stats {} at {}:{}", + authority, + caller.file(), + caller.line() + ); + Err(ErrorCode::UnableToLoadUserStatsAccount) + } + }; + } + } + + let loader = match self.0.get(authority) { + Some(loader) => loader, + None => { + let caller = Location::caller(); + msg!( + "Could not find user stats {} at {}:{}", + authority, + caller.file(), + caller.line() + ); + return Err(ErrorCode::UserStatsNotFound); + } + }; + + match loader.load_mut() { + Ok(perp_market) => Ok(perp_market), + Err(e) => { + let caller = Location::caller(); + msg!("{:?}", e); + msg!( + "Could not user stats {} at {}:{}", + authority, + caller.file(), + caller.line() + ); + Err(ErrorCode::UnableToLoadUserStatsAccount) + } + } + } + + pub fn load<'b, 'c>( + account_info_iter: &'c mut Peekable>>, + jit_maker_stats: Option<(Pubkey, AccountLoader<'b, UserStats>)>, + ) -> DriftResult> { + let mut user_stats_map = UserStatsMap(BTreeMap::new(), jit_maker_stats); + + let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); + while let Some(account_info) = account_info_iter.peek() { + let user_stats_key = account_info.key; + + let data = account_info + .try_borrow_data() + .or(Err(ErrorCode::CouldNotLoadUserStatsData))?; + + let expected_data_len = UserStats::SIZE; + if data.len() < expected_data_len { + break; + } + + let account_discriminator = array_ref![data, 0, 8]; + if account_discriminator != &user_stats_discriminator { + break; + } + + let authority_slice = array_ref![data, 8, 32]; + let authority = Pubkey::new(authority_slice); + + let user_stats_account_info = account_info_iter.next().safe_unwrap()?; + + let is_writable = user_stats_account_info.is_writable; + if !is_writable { + return Err(ErrorCode::UserStatsWrongMutability); + } + + let user_stats_account_loader: AccountLoader = + AccountLoader::try_from(user_stats_account_info) + .or(Err(ErrorCode::InvalidUserStatsAccount))?; + + user_stats_map + .0 + .insert(authority, user_stats_account_loader); + } + + Ok(user_stats_map) + } +} diff --git a/sdk/src/events/fetchLogs.ts b/sdk/src/events/fetchLogs.ts index 61e5124fb..8d288ace6 100644 --- a/sdk/src/events/fetchLogs.ts +++ b/sdk/src/events/fetchLogs.ts @@ -66,10 +66,7 @@ export async function fetchLogs( chunkedSignatures.map(async (chunk) => { const transactions = await connection.getTransactions( chunk.map((confirmedSignature) => confirmedSignature.signature), - { - commitment: finality, - maxSupportedTransactionVersion: 0, - } + finality ); return transactions.reduce((logs, transaction) => { diff --git a/sdk/src/idl/drift.json b/sdk/src/idl/drift.json index 677470891..4eef78b08 100644 --- a/sdk/src/idl/drift.json +++ b/sdk/src/idl/drift.json @@ -6188,6 +6188,7 @@ { "name": "Match", "fields": [ + "publicKey", { "defined": "usize" } @@ -8569,6 +8570,56 @@ "code": 6225, "name": "InvalidOracleForSettlePnl", "msg": "InvalidOracleForSettlePnl" + }, + { + "code": 6226, + "name": "CouldNotLoadUserData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6227, + "name": "UserWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6228, + "name": "InvalidUserAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6229, + "name": "CouldNotLoadUserStatsData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6230, + "name": "UserStatsWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6231, + "name": "InvalidUserStatsAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6232, + "name": "UserNotFound", + "msg": "UserNotFound" + }, + { + "code": 6233, + "name": "UnableToLoadUserAccount", + "msg": "UnableToLoadUserAccount" + }, + { + "code": 6234, + "name": "UserStatsNotFound", + "msg": "UserStatsNotFound" + }, + { + "code": 6235, + "name": "UnableToLoadUserStatsAccount", + "msg": "UnableToLoadUserStatsAccount" } ] } \ No newline at end of file From c4dd1ece0f576ea7dd0d102c8a80c9b3446b9eec Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 30 Jan 2023 22:27:19 -0500 Subject: [PATCH 02/29] program: dont use vec without capacity --- programs/drift/src/controller/orders.rs | 15 ++++++++++++++- programs/drift/src/math/orders.rs | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 9ef66da9c..ff216e55a 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1186,7 +1186,7 @@ fn sanitize_maker_order2<'a>( let maker_direction = taker_order.direction.opposite(); - let mut maker_order_info = vec![]; + let mut maker_order_info = Vec::with_capacity(32); for (maker_key, user_account_loader) in makers_and_referrer.0.iter_mut() { if maker_key == taker_key { continue; @@ -1303,6 +1303,8 @@ fn sanitize_maker_order2<'a>( } } + sort_maker_orders2(&mut maker_order_info, taker_order.direction); + Ok(maker_order_info) } @@ -1317,6 +1319,17 @@ fn sort_maker_orders( }); } +#[inline(always)] +fn sort_maker_orders2( + maker_order_info: &mut [(Pubkey, usize, u64)], + taker_order_direction: PositionDirection, +) { + maker_order_info.sort_by(|a, b| match taker_order_direction { + PositionDirection::Long => a.1.cmp(&b.1), + PositionDirection::Short => b.1.cmp(&a.1), + }); +} + #[allow(clippy::type_complexity)] fn sanitize_referrer<'a>( referrer: Option<&'a AccountLoader>, diff --git a/programs/drift/src/math/orders.rs b/programs/drift/src/math/orders.rs index 5e901d548..e2c84405d 100644 --- a/programs/drift/src/math/orders.rs +++ b/programs/drift/src/math/orders.rs @@ -633,7 +633,7 @@ pub fn find_maker_orders( slot: u64, tick_size: u64, ) -> DriftResult> { - let mut orders = vec![]; + let mut orders: Vec<(usize, u64)> = Vec::with_capacity(32); for (order_index, order) in user.orders.iter().enumerate() { if order.status != OrderStatus::Open { From bcb1b58280fe3631062c2aa094e0e2dd2955b82c Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 31 Jan 2023 11:50:53 -0500 Subject: [PATCH 03/29] referrer working --- programs/drift/src/controller/orders.rs | 78 +++++++++++++++++-------- tests/referrer.ts | 5 +- 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index ff216e55a..5bdee5f4a 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -765,8 +765,21 @@ pub fn fill_perp_order( slot, )?; - let referrer_key = if !user_stats.referrer.eq(&Pubkey::default()) { - Some(user_stats.referrer) + let referrer_keys = if !user_stats.referrer.eq(&Pubkey::default()) { + let referrer_authority_key = user_stats.referrer; + let mut referrer_user_key = Pubkey::default(); + for (maker_key, maker) in makers_and_referrer.0.iter() { + if load!(maker)?.authority == referrer_authority_key { + referrer_user_key = *maker_key; + break; + } + } + + if referrer_user_key == Pubkey::default() { + return Err(ErrorCode::ReferrerNotFound.into()); + } + + Some((referrer_authority_key, referrer_user_key)) } else { None }; @@ -825,7 +838,7 @@ pub fn fill_perp_order( &mut filler.as_deref_mut(), &filler_key, &mut filler_stats.as_deref_mut(), - referrer_key, + referrer_keys, spot_market_map, perp_market_map, oracle_map, @@ -1374,13 +1387,13 @@ fn fulfill_perp_order( user_order_index: usize, user_key: &Pubkey, user_stats: &mut UserStats, - makers_and_referrer: &mut UserMap, - makers_and_referrer_stats: &mut UserStatsMap, + makers_and_referrer: &UserMap, + makers_and_referrer_stats: &UserStatsMap, maker_order_info: Vec<(Pubkey, usize, u64)>, filler: &mut Option<&mut User>, filler_key: &Pubkey, filler_stats: &mut Option<&mut UserStats>, - referrer_key: Option, + referrer_keys: Option<(Pubkey, Pubkey)>, spot_market_map: &SpotMarketMap, perp_market_map: &PerpMarketMap, oracle_map: &mut OracleMap, @@ -1431,15 +1444,12 @@ fn fulfill_perp_order( let (fill_base_asset_amount, fill_quote_asset_amount) = match fulfillment_method { PerpFulfillmentMethod::AMM(maker_price) => { - let (mut referrer, mut referrer_stats) = if let Some(referrer_key) = referrer_key { - let referrer = makers_and_referrer.get_ref_mut(&referrer_key)?; - let referrer_stats = - makers_and_referrer_stats.get_ref_mut(&referrer.authority)?; - - (Some(referrer), Some(referrer_stats)) - } else { - (None, None) - }; + let (mut referrer, mut referrer_stats) = get_referrer( + &referrer_keys, + makers_and_referrer, + makers_and_referrer_stats, + None, + )?; let (fill_base_asset_amount, fill_quote_asset_amount) = fulfill_perp_order_with_amm( @@ -1475,15 +1485,12 @@ fn fulfill_perp_order( Some(makers_and_referrer_stats.get_ref_mut(&maker.authority)?) }; - let (mut referrer, mut referrer_stats) = if let Some(referrer_key) = referrer_key { - let referrer = makers_and_referrer.get_ref_mut(&referrer_key)?; - let referrer_stats = - makers_and_referrer_stats.get_ref_mut(&referrer.authority)?; - - (Some(referrer), Some(referrer_stats)) - } else { - (None, None) - }; + let (mut referrer, mut referrer_stats) = get_referrer( + &referrer_keys, + makers_and_referrer, + makers_and_referrer_stats, + Some(&maker), + )?; let (fill_base_asset_amount, fill_quote_asset_amount) = fulfill_perp_order_with_match( @@ -1595,6 +1602,29 @@ fn fulfill_perp_order( Ok((base_asset_amount, risk_increasing, updated_user_state)) } +fn get_referrer<'a>( + referrer_key: &'a Option<(Pubkey, Pubkey)>, + makers_and_referrer: &'a UserMap, + makers_and_referrer_stats: &'a UserStatsMap, + maker: Option<&User>, +) -> DriftResult<(Option>, Option>)> { + let (referrer_authority_key, referrer_user_key) = match referrer_key { + Some(referrer_keys) => referrer_keys, + None => return Ok((None, None)), + }; + + if let Some(maker) = maker { + if &maker.authority == referrer_authority_key { + return Ok((None, None)); + } + } + + let referrer = makers_and_referrer.get_ref_mut(referrer_user_key)?; + let referrer_stats = makers_and_referrer_stats.get_ref_mut(referrer_authority_key)?; + + return Ok((Some(referrer), Some(referrer_stats))); +} + fn determine_if_user_order_is_risk_decreasing( user: &User, market_index: u16, diff --git a/tests/referrer.ts b/tests/referrer.ts index eb9f2d896..37d3c5dbf 100644 --- a/tests/referrer.ts +++ b/tests/referrer.ts @@ -21,6 +21,7 @@ import { initializeQuoteSpotMarket, createFundedKeyPair, createUserWithUSDCAccount, + printTxLogs, } from './testHelpers'; import { BASE_PRECISION, @@ -229,7 +230,7 @@ describe('referrer', () => { const refereeStats = refereeDriftClient.getUserStats().getAccount(); assert(refereeStats.fees.totalRefereeDiscount.eq(new BN(5000))); - await refereeDriftClient.placeAndTakePerpOrder( + const txSig2 = await refereeDriftClient.placeAndTakePerpOrder( getMarketOrderParams({ baseAssetAmount: BASE_PRECISION, direction: PositionDirection.SHORT, @@ -238,6 +239,8 @@ describe('referrer', () => { undefined, refereeDriftClient.getUserStats().getReferrerInfo() ); + + await printTxLogs(connection, txSig2); }); it('withdraw', async () => { From a38c1a1e2240b6e193c6666e5b192e32fbbe5af7 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 27 Feb 2023 13:39:24 -0500 Subject: [PATCH 04/29] fix lifetime for jit maker --- programs/drift/src/instructions/user.rs | 4 +- programs/drift/src/lib.rs | 4 +- programs/drift/src/state/user_map.rs | 82 ++++++++----------------- sdk/src/idl/drift.json | 51 +++++++++++++++ 4 files changed, 79 insertions(+), 62 deletions(-) diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 249f36c47..544c62dff 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -952,8 +952,8 @@ pub fn handle_place_and_take_perp_order<'info>( #[access_control( fill_not_paused(&ctx.accounts.state) )] -pub fn handle_place_and_make_perp_order<'info>( - ctx: Context, +pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>( + ctx: Context<'a, 'b, 'c, 'info, PlaceAndMake<'info>>, params: OrderParams, taker_order_id: u32, ) -> Result<()> { diff --git a/programs/drift/src/lib.rs b/programs/drift/src/lib.rs index 3479de80f..a156535f1 100644 --- a/programs/drift/src/lib.rs +++ b/programs/drift/src/lib.rs @@ -110,8 +110,8 @@ pub mod drift { handle_place_and_take_perp_order(ctx, params, maker_order_id) } - pub fn place_and_make_perp_order( - ctx: Context, + pub fn place_and_make_perp_order<'a, 'b, 'c, 'info>( + ctx: Context<'a, 'b, 'c, 'info, PlaceAndMake<'info>>, params: OrderParams, taker_order_id: u32, ) -> Result<()> { diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 0e413745c..a5354f88c 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -14,12 +14,9 @@ use std::iter::Peekable; use std::panic::Location; use std::slice::Iter; -pub struct UserMap<'a, 'b>( - pub BTreeMap>, - pub Option<(Pubkey, AccountLoader<'b, User>, u32)>, -); +pub struct UserMap<'a>(pub BTreeMap>); -impl<'a, 'b> UserMap<'a, 'b> { +impl<'a> UserMap<'a> { // #[track_caller] // #[inline(always)] // pub fn get_ref(&self, market_index: &u16) -> DriftResult> { @@ -56,25 +53,6 @@ impl<'a, 'b> UserMap<'a, 'b> { #[track_caller] #[inline(always)] pub fn get_ref_mut(&self, user: &Pubkey) -> DriftResult> { - if let Some((jit_user, loader, _)) = &self.1 { - if jit_user == user { - return match loader.load_mut() { - Ok(user) => Ok(user), - Err(e) => { - let caller = Location::caller(); - msg!("{:?}", e); - msg!( - "Could not user {} at {}:{}", - user, - caller.file(), - caller.line() - ); - Err(ErrorCode::UnableToLoadUserAccount) - } - }; - } - } - let loader = match self.0.get(user) { Some(loader) => loader, None => { @@ -105,11 +83,11 @@ impl<'a, 'b> UserMap<'a, 'b> { } } - pub fn load<'c>( - account_info_iter: &'c mut Peekable>>, - jit_maker: Option<(Pubkey, AccountLoader<'b, User>, u32)>, - ) -> DriftResult> { - let mut user_map = UserMap(BTreeMap::new(), jit_maker); + pub fn load<'b>( + account_info_iter: &'b mut Peekable>>, + jit_maker: Option<(Pubkey, AccountLoader<'a, User>, u32)>, + ) -> DriftResult> { + let mut user_map = UserMap(BTreeMap::new()); let user_discriminator: [u8; 8] = User::discriminator(); while let Some(account_info) = account_info_iter.peek() { @@ -143,16 +121,17 @@ impl<'a, 'b> UserMap<'a, 'b> { user_map.0.insert(*user_key, user_account_loader); } + if let Some((jit_user, jit_user_loader, _)) = jit_maker { + user_map.0.insert(jit_user, jit_user_loader); + } + Ok(user_map) } } -pub struct UserStatsMap<'a, 'b>( - pub BTreeMap>, - pub Option<(Pubkey, AccountLoader<'b, UserStats>)>, -); +pub struct UserStatsMap<'a>(pub BTreeMap>); -impl<'a> UserStatsMap<'a, '_> { +impl<'a> UserStatsMap<'a> { // #[track_caller] // #[inline(always)] // pub fn get_ref(&self, market_index: &u16) -> DriftResult> { @@ -189,25 +168,6 @@ impl<'a> UserStatsMap<'a, '_> { #[track_caller] #[inline(always)] pub fn get_ref_mut(&self, authority: &Pubkey) -> DriftResult> { - if let Some((jit_authority, loader)) = &self.1 { - if jit_authority == authority { - return match loader.load_mut() { - Ok(perp_market) => Ok(perp_market), - Err(e) => { - let caller = Location::caller(); - msg!("{:?}", e); - msg!( - "Could not user stats {} at {}:{}", - authority, - caller.file(), - caller.line() - ); - Err(ErrorCode::UnableToLoadUserStatsAccount) - } - }; - } - } - let loader = match self.0.get(authority) { Some(loader) => loader, None => { @@ -238,11 +198,11 @@ impl<'a> UserStatsMap<'a, '_> { } } - pub fn load<'b, 'c>( - account_info_iter: &'c mut Peekable>>, - jit_maker_stats: Option<(Pubkey, AccountLoader<'b, UserStats>)>, - ) -> DriftResult> { - let mut user_stats_map = UserStatsMap(BTreeMap::new(), jit_maker_stats); + pub fn load<'b>( + account_info_iter: &'b mut Peekable>>, + jit_maker_stats: Option<(Pubkey, AccountLoader<'a, UserStats>)>, + ) -> DriftResult> { + let mut user_stats_map = UserStatsMap(BTreeMap::new()); let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); while let Some(account_info) = account_info_iter.peek() { @@ -281,6 +241,12 @@ impl<'a> UserStatsMap<'a, '_> { .insert(authority, user_stats_account_loader); } + if let Some((jit_user_stats, jit_user_stats_loader)) = jit_maker_stats { + user_stats_map + .0 + .insert(jit_user_stats, jit_user_stats_loader); + } + Ok(user_stats_map) } } diff --git a/sdk/src/idl/drift.json b/sdk/src/idl/drift.json index 2dba2cb09..3237735a2 100644 --- a/sdk/src/idl/drift.json +++ b/sdk/src/idl/drift.json @@ -6207,6 +6207,7 @@ { "name": "Match", "fields": [ + "publicKey", { "defined": "usize" } @@ -8601,6 +8602,56 @@ "code": 6227, "name": "TierViolationLiquidatingPerpPnl", "msg": "TierViolationLiquidatingPerpPnl" + }, + { + "code": 6228, + "name": "CouldNotLoadUserData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6229, + "name": "UserWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6230, + "name": "InvalidUserAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6231, + "name": "CouldNotLoadUserStatsData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6232, + "name": "UserStatsWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6233, + "name": "InvalidUserStatsAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6234, + "name": "UserNotFound", + "msg": "UserNotFound" + }, + { + "code": 6235, + "name": "UnableToLoadUserAccount", + "msg": "UnableToLoadUserAccount" + }, + { + "code": 6236, + "name": "UserStatsNotFound", + "msg": "UserStatsNotFound" + }, + { + "code": 6237, + "name": "UnableToLoadUserStatsAccount", + "msg": "UnableToLoadUserStatsAccount" } ] } \ No newline at end of file From 5073166d7ed70e37741b7710774fe9f89023340c Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 27 Feb 2023 16:55:52 -0500 Subject: [PATCH 05/29] tests working --- programs/drift/src/controller/orders.rs | 221 +---------- .../src/controller/orders/amm_jit_tests.rs | 346 ++++++++++++------ programs/drift/src/controller/orders/tests.rs | 317 ++++++++++------ programs/drift/src/math/fulfillment/tests.rs | 103 +++--- programs/drift/src/state/user_map.rs | 87 +++++ 5 files changed, 602 insertions(+), 472 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 4914f15a1..1d744de4f 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -795,7 +795,7 @@ pub fn fill_perp_order( (None, None) }; - let maker_order_info = sanitize_maker_order2( + let maker_order_info = sanitize_maker_order( perp_market_map, spot_market_map, oracle_map, @@ -806,7 +806,6 @@ pub fn fill_perp_order( &filler_key, state.perp_fee_structure.flat_filler_fee, oracle_price, - reserve_price_before, now, slot, )?; @@ -1039,173 +1038,6 @@ pub fn validate_market_within_price_band( #[allow(clippy::type_complexity)] fn sanitize_maker_order<'a>( - perp_market_map: &PerpMarketMap, - spot_market_map: &SpotMarketMap, - oracle_map: &mut OracleMap, - maker: Option<&'a AccountLoader>, - maker_stats: Option<&'a AccountLoader>, - taker_key: &Pubkey, - taker_authority: &Pubkey, - taker_order: &Order, - filler: &mut Option<&mut User>, - filler_key: &Pubkey, - filler_reward: u64, - oracle_price: i64, - now: i64, - slot: u64, -) -> DriftResult<( - Option>, - Option>, - Option, - Option>, -)> { - if maker.is_none() || maker_stats.is_none() { - return Ok((None, None, None, None)); - } - - let maker = maker.safe_unwrap()?; - if &maker.key() == taker_key { - return Ok((None, None, None, None)); - } - let maker_key = maker.key(); - let mut maker = load_mut!(maker)?; - - let maker_stats = if &maker.authority == taker_authority { - None - } else { - let maker_stats = load_mut!(maker_stats.safe_unwrap()?)?; - - validate!( - maker.authority.eq(&maker_stats.authority), - ErrorCode::InvalidMaker, - "maker authority != maker stats authority" - )?; - - Some(maker_stats) - }; - - if maker.is_being_liquidated() || maker.is_bankrupt() { - return Ok((None, None, None, None)); - } - - let market = perp_market_map.get_ref(&taker_order.market_index)?; - - let maker_direction = taker_order.direction.opposite(); - let mut maker_order_price_and_indexes = find_maker_orders( - &maker, - &maker_direction, - &MarketType::Perp, - taker_order.market_index, - Some(oracle_price), - slot, - market.amm.order_tick_size, - )?; - - drop(market); - - sort_maker_orders(&mut maker_order_price_and_indexes, taker_order.direction); - - let mut filtered_maker_order_price_and_indexes = vec![]; - for (maker_order_index, maker_order_price) in maker_order_price_and_indexes.iter() { - let maker_order_index = *maker_order_index; - let maker_order_price = *maker_order_price; - - let maker_order = &maker.orders[maker_order_index]; - if !is_maker_for_taker(maker_order, taker_order, slot)? { - continue; - } - - if !are_orders_same_market_but_different_sides(maker_order, taker_order) { - continue; - } - - let market = perp_market_map.get_ref(&taker_order.market_index)?; - - let breaches_oracle_price_limits = { - limit_price_breaches_oracle_price_bands( - maker_order_price, - maker_order.direction, - oracle_price, - market.margin_ratio_initial, - market.margin_ratio_maintenance, - )? - }; - - drop(market); - - let should_expire_order = should_expire_order(&maker, maker_order_index, now)?; - - let existing_base_asset_amount = maker - .get_perp_position(maker.orders[maker_order_index].market_index)? - .base_asset_amount; - let should_cancel_reduce_only_order = should_cancel_reduce_only_order( - &maker.orders[maker_order_index], - existing_base_asset_amount, - )?; - - if breaches_oracle_price_limits || should_expire_order || should_cancel_reduce_only_order { - let filler_reward = { - let mut market = - perp_market_map.get_ref_mut(&maker.orders[maker_order_index].market_index)?; - pay_keeper_flat_reward_for_perps( - &mut maker, - filler.as_deref_mut(), - market.deref_mut(), - filler_reward, - )? - }; - - let explanation = if breaches_oracle_price_limits { - OrderActionExplanation::OraclePriceBreachedLimitPrice - } else if should_expire_order { - OrderActionExplanation::OrderExpired - } else { - OrderActionExplanation::ReduceOnlyOrderIncreasedPosition - }; - - cancel_order( - maker_order_index, - maker.deref_mut(), - &maker_key, - perp_market_map, - spot_market_map, - oracle_map, - now, - slot, - explanation, - Some(filler_key), - filler_reward, - false, - )?; - - continue; - } - - filtered_maker_order_price_and_indexes.push((maker_order_index, maker_order_price)); - } - - if filtered_maker_order_price_and_indexes.is_empty() { - return Ok((None, None, None, None)); - } - - let market_index = taker_order.market_index; - settle_funding_payment( - &mut maker, - &maker_key, - perp_market_map.get_ref_mut(&market_index)?.deref_mut(), - now, - )?; - - Ok(( - Some(maker), - maker_stats, - Some(maker_key), - Some(filtered_maker_order_price_and_indexes), - )) -} - -#[allow(clippy::type_complexity)] -fn sanitize_maker_order2<'a>( perp_market_map: &PerpMarketMap, spot_market_map: &SpotMarketMap, oracle_map: &mut OracleMap, @@ -1216,14 +1048,9 @@ fn sanitize_maker_order2<'a>( filler_key: &Pubkey, filler_reward: u64, oracle_price: i64, - reserve_price: u64, now: i64, slot: u64, ) -> DriftResult> { - let market = perp_market_map.get_ref(&taker_order.market_index)?; - - let (amm_bid_price, amm_ask_price) = market.amm.bid_ask_price(reserve_price)?; - let maker_direction = taker_order.direction.opposite(); let mut maker_order_info = Vec::with_capacity(32); @@ -1238,6 +1065,7 @@ fn sanitize_maker_order2<'a>( continue; } + let mut market = perp_market_map.get_ref_mut(&taker_order.market_index)?; let maker_order_price_and_indexes = find_maker_orders( &maker, &maker_direction, @@ -1248,6 +1076,17 @@ fn sanitize_maker_order2<'a>( market.amm.order_tick_size, )?; + if maker_order_price_and_indexes.is_empty() { + continue; + } + + settle_funding_payment(&mut maker, &maker_key, &mut market, now)?; + + let initial_margin_ratio = market.margin_ratio_initial; + let maintenance_margin_ratio = market.margin_ratio_maintenance; + + drop(market); + for (maker_order_index, maker_order_price) in maker_order_price_and_indexes.iter() { let maker_order_index = *maker_order_index; let maker_order_price = *maker_order_price; @@ -1257,23 +1096,6 @@ fn sanitize_maker_order2<'a>( continue; } - if !maker_order.is_resting_limit_order(slot)? { - match maker_direction { - PositionDirection::Long => { - if maker_order_price >= amm_ask_price { - msg!("maker order {} crosses the amm price", maker_order.order_id); - continue; - } - } - PositionDirection::Short => { - if maker_order_price <= amm_bid_price { - msg!("maker order {} crosses the amm price", maker_order.order_id); - continue; - } - } - } - } - if !are_orders_same_market_but_different_sides(maker_order, taker_order) { continue; } @@ -1283,8 +1105,8 @@ fn sanitize_maker_order2<'a>( maker_order_price, maker_order.direction, oracle_price, - market.margin_ratio_initial, - market.margin_ratio_maintenance, + initial_margin_ratio, + maintenance_margin_ratio, )? }; @@ -1343,24 +1165,13 @@ fn sanitize_maker_order2<'a>( } } - sort_maker_orders2(&mut maker_order_info, taker_order.direction); + sort_maker_orders(&mut maker_order_info, taker_order.direction); Ok(maker_order_info) } #[inline(always)] fn sort_maker_orders( - maker_order_price_and_indexes: &mut [(usize, u64)], - taker_order_direction: PositionDirection, -) { - maker_order_price_and_indexes.sort_by(|a, b| match taker_order_direction { - PositionDirection::Long => a.1.cmp(&b.1), - PositionDirection::Short => b.1.cmp(&a.1), - }); -} - -#[inline(always)] -fn sort_maker_orders2( maker_order_info: &mut [(Pubkey, usize, u64)], taker_order_direction: PositionDirection, ) { diff --git a/programs/drift/src/controller/orders/amm_jit_tests.rs b/programs/drift/src/controller/orders/amm_jit_tests.rs index c27736fac..e4c9b4ccd 100644 --- a/programs/drift/src/controller/orders/amm_jit_tests.rs +++ b/programs/drift/src/controller/orders/amm_jit_tests.rs @@ -47,6 +47,7 @@ pub mod amm_jit { use crate::state::spot_market::{SpotBalanceType, SpotMarket}; use crate::state::spot_market_map::SpotMarketMap; use crate::state::user::{OrderStatus, OrderType, SpotPosition, User, UserStats}; + use crate::state::user_map::{UserMap, UserStatsMap}; use crate::test_utils::*; use crate::test_utils::{get_orders, get_positions, get_pyth_price, get_spot_positions}; @@ -237,7 +238,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -261,15 +266,25 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); fulfill_perp_order( @@ -277,15 +292,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -407,7 +420,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -431,15 +448,25 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -453,15 +480,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 99 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 99 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -476,6 +501,7 @@ pub mod amm_jit { .unwrap(); // maker got full size + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!( maker_position.base_asset_amount, @@ -590,7 +616,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -614,15 +644,25 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -636,15 +676,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 99 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 99 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -665,6 +703,7 @@ pub mod amm_jit { // make sure lps didnt get anything assert_eq!(market_after.amm.base_asset_amount_per_lp, 0); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); let maker_position = &maker.perp_positions[0]; // maker got (full - net_baa) assert_eq!( @@ -773,7 +812,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -797,15 +840,24 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -819,15 +871,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -845,6 +895,7 @@ pub mod amm_jit { // nets to zero assert_eq!(market_after.amm.base_asset_amount_with_amm, 0); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); let maker_position = &maker.perp_positions[0]; // maker got (full - net_baa) assert_eq!( @@ -970,7 +1021,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -994,15 +1049,24 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); let (base_asset_amount, _, _) = fulfill_perp_order( @@ -1010,15 +1074,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -1038,6 +1100,7 @@ pub mod amm_jit { assert_eq!(taker_position.base_asset_amount, -BASE_PRECISION_I64); assert_eq!(taker.orders[0], Order::default()); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!(maker_position.base_asset_amount, BASE_PRECISION_I64 / 2); assert_eq!(maker_position.quote_asset_amount, -49985000); @@ -1163,7 +1226,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -1188,14 +1255,24 @@ pub mod amm_jit { ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1209,15 +1286,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -1359,7 +1434,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -1383,22 +1462,25 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); - let mut filler_stats = UserStats::default(); - assert_eq!(market.amm.total_fee, 0); - assert_eq!(market.amm.total_fee_minus_distributions, 0); - assert_eq!(market.amm.net_revenue_since_last_funding, 0); - assert_eq!(market.amm.total_mm_fee, 0); - assert_eq!(market.amm.total_fee_withdrawn, 0); + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); let reserve_price_before = market.amm.reserve_price().unwrap(); assert_eq!(reserve_price_before, 100 * PRICE_PRECISION_U64); @@ -1408,15 +1490,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -1536,7 +1616,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -1560,15 +1644,24 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1583,15 +1676,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 10 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 10 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -1607,6 +1698,7 @@ pub mod amm_jit { assert_eq!(base_asset_amount, BASE_PRECISION_U64 / 2); // auctions not over so no amm fill + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!(maker_position.base_asset_amount, -BASE_PRECISION_I64 / 2); @@ -1722,7 +1814,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -1746,15 +1842,24 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1769,15 +1874,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 200 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 200 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -1928,11 +2031,23 @@ pub mod amm_jit { println!("start stop {} {}", auction_start_price, auction_end_price); let mut filler = User::default(); + let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + + let (taker_key, _, filler_key) = get_user_keys(); + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1976,6 +2091,7 @@ pub mod amm_jit { println!("mark: {} bid ask: {} {}", mark, bid, ask); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -1999,6 +2115,8 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); // fulfill with match fulfill_perp_order( @@ -2006,15 +2124,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, auction_price)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, auction_price)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -2198,10 +2314,21 @@ pub mod amm_jit { let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + + let (taker_key, _, filler_key) = get_user_keys(); + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -2247,6 +2374,7 @@ pub mod amm_jit { println!("mark: {} bid ask: {} {}", mark, bid, ask); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -2270,6 +2398,8 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); // fulfill with match fulfill_perp_order( @@ -2277,15 +2407,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, auction_price)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, auction_price)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -2442,7 +2570,11 @@ pub mod amm_jit { ..User::default() }; + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -2466,15 +2598,27 @@ pub mod amm_jit { }), ..User::default() }; + create_anchor_account_info!(maker, &maker_key, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -2490,15 +2634,13 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 10 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 10 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 31851a3e1..396318dc1 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -2446,6 +2446,7 @@ pub mod fulfill_order { OracleGuardRails, PriceDivergenceGuardRails, State, ValidityGuardRails, }; use crate::state::user::{OrderStatus, OrderType, SpotPosition, User, UserStats}; + use crate::state::user_map::{UserMap, UserStatsMap}; use crate::test_utils::*; use crate::test_utils::{get_orders, get_positions, get_pyth_price, get_spot_positions}; @@ -2650,7 +2651,11 @@ pub mod fulfill_order { ..User::default() }; + let maker_key = Pubkey::default(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -2674,15 +2679,24 @@ pub mod fulfill_order { }), ..User::default() }; + create_anchor_account_info!(maker, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); let (base_asset_amount, _, _) = fulfill_perp_order( @@ -2690,15 +2704,17 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![( + Pubkey::default(), + 0, + 100_010_000 * PRICE_PRECISION_U64 / 1_000_000, + )], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -2727,6 +2743,10 @@ pub mod fulfill_order { assert_eq!(taker_stats.taker_volume_30d, 100256237); assert_eq!(taker.orders[0], Order::default()); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); + let maker_stats = maker_and_referrer_stats + .get_ref_mut(&maker_authority) + .unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!(maker_position.base_asset_amount, -BASE_PRECISION_I64 / 2); assert_eq!(maker_position.quote_break_even_amount, 50_020_001); @@ -2862,7 +2882,11 @@ pub mod fulfill_order { ..User::default() }; + let maker_key = Pubkey::default(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders!( Order { market_index: 0, @@ -2897,15 +2921,25 @@ pub mod fulfill_order { }), ..User::default() }; + create_anchor_account_info!(maker, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); let (base_asset_amount, _, _) = fulfill_perp_order( @@ -2913,18 +2947,16 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![ - (0, 90 * PRICE_PRECISION_U64), - (1, 95 * PRICE_PRECISION_U64), - ]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![ + (maker_key, 0, 90 * PRICE_PRECISION_U64), + (maker_key, 1, 95 * PRICE_PRECISION_U64), + ], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -2948,6 +2980,7 @@ pub mod fulfill_order { assert_eq!(taker_position.open_bids, 0); assert_eq!(taker_position.open_orders, 0); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!(maker_position.base_asset_amount, -BASE_PRECISION_I64); assert_eq!(maker_position.quote_break_even_amount, 92527750); @@ -3051,7 +3084,11 @@ pub mod fulfill_order { ..User::default() }; + let maker_key = Pubkey::default(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -3075,15 +3112,25 @@ pub mod fulfill_order { }), ..User::default() }; + create_anchor_account_info!(maker, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let mut filler_stats = UserStats::default(); let (base_asset_amount, _, _) = fulfill_perp_order( @@ -3091,15 +3138,13 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -3128,6 +3173,10 @@ pub mod fulfill_order { assert_eq!(taker_stats.taker_volume_30d, 100281362); assert_eq!(taker.orders[0], Order::default()); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); + let maker_stats = maker_and_referrer_stats + .get_ref_mut(&maker_authority) + .unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!(maker_position.base_asset_amount, -BASE_PRECISION_I64 / 2); assert_eq!(maker_position.quote_break_even_amount, 50_020_001); @@ -3241,7 +3290,11 @@ pub mod fulfill_order { ..User::default() }; + let maker_key = Pubkey::default(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, post_only: true, @@ -3265,31 +3318,37 @@ pub mod fulfill_order { }), ..User::default() }; + create_anchor_account_info!(maker, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let now = 0_i64; let slot = 0_u64; let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let (base_asset_amount, _, _) = fulfill_perp_order( &mut taker, 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(0, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut None, &filler_key, &mut None, - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -3317,6 +3376,10 @@ pub mod fulfill_order { assert_eq!(taker_stats.fees.total_token_discount, 0); assert_eq!(taker_stats.taker_volume_30d, 50 * QUOTE_PRECISION_U64); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); + let maker_stats = maker_and_referrer_stats + .get_ref_mut(&maker_authority) + .unwrap(); let maker_position = &maker.perp_positions[0]; assert_eq!(maker_position.base_asset_amount, -BASE_PRECISION_I64 / 2); assert_eq!(maker_position.quote_asset_amount, 50015000); @@ -3442,15 +3505,13 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut None, - &mut None, - None, - None, + &mut UserMap::empty(), + &mut UserStatsMap::empty(), + vec![], &mut None, &filler_key, &mut None, - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -3769,6 +3830,9 @@ pub mod fulfill_order { }; // Maker has sol order and position at index 1, btc at index 1 + let maker_key = Pubkey::default(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker_orders = [Order::default(); 32]; maker_orders[0] = Order { market_index: 1, @@ -3804,6 +3868,7 @@ pub mod fulfill_order { }; let mut maker = User { + authority: maker_authority, orders: maker_orders, perp_positions: maker_positions, spot_positions: get_spot_positions(SpotPosition { @@ -3814,6 +3879,8 @@ pub mod fulfill_order { }), ..User::default() }; + create_anchor_account_info!(maker, User, maker_account_info); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); // random let now = 1; //80080880_i64; @@ -3821,10 +3888,16 @@ pub mod fulfill_order { let fee_structure = get_fee_structure(); - let (taker_key, maker_key, filler_key) = get_user_keys(); + let (taker_key, _, filler_key) = get_user_keys(); let mut taker_stats = UserStats::default(); - let mut maker_stats = UserStats::default(); + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let taker_before = taker; let maker_before = maker; @@ -3833,15 +3906,13 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut Some(&mut maker), - &mut Some(&mut maker_stats), - Some(vec![(1, 100 * PRICE_PRECISION_U64)]), - Some(&maker_key), + &mut makers_and_referrers, + &mut maker_and_referrer_stats, + vec![(maker_key, 1, 100 * PRICE_PRECISION_U64)], &mut None, &filler_key, &mut None, - &mut None, - &mut None, + None, &spot_market_map, &market_map, &mut oracle_map, @@ -3877,6 +3948,10 @@ pub mod fulfill_order { assert_eq!(taker.perp_positions[1], taker_before.perp_positions[1]); assert_eq!(taker.orders[1], taker_before.orders[1]); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); + let maker_stats = maker_and_referrer_stats + .get_ref_mut(&maker_authority) + .unwrap(); let maker_position = &maker.perp_positions[1]; assert_eq!(maker_position.base_asset_amount, -BASE_PRECISION_I64 / 2); assert_eq!(maker_position.quote_asset_amount, 50015000); @@ -3960,6 +4035,7 @@ pub mod fill_order { use super::*; use crate::error::ErrorCode; + use crate::state::user_map::{UserMap, UserStatsMap}; #[test] fn maker_order_canceled_for_breaching_oracle_price_band() { @@ -4084,7 +4160,11 @@ pub mod fill_order { let user_stats_account_loader: AccountLoader = AccountLoader::try_from(&user_stats_account_info).unwrap(); + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, order_id: 1, @@ -4111,14 +4191,16 @@ pub mod fill_order { }), ..User::default() }; - let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let maker_account_loader: AccountLoader = - AccountLoader::try_from(&maker_account_info).unwrap(); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); - create_anchor_account_info!(UserStats::default(), UserStats, maker_stats_account_info); - let maker_stats_account_loader: AccountLoader = - AccountLoader::try_from(&maker_stats_account_info).unwrap(); + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); create_anchor_account_info!(User::default(), &filler_key, User, user_account_info); @@ -4145,11 +4227,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - Some(&maker_account_loader), - Some(&maker_stats_account_loader), - Some(1), - None, - None, + &mut makers_and_referrers, + &mut maker_and_referrer_stats, &clock, ) .unwrap(); @@ -4157,7 +4236,7 @@ pub mod fill_order { assert_eq!(base_asset_amount, 0); // order canceled - let maker = maker_account_loader.load().unwrap(); + let maker = makers_and_referrers.get_ref_mut(&maker_key).unwrap(); assert_eq!(maker.orders[0], Order::default()); } @@ -4285,8 +4364,12 @@ pub mod fill_order { let user_stats_account_loader: AccountLoader = AccountLoader::try_from(&user_stats_account_info).unwrap(); + let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + let maker_authority = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); let maker_order_id = 1; let mut maker = User { + authority: maker_authority, orders: get_orders(Order { market_index: 0, order_id: maker_order_id, @@ -4314,14 +4397,16 @@ pub mod fill_order { }), ..User::default() }; - let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let maker_account_loader: AccountLoader = - AccountLoader::try_from(&maker_account_info).unwrap(); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); - create_anchor_account_info!(UserStats::default(), UserStats, maker_stats_account_info); - let maker_stats_account_loader: AccountLoader = - AccountLoader::try_from(&maker_stats_account_info).unwrap(); + let mut maker_stats = UserStats { + authority: maker_authority, + ..UserStats::default() + }; + create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); + let mut maker_and_referrer_stats = + UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); create_anchor_account_info!(User::default(), &filler_key, User, user_account_info); @@ -4348,11 +4433,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - Some(&maker_account_loader), - Some(&maker_stats_account_loader), - Some(maker_order_id + 1), - None, - None, + &mut makers_and_referrers, + &mut maker_and_referrer_stats, &clock, ) .unwrap(); @@ -4477,11 +4559,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - None, - None, - None, - None, - None, + &mut UserMap::empty(), + &mut UserStatsMap::empty(), &clock, ) .unwrap(); @@ -4645,11 +4724,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - None, - None, - None, - None, - None, + &mut UserMap::empty(), + &mut UserStatsMap::empty(), &clock, ); @@ -8053,25 +8129,48 @@ pub mod force_cancel_orders { pub mod sort_maker_orders { use crate::controller::orders::sort_maker_orders; use crate::controller::position::PositionDirection; + use solana_program::pubkey::Pubkey; #[test] fn bids() { - let mut bids = vec![(0, 1), (1, 10), (2, 100)]; + let mut bids = vec![ + (Pubkey::default(), 0, 1), + (Pubkey::default(), 1, 10), + (Pubkey::default(), 2, 100), + ]; let taker_direction = PositionDirection::Short; sort_maker_orders(&mut bids, taker_direction); - assert_eq!(bids, vec![(2, 100), (1, 10), (0, 1),]); + assert_eq!( + bids, + vec![ + (Pubkey::default(), 2, 100), + (Pubkey::default(), 1, 10), + (Pubkey::default(), 0, 1), + ] + ); } #[test] fn asks() { - let mut asks = vec![(2, 100), (1, 10), (0, 1)]; + let mut asks = vec![ + (Pubkey::default(), 2, 100), + (Pubkey::default(), 1, 10), + (Pubkey::default(), 0, 1), + ]; let taker_direction = PositionDirection::Long; sort_maker_orders(&mut asks, taker_direction); - assert_eq!(asks, vec![(0, 1), (1, 10), (2, 100)]); + assert_eq!( + asks, + vec![ + (Pubkey::default(), 0, 1), + (Pubkey::default(), 1, 10), + (Pubkey::default(), 2, 100) + ] + ); } } @@ -8096,6 +8195,7 @@ pub mod sanitize_maker_orders { use crate::state::spot_market::{SpotBalanceType, SpotMarket}; use crate::state::spot_market_map::SpotMarketMap; use crate::state::user::{OrderStatus, OrderType, SpotPosition, User, UserStats}; + use crate::state::user_map::UserMap; use crate::test_utils::*; use crate::test_utils::{ create_account_info, get_orders, get_positions, get_pyth_price, get_spot_positions, @@ -8267,24 +8367,19 @@ pub mod sanitize_maker_orders { }; let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let maker_account_loader: AccountLoader = - AccountLoader::try_from(&maker_account_info).unwrap(); - create_anchor_account_info!(UserStats::default(), UserStats, maker_stats_account_info); - let maker_stats_account_loader: AccountLoader = - AccountLoader::try_from(&maker_stats_account_info).unwrap(); + let mut makers_and_referrers = + UserMap::load(&mut vec![maker_account_info].iter().peekable(), None).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let (_, _, _, maker_order_price_and_indexes) = sanitize_maker_order( + let maker_order_price_and_indexes = sanitize_maker_order( &market_map, &spot_market_map, &mut oracle_map, - Some(&maker_account_loader), - Some(&maker_stats_account_loader), + &mut makers_and_referrers, &taker_key, - &taker_authority, &user.orders[0], &mut Some(&mut filler), &filler_key, @@ -8297,7 +8392,7 @@ pub mod sanitize_maker_orders { assert_eq!( maker_order_price_and_indexes, - Some(vec![(1, 100 * PRICE_PRECISION_U64)]) + vec![(maker_key, 1, 100 * PRICE_PRECISION_U64)] ); } @@ -8466,24 +8561,19 @@ pub mod sanitize_maker_orders { }; let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let maker_account_loader: AccountLoader = - AccountLoader::try_from(&maker_account_info).unwrap(); - create_anchor_account_info!(UserStats::default(), UserStats, maker_stats_account_info); - let maker_stats_account_loader: AccountLoader = - AccountLoader::try_from(&maker_stats_account_info).unwrap(); + let mut makers_and_referrers = + UserMap::load(&mut vec![maker_account_info].iter().peekable(), None).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let (_, _, _, maker_order_price_and_indexes) = sanitize_maker_order( + let maker_order_price_and_indexes = sanitize_maker_order( &market_map, &spot_market_map, &mut oracle_map, - Some(&maker_account_loader), - Some(&maker_stats_account_loader), + &mut makers_and_referrers, &taker_key, - &taker_authority, &user.orders[0], &mut Some(&mut filler), &filler_key, @@ -8496,7 +8586,7 @@ pub mod sanitize_maker_orders { assert_eq!( maker_order_price_and_indexes, - Some(vec![(1, 100 * PRICE_PRECISION_U64)]) + vec![(maker_key, 1, 100 * PRICE_PRECISION_U64)] ); } @@ -8654,24 +8744,19 @@ pub mod sanitize_maker_orders { }; let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let maker_account_loader: AccountLoader = - AccountLoader::try_from(&maker_account_info).unwrap(); - create_anchor_account_info!(UserStats::default(), UserStats, maker_stats_account_info); - let maker_stats_account_loader: AccountLoader = - AccountLoader::try_from(&maker_stats_account_info).unwrap(); + let mut makers_and_referrers = + UserMap::load(&mut vec![maker_account_info].iter().peekable(), None).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let (_, _, _, maker_order_price_and_indexes) = sanitize_maker_order( + let maker_order_price_and_indexes = sanitize_maker_order( &market_map, &spot_market_map, &mut oracle_map, - Some(&maker_account_loader), - Some(&maker_stats_account_loader), + &mut makers_and_referrers, &taker_key, - &taker_authority, &user.orders[0], &mut Some(&mut filler), &filler_key, @@ -8682,6 +8767,6 @@ pub mod sanitize_maker_orders { ) .unwrap(); - assert_eq!(maker_order_price_and_indexes, None,); + assert_eq!(maker_order_price_and_indexes, vec![],); } } diff --git a/programs/drift/src/math/fulfillment/tests.rs b/programs/drift/src/math/fulfillment/tests.rs index de0023ff0..ac000847f 100644 --- a/programs/drift/src/math/fulfillment/tests.rs +++ b/programs/drift/src/math/fulfillment/tests.rs @@ -9,6 +9,7 @@ mod determine_perp_fulfillment_methods { use crate::state::oracle::HistoricalOracleData; use crate::state::perp_market::{MarketStatus, PerpMarket, AMM}; use crate::state::user::Order; + use solana_program::pubkey::Pubkey; #[test] fn amm_available_and_taker_doesnt_cross_maker() { @@ -54,7 +55,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![(0, 103 * PRICE_PRECISION_U64)]), + &vec![(Pubkey::default(), 0, 103 * PRICE_PRECISION_U64)], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -111,7 +112,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![(0, 99 * PRICE_PRECISION_U64)]), + &vec![(Pubkey::default(), 0, 99 * PRICE_PRECISION_U64)], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -124,7 +125,7 @@ mod determine_perp_fulfillment_methods { assert_eq!( fulfillment_methods, [ - PerpFulfillmentMethod::Match(0), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), PerpFulfillmentMethod::AMM(None) ] ); @@ -180,7 +181,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![(0, 101 * PRICE_PRECISION_U64)]), + &vec![(Pubkey::default(), 0, 101 * PRICE_PRECISION_U64)], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -194,7 +195,7 @@ mod determine_perp_fulfillment_methods { fulfillment_methods, [ PerpFulfillmentMethod::AMM(Some(maker_order.price)), - PerpFulfillmentMethod::Match(0), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), PerpFulfillmentMethod::AMM(None) ] ); @@ -244,10 +245,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 99 * PRICE_PRECISION_U64), - (1, 101 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 101 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -260,9 +261,9 @@ mod determine_perp_fulfillment_methods { assert_eq!( fulfillment_methods, [ - PerpFulfillmentMethod::Match(0), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), PerpFulfillmentMethod::AMM(Some(101 * PRICE_PRECISION_U64)), - PerpFulfillmentMethod::Match(1), + PerpFulfillmentMethod::Match(Pubkey::default(), 1), PerpFulfillmentMethod::AMM(None), ] ); @@ -312,10 +313,14 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 99 * PRICE_PRECISION_U64), - (1, 99 * PRICE_PRECISION_U64 + PRICE_PRECISION_U64 / 2), - ]), + &vec![ + (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), + ( + Pubkey::default(), + 1, + 99 * PRICE_PRECISION_U64 + PRICE_PRECISION_U64 / 2, + ), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -328,8 +333,8 @@ mod determine_perp_fulfillment_methods { assert_eq!( fulfillment_methods, [ - PerpFulfillmentMethod::Match(0), - PerpFulfillmentMethod::Match(1), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), + PerpFulfillmentMethod::Match(Pubkey::default(), 1), PerpFulfillmentMethod::AMM(None), ] ); @@ -379,10 +384,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 102 * PRICE_PRECISION_U64), - (1, 103 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 102 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 103 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -396,9 +401,9 @@ mod determine_perp_fulfillment_methods { fulfillment_methods, [ PerpFulfillmentMethod::AMM(Some(102 * PRICE_PRECISION_U64)), - PerpFulfillmentMethod::Match(0), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), PerpFulfillmentMethod::AMM(Some(103 * PRICE_PRECISION_U64)), - PerpFulfillmentMethod::Match(1), + PerpFulfillmentMethod::Match(Pubkey::default(), 1), PerpFulfillmentMethod::AMM(None), ] ); @@ -448,10 +453,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 101 * PRICE_PRECISION_U64), - (1, 99 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 101 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 99 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -464,9 +469,9 @@ mod determine_perp_fulfillment_methods { assert_eq!( fulfillment_methods, [ - PerpFulfillmentMethod::Match(0), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), PerpFulfillmentMethod::AMM(Some(99 * PRICE_PRECISION_U64)), - PerpFulfillmentMethod::Match(1), + PerpFulfillmentMethod::Match(Pubkey::default(), 1), PerpFulfillmentMethod::AMM(None), ] ); @@ -516,10 +521,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 102 * PRICE_PRECISION_U64), - (1, 101 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 102 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 101 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -532,8 +537,8 @@ mod determine_perp_fulfillment_methods { assert_eq!( fulfillment_methods, [ - PerpFulfillmentMethod::Match(0), - PerpFulfillmentMethod::Match(1), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), + PerpFulfillmentMethod::Match(Pubkey::default(), 1), PerpFulfillmentMethod::AMM(None), ] ); @@ -583,10 +588,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 99 * PRICE_PRECISION_U64), - (1, 98 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 98 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -600,9 +605,9 @@ mod determine_perp_fulfillment_methods { fulfillment_methods, [ PerpFulfillmentMethod::AMM(Some(99 * PRICE_PRECISION_U64)), - PerpFulfillmentMethod::Match(0), + PerpFulfillmentMethod::Match(Pubkey::default(), 0), PerpFulfillmentMethod::AMM(Some(98 * PRICE_PRECISION_U64)), - PerpFulfillmentMethod::Match(1), + PerpFulfillmentMethod::Match(Pubkey::default(), 1), PerpFulfillmentMethod::AMM(None), ] ); @@ -652,10 +657,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 101 * PRICE_PRECISION_U64), - (1, 102 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 101 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 102 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -712,10 +717,10 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &Some(&vec![ - (0, 99 * PRICE_PRECISION_U64), - (1, 98 * PRICE_PRECISION_U64), - ]), + &vec![ + (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), + (Pubkey::default(), 1, 98 * PRICE_PRECISION_U64), + ], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index a5354f88c..0135bb713 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -129,6 +129,47 @@ impl<'a> UserMap<'a> { } } +#[cfg(test)] +impl<'a> UserMap<'a> { + pub fn load_one<'b>(account_info: &'b AccountInfo<'a>) -> DriftResult> { + let mut user_map = UserMap(BTreeMap::new()); + + let user_discriminator: [u8; 8] = User::discriminator(); + + let user_key = account_info.key; + + let data = account_info + .try_borrow_data() + .or(Err(ErrorCode::CouldNotLoadUserData))?; + + let expected_data_len = User::SIZE; + if data.len() < expected_data_len { + return Err(ErrorCode::CouldNotLoadUserData); + } + + let account_discriminator = array_ref![data, 0, 8]; + if account_discriminator != &user_discriminator { + return Err(ErrorCode::CouldNotLoadUserData); + } + + let is_writable = account_info.is_writable; + if !is_writable { + return Err(ErrorCode::UserWrongMutability); + } + + let user_account_loader: AccountLoader = + AccountLoader::try_from(account_info).or(Err(ErrorCode::InvalidUserAccount))?; + + user_map.0.insert(*user_key, user_account_loader); + + Ok(user_map) + } + + pub fn empty() -> UserMap<'a> { + UserMap(BTreeMap::new()) + } +} + pub struct UserStatsMap<'a>(pub BTreeMap>); impl<'a> UserStatsMap<'a> { @@ -250,3 +291,49 @@ impl<'a> UserStatsMap<'a> { Ok(user_stats_map) } } + +#[cfg(test)] +impl<'a> UserStatsMap<'a> { + pub fn load_one<'b>(account_info: &'b AccountInfo<'a>) -> DriftResult> { + let mut user_stats_map = UserStatsMap(BTreeMap::new()); + + let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); + + let user_stats_key = account_info.key; + + let data = account_info + .try_borrow_data() + .or(Err(ErrorCode::CouldNotLoadUserStatsData))?; + + let expected_data_len = UserStats::SIZE; + if data.len() < expected_data_len { + return Err(ErrorCode::DefaultError); + } + + let account_discriminator = array_ref![data, 0, 8]; + if account_discriminator != &user_stats_discriminator { + return Err(ErrorCode::DefaultError); + } + + let authority_slice = array_ref![data, 8, 32]; + let authority = Pubkey::new(authority_slice); + + let is_writable = account_info.is_writable; + if !is_writable { + return Err(ErrorCode::UserStatsWrongMutability); + } + + let user_stats_account_loader: AccountLoader = + AccountLoader::try_from(account_info).or(Err(ErrorCode::InvalidUserStatsAccount))?; + + user_stats_map + .0 + .insert(authority, user_stats_account_loader); + + Ok(user_stats_map) + } + + pub fn empty() -> UserStatsMap<'a> { + UserStatsMap(BTreeMap::new()) + } +} From 1be328ea50768dfddbedf59959bbb4a82b0dbbf9 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 27 Feb 2023 18:32:43 -0500 Subject: [PATCH 06/29] fix some easy warnings --- programs/drift/src/controller/orders.rs | 15 ++++++++------- programs/drift/src/math/fulfillment.rs | 2 +- programs/drift/src/state/user_map.rs | 2 -- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 1d744de4f..0766b0a91 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -821,7 +821,7 @@ pub fn fill_perp_order( } if referrer_user_key == Pubkey::default() { - return Err(ErrorCode::ReferrerNotFound.into()); + return Err(ErrorCode::ReferrerNotFound); } Some((referrer_authority_key, referrer_user_key)) @@ -1037,7 +1037,7 @@ pub fn validate_market_within_price_band( } #[allow(clippy::type_complexity)] -fn sanitize_maker_order<'a>( +fn sanitize_maker_order( perp_market_map: &PerpMarketMap, spot_market_map: &SpotMarketMap, oracle_map: &mut OracleMap, @@ -1059,7 +1059,7 @@ fn sanitize_maker_order<'a>( continue; } - let mut maker = load_mut!(&user_account_loader)?; + let mut maker = load_mut!(user_account_loader)?; if maker.is_being_liquidated() || maker.is_bankrupt() { continue; @@ -1080,7 +1080,7 @@ fn sanitize_maker_order<'a>( continue; } - settle_funding_payment(&mut maker, &maker_key, &mut market, now)?; + settle_funding_payment(&mut maker, maker_key, &mut market, now)?; let initial_margin_ratio = market.margin_ratio_initial; let maintenance_margin_ratio = market.margin_ratio_maintenance; @@ -1146,7 +1146,7 @@ fn sanitize_maker_order<'a>( cancel_order( maker_order_index, maker.deref_mut(), - &maker_key, + maker_key, perp_market_map, spot_market_map, oracle_map, @@ -1342,7 +1342,7 @@ fn fulfill_perp_order( &mut maker, &mut maker_stats.as_deref_mut(), *maker_order_index, - &maker_key, + maker_key, filler, filler_stats, filler_key, @@ -1442,6 +1442,7 @@ fn fulfill_perp_order( Ok((base_asset_amount, risk_increasing, updated_user_state)) } +#[allow(clippy::type_complexity)] fn get_referrer<'a>( referrer_key: &'a Option<(Pubkey, Pubkey)>, makers_and_referrer: &'a UserMap, @@ -1462,7 +1463,7 @@ fn get_referrer<'a>( let referrer = makers_and_referrer.get_ref_mut(referrer_user_key)?; let referrer_stats = makers_and_referrer_stats.get_ref_mut(referrer_authority_key)?; - return Ok((Some(referrer), Some(referrer_stats))); + Ok((Some(referrer), Some(referrer_stats))) } fn determine_if_user_order_is_risk_decreasing( diff --git a/programs/drift/src/math/fulfillment.rs b/programs/drift/src/math/fulfillment.rs index f2d662d45..544f1e639 100644 --- a/programs/drift/src/math/fulfillment.rs +++ b/programs/drift/src/math/fulfillment.rs @@ -12,7 +12,7 @@ mod tests; pub fn determine_perp_fulfillment_methods( taker_order: &Order, - maker_order_info: &Vec<(Pubkey, usize, u64)>, + maker_order_info: &[(Pubkey, usize, u64)], amm: &AMM, amm_reserve_price: u64, valid_oracle_price: Option, diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 0135bb713..8064162e6 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -247,8 +247,6 @@ impl<'a> UserStatsMap<'a> { let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); while let Some(account_info) = account_info_iter.peek() { - let user_stats_key = account_info.key; - let data = account_info .try_borrow_data() .or(Err(ErrorCode::CouldNotLoadUserStatsData))?; From 183d6de67055dadc9a08610a7b7c50f259362fef Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 27 Feb 2023 19:55:23 -0500 Subject: [PATCH 07/29] perp jit maker --- programs/drift/src/controller/orders.rs | 13 ++++++++++++- programs/drift/src/controller/orders/tests.rs | 7 +++++++ programs/drift/src/instructions/keeper.rs | 16 ++++------------ programs/drift/src/instructions/user.rs | 7 +++++-- programs/drift/src/lib.rs | 4 ++-- programs/drift/src/state/user_map.rs | 4 ++-- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 0766b0a91..8ce36c513 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -667,6 +667,7 @@ pub fn fill_perp_order( filler_stats: &AccountLoader, makers_and_referrer: &mut UserMap, makers_and_referrer_stats: &mut UserStatsMap, + jit_maker_order_id: Option, clock: &Clock, ) -> DriftResult<(u64, bool)> { let now = clock.unix_timestamp; @@ -806,6 +807,7 @@ pub fn fill_perp_order( &filler_key, state.perp_fee_structure.flat_filler_fee, oracle_price, + jit_maker_order_id, now, slot, )?; @@ -1048,12 +1050,14 @@ fn sanitize_maker_order( filler_key: &Pubkey, filler_reward: u64, oracle_price: i64, + jit_maker_order_id: Option, now: i64, slot: u64, ) -> DriftResult> { + let mut maker_order_info = Vec::with_capacity(32); + let maker_direction = taker_order.direction.opposite(); - let mut maker_order_info = Vec::with_capacity(32); for (maker_key, user_account_loader) in makers_and_referrer.0.iter_mut() { if maker_key == taker_key { continue; @@ -1100,6 +1104,13 @@ fn sanitize_maker_order( continue; } + if let Some(jit_maker_order_id) = jit_maker_order_id { + // if jit maker order id exists, must only use that order + if maker_order.order_id != jit_maker_order_id { + continue; + } + } + let breaches_oracle_price_limits = { limit_price_breaches_oracle_price_bands( maker_order_price, diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 396318dc1..5c67480fe 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -4229,6 +4229,7 @@ pub mod fill_order { &filler_stats_account_loader, &mut makers_and_referrers, &mut maker_and_referrer_stats, + None, &clock, ) .unwrap(); @@ -4435,6 +4436,7 @@ pub mod fill_order { &filler_stats_account_loader, &mut makers_and_referrers, &mut maker_and_referrer_stats, + None, &clock, ) .unwrap(); @@ -4561,6 +4563,7 @@ pub mod fill_order { &filler_stats_account_loader, &mut UserMap::empty(), &mut UserStatsMap::empty(), + None, &clock, ) .unwrap(); @@ -4726,6 +4729,7 @@ pub mod fill_order { &filler_stats_account_loader, &mut UserMap::empty(), &mut UserStatsMap::empty(), + None, &clock, ); @@ -8385,6 +8389,7 @@ pub mod sanitize_maker_orders { &filler_key, 0, oracle_price, + None, clock.unix_timestamp, clock.slot, ) @@ -8579,6 +8584,7 @@ pub mod sanitize_maker_orders { &filler_key, 0, oracle_price, + None, clock.unix_timestamp, clock.slot, ) @@ -8762,6 +8768,7 @@ pub mod sanitize_maker_orders { &filler_key, 0, oracle_price, + None, clock.unix_timestamp, clock.slot, ) diff --git a/programs/drift/src/instructions/keeper.rs b/programs/drift/src/instructions/keeper.rs index 9189b86b7..d0200ae63 100644 --- a/programs/drift/src/instructions/keeper.rs +++ b/programs/drift/src/instructions/keeper.rs @@ -31,11 +31,7 @@ use crate::{controller, load, math}; #[access_control( fill_not_paused(&ctx.accounts.state) )] -pub fn handle_fill_perp_order<'info>( - ctx: Context, - order_id: Option, - maker_order_id: Option, -) -> Result<()> { +pub fn handle_fill_perp_order<'info>(ctx: Context, order_id: Option) -> Result<()> { let (order_id, market_index) = { let user = &load!(ctx.accounts.user)?; // if there is no order id, use the users last order id @@ -51,7 +47,7 @@ pub fn handle_fill_perp_order<'info>( }; let user_key = &ctx.accounts.user.key(); - fill_order(ctx, order_id, market_index, maker_order_id).map_err(|e| { + fill_order(ctx, order_id, market_index).map_err(|e| { msg!( "Err filling order id {} for user {} for market index {}", order_id, @@ -64,12 +60,7 @@ pub fn handle_fill_perp_order<'info>( Ok(()) } -fn fill_order( - ctx: Context, - order_id: u32, - market_index: u16, - maker_order_id: Option, -) -> Result<()> { +fn fill_order(ctx: Context, order_id: u32, market_index: u16) -> Result<()> { let clock = &Clock::get()?; let state = &ctx.accounts.state; @@ -109,6 +100,7 @@ fn fill_order( &ctx.accounts.filler_stats, &mut makers_and_referrer, &mut makers_and_referrer_stats, + None, clock, )?; diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 544c62dff..7d9f34a12 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -927,6 +927,7 @@ pub fn handle_place_and_take_perp_order<'info>( &ctx.accounts.user_stats.clone(), &mut makers_and_referrer, &mut makers_and_referrer_stats, + None, &Clock::get()?, )?; @@ -1001,10 +1002,11 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>( let (order_id, authority) = { let user = load!(ctx.accounts.user)?; - (user.get_last_order_id(), user.authority) + let order_id = user.get_last_order_id(); + (order_id, user.authority) }; - let jit_maker = (ctx.accounts.user.key(), ctx.accounts.user.clone(), order_id); + let jit_maker = (ctx.accounts.user.key(), ctx.accounts.user.clone()); let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, Some(jit_maker))?; let jit_maker_stats = (authority, ctx.accounts.user_stats.clone()); let mut makers_and_referrer_stats = @@ -1022,6 +1024,7 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>( &ctx.accounts.user_stats.clone(), &mut makers_and_referrer, &mut makers_and_referrer_stats, + Some(order_id), clock, )?; diff --git a/programs/drift/src/lib.rs b/programs/drift/src/lib.rs index a156535f1..8d3040858 100644 --- a/programs/drift/src/lib.rs +++ b/programs/drift/src/lib.rs @@ -205,9 +205,9 @@ pub mod drift { pub fn fill_perp_order( ctx: Context, order_id: Option, - maker_order_id: Option, + _maker_order_id: Option, ) -> Result<()> { - handle_fill_perp_order(ctx, order_id, maker_order_id) + handle_fill_perp_order(ctx, order_id) } pub fn fill_spot_order( diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 8064162e6..6af506f1b 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -85,7 +85,7 @@ impl<'a> UserMap<'a> { pub fn load<'b>( account_info_iter: &'b mut Peekable>>, - jit_maker: Option<(Pubkey, AccountLoader<'a, User>, u32)>, + jit_maker: Option<(Pubkey, AccountLoader<'a, User>)>, ) -> DriftResult> { let mut user_map = UserMap(BTreeMap::new()); @@ -121,7 +121,7 @@ impl<'a> UserMap<'a> { user_map.0.insert(*user_key, user_account_loader); } - if let Some((jit_user, jit_user_loader, _)) = jit_maker { + if let Some((jit_user, jit_user_loader)) = jit_maker { user_map.0.insert(jit_user, jit_user_loader); } From 9f4e5fcea56ffa253447e391c8f9f0521ad7b0b1 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Mon, 27 Feb 2023 19:59:38 -0500 Subject: [PATCH 08/29] name tweak --- programs/drift/src/controller/orders.rs | 4 ++-- programs/drift/src/controller/orders/tests.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 8ce36c513..ff033b8d2 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -796,7 +796,7 @@ pub fn fill_perp_order( (None, None) }; - let maker_order_info = sanitize_maker_order( + let maker_order_info = get_maker_order_info( perp_market_map, spot_market_map, oracle_map, @@ -1039,7 +1039,7 @@ pub fn validate_market_within_price_band( } #[allow(clippy::type_complexity)] -fn sanitize_maker_order( +fn get_maker_order_info( perp_market_map: &PerpMarketMap, spot_market_map: &SpotMarketMap, oracle_map: &mut OracleMap, diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 5c67480fe..d934bf813 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -8178,12 +8178,12 @@ pub mod sort_maker_orders { } } -pub mod sanitize_maker_orders { +pub mod get_maker_order_info { use std::str::FromStr; use anchor_lang::prelude::{AccountLoader, Clock}; - use crate::controller::orders::sanitize_maker_order; + use crate::controller::orders::get_maker_order_info; use crate::controller::position::PositionDirection; use crate::create_account_info; use crate::create_anchor_account_info; @@ -8378,7 +8378,7 @@ pub mod sanitize_maker_orders { let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let maker_order_price_and_indexes = sanitize_maker_order( + let maker_order_price_and_indexes = get_maker_order_info( &market_map, &spot_market_map, &mut oracle_map, @@ -8573,7 +8573,7 @@ pub mod sanitize_maker_orders { let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let maker_order_price_and_indexes = sanitize_maker_order( + let maker_order_price_and_indexes = get_maker_order_info( &market_map, &spot_market_map, &mut oracle_map, @@ -8757,7 +8757,7 @@ pub mod sanitize_maker_orders { let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let maker_order_price_and_indexes = sanitize_maker_order( + let maker_order_price_and_indexes = get_maker_order_info( &market_map, &spot_market_map, &mut oracle_map, From ad9ec8b61d80156cf9c6b2248348ec09ba4e8aaf Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 08:42:31 -0500 Subject: [PATCH 09/29] add placeAndMakePerp order --- test-scripts/run-anchor-tests.sh | 1 + tests/placeAndMakePerp.ts | 215 +++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 tests/placeAndMakePerp.ts diff --git a/test-scripts/run-anchor-tests.sh b/test-scripts/run-anchor-tests.sh index a4f4aed2c..5f8f42cc0 100644 --- a/test-scripts/run-anchor-tests.sh +++ b/test-scripts/run-anchor-tests.sh @@ -35,6 +35,7 @@ test_files=( stopLimits.ts userOrderId.ts postOnly.ts + placeAndMakePerp.ts placeAndMakeSpotOrder.ts roundInFavorBaseAsset.ts marketOrderBaseAssetAmount.ts diff --git a/tests/placeAndMakePerp.ts b/tests/placeAndMakePerp.ts new file mode 100644 index 000000000..0f5c81dce --- /dev/null +++ b/tests/placeAndMakePerp.ts @@ -0,0 +1,215 @@ +import * as anchor from '@project-serum/anchor'; +import { assert } from 'chai'; + +import { Program } from '@project-serum/anchor'; + +import { Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js'; + +import { + TestClient, + BN, + PRICE_PRECISION, + TestClient, + PositionDirection, + User, + Wallet, + EventSubscriber, + BASE_PRECISION, + getLimitOrderParams, + OracleSource, +} from '../sdk/src'; + +import { + initializeQuoteSpotMarket, + initializeSolSpotMarket, + mockOracle, + mockUSDCMint, + mockUserUSDCAccount, + printTxLogs, + sleep, +} from './testHelpers'; +import { BulkAccountLoader, PEG_PRECISION, PostOnlyParams } from '../sdk'; + +describe('place and make perp order', () => { + const provider = anchor.AnchorProvider.local(undefined, { + commitment: 'confirmed', + preflightCommitment: 'confirmed', + }); + const connection = provider.connection; + anchor.setProvider(provider); + const chProgram = anchor.workspace.Drift as Program; + + let makerDriftClient: TestClient; + let makerDriftClientUser: User; + const eventSubscriber = new EventSubscriber(connection, chProgram, { + commitment: 'recent', + }); + eventSubscriber.subscribe(); + + const bulkAccountLoader = new BulkAccountLoader(connection, 'confirmed', 1); + + // ammInvariant == k == x * y + const mantissaSqrtScale = new BN(Math.sqrt(PRICE_PRECISION.toNumber())); + const ammInitialQuoteAssetReserve = new anchor.BN(5 * 10 ** 13).mul( + mantissaSqrtScale + ); + const ammInitialBaseAssetReserve = new anchor.BN(5 * 10 ** 13).mul( + mantissaSqrtScale + ); + + let usdcMint; + let userUSDCAccount; + + const usdcAmount = new BN(100 * 10 ** 6); + + let solUsd; + let marketIndexes; + let spotMarketIndexes; + let oracleInfos; + + before(async () => { + usdcMint = await mockUSDCMint(provider); + userUSDCAccount = await mockUserUSDCAccount(usdcMint, usdcAmount, provider); + + solUsd = await mockOracle(32.821); + + marketIndexes = [0]; + spotMarketIndexes = [0, 1]; + oracleInfos = [{ publicKey: solUsd, source: OracleSource.PYTH }]; + + makerDriftClient = new TestClient({ + connection, + wallet: provider.wallet, + programID: chProgram.programId, + opts: { + commitment: 'confirmed', + }, + activeSubAccountId: 0, + perpMarketIndexes: marketIndexes, + spotMarketIndexes: spotMarketIndexes, + oracleInfos, + accountSubscription: { + type: 'polling', + accountLoader: bulkAccountLoader, + }, + }); + await makerDriftClient.initialize(usdcMint.publicKey, true); + await makerDriftClient.subscribe(); + await initializeQuoteSpotMarket(makerDriftClient, usdcMint.publicKey); + + const periodicity = new BN(0); + await makerDriftClient.initializePerpMarket( + solUsd, + ammInitialBaseAssetReserve, + ammInitialQuoteAssetReserve, + periodicity, + new BN(32 * PEG_PRECISION.toNumber()) + ); + + await makerDriftClient.initializeUserAccountAndDepositCollateral( + usdcAmount, + userUSDCAccount.publicKey + ); + + makerDriftClientUser = new User({ + driftClient: makerDriftClient, + userAccountPublicKey: await makerDriftClient.getUserAccountPublicKey(), + }); + await makerDriftClientUser.subscribe(); + }); + + after(async () => { + await makerDriftClient.unsubscribe(); + await makerDriftClientUser.unsubscribe(); + await eventSubscriber.unsubscribe(); + }); + + it('make', async () => { + const keypair = new Keypair(); + await provider.connection.requestAirdrop(keypair.publicKey, 10 ** 9); + await sleep(1000); + const wallet = new Wallet(keypair); + const userUSDCAccount = await mockUserUSDCAccount( + usdcMint, + usdcAmount, + provider, + keypair.publicKey + ); + const takerDriftClient = new TestClient({ + connection, + wallet, + programID: chProgram.programId, + opts: { + commitment: 'confirmed', + }, + activeSubAccountId: 0, + perpMarketIndexes: marketIndexes, + spotMarketIndexes: spotMarketIndexes, + oracleInfos, + userStats: true, + accountSubscription: { + type: 'polling', + accountLoader: bulkAccountLoader, + }, + }); + await takerDriftClient.subscribe(); + await takerDriftClient.initializeUserAccountAndDepositCollateral( + usdcAmount, + userUSDCAccount.publicKey + ); + const takerDriftClientUser = new User({ + driftClient: takerDriftClient, + userAccountPublicKey: await takerDriftClient.getUserAccountPublicKey(), + }); + await takerDriftClientUser.subscribe(); + + const marketIndex = 0; + const baseAssetAmount = BASE_PRECISION; + const takerOrderParams = getLimitOrderParams({ + marketIndex, + direction: PositionDirection.LONG, + baseAssetAmount, + price: new BN(34).mul(PRICE_PRECISION), + auctionStartPrice: new BN(33).mul(PRICE_PRECISION), + auctionEndPrice: new BN(34).mul(PRICE_PRECISION), + auctionDuration: 10, + userOrderId: 1, + postOnly: PostOnlyParams.NONE, + }); + await takerDriftClient.placePerpOrder(takerOrderParams); + await takerDriftClientUser.fetchAccounts(); + const order = takerDriftClientUser.getOrderByUserOrderId(1); + assert(!order.postOnly); + + const makerOrderParams = getLimitOrderParams({ + marketIndex, + direction: PositionDirection.SHORT, + baseAssetAmount, + price: new BN(33).mul(PRICE_PRECISION), + userOrderId: 1, + postOnly: PostOnlyParams.MUST_POST_ONLY, + immediateOrCancel: true, + }); + + const txSig = await makerDriftClient.placeAndMakePerpOrder( + makerOrderParams, + { + taker: await takerDriftClient.getUserAccountPublicKey(), + order: takerDriftClient.getOrderByUserId(1), + takerUserAccount: takerDriftClient.getUserAccount(), + takerStats: takerDriftClient.getUserStatsAccountPublicKey(), + } + ); + + await printTxLogs(connection, txSig); + + const makerPosition = makerDriftClient.getUser().getPerpPosition(0); + assert(makerPosition.baseAssetAmount.eq(BASE_PRECISION.neg())); + + const takerPosition = takerDriftClient.getUser().getPerpPosition(0); + assert(takerPosition.baseAssetAmount.eq(BASE_PRECISION)); + + await takerDriftClientUser.unsubscribe(); + await takerDriftClient.unsubscribe(); + }); +}); From 10973e19399a60a472432dca6c1f686486c6596d Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 09:12:26 -0500 Subject: [PATCH 10/29] update get_referrer_info --- programs/drift/src/controller/orders.rs | 91 +++++++++++-------------- 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index ff033b8d2..7ec73f546 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -812,24 +812,8 @@ pub fn fill_perp_order( slot, )?; - let referrer_keys = if !user_stats.referrer.eq(&Pubkey::default()) { - let referrer_authority_key = user_stats.referrer; - let mut referrer_user_key = Pubkey::default(); - for (maker_key, maker) in makers_and_referrer.0.iter() { - if load!(maker)?.authority == referrer_authority_key { - referrer_user_key = *maker_key; - break; - } - } - - if referrer_user_key == Pubkey::default() { - return Err(ErrorCode::ReferrerNotFound); - } - - Some((referrer_authority_key, referrer_user_key)) - } else { - None - }; + let referrer_info = + get_referrer_info(user_stats, makers_and_referrer, makers_and_referrer_stats)?; let should_expire_order = should_expire_order(user, order_index, now)?; @@ -885,7 +869,7 @@ pub fn fill_perp_order( &mut filler.as_deref_mut(), &filler_key, &mut filler_stats.as_deref_mut(), - referrer_keys, + referrer_info, spot_market_map, perp_market_map, oracle_map, @@ -1192,43 +1176,44 @@ fn sort_maker_orders( }); } -#[allow(clippy::type_complexity)] -fn sanitize_referrer<'a>( - referrer: Option<&'a AccountLoader>, - referrer_stats: Option<&'a AccountLoader>, +fn get_referrer_info( user_stats: &UserStats, -) -> DriftResult<(Option>, Option>)> { - if referrer.is_none() || referrer_stats.is_none() { - validate!( - !user_stats.has_referrer(), - ErrorCode::InvalidReferrer, - "User has referrer but referrer/referrer stats missing" - )?; - - return Ok((None, None)); + makers_and_referrer: &UserMap, + makers_and_referrer_stats: &UserStatsMap, +) -> DriftResult> { + if user_stats.referrer.eq(&Pubkey::default()) { + return Ok(None); } - let referrer = load_mut!(referrer.safe_unwrap()?)?; - let referrer_stats = load_mut!(referrer_stats.safe_unwrap()?)?; validate!( - referrer.sub_account_id == 0, - ErrorCode::InvalidReferrer, - "Referrer must be user id 0" + makers_and_referrer_stats + .0 + .contains_key(&user_stats.referrer), + ErrorCode::ReferrerStatsNotFound )?; - validate!( - referrer.authority.eq(&referrer_stats.authority), - ErrorCode::InvalidReferrer, - "Referrer authority != Referrer stats authority" - )?; + let referrer_authority_key = user_stats.referrer; + let mut referrer_user_key = Pubkey::default(); + for (referrer_key, referrer) in makers_and_referrer.0.iter() { + let referrer = load!(referrer)?; + if referrer.authority != referrer_authority_key { + continue; + } - validate!( - referrer.authority.eq(&user_stats.referrer), - ErrorCode::InvalidReferrer, - "Referrer authority != user stats authority" - )?; + validate!( + referrer.sub_account_id == 0, + ErrorCode::InvalidReferrer, + "Referrer must be user id 0" + )?; - Ok((Some(referrer), Some(referrer_stats))) + referrer_user_key = *referrer_key; + } + + if referrer_user_key == Pubkey::default() { + return Err(ErrorCode::ReferrerNotFound); + } + + Ok(Some((referrer_authority_key, referrer_user_key))) } fn fulfill_perp_order( @@ -1242,7 +1227,7 @@ fn fulfill_perp_order( filler: &mut Option<&mut User>, filler_key: &Pubkey, filler_stats: &mut Option<&mut UserStats>, - referrer_keys: Option<(Pubkey, Pubkey)>, + referrer_info: Option<(Pubkey, Pubkey)>, spot_market_map: &SpotMarketMap, perp_market_map: &PerpMarketMap, oracle_map: &mut OracleMap, @@ -1296,7 +1281,7 @@ fn fulfill_perp_order( let (fill_base_asset_amount, fill_quote_asset_amount) = match fulfillment_method { PerpFulfillmentMethod::AMM(maker_price) => { let (mut referrer, mut referrer_stats) = get_referrer( - &referrer_keys, + &referrer_info, makers_and_referrer, makers_and_referrer_stats, None, @@ -1337,7 +1322,7 @@ fn fulfill_perp_order( }; let (mut referrer, mut referrer_stats) = get_referrer( - &referrer_keys, + &referrer_info, makers_and_referrer, makers_and_referrer_stats, Some(&maker), @@ -1455,12 +1440,12 @@ fn fulfill_perp_order( #[allow(clippy::type_complexity)] fn get_referrer<'a>( - referrer_key: &'a Option<(Pubkey, Pubkey)>, + referrer_info: &'a Option<(Pubkey, Pubkey)>, makers_and_referrer: &'a UserMap, makers_and_referrer_stats: &'a UserStatsMap, maker: Option<&User>, ) -> DriftResult<(Option>, Option>)> { - let (referrer_authority_key, referrer_user_key) = match referrer_key { + let (referrer_authority_key, referrer_user_key) = match referrer_info { Some(referrer_keys) => referrer_keys, None => return Ok((None, None)), }; From dad2364900781e1f2da2726781d1164327da67b2 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 09:15:38 -0500 Subject: [PATCH 11/29] fix warning --- programs/drift/src/instructions/user.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 7d9f34a12..3de4f913b 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -866,7 +866,7 @@ pub fn handle_cancel_orders( pub fn handle_place_and_take_perp_order<'info>( ctx: Context, params: OrderParams, - maker_order_id: Option, + _maker_order_id: Option, ) -> Result<()> { let clock = Clock::get()?; let state = &ctx.accounts.state; From 24ab5fed7d0bb1ac6a5b972ce313f722dec8216b Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 11:24:15 -0500 Subject: [PATCH 12/29] make the loading of user and user stats map more backwards compatible --- programs/drift/src/controller/orders/tests.rs | 9 +- programs/drift/src/instructions/keeper.rs | 6 +- programs/drift/src/instructions/user.rs | 19 +- programs/drift/src/state/user_map.rs | 180 ++++++++---------- tests/placeAndMakeSpotOrder.ts | 1 - 5 files changed, 100 insertions(+), 115 deletions(-) diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index d934bf813..3d331feaa 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -8372,8 +8372,7 @@ pub mod get_maker_order_info { let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = - UserMap::load(&mut vec![maker_account_info].iter().peekable(), None).unwrap(); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); @@ -8567,8 +8566,7 @@ pub mod get_maker_order_info { let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = - UserMap::load(&mut vec![maker_account_info].iter().peekable(), None).unwrap(); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); @@ -8751,8 +8749,7 @@ pub mod get_maker_order_info { let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = - UserMap::load(&mut vec![maker_account_info].iter().peekable(), None).unwrap(); + let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); diff --git a/programs/drift/src/instructions/keeper.rs b/programs/drift/src/instructions/keeper.rs index d0200ae63..a9cfd510f 100644 --- a/programs/drift/src/instructions/keeper.rs +++ b/programs/drift/src/instructions/keeper.rs @@ -24,7 +24,7 @@ use crate::state::spot_market_map::{ }; use crate::state::state::State; use crate::state::user::{MarketType, User, UserStats}; -use crate::state::user_map::{UserMap, UserStatsMap}; +use crate::state::user_map::load_user_maps; use crate::validate; use crate::{controller, load, math}; @@ -77,8 +77,8 @@ fn fill_order(ctx: Context, order_id: u32, market_index: u16) -> Resu Some(state.oracle_guard_rails), )?; - let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, None)?; - let mut makers_and_referrer_stats = UserStatsMap::load(remaining_accounts_iter, None)?; + let (mut makers_and_referrer, mut makers_and_referrer_stats) = + load_user_maps(remaining_accounts_iter)?; controller::repeg::update_amm( market_index, diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 3de4f913b..70ad26949 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -39,7 +39,7 @@ use crate::state::traits::Size; use crate::state::user::{ MarketType, OrderTriggerCondition, OrderType, User, UserStats, UserStatus, }; -use crate::state::user_map::{UserMap, UserStatsMap}; +use crate::state::user_map::load_user_maps; use crate::validate; use crate::validation::user::validate_user_deletion; use crate::validation::whitelist::validate_whitelist_token; @@ -889,8 +889,8 @@ pub fn handle_place_and_take_perp_order<'info>( return Err(print_error!(ErrorCode::InvalidOrderPostOnly)().into()); } - let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, None)?; - let mut makers_and_referrer_stats = UserStatsMap::load(remaining_accounts_iter, None)?; + let (mut makers_and_referrer, mut makers_and_referrer_stats) = + load_user_maps(remaining_accounts_iter)?; let is_immediate_or_cancel = params.immediate_or_cancel; @@ -1006,11 +1006,14 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>( (order_id, user.authority) }; - let jit_maker = (ctx.accounts.user.key(), ctx.accounts.user.clone()); - let mut makers_and_referrer = UserMap::load(remaining_accounts_iter, Some(jit_maker))?; - let jit_maker_stats = (authority, ctx.accounts.user_stats.clone()); - let mut makers_and_referrer_stats = - UserStatsMap::load(remaining_accounts_iter, Some(jit_maker_stats))?; + let (mut makers_and_referrer, mut makers_and_referrer_stats) = + load_user_maps(remaining_accounts_iter)?; + makers_and_referrer + .0 + .insert(ctx.accounts.user.key(), ctx.accounts.user.clone()); + makers_and_referrer_stats + .0 + .insert(authority, ctx.accounts.user_stats.clone()); controller::orders::fill_perp_order( taker_order_id, diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 6af506f1b..600e60486 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -2,6 +2,7 @@ use crate::error::{DriftResult, ErrorCode}; use crate::math::safe_unwrap::SafeUnwrap; use crate::state::traits::Size; use crate::state::user::{User, UserStats}; +use crate::validate; use anchor_lang::prelude::AccountLoader; use anchor_lang::Discriminator; use arrayref::array_ref; @@ -83,49 +84,8 @@ impl<'a> UserMap<'a> { } } - pub fn load<'b>( - account_info_iter: &'b mut Peekable>>, - jit_maker: Option<(Pubkey, AccountLoader<'a, User>)>, - ) -> DriftResult> { - let mut user_map = UserMap(BTreeMap::new()); - - let user_discriminator: [u8; 8] = User::discriminator(); - while let Some(account_info) = account_info_iter.peek() { - let user_key = account_info.key; - - let data = account_info - .try_borrow_data() - .or(Err(ErrorCode::CouldNotLoadUserData))?; - - let expected_data_len = User::SIZE; - if data.len() < expected_data_len { - break; - } - - let account_discriminator = array_ref![data, 0, 8]; - if account_discriminator != &user_discriminator { - break; - } - - let user_account_info = account_info_iter.next().safe_unwrap()?; - - let is_writable = user_account_info.is_writable; - if !is_writable { - return Err(ErrorCode::UserWrongMutability); - } - - let user_account_loader: AccountLoader = - AccountLoader::try_from(user_account_info) - .or(Err(ErrorCode::InvalidUserAccount))?; - - user_map.0.insert(*user_key, user_account_loader); - } - - if let Some((jit_user, jit_user_loader)) = jit_maker { - user_map.0.insert(jit_user, jit_user_loader); - } - - Ok(user_map) + pub fn empty() -> UserMap<'a> { + UserMap(BTreeMap::new()) } } @@ -164,10 +124,6 @@ impl<'a> UserMap<'a> { Ok(user_map) } - - pub fn empty() -> UserMap<'a> { - UserMap(BTreeMap::new()) - } } pub struct UserStatsMap<'a>(pub BTreeMap>); @@ -239,54 +195,8 @@ impl<'a> UserStatsMap<'a> { } } - pub fn load<'b>( - account_info_iter: &'b mut Peekable>>, - jit_maker_stats: Option<(Pubkey, AccountLoader<'a, UserStats>)>, - ) -> DriftResult> { - let mut user_stats_map = UserStatsMap(BTreeMap::new()); - - let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); - while let Some(account_info) = account_info_iter.peek() { - let data = account_info - .try_borrow_data() - .or(Err(ErrorCode::CouldNotLoadUserStatsData))?; - - let expected_data_len = UserStats::SIZE; - if data.len() < expected_data_len { - break; - } - - let account_discriminator = array_ref![data, 0, 8]; - if account_discriminator != &user_stats_discriminator { - break; - } - - let authority_slice = array_ref![data, 8, 32]; - let authority = Pubkey::new(authority_slice); - - let user_stats_account_info = account_info_iter.next().safe_unwrap()?; - - let is_writable = user_stats_account_info.is_writable; - if !is_writable { - return Err(ErrorCode::UserStatsWrongMutability); - } - - let user_stats_account_loader: AccountLoader = - AccountLoader::try_from(user_stats_account_info) - .or(Err(ErrorCode::InvalidUserStatsAccount))?; - - user_stats_map - .0 - .insert(authority, user_stats_account_loader); - } - - if let Some((jit_user_stats, jit_user_stats_loader)) = jit_maker_stats { - user_stats_map - .0 - .insert(jit_user_stats, jit_user_stats_loader); - } - - Ok(user_stats_map) + pub fn empty() -> UserStatsMap<'a> { + UserStatsMap(BTreeMap::new()) } } @@ -330,8 +240,84 @@ impl<'a> UserStatsMap<'a> { Ok(user_stats_map) } +} - pub fn empty() -> UserStatsMap<'a> { - UserStatsMap(BTreeMap::new()) +pub fn load_user_maps<'a>( + account_info_iter: &mut Peekable>>, +) -> DriftResult<(UserMap<'a>, UserStatsMap<'a>)> { + let mut user_map = UserMap::empty(); + let mut user_stats_map = UserStatsMap::empty(); + + let user_discriminator: [u8; 8] = User::discriminator(); + let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); + while let Some(user_account_info) = account_info_iter.peek() { + let user_key = user_account_info.key; + + let data = user_account_info + .try_borrow_data() + .or(Err(ErrorCode::CouldNotLoadUserData))?; + + let expected_data_len = User::SIZE; + if data.len() < expected_data_len { + break; + } + + let account_discriminator = array_ref![data, 0, 8]; + if account_discriminator != &user_discriminator { + break; + } + + let user_account_info = account_info_iter.next().safe_unwrap()?; + + let is_writable = user_account_info.is_writable; + if !is_writable { + return Err(ErrorCode::UserWrongMutability); + } + + let user_account_loader: AccountLoader = + AccountLoader::try_from(user_account_info).or(Err(ErrorCode::InvalidUserAccount))?; + + user_map.0.insert(*user_key, user_account_loader); + + validate!( + account_info_iter.peek().is_some(), + ErrorCode::UserStatsNotFound + )?; + + let user_stats_account_info = account_info_iter.peek().safe_unwrap()?; + + let data = user_stats_account_info + .try_borrow_data() + .or(Err(ErrorCode::CouldNotLoadUserStatsData))?; + + let expected_data_len = UserStats::SIZE; + if data.len() < expected_data_len { + return Err(ErrorCode::InvalidUserStatsAccount); + } + + let account_discriminator = array_ref![data, 0, 8]; + if account_discriminator != &user_stats_discriminator { + return Err(ErrorCode::InvalidUserStatsAccount); + } + + let authority_slice = array_ref![data, 8, 32]; + let authority = Pubkey::new(authority_slice); + + let user_stats_account_info = account_info_iter.next().safe_unwrap()?; + + let is_writable = user_stats_account_info.is_writable; + if !is_writable { + return Err(ErrorCode::UserStatsWrongMutability); + } + + let user_stats_account_loader: AccountLoader = + AccountLoader::try_from(user_stats_account_info) + .or(Err(ErrorCode::InvalidUserStatsAccount))?; + + user_stats_map + .0 + .insert(authority, user_stats_account_loader); } + + Ok((user_map, user_stats_map)) } diff --git a/tests/placeAndMakeSpotOrder.ts b/tests/placeAndMakeSpotOrder.ts index 88ff538b3..7ce98fd43 100644 --- a/tests/placeAndMakeSpotOrder.ts +++ b/tests/placeAndMakeSpotOrder.ts @@ -9,7 +9,6 @@ import { TestClient, BN, PRICE_PRECISION, - TestClient, PositionDirection, User, Wallet, From b63cd183f1fdd5f04efd250a190627187a8e26f3 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 15:43:18 -0500 Subject: [PATCH 13/29] change multipleMakerOrders test to have multiple makers --- sdk/src/driftClient.ts | 49 +++++++++++++--------- sdk/src/types.ts | 2 +- tests/multipleMakerOrders.ts | 81 +++++++++++++++++++++++++++++------- 3 files changed, 96 insertions(+), 36 deletions(-) diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index 17cfc47e3..07453a95b 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -2214,7 +2214,7 @@ export class DriftClient { userAccountPublicKey: PublicKey, user: UserAccount, order?: Pick, - makerInfo?: MakerInfo, + makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams ): Promise { @@ -2240,7 +2240,7 @@ export class DriftClient { userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Pick, - makerInfo?: MakerInfo, + makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo ): Promise { const userStatsPublicKey = getUserStatsAccountPublicKey( @@ -2257,45 +2257,54 @@ export class DriftClient { (order) => order.orderId === userAccount.nextOrderId - 1 ).marketIndex; + makerInfo = Array.isArray(makerInfo) + ? makerInfo + : makerInfo + ? [makerInfo] + : []; + const userAccounts = [userAccount]; - if (makerInfo !== undefined) { - userAccounts.push(makerInfo.makerUserAccount); + for (const maker of makerInfo) { + userAccounts.push(maker.makerUserAccount); } const remainingAccounts = this.getRemainingAccounts({ userAccounts, writablePerpMarketIndexes: [marketIndex], }); - if (makerInfo) { + for (const maker of makerInfo) { remainingAccounts.push({ - pubkey: makerInfo.maker, + pubkey: maker.maker, isWritable: true, isSigner: false, }); remainingAccounts.push({ - pubkey: makerInfo.makerStats, + pubkey: maker.makerStats, isWritable: true, isSigner: false, }); } if (referrerInfo) { - remainingAccounts.push({ - pubkey: referrerInfo.referrer, - isWritable: true, - isSigner: false, - }); - remainingAccounts.push({ - pubkey: referrerInfo.referrerStats, - isWritable: true, - isSigner: false, - }); + const referrerIsMaker = + makerInfo.find((maker) => maker.maker.equals(referrerInfo.referrer)) !== + undefined; + if (!referrerIsMaker) { + remainingAccounts.push({ + pubkey: referrerInfo.referrer, + isWritable: true, + isSigner: false, + }); + remainingAccounts.push({ + pubkey: referrerInfo.referrerStats, + isWritable: true, + isSigner: false, + }); + } } const orderId = order.orderId; - const makerOrderId = makerInfo ? makerInfo.order.orderId : null; - - return await this.program.instruction.fillPerpOrder(orderId, makerOrderId, { + return await this.program.instruction.fillPerpOrder(orderId, null, { accounts: { state: await this.getStatePublicKey(), filler: fillerPublicKey, diff --git a/sdk/src/types.ts b/sdk/src/types.ts index 335ac8e20..1523bb46f 100644 --- a/sdk/src/types.ts +++ b/sdk/src/types.ts @@ -901,7 +901,7 @@ export type MakerInfo = { maker: PublicKey; makerStats: PublicKey; makerUserAccount: UserAccount; - order: Order; + order?: Order; }; export type TakerInfo = { diff --git a/tests/multipleMakerOrders.ts b/tests/multipleMakerOrders.ts index b64aa14b3..6e8a30cfb 100644 --- a/tests/multipleMakerOrders.ts +++ b/tests/multipleMakerOrders.ts @@ -179,6 +179,30 @@ describe('multiple maker orders', () => { }); } + const [secondMakerDriftClient, secondMakerUSDCAccount] = + await createUserWithUSDCAccount( + provider, + usdcMint, + chProgram, + usdcAmount, + marketIndexes, + spotMarketIndexes, + oracleInfos, + bulkAccountLoader + ); + + await secondMakerDriftClient.deposit(usdcAmount, 0, secondMakerUSDCAccount); + + for (let i = 0; i < 6; i++) { + await secondMakerDriftClient.placePerpOrder({ + marketIndex: 0, + direction: PositionDirection.SHORT, + price: new BN(95 + i).mul(PRICE_PRECISION), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + const takerBaseAssetAmount = new BN(6).mul(BASE_PRECISION); await takerDriftClient.placePerpOrder({ marketIndex: 0, @@ -188,16 +212,23 @@ describe('multiple maker orders', () => { baseAssetAmount: takerBaseAssetAmount, }); - const txSig = await fillerDriftClient.fillPerpOrder( - await takerDriftClient.getUserAccountPublicKey(), - takerDriftClient.getUserAccount(), - takerDriftClient.getOrder(1), + const makerInfo = [ { maker: await makerDriftClient.getUserAccountPublicKey(), makerUserAccount: makerDriftClient.getUserAccount(), - order: makerDriftClient.getOrder(1), makerStats: await makerDriftClient.getUserStatsAccountPublicKey(), - } + }, + { + maker: await secondMakerDriftClient.getUserAccountPublicKey(), + makerUserAccount: secondMakerDriftClient.getUserAccount(), + makerStats: await secondMakerDriftClient.getUserStatsAccountPublicKey(), + }, + ]; + const txSig = await fillerDriftClient.fillPerpOrder( + await takerDriftClient.getUserAccountPublicKey(), + takerDriftClient.getUserAccount(), + takerDriftClient.getOrder(1), + makerInfo ); await printTxLogs(connection, txSig); @@ -209,11 +240,25 @@ describe('multiple maker orders', () => { const takerPosition = takerDriftClient.getUser().getPerpPosition(0); assert(takerPosition.baseAssetAmount.eq(takerBaseAssetAmount)); - assert(takerPosition.quoteAssetAmount.eq(new BN(-585585000))); + assert(takerPosition.quoteAssetAmount.eq(new BN(-576576000))); const makerPosition = makerDriftClient.getUser().getPerpPosition(0); - assert(makerPosition.baseAssetAmount.eq(takerBaseAssetAmount.neg())); - assert(makerPosition.quoteAssetAmount.eq(new BN(585117000))); + assert( + makerPosition.baseAssetAmount.eq( + takerBaseAssetAmount.neg().div(new BN(2)) + ) + ); + assert(makerPosition.quoteAssetAmount.eq(new BN(288057600))); + + const secondMakerPosition = secondMakerDriftClient + .getUser() + .getPerpPosition(0); + assert( + secondMakerPosition.baseAssetAmount.eq( + takerBaseAssetAmount.neg().div(new BN(2)) + ) + ); + assert(secondMakerPosition.quoteAssetAmount.eq(new BN(288057600))); for (let i = 0; i < 3; i++) { await makerDriftClient.placePerpOrder({ @@ -225,6 +270,16 @@ describe('multiple maker orders', () => { }); } + for (let i = 0; i < 3; i++) { + await secondMakerDriftClient.placePerpOrder({ + marketIndex: 0, + direction: PositionDirection.LONG, + price: new BN(101 - i).mul(PRICE_PRECISION), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + await takerDriftClient.placePerpOrder({ marketIndex: 0, orderType: OrderType.LIMIT, @@ -237,12 +292,7 @@ describe('multiple maker orders', () => { await takerDriftClient.getUserAccountPublicKey(), takerDriftClient.getUserAccount(), takerDriftClient.getOrder(2), - { - maker: await makerDriftClient.getUserAccountPublicKey(), - makerUserAccount: makerDriftClient.getUserAccount(), - order: makerDriftClient.getOrder(7), - makerStats: await makerDriftClient.getUserStatsAccountPublicKey(), - } + makerInfo ); const takerPosition2 = takerDriftClient.getUser().getPerpPosition(0); @@ -252,5 +302,6 @@ describe('multiple maker orders', () => { await takerDriftClient.unsubscribe(); await makerDriftClient.unsubscribe(); + await secondMakerDriftClient.unsubscribe(); }); }); From c5797527520c8d2177fab0d6fd0d536a098a305b Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 16:18:20 -0500 Subject: [PATCH 14/29] fix warnings --- programs/drift/src/controller/orders.rs | 8 +- .../src/controller/orders/amm_jit_tests.rs | 108 ++++++++---------- programs/drift/src/controller/orders/tests.rs | 91 +++++++-------- programs/drift/src/instructions/keeper.rs | 7 +- programs/drift/src/instructions/user.rs | 11 +- programs/drift/src/math/fulfillment/tests.rs | 22 ++-- programs/drift/src/state/user_map.rs | 2 +- tests/placeAndMakePerp.ts | 4 +- 8 files changed, 115 insertions(+), 138 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 7ec73f546..10ecb597a 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -665,8 +665,8 @@ pub fn fill_perp_order( oracle_map: &mut OracleMap, filler: &AccountLoader, filler_stats: &AccountLoader, - makers_and_referrer: &mut UserMap, - makers_and_referrer_stats: &mut UserStatsMap, + makers_and_referrer: &UserMap, + makers_and_referrer_stats: &UserStatsMap, jit_maker_order_id: Option, clock: &Clock, ) -> DriftResult<(u64, bool)> { @@ -1027,7 +1027,7 @@ fn get_maker_order_info( perp_market_map: &PerpMarketMap, spot_market_map: &SpotMarketMap, oracle_map: &mut OracleMap, - makers_and_referrer: &mut UserMap, + makers_and_referrer: &UserMap, taker_key: &Pubkey, taker_order: &Order, filler: &mut Option<&mut User>, @@ -1042,7 +1042,7 @@ fn get_maker_order_info( let maker_direction = taker_order.direction.opposite(); - for (maker_key, user_account_loader) in makers_and_referrer.0.iter_mut() { + for (maker_key, user_account_loader) in makers_and_referrer.0.iter() { if maker_key == taker_key { continue; } diff --git a/programs/drift/src/controller/orders/amm_jit_tests.rs b/programs/drift/src/controller/orders/amm_jit_tests.rs index e4c9b4ccd..33c256508 100644 --- a/programs/drift/src/controller/orders/amm_jit_tests.rs +++ b/programs/drift/src/controller/orders/amm_jit_tests.rs @@ -267,7 +267,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -282,8 +282,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); @@ -292,8 +291,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -449,7 +448,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -464,8 +463,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); @@ -480,8 +478,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 99 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -645,7 +643,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -660,8 +658,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); @@ -676,8 +673,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 99 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -841,7 +838,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -856,8 +853,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -871,8 +867,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -1050,7 +1046,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -1065,8 +1061,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); let (base_asset_amount, _, _) = fulfill_perp_order( @@ -1074,8 +1069,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -1256,7 +1251,7 @@ pub mod amm_jit { }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -1271,8 +1266,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1286,8 +1280,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -1463,7 +1457,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -1478,8 +1472,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); let reserve_price_before = market.amm.reserve_price().unwrap(); @@ -1490,8 +1483,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -1645,7 +1638,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -1660,8 +1653,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1676,8 +1668,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 10 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -1843,7 +1835,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -1858,8 +1850,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -1874,8 +1865,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 200 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, @@ -2046,8 +2037,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -2116,7 +2106,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); // fulfill with match fulfill_perp_order( @@ -2124,8 +2114,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, auction_price)], &mut Some(&mut filler), &filler_key, @@ -2327,8 +2317,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -2399,7 +2388,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); // fulfill with match fulfill_perp_order( @@ -2407,8 +2396,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, auction_price)], &mut Some(&mut filler), &filler_key, @@ -2599,7 +2588,7 @@ pub mod amm_jit { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -2617,8 +2606,7 @@ pub mod amm_jit { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); assert_eq!(market.amm.total_fee, 0); @@ -2634,8 +2622,8 @@ pub mod amm_jit { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 10 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 3d331feaa..5c7441c2e 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -2680,7 +2680,7 @@ pub mod fulfill_order { ..User::default() }; create_anchor_account_info!(maker, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -2694,8 +2694,7 @@ pub mod fulfill_order { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); @@ -2704,8 +2703,8 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![( Pubkey::default(), 0, @@ -2922,7 +2921,7 @@ pub mod fulfill_order { ..User::default() }; create_anchor_account_info!(maker, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -2937,8 +2936,7 @@ pub mod fulfill_order { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); @@ -2947,8 +2945,8 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![ (maker_key, 0, 90 * PRICE_PRECISION_U64), (maker_key, 1, 95 * PRICE_PRECISION_U64), @@ -3113,7 +3111,7 @@ pub mod fulfill_order { ..User::default() }; create_anchor_account_info!(maker, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut filler = User::default(); @@ -3128,8 +3126,7 @@ pub mod fulfill_order { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let mut filler_stats = UserStats::default(); @@ -3138,8 +3135,8 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000)], &mut Some(&mut filler), &filler_key, @@ -3319,7 +3316,7 @@ pub mod fulfill_order { ..User::default() }; create_anchor_account_info!(maker, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let now = 0_i64; let slot = 0_u64; @@ -3334,16 +3331,15 @@ pub mod fulfill_order { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let (base_asset_amount, _, _) = fulfill_perp_order( &mut taker, 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut None, &filler_key, @@ -3505,8 +3501,8 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut UserMap::empty(), - &mut UserStatsMap::empty(), + &UserMap::empty(), + &UserStatsMap::empty(), vec![], &mut None, &filler_key, @@ -3880,7 +3876,7 @@ pub mod fulfill_order { ..User::default() }; create_anchor_account_info!(maker, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); // random let now = 1; //80080880_i64; @@ -3896,8 +3892,7 @@ pub mod fulfill_order { ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let taker_before = taker; let maker_before = maker; @@ -3906,8 +3901,8 @@ pub mod fulfill_order { 0, &taker_key, &mut taker_stats, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, vec![(maker_key, 1, 100 * PRICE_PRECISION_U64)], &mut None, &filler_key, @@ -4192,15 +4187,14 @@ pub mod fill_order { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut maker_stats = UserStats { authority: maker_authority, ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); create_anchor_account_info!(User::default(), &filler_key, User, user_account_info); @@ -4227,8 +4221,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, None, &clock, ) @@ -4399,15 +4393,14 @@ pub mod fill_order { ..User::default() }; create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let mut maker_stats = UserStats { authority: maker_authority, ..UserStats::default() }; create_anchor_account_info!(maker_stats, UserStats, maker_stats_account_info); - let mut maker_and_referrer_stats = - UserStatsMap::load_one(&maker_stats_account_info).unwrap(); + let maker_and_referrer_stats = UserStatsMap::load_one(&maker_stats_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); create_anchor_account_info!(User::default(), &filler_key, User, user_account_info); @@ -4434,8 +4427,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - &mut makers_and_referrers, - &mut maker_and_referrer_stats, + &makers_and_referrers, + &maker_and_referrer_stats, None, &clock, ) @@ -4561,8 +4554,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - &mut UserMap::empty(), - &mut UserStatsMap::empty(), + &UserMap::empty(), + &UserStatsMap::empty(), None, &clock, ) @@ -4727,8 +4720,8 @@ pub mod fill_order { &mut oracle_map, &filler_account_loader, &filler_stats_account_loader, - &mut UserMap::empty(), - &mut UserStatsMap::empty(), + &UserMap::empty(), + &UserStatsMap::empty(), None, &clock, ); @@ -8181,7 +8174,7 @@ pub mod sort_maker_orders { pub mod get_maker_order_info { use std::str::FromStr; - use anchor_lang::prelude::{AccountLoader, Clock}; + use anchor_lang::prelude::Clock; use crate::controller::orders::get_maker_order_info; use crate::controller::position::PositionDirection; @@ -8198,7 +8191,7 @@ pub mod get_maker_order_info { use crate::state::perp_market_map::PerpMarketMap; use crate::state::spot_market::{SpotBalanceType, SpotMarket}; use crate::state::spot_market_map::SpotMarketMap; - use crate::state::user::{OrderStatus, OrderType, SpotPosition, User, UserStats}; + use crate::state::user::{OrderStatus, OrderType, SpotPosition, User}; use crate::state::user_map::UserMap; use crate::test_utils::*; use crate::test_utils::{ @@ -8372,7 +8365,7 @@ pub mod get_maker_order_info { let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); @@ -8381,7 +8374,7 @@ pub mod get_maker_order_info { &market_map, &spot_market_map, &mut oracle_map, - &mut makers_and_referrers, + &makers_and_referrers, &taker_key, &user.orders[0], &mut Some(&mut filler), @@ -8566,7 +8559,7 @@ pub mod get_maker_order_info { let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); @@ -8575,7 +8568,7 @@ pub mod get_maker_order_info { &market_map, &spot_market_map, &mut oracle_map, - &mut makers_and_referrers, + &makers_and_referrers, &taker_key, &user.orders[0], &mut Some(&mut filler), @@ -8749,7 +8742,7 @@ pub mod get_maker_order_info { let maker_key = Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); create_anchor_account_info!(maker, &maker_key, User, maker_account_info); - let mut makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); @@ -8758,7 +8751,7 @@ pub mod get_maker_order_info { &market_map, &spot_market_map, &mut oracle_map, - &mut makers_and_referrers, + &makers_and_referrers, &taker_key, &user.orders[0], &mut Some(&mut filler), diff --git a/programs/drift/src/instructions/keeper.rs b/programs/drift/src/instructions/keeper.rs index a9cfd510f..934ab017d 100644 --- a/programs/drift/src/instructions/keeper.rs +++ b/programs/drift/src/instructions/keeper.rs @@ -77,8 +77,7 @@ fn fill_order(ctx: Context, order_id: u32, market_index: u16) -> Resu Some(state.oracle_guard_rails), )?; - let (mut makers_and_referrer, mut makers_and_referrer_stats) = - load_user_maps(remaining_accounts_iter)?; + let (makers_and_referrer, makers_and_referrer_stats) = load_user_maps(remaining_accounts_iter)?; controller::repeg::update_amm( market_index, @@ -98,8 +97,8 @@ fn fill_order(ctx: Context, order_id: u32, market_index: u16) -> Resu &mut oracle_map, &ctx.accounts.filler, &ctx.accounts.filler_stats, - &mut makers_and_referrer, - &mut makers_and_referrer_stats, + &makers_and_referrer, + &makers_and_referrer_stats, None, clock, )?; diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 70ad26949..317b9268e 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -889,8 +889,7 @@ pub fn handle_place_and_take_perp_order<'info>( return Err(print_error!(ErrorCode::InvalidOrderPostOnly)().into()); } - let (mut makers_and_referrer, mut makers_and_referrer_stats) = - load_user_maps(remaining_accounts_iter)?; + let (makers_and_referrer, makers_and_referrer_stats) = load_user_maps(remaining_accounts_iter)?; let is_immediate_or_cancel = params.immediate_or_cancel; @@ -925,8 +924,8 @@ pub fn handle_place_and_take_perp_order<'info>( &mut oracle_map, &user.clone(), &ctx.accounts.user_stats.clone(), - &mut makers_and_referrer, - &mut makers_and_referrer_stats, + &makers_and_referrer, + &makers_and_referrer_stats, None, &Clock::get()?, )?; @@ -1025,8 +1024,8 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>( &mut oracle_map, &ctx.accounts.user.clone(), &ctx.accounts.user_stats.clone(), - &mut makers_and_referrer, - &mut makers_and_referrer_stats, + &makers_and_referrer, + &makers_and_referrer_stats, Some(order_id), clock, )?; diff --git a/programs/drift/src/math/fulfillment/tests.rs b/programs/drift/src/math/fulfillment/tests.rs index ac000847f..7b0af30ce 100644 --- a/programs/drift/src/math/fulfillment/tests.rs +++ b/programs/drift/src/math/fulfillment/tests.rs @@ -55,7 +55,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![(Pubkey::default(), 0, 103 * PRICE_PRECISION_U64)], + &[(Pubkey::default(), 0, 103 * PRICE_PRECISION_U64)], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -112,7 +112,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![(Pubkey::default(), 0, 99 * PRICE_PRECISION_U64)], + &[(Pubkey::default(), 0, 99 * PRICE_PRECISION_U64)], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -181,7 +181,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![(Pubkey::default(), 0, 101 * PRICE_PRECISION_U64)], + &[(Pubkey::default(), 0, 101 * PRICE_PRECISION_U64)], &market.amm, market.amm.reserve_price().unwrap(), Some(oracle_price), @@ -245,7 +245,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 101 * PRICE_PRECISION_U64), ], @@ -313,7 +313,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), ( Pubkey::default(), @@ -384,7 +384,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 102 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 103 * PRICE_PRECISION_U64), ], @@ -453,7 +453,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 101 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 99 * PRICE_PRECISION_U64), ], @@ -521,7 +521,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 102 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 101 * PRICE_PRECISION_U64), ], @@ -588,7 +588,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 98 * PRICE_PRECISION_U64), ], @@ -657,7 +657,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 101 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 102 * PRICE_PRECISION_U64), ], @@ -717,7 +717,7 @@ mod determine_perp_fulfillment_methods { let fulfillment_methods = determine_perp_fulfillment_methods( &taker_order, - &vec![ + &[ (Pubkey::default(), 0, 99 * PRICE_PRECISION_U64), (Pubkey::default(), 1, 98 * PRICE_PRECISION_U64), ], diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 600e60486..6e3344c50 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -207,7 +207,7 @@ impl<'a> UserStatsMap<'a> { let user_stats_discriminator: [u8; 8] = UserStats::discriminator(); - let user_stats_key = account_info.key; + let _user_stats_key = account_info.key; let data = account_info .try_borrow_data() diff --git a/tests/placeAndMakePerp.ts b/tests/placeAndMakePerp.ts index 0f5c81dce..36e43ad0d 100644 --- a/tests/placeAndMakePerp.ts +++ b/tests/placeAndMakePerp.ts @@ -3,10 +3,9 @@ import { assert } from 'chai'; import { Program } from '@project-serum/anchor'; -import { Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js'; +import { Keypair } from '@solana/web3.js'; import { - TestClient, BN, PRICE_PRECISION, TestClient, @@ -21,7 +20,6 @@ import { import { initializeQuoteSpotMarket, - initializeSolSpotMarket, mockOracle, mockUSDCMint, mockUserUSDCAccount, From 49c92a78494ac1ce8a298bb9c33f0ca079e51a58 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 16:41:47 -0500 Subject: [PATCH 15/29] dont let client pass in same maker twice --- programs/drift/src/instructions/user.rs | 8 ++---- programs/drift/src/state/user_map.rs | 36 ++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 317b9268e..9cbff3d76 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -1007,12 +1007,8 @@ pub fn handle_place_and_make_perp_order<'a, 'b, 'c, 'info>( let (mut makers_and_referrer, mut makers_and_referrer_stats) = load_user_maps(remaining_accounts_iter)?; - makers_and_referrer - .0 - .insert(ctx.accounts.user.key(), ctx.accounts.user.clone()); - makers_and_referrer_stats - .0 - .insert(authority, ctx.accounts.user_stats.clone()); + makers_and_referrer.insert(ctx.accounts.user.key(), ctx.accounts.user.clone())?; + makers_and_referrer_stats.insert(authority, ctx.accounts.user_stats.clone())?; controller::orders::fill_perp_order( taker_order_id, diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 6e3344c50..6614a0087 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -84,6 +84,19 @@ impl<'a> UserMap<'a> { } } + pub fn insert(&mut self, user: Pubkey, account_loader: AccountLoader<'a, User>) -> DriftResult { + validate!( + !self.0.contains_key(&user), + ErrorCode::InvalidUserAccount, + "User already exists in map {:?}", + user + )?; + + self.0.insert(user, account_loader); + + Ok(()) + } + pub fn empty() -> UserMap<'a> { UserMap(BTreeMap::new()) } @@ -120,7 +133,7 @@ impl<'a> UserMap<'a> { let user_account_loader: AccountLoader = AccountLoader::try_from(account_info).or(Err(ErrorCode::InvalidUserAccount))?; - user_map.0.insert(*user_key, user_account_loader); + user_map.insert(*user_key, user_account_loader)?; Ok(user_map) } @@ -195,6 +208,23 @@ impl<'a> UserStatsMap<'a> { } } + pub fn insert( + &mut self, + authority: Pubkey, + account_loader: AccountLoader<'a, UserStats>, + ) -> DriftResult { + validate!( + !self.0.contains_key(&authority), + ErrorCode::InvalidUserStatsAccount, + "User stats already exists in map {:?}", + authority + )?; + + self.0.insert(authority, account_loader); + + Ok(()) + } + pub fn empty() -> UserStatsMap<'a> { UserStatsMap(BTreeMap::new()) } @@ -314,9 +344,7 @@ pub fn load_user_maps<'a>( AccountLoader::try_from(user_stats_account_info) .or(Err(ErrorCode::InvalidUserStatsAccount))?; - user_stats_map - .0 - .insert(authority, user_stats_account_loader); + user_stats_map.insert(authority, user_stats_account_loader)?; } Ok((user_map, user_stats_map)) From c0096d6bc8bc990dd50cb621d1b8071956a5ce5b Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 20:35:57 -0500 Subject: [PATCH 16/29] maker_order_info renamed to maker_orders_info --- programs/drift/src/controller/orders.rs | 22 +++++++++---------- programs/drift/src/controller/orders/tests.rs | 10 ++++----- programs/drift/src/math/fulfillment.rs | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 10ecb597a..7f751927d 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -796,7 +796,7 @@ pub fn fill_perp_order( (None, None) }; - let maker_order_info = get_maker_order_info( + let maker_orders_info = get_maker_orders_info( perp_market_map, spot_market_map, oracle_map, @@ -865,7 +865,7 @@ pub fn fill_perp_order( user_stats, makers_and_referrer, makers_and_referrer_stats, - maker_order_info, + maker_orders_info, &mut filler.as_deref_mut(), &filler_key, &mut filler_stats.as_deref_mut(), @@ -1023,7 +1023,7 @@ pub fn validate_market_within_price_band( } #[allow(clippy::type_complexity)] -fn get_maker_order_info( +fn get_maker_orders_info( perp_market_map: &PerpMarketMap, spot_market_map: &SpotMarketMap, oracle_map: &mut OracleMap, @@ -1038,7 +1038,7 @@ fn get_maker_order_info( now: i64, slot: u64, ) -> DriftResult> { - let mut maker_order_info = Vec::with_capacity(32); + let mut maker_orders_info = Vec::with_capacity(32); let maker_direction = taker_order.direction.opposite(); @@ -1156,21 +1156,21 @@ fn get_maker_order_info( continue; } - maker_order_info.push((*maker_key, maker_order_index, maker_order_price)); + maker_orders_info.push((*maker_key, maker_order_index, maker_order_price)); } } - sort_maker_orders(&mut maker_order_info, taker_order.direction); + sort_maker_orders(&mut maker_orders_info, taker_order.direction); - Ok(maker_order_info) + Ok(maker_orders_info) } #[inline(always)] fn sort_maker_orders( - maker_order_info: &mut [(Pubkey, usize, u64)], + maker_orders_info: &mut [(Pubkey, usize, u64)], taker_order_direction: PositionDirection, ) { - maker_order_info.sort_by(|a, b| match taker_order_direction { + maker_orders_info.sort_by(|a, b| match taker_order_direction { PositionDirection::Long => a.1.cmp(&b.1), PositionDirection::Short => b.1.cmp(&a.1), }); @@ -1223,7 +1223,7 @@ fn fulfill_perp_order( user_stats: &mut UserStats, makers_and_referrer: &UserMap, makers_and_referrer_stats: &UserStatsMap, - maker_order_info: Vec<(Pubkey, usize, u64)>, + maker_orders_info: Vec<(Pubkey, usize, u64)>, filler: &mut Option<&mut User>, filler_key: &Pubkey, filler_stats: &mut Option<&mut UserStats>, @@ -1253,7 +1253,7 @@ fn fulfill_perp_order( determine_perp_fulfillment_methods( &user.orders[user_order_index], - &maker_order_info, + &maker_orders_info, &market.amm, reserve_price_before, Some(oracle_price), diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 5c7441c2e..13f542f9b 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -8171,12 +8171,12 @@ pub mod sort_maker_orders { } } -pub mod get_maker_order_info { +pub mod get_maker_orders_info { use std::str::FromStr; use anchor_lang::prelude::Clock; - use crate::controller::orders::get_maker_order_info; + use crate::controller::orders::get_maker_orders_info; use crate::controller::position::PositionDirection; use crate::create_account_info; use crate::create_anchor_account_info; @@ -8370,7 +8370,7 @@ pub mod get_maker_order_info { let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let maker_order_price_and_indexes = get_maker_order_info( + let maker_order_price_and_indexes = get_maker_orders_info( &market_map, &spot_market_map, &mut oracle_map, @@ -8564,7 +8564,7 @@ pub mod get_maker_order_info { let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let maker_order_price_and_indexes = get_maker_order_info( + let maker_order_price_and_indexes = get_maker_orders_info( &market_map, &spot_market_map, &mut oracle_map, @@ -8747,7 +8747,7 @@ pub mod get_maker_order_info { let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); - let maker_order_price_and_indexes = get_maker_order_info( + let maker_order_price_and_indexes = get_maker_orders_info( &market_map, &spot_market_map, &mut oracle_map, diff --git a/programs/drift/src/math/fulfillment.rs b/programs/drift/src/math/fulfillment.rs index 544f1e639..18cf70292 100644 --- a/programs/drift/src/math/fulfillment.rs +++ b/programs/drift/src/math/fulfillment.rs @@ -12,7 +12,7 @@ mod tests; pub fn determine_perp_fulfillment_methods( taker_order: &Order, - maker_order_info: &[(Pubkey, usize, u64)], + maker_orders_info: &[(Pubkey, usize, u64)], amm: &AMM, amm_reserve_price: u64, valid_oracle_price: Option, @@ -33,7 +33,7 @@ pub fn determine_perp_fulfillment_methods( 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_order_info.iter() { + for (maker_key, maker_order_index, maker_price) in maker_orders_info.iter() { let taker_crosses_maker = match taker_price { Some(taker_price) => do_orders_cross(maker_direction, *maker_price, taker_price), None => true, From 6f9e89409939ccf7d9f7de87f75540533249fa8c Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 28 Feb 2023 20:42:22 -0500 Subject: [PATCH 17/29] add get_ref to user maps --- programs/drift/src/controller/orders.rs | 2 +- programs/drift/src/state/user_map.rs | 136 ++++++++++++------------ 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 7f751927d..b8ccbb7da 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1404,7 +1404,7 @@ fn fulfill_perp_order( } for (maker_key, _) in makers_filled { - let maker = makers_and_referrer.get_ref_mut(&maker_key)?; + let maker = makers_and_referrer.get_ref(&maker_key)?; let (_, maker_total_collateral, maker_margin_requirement_plus_buffer, _) = calculate_margin_requirement_and_total_collateral( diff --git a/programs/drift/src/state/user_map.rs b/programs/drift/src/state/user_map.rs index 6614a0087..d9070a888 100644 --- a/programs/drift/src/state/user_map.rs +++ b/programs/drift/src/state/user_map.rs @@ -9,7 +9,7 @@ use arrayref::array_ref; use solana_program::account_info::AccountInfo; use solana_program::msg; use solana_program::pubkey::Pubkey; -use std::cell::RefMut; +use std::cell::{Ref, RefMut}; use std::collections::BTreeMap; use std::iter::Peekable; use std::panic::Location; @@ -18,39 +18,39 @@ use std::slice::Iter; pub struct UserMap<'a>(pub BTreeMap>); impl<'a> UserMap<'a> { - // #[track_caller] - // #[inline(always)] - // pub fn get_ref(&self, market_index: &u16) -> DriftResult> { - // let loader = match self.0.get(market_index) { - // Some(loader) => loader, - // None => { - // let caller = Location::caller(); - // msg!( - // "Could not find perp market {} at {}:{}", - // market_index, - // caller.file(), - // caller.line() - // ); - // return Err(ErrorCode::PerpMarketNotFound); - // } - // }; - // - // match loader.load() { - // Ok(perp_market) => Ok(perp_market), - // Err(e) => { - // let caller = Location::caller(); - // msg!("{:?}", e); - // msg!( - // "Could not load perp market {} at {}:{}", - // market_index, - // caller.file(), - // caller.line() - // ); - // Err(ErrorCode::UnableToLoadPerpMarketAccount) - // } - // } - // } - // + #[track_caller] + #[inline(always)] + pub fn get_ref(&self, user: &Pubkey) -> DriftResult> { + let loader = match self.0.get(user) { + Some(loader) => loader, + None => { + let caller = Location::caller(); + msg!( + "Could not find user {} at {}:{}", + user, + caller.file(), + caller.line() + ); + return Err(ErrorCode::UserNotFound); + } + }; + + match loader.load() { + Ok(user) => Ok(user), + Err(e) => { + let caller = Location::caller(); + msg!("{:?}", e); + msg!( + "Could not load user {} at {}:{}", + user, + caller.file(), + caller.line() + ); + Err(ErrorCode::UnableToLoadUserAccount) + } + } + } + #[track_caller] #[inline(always)] pub fn get_ref_mut(&self, user: &Pubkey) -> DriftResult> { @@ -64,7 +64,7 @@ impl<'a> UserMap<'a> { caller.file(), caller.line() ); - return Err(ErrorCode::PerpMarketNotFound); + return Err(ErrorCode::UserNotFound); } }; @@ -142,39 +142,39 @@ impl<'a> UserMap<'a> { pub struct UserStatsMap<'a>(pub BTreeMap>); impl<'a> UserStatsMap<'a> { - // #[track_caller] - // #[inline(always)] - // pub fn get_ref(&self, market_index: &u16) -> DriftResult> { - // let loader = match self.0.get(market_index) { - // Some(loader) => loader, - // None => { - // let caller = Location::caller(); - // msg!( - // "Could not find perp market {} at {}:{}", - // market_index, - // caller.file(), - // caller.line() - // ); - // return Err(ErrorCode::PerpMarketNotFound); - // } - // }; - // - // match loader.load() { - // Ok(perp_market) => Ok(perp_market), - // Err(e) => { - // let caller = Location::caller(); - // msg!("{:?}", e); - // msg!( - // "Could not load perp market {} at {}:{}", - // market_index, - // caller.file(), - // caller.line() - // ); - // Err(ErrorCode::UnableToLoadPerpMarketAccount) - // } - // } - // } - // + #[track_caller] + #[inline(always)] + pub fn get_ref(&self, authority: &Pubkey) -> DriftResult> { + let loader = match self.0.get(authority) { + Some(loader) => loader, + None => { + let caller = Location::caller(); + msg!( + "Could not find user stats {} at {}:{}", + authority, + caller.file(), + caller.line() + ); + return Err(ErrorCode::UserStatsNotFound); + } + }; + + match loader.load() { + Ok(user_stats) => Ok(user_stats), + Err(e) => { + let caller = Location::caller(); + msg!("{:?}", e); + msg!( + "Could not user stats {} at {}:{}", + authority, + caller.file(), + caller.line() + ); + Err(ErrorCode::UnableToLoadUserStatsAccount) + } + } + } + #[track_caller] #[inline(always)] pub fn get_ref_mut(&self, authority: &Pubkey) -> DriftResult> { From 7a59dda4a6d3cf3aaf5dfb123367b4dc964fabc2 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Wed, 1 Mar 2023 09:12:39 -0500 Subject: [PATCH 18/29] add multiple makers test for get_maker_order_info --- programs/drift/src/controller/orders.rs | 4 +- programs/drift/src/controller/orders/tests.rs | 258 +++++++++++++++++- 2 files changed, 258 insertions(+), 4 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index b8ccbb7da..04ad117fc 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1171,8 +1171,8 @@ fn sort_maker_orders( taker_order_direction: PositionDirection, ) { maker_orders_info.sort_by(|a, b| match taker_order_direction { - PositionDirection::Long => a.1.cmp(&b.1), - PositionDirection::Short => b.1.cmp(&a.1), + PositionDirection::Long => a.2.cmp(&b.2), + PositionDirection::Short => b.2.cmp(&a.2), }); } diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 13f542f9b..1012ba6f1 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -8174,11 +8174,10 @@ pub mod sort_maker_orders { pub mod get_maker_orders_info { use std::str::FromStr; - use anchor_lang::prelude::Clock; + use anchor_lang::prelude::{AccountLoader, Clock}; use crate::controller::orders::get_maker_orders_info; use crate::controller::position::PositionDirection; - use crate::create_account_info; use crate::create_anchor_account_info; use crate::math::constants::{ AMM_RESERVE_PRECISION, BASE_PRECISION_I64, BASE_PRECISION_U64, PEG_PRECISION, @@ -8197,6 +8196,7 @@ pub mod get_maker_orders_info { use crate::test_utils::{ create_account_info, get_orders, get_positions, get_pyth_price, get_spot_positions, }; + use crate::{create_account_info, get_orders}; use super::*; @@ -8766,4 +8766,258 @@ pub mod get_maker_orders_info { assert_eq!(maker_order_price_and_indexes, vec![],); } + + #[test] + fn two_makers() { + let clock = Clock { + slot: 6, + epoch_start_timestamp: 0, + epoch: 0, + leader_schedule_epoch: 0, + unix_timestamp: 0, + }; + + let mut pyth_price = get_pyth_price(100, 6); + let oracle_price = 100 * PRICE_PRECISION_I64; + let oracle_price_key = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); + let pyth_program = crate::ids::pyth_program::id(); + create_account_info!( + pyth_price, + &oracle_price_key, + &pyth_program, + oracle_account_info + ); + let mut oracle_map = OracleMap::load_one(&oracle_account_info, clock.slot, None).unwrap(); + + let mut market = PerpMarket { + amm: AMM { + base_asset_reserve: 100 * AMM_RESERVE_PRECISION, + quote_asset_reserve: 100 * AMM_RESERVE_PRECISION, + terminal_quote_asset_reserve: 100 * AMM_RESERVE_PRECISION, + sqrt_k: 100 * AMM_RESERVE_PRECISION, + peg_multiplier: 100 * PEG_PRECISION, + max_slippage_ratio: 100, + max_fill_reserve_fraction: 100, + order_step_size: 1000, + order_tick_size: 1, + oracle: oracle_price_key, + max_spread: 1000, + base_spread: 0, + long_spread: 0, + short_spread: 0, + historical_oracle_data: HistoricalOracleData { + last_oracle_price_twap: pyth_price.twap as i64, + last_oracle_price_twap_5min: pyth_price.twap as i64, + last_oracle_price: pyth_price.agg.price as i64, + ..HistoricalOracleData::default() + }, + ..AMM::default() + }, + margin_ratio_initial: 1000, + margin_ratio_maintenance: 500, + status: MarketStatus::Initialized, + ..PerpMarket::default() + }; + market.status = MarketStatus::Active; + market.amm.max_base_asset_reserve = u128::MAX; + market.amm.min_base_asset_reserve = 0; + let (new_ask_base_asset_reserve, new_ask_quote_asset_reserve) = + crate::math::amm_spread::calculate_spread_reserves( + &market.amm, + PositionDirection::Long, + ) + .unwrap(); + let (new_bid_base_asset_reserve, new_bid_quote_asset_reserve) = + crate::math::amm_spread::calculate_spread_reserves( + &market.amm, + PositionDirection::Short, + ) + .unwrap(); + market.amm.ask_base_asset_reserve = new_ask_base_asset_reserve; + market.amm.bid_base_asset_reserve = new_bid_base_asset_reserve; + market.amm.ask_quote_asset_reserve = new_ask_quote_asset_reserve; + market.amm.bid_quote_asset_reserve = new_bid_quote_asset_reserve; + create_anchor_account_info!(market, PerpMarket, market_account_info); + let market_map = PerpMarketMap::load_one(&market_account_info, true).unwrap(); + + let mut spot_market = SpotMarket { + market_index: 0, + oracle_source: OracleSource::QuoteAsset, + cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, + decimals: 6, + initial_asset_weight: SPOT_WEIGHT_PRECISION, + maintenance_asset_weight: SPOT_WEIGHT_PRECISION, + ..SpotMarket::default() + }; + create_anchor_account_info!(spot_market, SpotMarket, spot_market_account_info); + let spot_market_map = SpotMarketMap::load_one(&spot_market_account_info, true).unwrap(); + + let taker_key = Pubkey::default(); + let taker_authority = + Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); + let user = User { + authority: taker_authority, + orders: get_orders(Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Market, + direction: PositionDirection::Long, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + auction_start_price: 0, + auction_end_price: 50 * PRICE_PRECISION_I64, + auction_duration: 5, + price: 100 * PRICE_PRECISION_U64, + max_ts: 1, + ..Order::default() + }), + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 1, + open_bids: BASE_PRECISION_I64, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + + let mut first_maker = User { + orders: get_orders!( + Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 100 * PRICE_PRECISION_U64, + ..Order::default() + }, + Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 102 * PRICE_PRECISION_U64, + ..Order::default() + } + ), + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 2, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + let first_maker_key = + Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + create_anchor_account_info!( + first_maker, + &first_maker_key, + User, + first_maker_account_info + ); + + let mut second_maker = User { + orders: get_orders!( + Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 101 * PRICE_PRECISION_U64, + ..Order::default() + }, + Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 103 * PRICE_PRECISION_U64, + ..Order::default() + } + ), + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 2, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + let second_maker_key = + Pubkey::from_str("My11111111111111111111111111111111111111112").unwrap(); + create_anchor_account_info!( + second_maker, + &second_maker_key, + User, + second_maker_account_info + ); + + let mut makers_and_referrers = UserMap::load_one(&first_maker_account_info).unwrap(); + makers_and_referrers + .insert( + second_maker_key, + AccountLoader::try_from(&second_maker_account_info).unwrap(), + ) + .unwrap(); + + let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); + let mut filler = User::default(); + + let maker_order_price_and_indexes = get_maker_orders_info( + &market_map, + &spot_market_map, + &mut oracle_map, + &makers_and_referrers, + &taker_key, + &user.orders[0], + &mut Some(&mut filler), + &filler_key, + 0, + oracle_price, + None, + clock.unix_timestamp, + clock.slot, + ) + .unwrap(); + + assert_eq!( + maker_order_price_and_indexes, + vec![ + (first_maker_key, 0, 100000000), + (second_maker_key, 0, 101000000), + (first_maker_key, 1, 102000000), + (second_maker_key, 1, 103000000), + ], + ); + } } From ed670c89164471fcfdfb5bdb84b3aa1f0fda47de Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Wed, 1 Mar 2023 09:48:02 -0500 Subject: [PATCH 19/29] add jit maker test --- programs/drift/src/controller/orders/tests.rs | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 1012ba6f1..95d6698f8 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -9020,4 +9020,200 @@ pub mod get_maker_orders_info { ], ); } + + #[test] + fn jit_maker_order_id() { + let clock = Clock { + slot: 6, + epoch_start_timestamp: 0, + epoch: 0, + leader_schedule_epoch: 0, + unix_timestamp: 0, + }; + + let mut pyth_price = get_pyth_price(100, 6); + let oracle_price = 100 * PRICE_PRECISION_I64; + let oracle_price_key = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); + let pyth_program = crate::ids::pyth_program::id(); + create_account_info!( + pyth_price, + &oracle_price_key, + &pyth_program, + oracle_account_info + ); + let mut oracle_map = OracleMap::load_one(&oracle_account_info, clock.slot, None).unwrap(); + + let mut market = PerpMarket { + amm: AMM { + base_asset_reserve: 100 * AMM_RESERVE_PRECISION, + quote_asset_reserve: 100 * AMM_RESERVE_PRECISION, + terminal_quote_asset_reserve: 100 * AMM_RESERVE_PRECISION, + sqrt_k: 100 * AMM_RESERVE_PRECISION, + peg_multiplier: 100 * PEG_PRECISION, + max_slippage_ratio: 100, + max_fill_reserve_fraction: 100, + order_step_size: 1000, + order_tick_size: 1, + oracle: oracle_price_key, + max_spread: 1000, + base_spread: 0, + long_spread: 0, + short_spread: 0, + historical_oracle_data: HistoricalOracleData { + last_oracle_price_twap: pyth_price.twap as i64, + last_oracle_price_twap_5min: pyth_price.twap as i64, + last_oracle_price: pyth_price.agg.price as i64, + ..HistoricalOracleData::default() + }, + ..AMM::default() + }, + margin_ratio_initial: 1000, + margin_ratio_maintenance: 500, + status: MarketStatus::Initialized, + ..PerpMarket::default() + }; + market.status = MarketStatus::Active; + market.amm.max_base_asset_reserve = u128::MAX; + market.amm.min_base_asset_reserve = 0; + let (new_ask_base_asset_reserve, new_ask_quote_asset_reserve) = + crate::math::amm_spread::calculate_spread_reserves( + &market.amm, + PositionDirection::Long, + ) + .unwrap(); + let (new_bid_base_asset_reserve, new_bid_quote_asset_reserve) = + crate::math::amm_spread::calculate_spread_reserves( + &market.amm, + PositionDirection::Short, + ) + .unwrap(); + market.amm.ask_base_asset_reserve = new_ask_base_asset_reserve; + market.amm.bid_base_asset_reserve = new_bid_base_asset_reserve; + market.amm.ask_quote_asset_reserve = new_ask_quote_asset_reserve; + market.amm.bid_quote_asset_reserve = new_bid_quote_asset_reserve; + create_anchor_account_info!(market, PerpMarket, market_account_info); + let market_map = PerpMarketMap::load_one(&market_account_info, true).unwrap(); + + let mut spot_market = SpotMarket { + market_index: 0, + oracle_source: OracleSource::QuoteAsset, + cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, + decimals: 6, + initial_asset_weight: SPOT_WEIGHT_PRECISION, + maintenance_asset_weight: SPOT_WEIGHT_PRECISION, + ..SpotMarket::default() + }; + create_anchor_account_info!(spot_market, SpotMarket, spot_market_account_info); + let spot_market_map = SpotMarketMap::load_one(&spot_market_account_info, true).unwrap(); + + let taker_key = Pubkey::default(); + let taker_authority = + Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); + let user = User { + authority: taker_authority, + orders: get_orders(Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Market, + direction: PositionDirection::Long, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + auction_start_price: 0, + auction_end_price: 50 * PRICE_PRECISION_I64, + auction_duration: 5, + price: 100 * PRICE_PRECISION_U64, + max_ts: 1, + ..Order::default() + }), + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 1, + open_bids: BASE_PRECISION_I64, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + + let mut first_maker = User { + orders: get_orders!( + Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 100 * PRICE_PRECISION_U64, + ..Order::default() + }, + Order { + market_index: 0, + order_id: 2, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 102 * PRICE_PRECISION_U64, + ..Order::default() + } + ), + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 2, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + let first_maker_key = + Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + create_anchor_account_info!( + first_maker, + &first_maker_key, + User, + first_maker_account_info + ); + + let mut makers_and_referrers = UserMap::load_one(&first_maker_account_info).unwrap(); + + let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); + let mut filler = User::default(); + + let maker_order_price_and_indexes = get_maker_orders_info( + &market_map, + &spot_market_map, + &mut oracle_map, + &makers_and_referrers, + &taker_key, + &user.orders[0], + &mut Some(&mut filler), + &filler_key, + 0, + oracle_price, + Some(2), + clock.unix_timestamp, + clock.slot, + ) + .unwrap(); + + assert_eq!( + maker_order_price_and_indexes, + vec![(first_maker_key, 1, 102000000),], + ); + } } From 4d09844f4258a280904e47fa1568e2c6d573a4a3 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Wed, 1 Mar 2023 09:50:20 -0500 Subject: [PATCH 20/29] tweak sort_maker_orders to make them less likely to have false positive --- programs/drift/src/controller/orders/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 95d6698f8..c631e7493 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -8132,8 +8132,8 @@ pub mod sort_maker_orders { fn bids() { let mut bids = vec![ (Pubkey::default(), 0, 1), - (Pubkey::default(), 1, 10), (Pubkey::default(), 2, 100), + (Pubkey::default(), 1, 10), ]; let taker_direction = PositionDirection::Short; @@ -8152,8 +8152,8 @@ pub mod sort_maker_orders { #[test] fn asks() { let mut asks = vec![ - (Pubkey::default(), 2, 100), (Pubkey::default(), 1, 10), + (Pubkey::default(), 2, 100), (Pubkey::default(), 0, 1), ]; let taker_direction = PositionDirection::Long; @@ -9189,7 +9189,7 @@ pub mod get_maker_orders_info { first_maker_account_info ); - let mut makers_and_referrers = UserMap::load_one(&first_maker_account_info).unwrap(); + let makers_and_referrers = UserMap::load_one(&first_maker_account_info).unwrap(); let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); let mut filler = User::default(); From bfeb2d2ea80956103a4d8b4dfe54eee763bf75d4 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Wed, 1 Mar 2023 09:53:50 -0500 Subject: [PATCH 21/29] test for two_makers_with_max_orders --- programs/drift/src/controller/orders/tests.rs | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index c631e7493..4609baa9b 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -9216,4 +9216,224 @@ pub mod get_maker_orders_info { vec![(first_maker_key, 1, 102000000),], ); } + + #[test] + fn two_makers_with_max_orders() { + let clock = Clock { + slot: 6, + epoch_start_timestamp: 0, + epoch: 0, + leader_schedule_epoch: 0, + unix_timestamp: 0, + }; + + let mut pyth_price = get_pyth_price(100, 6); + let oracle_price = 100 * PRICE_PRECISION_I64; + let oracle_price_key = + Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap(); + let pyth_program = crate::ids::pyth_program::id(); + create_account_info!( + pyth_price, + &oracle_price_key, + &pyth_program, + oracle_account_info + ); + let mut oracle_map = OracleMap::load_one(&oracle_account_info, clock.slot, None).unwrap(); + + let mut market = PerpMarket { + amm: AMM { + base_asset_reserve: 100 * AMM_RESERVE_PRECISION, + quote_asset_reserve: 100 * AMM_RESERVE_PRECISION, + terminal_quote_asset_reserve: 100 * AMM_RESERVE_PRECISION, + sqrt_k: 100 * AMM_RESERVE_PRECISION, + peg_multiplier: 100 * PEG_PRECISION, + max_slippage_ratio: 100, + max_fill_reserve_fraction: 100, + order_step_size: 1000, + order_tick_size: 1, + oracle: oracle_price_key, + max_spread: 1000, + base_spread: 0, + long_spread: 0, + short_spread: 0, + historical_oracle_data: HistoricalOracleData { + last_oracle_price_twap: pyth_price.twap as i64, + last_oracle_price_twap_5min: pyth_price.twap as i64, + last_oracle_price: pyth_price.agg.price as i64, + ..HistoricalOracleData::default() + }, + ..AMM::default() + }, + margin_ratio_initial: 1000, + margin_ratio_maintenance: 500, + status: MarketStatus::Initialized, + ..PerpMarket::default() + }; + market.status = MarketStatus::Active; + market.amm.max_base_asset_reserve = u128::MAX; + market.amm.min_base_asset_reserve = 0; + let (new_ask_base_asset_reserve, new_ask_quote_asset_reserve) = + crate::math::amm_spread::calculate_spread_reserves( + &market.amm, + PositionDirection::Long, + ) + .unwrap(); + let (new_bid_base_asset_reserve, new_bid_quote_asset_reserve) = + crate::math::amm_spread::calculate_spread_reserves( + &market.amm, + PositionDirection::Short, + ) + .unwrap(); + market.amm.ask_base_asset_reserve = new_ask_base_asset_reserve; + market.amm.bid_base_asset_reserve = new_bid_base_asset_reserve; + market.amm.ask_quote_asset_reserve = new_ask_quote_asset_reserve; + market.amm.bid_quote_asset_reserve = new_bid_quote_asset_reserve; + create_anchor_account_info!(market, PerpMarket, market_account_info); + let market_map = PerpMarketMap::load_one(&market_account_info, true).unwrap(); + + let mut spot_market = SpotMarket { + market_index: 0, + oracle_source: OracleSource::QuoteAsset, + cumulative_deposit_interest: SPOT_CUMULATIVE_INTEREST_PRECISION, + decimals: 6, + initial_asset_weight: SPOT_WEIGHT_PRECISION, + maintenance_asset_weight: SPOT_WEIGHT_PRECISION, + ..SpotMarket::default() + }; + create_anchor_account_info!(spot_market, SpotMarket, spot_market_account_info); + let spot_market_map = SpotMarketMap::load_one(&spot_market_account_info, true).unwrap(); + + let taker_key = Pubkey::default(); + let taker_authority = + Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); + let user = User { + authority: taker_authority, + orders: get_orders(Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Market, + direction: PositionDirection::Long, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + auction_start_price: 0, + auction_end_price: 50 * PRICE_PRECISION_I64, + auction_duration: 5, + price: 100 * PRICE_PRECISION_U64, + max_ts: 1, + ..Order::default() + }), + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 1, + open_bids: BASE_PRECISION_I64, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + + let mut first_maker = User { + orders: [Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 100 * PRICE_PRECISION_U64, + ..Order::default() + }; 32], + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 2, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + let first_maker_key = + Pubkey::from_str("My11111111111111111111111111111111111111113").unwrap(); + create_anchor_account_info!( + first_maker, + &first_maker_key, + User, + first_maker_account_info + ); + + let mut second_maker = User { + orders: [Order { + market_index: 0, + order_id: 1, + status: OrderStatus::Open, + order_type: OrderType::Limit, + direction: PositionDirection::Short, + base_asset_amount: BASE_PRECISION_U64, + slot: 0, + price: 101 * PRICE_PRECISION_U64, + ..Order::default() + }; 32], + perp_positions: get_positions(PerpPosition { + market_index: 0, + open_orders: 2, + ..PerpPosition::default() + }), + spot_positions: get_spot_positions(SpotPosition { + market_index: 0, + balance_type: SpotBalanceType::Deposit, + scaled_balance: 100 * SPOT_BALANCE_PRECISION_U64, + ..SpotPosition::default() + }), + ..User::default() + }; + let second_maker_key = + Pubkey::from_str("My11111111111111111111111111111111111111112").unwrap(); + create_anchor_account_info!( + second_maker, + &second_maker_key, + User, + second_maker_account_info + ); + + let mut makers_and_referrers = UserMap::load_one(&first_maker_account_info).unwrap(); + makers_and_referrers + .insert( + second_maker_key, + AccountLoader::try_from(&second_maker_account_info).unwrap(), + ) + .unwrap(); + + let filler_key = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap(); + let mut filler = User::default(); + + let maker_order_price_and_indexes = get_maker_orders_info( + &market_map, + &spot_market_map, + &mut oracle_map, + &makers_and_referrers, + &taker_key, + &user.orders[0], + &mut Some(&mut filler), + &filler_key, + 0, + oracle_price, + None, + clock.unix_timestamp, + clock.slot, + ) + .unwrap(); + + assert_eq!(maker_order_price_and_indexes.len(), 64); + } } From 176b9d31a6724da597787e8848ac779740f25eba Mon Sep 17 00:00:00 2001 From: 0xbigz Date: Thu, 2 Mar 2023 11:21:08 -0500 Subject: [PATCH 22/29] multipleMakerOrders.ts and changes for success --- programs/drift/src/math/amm_spread.rs | 6 +- tests/multipleMakerOrders.ts | 257 ++++++++++++++++++++++++-- 2 files changed, 244 insertions(+), 19 deletions(-) diff --git a/programs/drift/src/math/amm_spread.rs b/programs/drift/src/math/amm_spread.rs index 9934720c0..9478b34ed 100644 --- a/programs/drift/src/math/amm_spread.rs +++ b/programs/drift/src/math/amm_spread.rs @@ -58,12 +58,14 @@ pub fn calculate_base_asset_amount_to_trade_to_price( if new_base_asset_reserve > base_asset_reserve_before { let max_trade_amount = new_base_asset_reserve .safe_sub(base_asset_reserve_before)? - .cast::()?; + .cast::() + .unwrap_or(u64::MAX); Ok((max_trade_amount, PositionDirection::Short)) } else { let max_trade_amount = base_asset_reserve_before .safe_sub(new_base_asset_reserve)? - .cast::()?; + .cast::() + .unwrap_or(u64::MAX); Ok((max_trade_amount, PositionDirection::Long)) } } diff --git a/tests/multipleMakerOrders.ts b/tests/multipleMakerOrders.ts index 6e8a30cfb..449b8c28f 100644 --- a/tests/multipleMakerOrders.ts +++ b/tests/multipleMakerOrders.ts @@ -56,9 +56,10 @@ describe('multiple maker orders', () => { mantissaSqrtScale ); - const usdcAmount = new BN(1000 * 10 ** 6); + const usdcAmount = new BN(100000 * 10 ** 6); let solUsd; + let dogUsd; let marketIndexes; let spotMarketIndexes; let oracleInfos; @@ -68,8 +69,9 @@ describe('multiple maker orders', () => { userUSDCAccount = await mockUserUSDCAccount(usdcMint, usdcAmount, provider); solUsd = await mockOracle(100); + dogUsd = await mockOracle(0.6899, -4, 0); - marketIndexes = [0]; + marketIndexes = [0, 1]; spotMarketIndexes = [0]; oracleInfos = [{ publicKey: solUsd, source: OracleSource.PYTH }]; @@ -110,6 +112,23 @@ describe('multiple maker orders', () => { PRICE_PRECISION.toNumber() / 8 ); + await fillerDriftClient.initializePerpMarket( + dogUsd, + ammInitialBaseAssetReserve.div(new BN(100000)), + ammInitialQuoteAssetReserve.div(new BN(100000)), + periodicity, + new BN(0.69 * PEG_PRECISION.toNumber()), + OracleSource.PYTH, + MARGIN_PRECISION.toNumber() / 4, // 4x + MARGIN_PRECISION.toNumber() / 5 // 5x + ); + await fillerDriftClient.updatePerpMarketStatus(1, MarketStatus.ACTIVE); + + await fillerDriftClient.updatePerpMarketBaseSpread( + 1, + PRICE_PRECISION.toNumber() / 80 + ); + await fillerDriftClient.updatePerpMarketMarginRatio( 0, MARGIN_PRECISION.toNumber() / 2, @@ -140,7 +159,172 @@ describe('multiple maker orders', () => { await eventSubscriber.unsubscribe(); }); - it('long', async () => { + // it('taker long solUsd', async () => { + // const [takerDriftClient, takerUSDCAccount] = + // await createUserWithUSDCAccount( + // provider, + // usdcMint, + // chProgram, + // usdcAmount, + // marketIndexes, + // spotMarketIndexes, + // oracleInfos, + // bulkAccountLoader + // ); + + // await takerDriftClient.deposit(usdcAmount, 0, takerUSDCAccount); + + // const [makerDriftClient, makerUSDCAccount] = + // await createUserWithUSDCAccount( + // provider, + // usdcMint, + // chProgram, + // usdcAmount, + // marketIndexes, + // spotMarketIndexes, + // oracleInfos, + // bulkAccountLoader + // ); + + // await makerDriftClient.deposit(usdcAmount, 0, makerUSDCAccount); + + // for (let i = 0; i < 6; i++) { + // await makerDriftClient.placePerpOrder({ + // marketIndex: 0, + // direction: PositionDirection.SHORT, + // price: new BN(95 + i).mul(PRICE_PRECISION), + // orderType: OrderType.LIMIT, + // baseAssetAmount: BASE_PRECISION, + // }); + // } + + // const [secondMakerDriftClient, secondMakerUSDCAccount] = + // await createUserWithUSDCAccount( + // provider, + // usdcMint, + // chProgram, + // usdcAmount, + // marketIndexes, + // spotMarketIndexes, + // oracleInfos, + // bulkAccountLoader + // ); + + // await secondMakerDriftClient.deposit(usdcAmount, 0, secondMakerUSDCAccount); + + // for (let i = 0; i < 6; i++) { + // await secondMakerDriftClient.placePerpOrder({ + // marketIndex: 0, + // direction: PositionDirection.SHORT, + // price: new BN(95 + i).mul(PRICE_PRECISION), + // orderType: OrderType.LIMIT, + // baseAssetAmount: BASE_PRECISION, + // }); + // } + + // const takerBaseAssetAmount = new BN(6).mul(BASE_PRECISION); + // await takerDriftClient.placePerpOrder({ + // marketIndex: 0, + // orderType: OrderType.LIMIT, + // price: new BN(100).mul(PRICE_PRECISION), + // direction: PositionDirection.LONG, + // baseAssetAmount: takerBaseAssetAmount, + // }); + + // const makerInfo = [ + // { + // maker: await makerDriftClient.getUserAccountPublicKey(), + // makerUserAccount: makerDriftClient.getUserAccount(), + // makerStats: await makerDriftClient.getUserStatsAccountPublicKey(), + // }, + // { + // maker: await secondMakerDriftClient.getUserAccountPublicKey(), + // makerUserAccount: secondMakerDriftClient.getUserAccount(), + // makerStats: await secondMakerDriftClient.getUserStatsAccountPublicKey(), + // }, + // ]; + // const txSig = await fillerDriftClient.fillPerpOrder( + // await takerDriftClient.getUserAccountPublicKey(), + // takerDriftClient.getUserAccount(), + // takerDriftClient.getOrder(1), + // makerInfo + // ); + + // await printTxLogs(connection, txSig); + + // const orderActionRecords = eventSubscriber + // .getEventsArray('OrderActionRecord') + // .filter((record) => isVariant(record.action, 'fill')); + // assert(orderActionRecords.length === 6); + + // const takerPosition = takerDriftClient.getUser().getPerpPosition(0); + // assert(takerPosition.baseAssetAmount.eq(takerBaseAssetAmount)); + // assert(takerPosition.quoteAssetAmount.eq(new BN(-576576000))); + + // const makerPosition = makerDriftClient.getUser().getPerpPosition(0); + // assert( + // makerPosition.baseAssetAmount.eq( + // takerBaseAssetAmount.neg().div(new BN(2)) + // ) + // ); + // assert(makerPosition.quoteAssetAmount.eq(new BN(288057600))); + + // const secondMakerPosition = secondMakerDriftClient + // .getUser() + // .getPerpPosition(0); + // assert( + // secondMakerPosition.baseAssetAmount.eq( + // takerBaseAssetAmount.neg().div(new BN(2)) + // ) + // ); + // assert(secondMakerPosition.quoteAssetAmount.eq(new BN(288057600))); + + // for (let i = 0; i < 3; i++) { + // await makerDriftClient.placePerpOrder({ + // marketIndex: 0, + // direction: PositionDirection.LONG, + // price: new BN(101 - i).mul(PRICE_PRECISION), + // orderType: OrderType.LIMIT, + // baseAssetAmount: BASE_PRECISION, + // }); + // } + + // for (let i = 0; i < 3; i++) { + // await secondMakerDriftClient.placePerpOrder({ + // marketIndex: 0, + // direction: PositionDirection.LONG, + // price: new BN(101 - i).mul(PRICE_PRECISION), + // orderType: OrderType.LIMIT, + // baseAssetAmount: BASE_PRECISION, + // }); + // } + + // await takerDriftClient.placePerpOrder({ + // marketIndex: 0, + // orderType: OrderType.LIMIT, + // price: new BN(90).mul(PRICE_PRECISION), + // direction: PositionDirection.SHORT, + // baseAssetAmount: takerBaseAssetAmount, + // }); + + // const txSig2 = await fillerDriftClient.fillPerpOrder( + // await takerDriftClient.getUserAccountPublicKey(), + // takerDriftClient.getUserAccount(), + // takerDriftClient.getOrder(2), + // makerInfo + // ); + + // const takerPosition2 = takerDriftClient.getUser().getPerpPosition(0); + // assert(takerPosition2.baseAssetAmount.eq(new BN(0))); + + // await printTxLogs(connection, txSig2); + + // await takerDriftClient.unsubscribe(); + // await makerDriftClient.unsubscribe(); + // await secondMakerDriftClient.unsubscribe(); + // }); + + it('taker short dogUsd', async () => { const [takerDriftClient, takerUSDCAccount] = await createUserWithUSDCAccount( provider, @@ -169,11 +353,11 @@ describe('multiple maker orders', () => { await makerDriftClient.deposit(usdcAmount, 0, makerUSDCAccount); - for (let i = 0; i < 6; i++) { + for (let i = 0; i < 1; i++) { await makerDriftClient.placePerpOrder({ - marketIndex: 0, - direction: PositionDirection.SHORT, - price: new BN(95 + i).mul(PRICE_PRECISION), + marketIndex: 1, + direction: PositionDirection.LONG, + price: new BN((0.69 - i / 100) * PRICE_PRECISION.toNumber()), orderType: OrderType.LIMIT, baseAssetAmount: BASE_PRECISION, }); @@ -193,22 +377,55 @@ describe('multiple maker orders', () => { await secondMakerDriftClient.deposit(usdcAmount, 0, secondMakerUSDCAccount); - for (let i = 0; i < 6; i++) { + for (let i = 0; i < 16; i++) { await secondMakerDriftClient.placePerpOrder({ - marketIndex: 0, - direction: PositionDirection.SHORT, - price: new BN(95 + i).mul(PRICE_PRECISION), + marketIndex: 1, + direction: PositionDirection.LONG, + price: new BN((0.69 - i / 50) * PRICE_PRECISION.toNumber()), orderType: OrderType.LIMIT, baseAssetAmount: BASE_PRECISION, }); } - const takerBaseAssetAmount = new BN(6).mul(BASE_PRECISION); + const [thirdMakerDriftClient, thirdMakerUSDCAccount] = + await createUserWithUSDCAccount( + provider, + usdcMint, + chProgram, + usdcAmount, + marketIndexes, + spotMarketIndexes, + oracleInfos, + bulkAccountLoader + ); + await thirdMakerDriftClient.deposit(usdcAmount, 0, thirdMakerUSDCAccount); + + for (let i = 0; i < 32; i++) { + if (i % 2 == 0) { + await thirdMakerDriftClient.placePerpOrder({ + marketIndex: 1, + direction: PositionDirection.LONG, + price: new BN((0.69 - i / 300) * PRICE_PRECISION.toNumber()), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } else { + await thirdMakerDriftClient.placePerpOrder({ + marketIndex: 1, + direction: PositionDirection.LONG, + oraclePriceOffset: -(i / 300) * PRICE_PRECISION.toNumber(), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + } + + const takerBaseAssetAmount = new BN(600).mul(BASE_PRECISION); await takerDriftClient.placePerpOrder({ - marketIndex: 0, + marketIndex: 1, orderType: OrderType.LIMIT, - price: new BN(100).mul(PRICE_PRECISION), - direction: PositionDirection.LONG, + price: new BN(0.675 * PRICE_PRECISION.toNumber()), + direction: PositionDirection.SHORT, baseAssetAmount: takerBaseAssetAmount, }); @@ -223,6 +440,11 @@ describe('multiple maker orders', () => { makerUserAccount: secondMakerDriftClient.getUserAccount(), makerStats: await secondMakerDriftClient.getUserStatsAccountPublicKey(), }, + { + maker: await thirdMakerDriftClient.getUserAccountPublicKey(), + makerUserAccount: thirdMakerDriftClient.getUserAccount(), + makerStats: await thirdMakerDriftClient.getUserStatsAccountPublicKey(), + }, ]; const txSig = await fillerDriftClient.fillPerpOrder( await takerDriftClient.getUserAccountPublicKey(), @@ -236,6 +458,7 @@ describe('multiple maker orders', () => { const orderActionRecords = eventSubscriber .getEventsArray('OrderActionRecord') .filter((record) => isVariant(record.action, 'fill')); + console.log('orderActionRecords.length=', orderActionRecords.length); assert(orderActionRecords.length === 6); const takerPosition = takerDriftClient.getUser().getPerpPosition(0); @@ -262,7 +485,7 @@ describe('multiple maker orders', () => { for (let i = 0; i < 3; i++) { await makerDriftClient.placePerpOrder({ - marketIndex: 0, + marketIndex: 1, direction: PositionDirection.LONG, price: new BN(101 - i).mul(PRICE_PRECISION), orderType: OrderType.LIMIT, @@ -272,7 +495,7 @@ describe('multiple maker orders', () => { for (let i = 0; i < 3; i++) { await secondMakerDriftClient.placePerpOrder({ - marketIndex: 0, + marketIndex: 1, direction: PositionDirection.LONG, price: new BN(101 - i).mul(PRICE_PRECISION), orderType: OrderType.LIMIT, From 67efeb1e98cff54a53b2d7896c9cc9efb98630da Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Thu, 2 Mar 2023 11:40:54 -0500 Subject: [PATCH 23/29] fix memory runnung out --- programs/drift/src/controller/orders.rs | 2 +- programs/drift/src/math/fulfillment.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 04ad117fc..c2fa1968c 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1369,7 +1369,7 @@ fn fulfill_perp_order( } for order_record in order_records { - emit!(order_record) + emit_stack::<_, { OrderActionRecord::SIZE }>(order_record)?; } let perp_market = perp_market_map.get_ref(&market_index)?; diff --git a/programs/drift/src/math/fulfillment.rs b/programs/drift/src/math/fulfillment.rs index 18cf70292..d26de2e5c 100644 --- a/programs/drift/src/math/fulfillment.rs +++ b/programs/drift/src/math/fulfillment.rs @@ -20,7 +20,7 @@ pub fn determine_perp_fulfillment_methods( slot: u64, min_auction_duration: u8, ) -> DriftResult> { - let mut fulfillment_methods = vec![]; + let mut fulfillment_methods = Vec::with_capacity(8); let can_fill_with_amm = amm_is_available && valid_oracle_price.is_some() From 9fd07cc0ea3f9f51609da7ae9fb086f3d89def16 Mon Sep 17 00:00:00 2001 From: 0xbigz Date: Thu, 2 Mar 2023 12:48:12 -0500 Subject: [PATCH 24/29] tests/multipleMakerOrders.ts: finish p2 test --- tests/multipleMakerOrders.ts | 440 ++++++++++++++++++++--------------- 1 file changed, 246 insertions(+), 194 deletions(-) diff --git a/tests/multipleMakerOrders.ts b/tests/multipleMakerOrders.ts index 449b8c28f..2cf6abe4b 100644 --- a/tests/multipleMakerOrders.ts +++ b/tests/multipleMakerOrders.ts @@ -159,170 +159,170 @@ describe('multiple maker orders', () => { await eventSubscriber.unsubscribe(); }); - // it('taker long solUsd', async () => { - // const [takerDriftClient, takerUSDCAccount] = - // await createUserWithUSDCAccount( - // provider, - // usdcMint, - // chProgram, - // usdcAmount, - // marketIndexes, - // spotMarketIndexes, - // oracleInfos, - // bulkAccountLoader - // ); - - // await takerDriftClient.deposit(usdcAmount, 0, takerUSDCAccount); - - // const [makerDriftClient, makerUSDCAccount] = - // await createUserWithUSDCAccount( - // provider, - // usdcMint, - // chProgram, - // usdcAmount, - // marketIndexes, - // spotMarketIndexes, - // oracleInfos, - // bulkAccountLoader - // ); - - // await makerDriftClient.deposit(usdcAmount, 0, makerUSDCAccount); - - // for (let i = 0; i < 6; i++) { - // await makerDriftClient.placePerpOrder({ - // marketIndex: 0, - // direction: PositionDirection.SHORT, - // price: new BN(95 + i).mul(PRICE_PRECISION), - // orderType: OrderType.LIMIT, - // baseAssetAmount: BASE_PRECISION, - // }); - // } - - // const [secondMakerDriftClient, secondMakerUSDCAccount] = - // await createUserWithUSDCAccount( - // provider, - // usdcMint, - // chProgram, - // usdcAmount, - // marketIndexes, - // spotMarketIndexes, - // oracleInfos, - // bulkAccountLoader - // ); - - // await secondMakerDriftClient.deposit(usdcAmount, 0, secondMakerUSDCAccount); - - // for (let i = 0; i < 6; i++) { - // await secondMakerDriftClient.placePerpOrder({ - // marketIndex: 0, - // direction: PositionDirection.SHORT, - // price: new BN(95 + i).mul(PRICE_PRECISION), - // orderType: OrderType.LIMIT, - // baseAssetAmount: BASE_PRECISION, - // }); - // } - - // const takerBaseAssetAmount = new BN(6).mul(BASE_PRECISION); - // await takerDriftClient.placePerpOrder({ - // marketIndex: 0, - // orderType: OrderType.LIMIT, - // price: new BN(100).mul(PRICE_PRECISION), - // direction: PositionDirection.LONG, - // baseAssetAmount: takerBaseAssetAmount, - // }); - - // const makerInfo = [ - // { - // maker: await makerDriftClient.getUserAccountPublicKey(), - // makerUserAccount: makerDriftClient.getUserAccount(), - // makerStats: await makerDriftClient.getUserStatsAccountPublicKey(), - // }, - // { - // maker: await secondMakerDriftClient.getUserAccountPublicKey(), - // makerUserAccount: secondMakerDriftClient.getUserAccount(), - // makerStats: await secondMakerDriftClient.getUserStatsAccountPublicKey(), - // }, - // ]; - // const txSig = await fillerDriftClient.fillPerpOrder( - // await takerDriftClient.getUserAccountPublicKey(), - // takerDriftClient.getUserAccount(), - // takerDriftClient.getOrder(1), - // makerInfo - // ); - - // await printTxLogs(connection, txSig); - - // const orderActionRecords = eventSubscriber - // .getEventsArray('OrderActionRecord') - // .filter((record) => isVariant(record.action, 'fill')); - // assert(orderActionRecords.length === 6); - - // const takerPosition = takerDriftClient.getUser().getPerpPosition(0); - // assert(takerPosition.baseAssetAmount.eq(takerBaseAssetAmount)); - // assert(takerPosition.quoteAssetAmount.eq(new BN(-576576000))); - - // const makerPosition = makerDriftClient.getUser().getPerpPosition(0); - // assert( - // makerPosition.baseAssetAmount.eq( - // takerBaseAssetAmount.neg().div(new BN(2)) - // ) - // ); - // assert(makerPosition.quoteAssetAmount.eq(new BN(288057600))); - - // const secondMakerPosition = secondMakerDriftClient - // .getUser() - // .getPerpPosition(0); - // assert( - // secondMakerPosition.baseAssetAmount.eq( - // takerBaseAssetAmount.neg().div(new BN(2)) - // ) - // ); - // assert(secondMakerPosition.quoteAssetAmount.eq(new BN(288057600))); - - // for (let i = 0; i < 3; i++) { - // await makerDriftClient.placePerpOrder({ - // marketIndex: 0, - // direction: PositionDirection.LONG, - // price: new BN(101 - i).mul(PRICE_PRECISION), - // orderType: OrderType.LIMIT, - // baseAssetAmount: BASE_PRECISION, - // }); - // } - - // for (let i = 0; i < 3; i++) { - // await secondMakerDriftClient.placePerpOrder({ - // marketIndex: 0, - // direction: PositionDirection.LONG, - // price: new BN(101 - i).mul(PRICE_PRECISION), - // orderType: OrderType.LIMIT, - // baseAssetAmount: BASE_PRECISION, - // }); - // } - - // await takerDriftClient.placePerpOrder({ - // marketIndex: 0, - // orderType: OrderType.LIMIT, - // price: new BN(90).mul(PRICE_PRECISION), - // direction: PositionDirection.SHORT, - // baseAssetAmount: takerBaseAssetAmount, - // }); - - // const txSig2 = await fillerDriftClient.fillPerpOrder( - // await takerDriftClient.getUserAccountPublicKey(), - // takerDriftClient.getUserAccount(), - // takerDriftClient.getOrder(2), - // makerInfo - // ); - - // const takerPosition2 = takerDriftClient.getUser().getPerpPosition(0); - // assert(takerPosition2.baseAssetAmount.eq(new BN(0))); - - // await printTxLogs(connection, txSig2); - - // await takerDriftClient.unsubscribe(); - // await makerDriftClient.unsubscribe(); - // await secondMakerDriftClient.unsubscribe(); - // }); + it('taker long solUsd', async () => { + const [takerDriftClient, takerUSDCAccount] = + await createUserWithUSDCAccount( + provider, + usdcMint, + chProgram, + usdcAmount, + marketIndexes, + spotMarketIndexes, + oracleInfos, + bulkAccountLoader + ); + + await takerDriftClient.deposit(usdcAmount, 0, takerUSDCAccount); + + const [makerDriftClient, makerUSDCAccount] = + await createUserWithUSDCAccount( + provider, + usdcMint, + chProgram, + usdcAmount, + marketIndexes, + spotMarketIndexes, + oracleInfos, + bulkAccountLoader + ); + + await makerDriftClient.deposit(usdcAmount, 0, makerUSDCAccount); + + for (let i = 0; i < 6; i++) { + await makerDriftClient.placePerpOrder({ + marketIndex: 0, + direction: PositionDirection.SHORT, + price: new BN(95 + i).mul(PRICE_PRECISION), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + + const [secondMakerDriftClient, secondMakerUSDCAccount] = + await createUserWithUSDCAccount( + provider, + usdcMint, + chProgram, + usdcAmount, + marketIndexes, + spotMarketIndexes, + oracleInfos, + bulkAccountLoader + ); + + await secondMakerDriftClient.deposit(usdcAmount, 0, secondMakerUSDCAccount); + + for (let i = 0; i < 6; i++) { + await secondMakerDriftClient.placePerpOrder({ + marketIndex: 0, + direction: PositionDirection.SHORT, + price: new BN(95 + i).mul(PRICE_PRECISION), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + + const takerBaseAssetAmount = new BN(6).mul(BASE_PRECISION); + await takerDriftClient.placePerpOrder({ + marketIndex: 0, + orderType: OrderType.LIMIT, + price: new BN(100).mul(PRICE_PRECISION), + direction: PositionDirection.LONG, + baseAssetAmount: takerBaseAssetAmount, + }); + + const makerInfo = [ + { + maker: await makerDriftClient.getUserAccountPublicKey(), + makerUserAccount: makerDriftClient.getUserAccount(), + makerStats: await makerDriftClient.getUserStatsAccountPublicKey(), + }, + { + maker: await secondMakerDriftClient.getUserAccountPublicKey(), + makerUserAccount: secondMakerDriftClient.getUserAccount(), + makerStats: await secondMakerDriftClient.getUserStatsAccountPublicKey(), + }, + ]; + const txSig = await fillerDriftClient.fillPerpOrder( + await takerDriftClient.getUserAccountPublicKey(), + takerDriftClient.getUserAccount(), + takerDriftClient.getOrder(1), + makerInfo + ); + + await printTxLogs(connection, txSig); + + const orderActionRecords = eventSubscriber + .getEventsArray('OrderActionRecord') + .filter((record) => isVariant(record.action, 'fill')); + assert(orderActionRecords.length === 6); + + const takerPosition = takerDriftClient.getUser().getPerpPosition(0); + assert(takerPosition.baseAssetAmount.eq(takerBaseAssetAmount)); + assert(takerPosition.quoteAssetAmount.eq(new BN(-576576000))); + + const makerPosition = makerDriftClient.getUser().getPerpPosition(0); + assert( + makerPosition.baseAssetAmount.eq( + takerBaseAssetAmount.neg().div(new BN(2)) + ) + ); + assert(makerPosition.quoteAssetAmount.eq(new BN(288057600))); + + const secondMakerPosition = secondMakerDriftClient + .getUser() + .getPerpPosition(0); + assert( + secondMakerPosition.baseAssetAmount.eq( + takerBaseAssetAmount.neg().div(new BN(2)) + ) + ); + assert(secondMakerPosition.quoteAssetAmount.eq(new BN(288057600))); + + for (let i = 0; i < 3; i++) { + await makerDriftClient.placePerpOrder({ + marketIndex: 0, + direction: PositionDirection.LONG, + price: new BN(101 - i).mul(PRICE_PRECISION), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + + for (let i = 0; i < 3; i++) { + await secondMakerDriftClient.placePerpOrder({ + marketIndex: 0, + direction: PositionDirection.LONG, + price: new BN(101 - i).mul(PRICE_PRECISION), + orderType: OrderType.LIMIT, + baseAssetAmount: BASE_PRECISION, + }); + } + + await takerDriftClient.placePerpOrder({ + marketIndex: 0, + orderType: OrderType.LIMIT, + price: new BN(90).mul(PRICE_PRECISION), + direction: PositionDirection.SHORT, + baseAssetAmount: takerBaseAssetAmount, + }); + + const txSig2 = await fillerDriftClient.fillPerpOrder( + await takerDriftClient.getUserAccountPublicKey(), + takerDriftClient.getUserAccount(), + takerDriftClient.getOrder(2), + makerInfo + ); + + const takerPosition2 = takerDriftClient.getUser().getPerpPosition(0); + assert(takerPosition2.baseAssetAmount.eq(new BN(0))); + + await printTxLogs(connection, txSig2); + + await takerDriftClient.unsubscribe(); + await makerDriftClient.unsubscribe(); + await secondMakerDriftClient.unsubscribe(); + }); it('taker short dogUsd', async () => { const [takerDriftClient, takerUSDCAccount] = @@ -381,7 +381,7 @@ describe('multiple maker orders', () => { await secondMakerDriftClient.placePerpOrder({ marketIndex: 1, direction: PositionDirection.LONG, - price: new BN((0.69 - i / 50) * PRICE_PRECISION.toNumber()), + price: new BN((0.69 - i / 500) * PRICE_PRECISION.toNumber()), orderType: OrderType.LIMIT, baseAssetAmount: BASE_PRECISION, }); @@ -405,7 +405,7 @@ describe('multiple maker orders', () => { await thirdMakerDriftClient.placePerpOrder({ marketIndex: 1, direction: PositionDirection.LONG, - price: new BN((0.69 - i / 300) * PRICE_PRECISION.toNumber()), + price: new BN((0.69 - i / 1000) * PRICE_PRECISION.toNumber()), orderType: OrderType.LIMIT, baseAssetAmount: BASE_PRECISION, }); @@ -413,7 +413,7 @@ describe('multiple maker orders', () => { await thirdMakerDriftClient.placePerpOrder({ marketIndex: 1, direction: PositionDirection.LONG, - oraclePriceOffset: -(i / 300) * PRICE_PRECISION.toNumber(), + oraclePriceOffset: -(i / 1000) * PRICE_PRECISION.toNumber(), orderType: OrderType.LIMIT, baseAssetAmount: BASE_PRECISION, }); @@ -459,56 +459,95 @@ describe('multiple maker orders', () => { .getEventsArray('OrderActionRecord') .filter((record) => isVariant(record.action, 'fill')); console.log('orderActionRecords.length=', orderActionRecords.length); - assert(orderActionRecords.length === 6); + assert(orderActionRecords.length === 8); - const takerPosition = takerDriftClient.getUser().getPerpPosition(0); - assert(takerPosition.baseAssetAmount.eq(takerBaseAssetAmount)); - assert(takerPosition.quoteAssetAmount.eq(new BN(-576576000))); + const takerPosition = takerDriftClient.getUser().getPerpPosition(1); + console.log( + 'takerPosition.baseAssetAmount=', + takerPosition.baseAssetAmount.toString() + ); + console.log( + 'takerPosition.quoteAssetAmount=', + takerPosition.quoteAssetAmount.toString() + ); + assert(takerPosition.baseAssetAmount.eq(new BN('-402763100000'))); + assert(takerPosition.quoteAssetAmount.eq(new BN('273795699'))); - const makerPosition = makerDriftClient.getUser().getPerpPosition(0); - assert( - makerPosition.baseAssetAmount.eq( - takerBaseAssetAmount.neg().div(new BN(2)) - ) + const makerPosition = makerDriftClient.getUser().getPerpPosition(1); + console.log( + 'makerPosition.baseAssetAmount=', + makerPosition.baseAssetAmount.toString() ); - assert(makerPosition.quoteAssetAmount.eq(new BN(288057600))); + console.log( + 'makerPosition.quoteAssetAmount=', + makerPosition.quoteAssetAmount.toString() + ); + assert(makerPosition.baseAssetAmount.eq(new BN('1000000000'))); + assert(makerPosition.quoteAssetAmount.eq(new BN('-689862'))); const secondMakerPosition = secondMakerDriftClient .getUser() - .getPerpPosition(0); - assert( - secondMakerPosition.baseAssetAmount.eq( - takerBaseAssetAmount.neg().div(new BN(2)) - ) + .getPerpPosition(1); + console.log( + 'secondMakerPosition.baseAssetAmount=', + secondMakerPosition.baseAssetAmount.toString() ); - assert(secondMakerPosition.quoteAssetAmount.eq(new BN(288057600))); + console.log( + 'secondMakerPosition.quoteAssetAmount=', + secondMakerPosition.quoteAssetAmount.toString() + ); + assert(secondMakerPosition.baseAssetAmount.eq(new BN('2000000000'))); + assert(secondMakerPosition.quoteAssetAmount.eq(new BN('-1377725'))); + + const thirdMakerPosition = thirdMakerDriftClient + .getUser() + .getPerpPosition(1); + console.log( + 'thirdMakerPosition.baseAssetAmount=', + thirdMakerPosition.baseAssetAmount.toString() + ); + console.log( + 'thirdMakerPosition.quoteAssetAmount=', + thirdMakerPosition.quoteAssetAmount.toString() + ); + assert(thirdMakerPosition.baseAssetAmount.eq(new BN('4000000000'))); + assert(thirdMakerPosition.quoteAssetAmount.eq(new BN('-2753251'))); + + const dogMarket = takerDriftClient.getPerpMarketAccount(1); + console.log( + 'dogMarket.amm.baseAssetAmountWithAmm=', + dogMarket.amm.baseAssetAmountWithAmm.toString() + ); + assert(dogMarket.amm.baseAssetAmountWithAmm.eq(new BN('-395763100000'))); + + // close position for (let i = 0; i < 3; i++) { await makerDriftClient.placePerpOrder({ marketIndex: 1, - direction: PositionDirection.LONG, - price: new BN(101 - i).mul(PRICE_PRECISION), + direction: PositionDirection.SHORT, + price: new BN((0.69 + i / 100) * PRICE_PRECISION.toNumber()), orderType: OrderType.LIMIT, baseAssetAmount: BASE_PRECISION, }); } - for (let i = 0; i < 3; i++) { + for (let i = 1; i < 2; i++) { await secondMakerDriftClient.placePerpOrder({ marketIndex: 1, - direction: PositionDirection.LONG, - price: new BN(101 - i).mul(PRICE_PRECISION), + direction: PositionDirection.SHORT, + price: new BN((0.69 + i / 400) * PRICE_PRECISION.toNumber()), orderType: OrderType.LIMIT, - baseAssetAmount: BASE_PRECISION, + baseAssetAmount: BASE_PRECISION.mul(new BN(100)), }); } await takerDriftClient.placePerpOrder({ - marketIndex: 0, + marketIndex: 1, orderType: OrderType.LIMIT, - price: new BN(90).mul(PRICE_PRECISION), - direction: PositionDirection.SHORT, - baseAssetAmount: takerBaseAssetAmount, + price: new BN(0.75 * PRICE_PRECISION.toNumber()), + direction: PositionDirection.LONG, + baseAssetAmount: takerPosition.baseAssetAmount, }); const txSig2 = await fillerDriftClient.fillPerpOrder( @@ -518,9 +557,22 @@ describe('multiple maker orders', () => { makerInfo ); - const takerPosition2 = takerDriftClient.getUser().getPerpPosition(0); + const takerPosition2 = takerDriftClient.getUser().getPerpPosition(1); + console.log( + 'takerPosition2.baseAssetAmount=', + takerPosition2.baseAssetAmount.toString() + ); assert(takerPosition2.baseAssetAmount.eq(new BN(0))); + const dogMarketAfter = takerDriftClient.getPerpMarketAccount(1); + console.log( + 'dogMarketAfter.amm.baseAssetAmountWithAmm=', + dogMarketAfter.amm.baseAssetAmountWithAmm.toString() + ); + assert( + dogMarketAfter.amm.baseAssetAmountWithAmm.eq(new BN('-65918100000')) + ); + await printTxLogs(connection, txSig2); await takerDriftClient.unsubscribe(); From f6f6ed8c1d369560d16ea47aa58e4a8d443bf2a9 Mon Sep 17 00:00:00 2001 From: 0xbigz Date: Thu, 2 Mar 2023 12:52:23 -0500 Subject: [PATCH 25/29] tests/multipleMakerOrders.ts: fix assert --- tests/multipleMakerOrders.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/multipleMakerOrders.ts b/tests/multipleMakerOrders.ts index 2cf6abe4b..6790f3aa6 100644 --- a/tests/multipleMakerOrders.ts +++ b/tests/multipleMakerOrders.ts @@ -459,7 +459,7 @@ describe('multiple maker orders', () => { .getEventsArray('OrderActionRecord') .filter((record) => isVariant(record.action, 'fill')); console.log('orderActionRecords.length=', orderActionRecords.length); - assert(orderActionRecords.length === 8); + assert(orderActionRecords.length === 20); const takerPosition = takerDriftClient.getUser().getPerpPosition(1); console.log( From 4d1f247f72d168568f58d537d369afe12173ace3 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Fri, 3 Mar 2023 15:14:30 -0500 Subject: [PATCH 26/29] fixed vector size for get_maker_orders_info --- programs/drift/src/controller/orders.rs | 42 ++++++++++++------- .../src/controller/orders/amm_jit_tests.rs | 24 +++++------ programs/drift/src/controller/orders/tests.rs | 42 +++++++++---------- 3 files changed, 58 insertions(+), 50 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index c2fa1968c..0d37cdd1a 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -2,6 +2,7 @@ use std::cell::RefMut; use std::collections::BTreeMap; use std::num::NonZeroU64; use std::ops::DerefMut; +use std::u64; use anchor_lang::prelude::*; use serum_dex::instruction::{NewOrderInstructionV3, SelfTradeBehavior}; @@ -865,7 +866,7 @@ pub fn fill_perp_order( user_stats, makers_and_referrer, makers_and_referrer_stats, - maker_orders_info, + &maker_orders_info, &mut filler.as_deref_mut(), &filler_key, &mut filler_stats.as_deref_mut(), @@ -1038,10 +1039,10 @@ fn get_maker_orders_info( now: i64, slot: u64, ) -> DriftResult> { - let mut maker_orders_info = Vec::with_capacity(32); - let maker_direction = taker_order.direction.opposite(); + let mut maker_orders_info = Vec::with_capacity(16); + for (maker_key, user_account_loader) in makers_and_referrer.0.iter() { if maker_key == taker_key { continue; @@ -1156,24 +1157,35 @@ fn get_maker_orders_info( continue; } - maker_orders_info.push((*maker_key, maker_order_index, maker_order_price)); + insert_maker_order_info( + &mut maker_orders_info, + (*maker_key, maker_order_index, maker_order_price), + maker_direction, + ); } } - sort_maker_orders(&mut maker_orders_info, taker_order.direction); - Ok(maker_orders_info) } #[inline(always)] -fn sort_maker_orders( - maker_orders_info: &mut [(Pubkey, usize, u64)], - taker_order_direction: PositionDirection, +fn insert_maker_order_info( + maker_orders_info: &mut Vec<(Pubkey, usize, u64)>, + maker_order_info: (Pubkey, usize, u64), + direction: PositionDirection, ) { - maker_orders_info.sort_by(|a, b| match taker_order_direction { - PositionDirection::Long => a.2.cmp(&b.2), - PositionDirection::Short => b.2.cmp(&a.2), - }); + let price = maker_order_info.2; + let index = match maker_orders_info.binary_search_by(|item| match direction { + PositionDirection::Short => item.2.cmp(&price), + PositionDirection::Long => price.cmp(&item.2), + }) { + Ok(index) => index, + Err(index) => index, + }; + + if index < maker_orders_info.capacity() { + maker_orders_info.insert(index, maker_order_info); + } } fn get_referrer_info( @@ -1223,7 +1235,7 @@ fn fulfill_perp_order( user_stats: &mut UserStats, makers_and_referrer: &UserMap, makers_and_referrer_stats: &UserStatsMap, - maker_orders_info: Vec<(Pubkey, usize, u64)>, + maker_orders_info: &[(Pubkey, usize, u64)], filler: &mut Option<&mut User>, filler_key: &Pubkey, filler_stats: &mut Option<&mut UserStats>, @@ -1253,7 +1265,7 @@ fn fulfill_perp_order( determine_perp_fulfillment_methods( &user.orders[user_order_index], - &maker_orders_info, + maker_orders_info, &market.amm, reserve_price_before, Some(oracle_price), diff --git a/programs/drift/src/controller/orders/amm_jit_tests.rs b/programs/drift/src/controller/orders/amm_jit_tests.rs index 33c256508..ecc00090a 100644 --- a/programs/drift/src/controller/orders/amm_jit_tests.rs +++ b/programs/drift/src/controller/orders/amm_jit_tests.rs @@ -293,7 +293,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -480,7 +480,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 99 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 99 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -675,7 +675,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 99 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 99 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -869,7 +869,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -1071,7 +1071,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -1282,7 +1282,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -1485,7 +1485,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -1670,7 +1670,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 10 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 10 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -1867,7 +1867,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 200 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 200 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -2116,7 +2116,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, auction_price)], + &[(maker_key, 0, auction_price)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -2398,7 +2398,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, auction_price)], + &[(maker_key, 0, auction_price)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -2624,7 +2624,7 @@ pub mod amm_jit { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 10 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 10 * PRICE_PRECISION_U64)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index 4609baa9b..ada0ea641 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -2705,7 +2705,7 @@ pub mod fulfill_order { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![( + &[( Pubkey::default(), 0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000, @@ -2947,7 +2947,7 @@ pub mod fulfill_order { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![ + &[ (maker_key, 0, 90 * PRICE_PRECISION_U64), (maker_key, 1, 95 * PRICE_PRECISION_U64), ], @@ -3137,7 +3137,7 @@ pub mod fulfill_order { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000)], + &[(maker_key, 0, 100_010_000 * PRICE_PRECISION_U64 / 1_000_000)], &mut Some(&mut filler), &filler_key, &mut Some(&mut filler_stats), @@ -3340,7 +3340,7 @@ pub mod fulfill_order { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 0, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 0, 100 * PRICE_PRECISION_U64)], &mut None, &filler_key, &mut None, @@ -3503,7 +3503,7 @@ pub mod fulfill_order { &mut taker_stats, &UserMap::empty(), &UserStatsMap::empty(), - vec![], + &[], &mut None, &filler_key, &mut None, @@ -3903,7 +3903,7 @@ pub mod fulfill_order { &mut taker_stats, &makers_and_referrers, &maker_and_referrer_stats, - vec![(maker_key, 1, 100 * PRICE_PRECISION_U64)], + &[(maker_key, 1, 100 * PRICE_PRECISION_U64)], &mut None, &filler_key, &mut None, @@ -8123,21 +8123,19 @@ pub mod force_cancel_orders { } } -pub mod sort_maker_orders { - use crate::controller::orders::sort_maker_orders; +pub mod insert_maker_order_info { + use crate::controller::orders::insert_maker_order_info; use crate::controller::position::PositionDirection; use solana_program::pubkey::Pubkey; #[test] fn bids() { - let mut bids = vec![ - (Pubkey::default(), 0, 1), - (Pubkey::default(), 2, 100), - (Pubkey::default(), 1, 10), - ]; - let taker_direction = PositionDirection::Short; + let mut bids = Vec::with_capacity(3); + bids.push((Pubkey::default(), 1, 10)); + bids.push((Pubkey::default(), 0, 1)); + let maker_direction = PositionDirection::Long; - sort_maker_orders(&mut bids, taker_direction); + insert_maker_order_info(&mut bids, (Pubkey::default(), 2, 100), maker_direction); assert_eq!( bids, @@ -8151,14 +8149,12 @@ pub mod sort_maker_orders { #[test] fn asks() { - let mut asks = vec![ - (Pubkey::default(), 1, 10), - (Pubkey::default(), 2, 100), - (Pubkey::default(), 0, 1), - ]; - let taker_direction = PositionDirection::Long; - - sort_maker_orders(&mut asks, taker_direction); + let mut asks = Vec::with_capacity(3); + asks.push((Pubkey::default(), 0, 1)); + asks.push((Pubkey::default(), 1, 10)); + let maker_direction = PositionDirection::Short; + + insert_maker_order_info(&mut asks, (Pubkey::default(), 2, 100), maker_direction); assert_eq!( asks, From dff08acf5a74385e2d088ce12e7d3f678fcf57e1 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Fri, 3 Mar 2023 16:07:39 -0500 Subject: [PATCH 27/29] dont append order records to vec, just immediately --- programs/drift/src/controller/orders.rs | 27 +--- programs/drift/src/controller/orders/tests.rs | 129 ------------------ 2 files changed, 4 insertions(+), 152 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 0d37cdd1a..84b2c3d79 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1281,7 +1281,6 @@ fn fulfill_perp_order( let mut base_asset_amount = 0_u64; let mut quote_asset_amount = 0_u64; - let mut order_records: Vec = vec![]; let mut makers_filled: BTreeMap = BTreeMap::new(); for fulfillment_method in fulfillment_methods.iter() { if user.orders[user_order_index].status != OrderStatus::Open { @@ -1317,7 +1316,6 @@ fn fulfill_perp_order( &mut referrer.as_deref_mut(), &mut referrer_stats.as_deref_mut(), fee_structure, - &mut order_records, None, *maker_price, true, @@ -1362,7 +1360,6 @@ fn fulfill_perp_order( slot, fee_structure, oracle_map, - &mut order_records, )?; if fill_base_asset_amount != 0 { @@ -1380,10 +1377,6 @@ fn fulfill_perp_order( .update_volume_24h(fill_quote_asset_amount, user_order_direction, now)?; } - for order_record in order_records { - emit_stack::<_, { OrderActionRecord::SIZE }>(order_record)?; - } - let perp_market = perp_market_map.get_ref(&market_index)?; let taker_maintenance_margin_buffer = calculate_maintenance_buffer_ratio( perp_market.margin_ratio_initial, @@ -1521,7 +1514,6 @@ pub fn fulfill_perp_order_with_amm( referrer: &mut Option<&mut User>, referrer_stats: &mut Option<&mut UserStats>, fee_structure: &FeeStructure, - order_records: &mut Vec, override_base_asset_amount: Option, override_fill_price: Option, split_with_lps: bool, @@ -1762,7 +1754,7 @@ pub fn fulfill_perp_order_with_amm( maker_order, oracle_map.get_price_data(&market.amm.oracle)?.price, )?; - order_records.push(order_action_record); + emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; // Cant reset order until after its logged if user.orders[order_index].get_base_asset_amount_unfilled(None)? == 0 { @@ -1795,7 +1787,6 @@ pub fn fulfill_perp_order_with_match( slot: u64, fee_structure: &FeeStructure, oracle_map: &mut OracleMap, - order_records: &mut Vec, ) -> DriftResult<(u64, u64)> { if !are_orders_same_market_but_different_sides( &maker.orders[maker_order_index], @@ -1912,7 +1903,6 @@ pub fn fulfill_perp_order_with_match( &mut None, &mut None, fee_structure, - order_records, Some(jit_base_asset_amount), Some(maker_price), // match the makers price false, // dont split with the lps @@ -2145,7 +2135,7 @@ pub fn fulfill_perp_order_with_match( Some(maker.orders[maker_order_index]), oracle_map.get_price_data(&market.amm.oracle)?.price, )?; - order_records.push(order_action_record); + emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; if taker.orders[taker_order_index].get_base_asset_amount_unfilled(None)? == 0 { taker.orders[taker_order_index] = Order::default(); @@ -3276,7 +3266,6 @@ fn fulfill_spot_order( let mut quote_market = spot_market_map.get_quote_spot_market_mut()?; let mut base_market = spot_market_map.get_ref_mut(&base_market_index)?; - let mut order_records: Vec = vec![]; let mut base_asset_amount = 0_u64; for fulfillment_method in fulfillment_methods.iter() { if user.orders[user_order_index].status != OrderStatus::Open { @@ -3302,7 +3291,6 @@ fn fulfill_spot_order( slot, oracle_map, fee_structure, - &mut order_records, )?, SpotFulfillmentMethod::SerumV3 => fulfill_spot_order_with_serum( &mut base_market, @@ -3318,7 +3306,6 @@ fn fulfill_spot_order( slot, oracle_map, fee_structure, - &mut order_records, serum_fulfillment_params, )?, }; @@ -3336,10 +3323,6 @@ fn fulfill_spot_order( drop(base_market); drop(quote_market); - for order_record in order_records { - emit!(order_record) - } - let (_, taker_total_collateral, taker_margin_requirement_plus_buffer, _) = calculate_margin_requirement_and_total_collateral( user, @@ -3416,7 +3399,6 @@ pub fn fulfill_spot_order_with_match( slot: u64, oracle_map: &mut OracleMap, fee_structure: &FeeStructure, - order_records: &mut Vec, ) -> DriftResult { if !are_orders_same_market_but_different_sides( &maker.orders[maker_order_index], @@ -3725,7 +3707,7 @@ pub fn fulfill_spot_order_with_match( Some(maker.orders[maker_order_index]), oracle_map.get_price_data(&base_market.oracle)?.price, )?; - order_records.push(order_action_record); + emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; // Clear taker/maker order if completely filled if taker.orders[taker_order_index].get_base_asset_amount_unfilled(None)? == 0 { @@ -3755,7 +3737,6 @@ pub fn fulfill_spot_order_with_serum( slot: u64, oracle_map: &mut OracleMap, fee_structure: &FeeStructure, - order_records: &mut Vec, serum_fulfillment_params: &mut Option, ) -> DriftResult { let serum_new_order_accounts = match serum_fulfillment_params { @@ -4186,7 +4167,7 @@ pub fn fulfill_spot_order_with_serum( None, oracle_price, )?; - order_records.push(order_action_record); + emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?; if taker.orders[taker_order_index].get_base_asset_amount_unfilled(None)? == 0 { taker.orders[taker_order_index] = Order::default(); diff --git a/programs/drift/src/controller/orders/tests.rs b/programs/drift/src/controller/orders/tests.rs index ada0ea641..678f110d4 100644 --- a/programs/drift/src/controller/orders/tests.rs +++ b/programs/drift/src/controller/orders/tests.rs @@ -100,8 +100,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -126,7 +124,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -217,8 +214,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -243,7 +238,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -334,8 +328,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -360,7 +352,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -451,8 +442,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -477,7 +466,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -568,8 +556,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -594,7 +580,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -651,8 +636,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -677,7 +660,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -735,8 +717,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -761,7 +741,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -819,8 +798,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -845,7 +822,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -903,8 +879,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -929,7 +903,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1007,8 +980,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1033,7 +1004,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1114,8 +1084,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1140,7 +1108,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1228,8 +1195,6 @@ pub mod fulfill_order_with_maker_order { let fee_structure = get_fee_structure(); let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1254,7 +1219,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1343,8 +1307,6 @@ pub mod fulfill_order_with_maker_order { let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1369,7 +1331,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1482,8 +1443,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1508,7 +1467,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1596,8 +1554,6 @@ pub mod fulfill_order_with_maker_order { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1622,7 +1578,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -1692,8 +1647,6 @@ pub mod fulfill_order_with_maker_order { let fee_structure = get_fee_structure(); let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1720,7 +1673,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut oracle_map, - &mut order_records, ) .unwrap(); @@ -1834,8 +1786,6 @@ pub mod fulfill_order_with_maker_order { let fee_structure = get_fee_structure(); let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1862,7 +1812,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut oracle_map, - &mut order_records, ) .unwrap(); @@ -1966,8 +1915,6 @@ pub mod fulfill_order_with_maker_order { let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -1992,7 +1939,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut oracle_map, - &mut order_records, ) .unwrap(); @@ -2107,8 +2053,6 @@ pub mod fulfill_order_with_maker_order { let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -2133,7 +2077,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut oracle_map, - &mut order_records, ) .unwrap(); @@ -2232,8 +2175,6 @@ pub mod fulfill_order_with_maker_order { let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -2258,7 +2199,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -2356,8 +2296,6 @@ pub mod fulfill_order_with_maker_order { let fee_structure = get_fee_structure(); let (maker_key, taker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -2382,7 +2320,6 @@ pub mod fulfill_order_with_maker_order { slot, &fee_structure, &mut get_oracle_map(), - &mut order_records, ) .unwrap(); @@ -4816,8 +4753,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -4839,7 +4774,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -4944,8 +4878,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -4967,7 +4899,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5072,8 +5003,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5095,7 +5024,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5200,8 +5128,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5223,7 +5149,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5328,8 +5253,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5351,7 +5274,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5430,8 +5352,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5453,7 +5373,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5532,8 +5451,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5555,7 +5472,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5634,8 +5550,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5657,7 +5571,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5736,8 +5649,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5759,7 +5670,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -5876,8 +5786,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -5899,7 +5807,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6018,8 +5925,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6041,7 +5946,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6144,8 +6048,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6167,7 +6069,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6270,8 +6171,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6293,7 +6192,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6397,8 +6295,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6420,7 +6316,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6497,8 +6392,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6520,7 +6413,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6597,8 +6489,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6620,7 +6510,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6697,8 +6586,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6720,7 +6607,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6797,8 +6683,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6820,7 +6704,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6897,8 +6780,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -6920,7 +6801,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -6997,8 +6877,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -7020,7 +6898,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -7097,8 +6974,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -7120,7 +6995,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); @@ -7197,8 +7071,6 @@ pub mod fulfill_spot_order_with_match { let (taker_key, maker_key, filler_key) = get_user_keys(); - let mut order_records = vec![]; - let mut taker_stats = UserStats::default(); let mut maker_stats = UserStats::default(); @@ -7220,7 +7092,6 @@ pub mod fulfill_spot_order_with_match { slot, &mut get_oracle_map(), &fee_structure, - &mut order_records, ) .unwrap(); From f0837a84180afc51cbb054b4d431b0128294f293 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Fri, 3 Mar 2023 17:20:54 -0500 Subject: [PATCH 28/29] fix unsubscribe for multipleMakerOrders.ts --- tests/multipleMakerOrders.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/multipleMakerOrders.ts b/tests/multipleMakerOrders.ts index 6790f3aa6..ea6c7fec4 100644 --- a/tests/multipleMakerOrders.ts +++ b/tests/multipleMakerOrders.ts @@ -578,5 +578,6 @@ describe('multiple maker orders', () => { await takerDriftClient.unsubscribe(); await makerDriftClient.unsubscribe(); await secondMakerDriftClient.unsubscribe(); + await thirdMakerDriftClient.unsubscribe(); }); }); From bed48be4b59ebca2770253ae81c3f4de026e02ff Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Fri, 3 Mar 2023 17:48:14 -0500 Subject: [PATCH 29/29] CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8706fc3cf..826080f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- program: allow multiple makers in fill_perp_order ([#341](https://github.com/drift-labs/protocol-v2/pull/341)) + ### Fixes ### Breaking