@@ -5925,6 +5925,164 @@ pub mod fulfill_order {
59255925 assert_eq ! ( maker_stats. filler_volume_30d, 50251257 ) ; // gets filler volume
59265926 assert ! ( maker. orders[ 0 ] . is_available( ) ) ;
59275927 }
5928+
5929+ #[ test]
5930+ fn paused_operations_blocks_amm_fill ( ) {
5931+ let now = 0_i64 ;
5932+ let slot = 0_u64 ;
5933+
5934+ let mut oracle_price = get_pyth_price ( 100 , 6 ) ;
5935+ let oracle_price_key =
5936+ Pubkey :: from_str ( "J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix" ) . unwrap ( ) ;
5937+ let pyth_program = crate :: ids:: pyth_program:: id ( ) ;
5938+ create_account_info ! (
5939+ oracle_price,
5940+ & oracle_price_key,
5941+ & pyth_program,
5942+ oracle_account_info
5943+ ) ;
5944+ let mut oracle_map = OracleMap :: load_one ( & oracle_account_info, slot, None ) . unwrap ( ) ;
5945+
5946+ let mut market = PerpMarket {
5947+ amm : AMM {
5948+ base_asset_reserve : 100 * AMM_RESERVE_PRECISION ,
5949+ quote_asset_reserve : 100 * AMM_RESERVE_PRECISION ,
5950+ bid_base_asset_reserve : 100 * AMM_RESERVE_PRECISION ,
5951+ bid_quote_asset_reserve : 100 * AMM_RESERVE_PRECISION ,
5952+ ask_base_asset_reserve : 100 * AMM_RESERVE_PRECISION ,
5953+ ask_quote_asset_reserve : 100 * AMM_RESERVE_PRECISION ,
5954+ sqrt_k : 100 * AMM_RESERVE_PRECISION ,
5955+ peg_multiplier : 100 * PEG_PRECISION ,
5956+ max_slippage_ratio : 50 ,
5957+ max_fill_reserve_fraction : 100 ,
5958+ order_step_size : 1000 ,
5959+ order_tick_size : 1 ,
5960+ oracle : oracle_price_key,
5961+ base_spread : 0 ,
5962+ base_asset_amount_with_amm : -1000000000 ,
5963+ amm_jit_intensity : 100 ,
5964+ max_base_asset_reserve : 200 * AMM_RESERVE_PRECISION ,
5965+ min_base_asset_reserve : 0 ,
5966+ historical_oracle_data : HistoricalOracleData {
5967+ last_oracle_price : ( 100 * PRICE_PRECISION ) as i64 ,
5968+ last_oracle_price_twap : ( 100 * PRICE_PRECISION ) as i64 ,
5969+ last_oracle_price_twap_5min : ( 100 * PRICE_PRECISION ) as i64 ,
5970+ ..HistoricalOracleData :: default ( )
5971+ } ,
5972+ ..AMM :: default ( )
5973+ } ,
5974+ margin_ratio_initial : 1000 ,
5975+ margin_ratio_maintenance : 500 ,
5976+ status : MarketStatus :: Initialized ,
5977+ ..PerpMarket :: default_test ( )
5978+ } ;
5979+
5980+ create_anchor_account_info ! ( market, PerpMarket , market_account_info) ;
5981+ let market_map = PerpMarketMap :: load_one ( & market_account_info, true ) . unwrap ( ) ;
5982+
5983+ let mut spot_market = SpotMarket {
5984+ market_index : 0 ,
5985+ oracle_source : OracleSource :: QuoteAsset ,
5986+ cumulative_deposit_interest : SPOT_CUMULATIVE_INTEREST_PRECISION ,
5987+ decimals : 6 ,
5988+ initial_asset_weight : SPOT_WEIGHT_PRECISION ,
5989+ maintenance_asset_weight : SPOT_WEIGHT_PRECISION ,
5990+ historical_oracle_data : HistoricalOracleData :: default_price ( QUOTE_PRECISION_I64 ) ,
5991+ ..SpotMarket :: default ( )
5992+ } ;
5993+ create_anchor_account_info ! ( spot_market, SpotMarket , spot_market_account_info) ;
5994+ let spot_market_map = SpotMarketMap :: load_one ( & spot_market_account_info, true ) . unwrap ( ) ;
5995+
5996+ let mut taker = User {
5997+ orders : get_orders ( Order {
5998+ market_index : 0 ,
5999+ status : OrderStatus :: Open ,
6000+ order_type : OrderType :: Market ,
6001+ direction : PositionDirection :: Long ,
6002+ base_asset_amount : BASE_PRECISION_U64 ,
6003+ slot : 0 ,
6004+ auction_start_price : 0 ,
6005+ auction_end_price : 100 * PRICE_PRECISION_I64 ,
6006+ auction_duration : 0 ,
6007+ price : 150 * PRICE_PRECISION_U64 ,
6008+ ..Order :: default ( )
6009+ } ) ,
6010+ perp_positions : get_positions ( PerpPosition {
6011+ market_index : 0 ,
6012+ open_orders : 1 ,
6013+ open_bids : BASE_PRECISION_I64 ,
6014+ ..PerpPosition :: default ( )
6015+ } ) ,
6016+ spot_positions : get_spot_positions ( SpotPosition {
6017+ market_index : 0 ,
6018+ balance_type : SpotBalanceType :: Deposit ,
6019+ scaled_balance : 100 * SPOT_BALANCE_PRECISION_U64 ,
6020+ ..SpotPosition :: default ( )
6021+ } ) ,
6022+ ..User :: default ( )
6023+ } ;
6024+
6025+ let mut filler = User :: default ( ) ;
6026+ let fee_structure = get_fee_structure ( ) ;
6027+ let ( taker_key, _, filler_key) = get_user_keys ( ) ;
6028+
6029+ let mut taker_stats = UserStats {
6030+ paused_operations : 4 ,
6031+ ..UserStats :: default ( )
6032+ } ;
6033+ let mut filler_stats = UserStats :: default ( ) ;
6034+
6035+ let order_index = 0 ;
6036+ let min_auction_duration = 0 ;
6037+ let user_can_skip_auction_duration = taker
6038+ . can_skip_auction_duration ( & taker_stats, false )
6039+ . unwrap ( ) ;
6040+ let is_amm_available = get_amm_is_available (
6041+ & taker. orders [ order_index] ,
6042+ min_auction_duration,
6043+ & market,
6044+ & mut oracle_map,
6045+ slot,
6046+ user_can_skip_auction_duration,
6047+ ) ;
6048+
6049+ assert ! ( !user_can_skip_auction_duration) ;
6050+ assert ! ( !is_amm_available) ;
6051+
6052+ let ( base_asset_amount, _) = fulfill_perp_order (
6053+ & mut taker,
6054+ order_index,
6055+ & taker_key,
6056+ & mut taker_stats,
6057+ & UserMap :: empty ( ) ,
6058+ & UserStatsMap :: empty ( ) ,
6059+ & [ ] ,
6060+ & mut Some ( & mut filler) ,
6061+ & filler_key,
6062+ & mut Some ( & mut filler_stats) ,
6063+ None ,
6064+ & spot_market_map,
6065+ & market_map,
6066+ & mut oracle_map,
6067+ & fee_structure,
6068+ 0 ,
6069+ Some ( market. amm . historical_oracle_data . last_oracle_price ) ,
6070+ now,
6071+ slot,
6072+ is_amm_available,
6073+ FillMode :: Fill ,
6074+ false ,
6075+ & mut None ,
6076+ false ,
6077+ )
6078+ . unwrap ( ) ;
6079+
6080+ assert_eq ! ( base_asset_amount, 0 ) ;
6081+ assert_eq ! ( taker. perp_positions[ 0 ] . base_asset_amount, 0 ) ;
6082+
6083+ let market_after = market_map. get_ref ( & 0 ) . unwrap ( ) ;
6084+ assert_eq ! ( market_after. amm. base_asset_amount_with_amm, -1000000000 ) ;
6085+ }
59286086}
59296087
59306088pub mod fill_order {
0 commit comments