diff --git a/programs/drift/src/controller/amm.rs b/programs/drift/src/controller/amm.rs index 981afa112..ddae482a8 100644 --- a/programs/drift/src/controller/amm.rs +++ b/programs/drift/src/controller/amm.rs @@ -16,7 +16,7 @@ use crate::math::amm_spread::{calculate_spread_reserves, get_spread_reserves}; use crate::math::casting::Cast; use crate::math::constants::{ CONCENTRATION_PRECISION, FEE_POOL_TO_REVENUE_POOL_THRESHOLD, K_BPS_UPDATE_SCALE, - MAX_CONCENTRATION_COEFFICIENT, MAX_K_BPS_INCREASE, MAX_SQRT_K, PRICE_TO_PEG_PRECISION_RATIO, + MAX_CONCENTRATION_COEFFICIENT, MAX_K_BPS_INCREASE, MAX_SQRT_K, }; use crate::math::cp_curve::get_update_k_result; use crate::math::repeg::get_total_fee_lower_bound; @@ -152,35 +152,6 @@ pub fn calculate_base_swap_output_with_spread( )) } -#[allow(dead_code)] -fn calculate_base_swap_output_without_spread( - amm: &mut AMM, - base_asset_swap_amount: u128, - direction: SwapDirection, -) -> DriftResult<(u128, u128, u128, u128)> { - let initial_quote_asset_reserve = amm.quote_asset_reserve; - let (new_quote_asset_reserve, new_base_asset_reserve) = amm::calculate_swap_output( - base_asset_swap_amount, - amm.base_asset_reserve, - direction, - amm.sqrt_k, - )?; - - let quote_asset_amount = calculate_quote_asset_amount_swapped( - initial_quote_asset_reserve, - new_quote_asset_reserve, - direction, - amm.peg_multiplier, - )?; - - Ok(( - new_base_asset_reserve, - new_quote_asset_reserve, - quote_asset_amount, - 0, - )) -} - pub fn update_spread_reserves(amm: &mut AMM) -> DriftResult { let (new_ask_base_asset_reserve, new_ask_quote_asset_reserve) = calculate_spread_reserves(amm, PositionDirection::Long)?; @@ -382,6 +353,7 @@ pub fn get_fee_pool_tokens( )? .cast() } + fn calculate_revenue_pool_transfer( market: &PerpMarket, spot_market: &SpotMarket, @@ -764,22 +736,3 @@ pub fn move_price( Ok(()) } - -#[allow(dead_code)] -pub fn move_to_price(amm: &mut AMM, target_price: u128) -> DriftResult { - let sqrt_k = bn::U256::from(amm.sqrt_k); - let k = sqrt_k.safe_mul(sqrt_k)?; - - let new_base_asset_amount_squared = k - .safe_mul(bn::U256::from(amm.peg_multiplier))? - .safe_mul(bn::U256::from(PRICE_TO_PEG_PRECISION_RATIO))? - .safe_div(bn::U256::from(target_price))?; - - let new_base_asset_amount = new_base_asset_amount_squared.integer_sqrt(); - let new_quote_asset_amount = k.safe_div(new_base_asset_amount)?; - - amm.base_asset_reserve = new_base_asset_amount.try_to_u128()?; - amm.quote_asset_reserve = new_quote_asset_amount.try_to_u128()?; - - Ok(()) -} diff --git a/programs/drift/src/controller/spot_balance.rs b/programs/drift/src/controller/spot_balance.rs index d8e5327bd..84dffe484 100644 --- a/programs/drift/src/controller/spot_balance.rs +++ b/programs/drift/src/controller/spot_balance.rs @@ -20,7 +20,7 @@ use crate::math::stats::{calculate_new_twap, calculate_weighted_average}; use crate::state::events::SpotInterestRecord; use crate::state::oracle::OraclePriceData; -use crate::state::perp_market::{MarketStatus, PerpMarket}; +use crate::state::perp_market::MarketStatus; use crate::state::spot_market::{SpotBalance, SpotBalanceType, SpotMarket}; use crate::validate; @@ -378,23 +378,6 @@ pub fn transfer_spot_balance_to_revenue_pool( Ok(()) } -pub fn check_perp_market_valid( - perp_market: &PerpMarket, - spot_market: &SpotMarket, - spot_balance: &mut dyn SpotBalance, - current_slot: u64, -) -> DriftResult { - // todo - - if perp_market.amm.oracle == spot_market.oracle - && spot_balance.balance_type() == &SpotBalanceType::Borrow - && (perp_market.amm.last_update_slot != current_slot || !perp_market.amm.last_oracle_valid) - { - return Err(ErrorCode::InvalidOracle); - } - - Ok(()) -} pub fn update_spot_market_and_check_validity( spot_market: &mut SpotMarket, oracle_price_data: &OraclePriceData, diff --git a/programs/drift/src/controller/spot_balance/tests.rs b/programs/drift/src/controller/spot_balance/tests.rs index 379bdc558..ed03cf898 100644 --- a/programs/drift/src/controller/spot_balance/tests.rs +++ b/programs/drift/src/controller/spot_balance/tests.rs @@ -34,6 +34,24 @@ use crate::state::user::{Order, PerpPosition, SpotPosition, User}; use crate::test_utils::*; use crate::test_utils::{get_pyth_price, get_spot_positions}; +pub fn check_perp_market_valid( + perp_market: &PerpMarket, + spot_market: &SpotMarket, + spot_balance: &mut dyn SpotBalance, + current_slot: u64, +) -> DriftResult { + // todo + + if perp_market.amm.oracle == spot_market.oracle + && spot_balance.balance_type() == &SpotBalanceType::Borrow + && (perp_market.amm.last_update_slot != current_slot || !perp_market.amm.last_oracle_valid) + { + return Err(ErrorCode::InvalidOracle); + } + + Ok(()) +} + #[test] fn test_daily_withdraw_limits() { let now = 0_i64; diff --git a/programs/drift/src/controller/spot_position.rs b/programs/drift/src/controller/spot_position.rs index 36809cfeb..7c1846ba0 100644 --- a/programs/drift/src/controller/spot_position.rs +++ b/programs/drift/src/controller/spot_position.rs @@ -150,6 +150,7 @@ pub fn update_spot_balances_and_cumulative_deposits_with_limits( Ok(()) } +#[cfg(test)] pub fn transfer_spot_position_deposit( token_amount: i128, spot_market: &mut SpotMarket, diff --git a/programs/drift/src/math/amm.rs b/programs/drift/src/math/amm.rs index 27d938ada..fc96faf01 100644 --- a/programs/drift/src/math/amm.rs +++ b/programs/drift/src/math/amm.rs @@ -62,26 +62,6 @@ pub fn calculate_bid_ask_bounds( Ok((bid_bounded_base, ask_bounded_base)) } -pub fn calculate_terminal_price(amm: &mut AMM) -> DriftResult { - let swap_direction = if amm.base_asset_amount_with_amm > 0 { - SwapDirection::Add - } else { - SwapDirection::Remove - }; - let (new_quote_asset_amount, new_base_asset_amount) = calculate_swap_output( - amm.base_asset_amount_with_amm.unsigned_abs(), - amm.base_asset_reserve, - swap_direction, - amm.sqrt_k, - )?; - - calculate_price( - new_quote_asset_amount, - new_base_asset_amount, - amm.peg_multiplier, - ) -} - pub fn calculate_market_open_bids_asks(amm: &AMM) -> DriftResult<(i128, i128)> { let base_asset_reserve = amm.base_asset_reserve; let min_base_asset_reserve = amm.min_base_asset_reserve; diff --git a/programs/drift/src/math/auction.rs b/programs/drift/src/math/auction.rs index 87d593e51..8d5f48fcf 100644 --- a/programs/drift/src/math/auction.rs +++ b/programs/drift/src/math/auction.rs @@ -194,24 +194,6 @@ fn calculate_auction_price_for_oracle_offset_auction( Ok(price) } -pub fn does_auction_satisfy_maker_order( - maker_order: &Order, - taker_order: &Order, - auction_price: u64, -) -> bool { - // TODO more conditions to check? - if maker_order.direction == taker_order.direction - || maker_order.market_index != taker_order.market_index - { - return false; - } - - match maker_order.direction { - PositionDirection::Long => auction_price <= maker_order.price, - PositionDirection::Short => auction_price >= maker_order.price, - } -} - pub fn is_auction_complete(order_slot: u64, auction_duration: u8, slot: u64) -> DriftResult { if auction_duration == 0 { return Ok(true); diff --git a/programs/drift/src/math/cp_curve.rs b/programs/drift/src/math/cp_curve.rs index c01088c58..486f335bd 100644 --- a/programs/drift/src/math/cp_curve.rs +++ b/programs/drift/src/math/cp_curve.rs @@ -9,7 +9,7 @@ use crate::math::constants::{ AMM_RESERVE_PRECISION, AMM_TO_QUOTE_PRECISION_RATIO_I128, K_BPS_UPDATE_SCALE, MAX_K_BPS_DECREASE, MAX_SQRT_K, PEG_PRECISION, PERCENTAGE_PRECISION_I128, QUOTE_PRECISION, }; -use crate::math::position::{_calculate_base_asset_value_and_pnl, calculate_base_asset_value}; +use crate::math::position::{calculate_base_asset_value, calculate_base_asset_value_and_pnl}; use crate::math::safe_math::SafeMath; use crate::state::perp_market::{MarketStatus, PerpMarket}; @@ -175,7 +175,7 @@ pub fn adjust_k_cost( let mut market_clone = *market; // Find the net market value before adjusting k - let (current_net_market_value, _) = _calculate_base_asset_value_and_pnl( + let (current_net_market_value, _) = calculate_base_asset_value_and_pnl( market_clone.amm.base_asset_amount_with_amm, 0, &market_clone.amm, @@ -184,7 +184,7 @@ pub fn adjust_k_cost( update_k(&mut market_clone, update_k_result)?; - let (_new_net_market_value, cost) = _calculate_base_asset_value_and_pnl( + let (_new_net_market_value, cost) = calculate_base_asset_value_and_pnl( market_clone.amm.base_asset_amount_with_amm, current_net_market_value, &market_clone.amm, @@ -207,7 +207,7 @@ pub fn adjust_k_cost_and_update( update_k(market, update_k_result)?; - let (_new_net_market_value, cost) = _calculate_base_asset_value_and_pnl( + let (_new_net_market_value, cost) = calculate_base_asset_value_and_pnl( market.amm.base_asset_amount_with_amm, current_net_market_value, &market.amm, diff --git a/programs/drift/src/math/funding.rs b/programs/drift/src/math/funding.rs index 646aa7ac1..8eb2ca2e0 100644 --- a/programs/drift/src/math/funding.rs +++ b/programs/drift/src/math/funding.rs @@ -1,4 +1,4 @@ -use std::cmp::{max, min}; +use std::cmp::max; use solana_program::msg; @@ -7,7 +7,7 @@ use crate::math::bn; use crate::math::casting::Cast; use crate::math::constants::{ AMM_TO_QUOTE_PRECISION_RATIO, AMM_TO_QUOTE_PRECISION_RATIO_I128, FUNDING_RATE_BUFFER, - ONE_HOUR_I128, PRICE_PRECISION, QUOTE_TO_BASE_AMT_FUNDING_PRECISION, + PRICE_PRECISION, QUOTE_TO_BASE_AMT_FUNDING_PRECISION, }; use crate::math::repeg::{calculate_fee_pool, get_total_fee_lower_bound}; use crate::math::safe_math::SafeMath; @@ -18,31 +18,6 @@ use crate::state::user::PerpPosition; #[cfg(test)] mod tests; -pub fn calculate_funding_rate( - mid_price_twap: u128, - oracle_price_twap: i128, - funding_period: i64, -) -> DriftResult { - // funding period = 1 hour, window = 1 day - // low periodicity => quickly updating/settled funding rates - // => lower funding rate payment per interval - let period_adjustment = (24_i128) - .safe_mul(ONE_HOUR_I128)? - .safe_div(max(ONE_HOUR_I128, funding_period as i128))?; - - let price_spread = mid_price_twap.cast::()?.safe_sub(oracle_price_twap)?; - - // clamp price divergence to 3% for funding rate calculation - let max_price_spread = oracle_price_twap.safe_div(33)?; // 3% - let clamped_price_spread = max(-max_price_spread, min(price_spread, max_price_spread)); - - let funding_rate = clamped_price_spread - .safe_mul(FUNDING_RATE_BUFFER.cast()?)? - .safe_div(period_adjustment.cast()?)?; - - Ok(funding_rate) -} - /// With a virtual AMM, there can be an imbalance between longs and shorts and thus funding can be asymmetric. /// To account for this, amm keeps track of the cumulative funding rate for both longs and shorts. /// When there is a period with asymmetric funding, the protocol will pay/receive funding from/to it's collected fees. diff --git a/programs/drift/src/math/funding/tests.rs b/programs/drift/src/math/funding/tests.rs index 178b050f2..911ea520a 100644 --- a/programs/drift/src/math/funding/tests.rs +++ b/programs/drift/src/math/funding/tests.rs @@ -1,9 +1,35 @@ use crate::math::constants::{ - AMM_RESERVE_PRECISION, PRICE_PRECISION, PRICE_PRECISION_U64, QUOTE_PRECISION, + AMM_RESERVE_PRECISION, ONE_HOUR_I128, PRICE_PRECISION, PRICE_PRECISION_U64, QUOTE_PRECISION, }; use crate::math::funding::*; use crate::state::oracle::HistoricalOracleData; use crate::state::perp_market::{PerpMarket, AMM}; +use std::cmp::min; + +fn calculate_funding_rate( + mid_price_twap: u128, + oracle_price_twap: i128, + funding_period: i64, +) -> DriftResult { + // funding period = 1 hour, window = 1 day + // low periodicity => quickly updating/settled funding rates + // => lower funding rate payment per interval + let period_adjustment = (24_i128) + .safe_mul(ONE_HOUR_I128)? + .safe_div(max(ONE_HOUR_I128, funding_period as i128))?; + + let price_spread = mid_price_twap.cast::()?.safe_sub(oracle_price_twap)?; + + // clamp price divergence to 3% for funding rate calculation + let max_price_spread = oracle_price_twap.safe_div(33)?; // 3% + let clamped_price_spread = max(-max_price_spread, min(price_spread, max_price_spread)); + + let funding_rate = clamped_price_spread + .safe_mul(FUNDING_RATE_BUFFER.cast()?)? + .safe_div(period_adjustment.cast()?)?; + + Ok(funding_rate) +} #[test] fn balanced_funding_test() { diff --git a/programs/drift/src/math/helpers.rs b/programs/drift/src/math/helpers.rs index 24ddafa98..9826a71ca 100644 --- a/programs/drift/src/math/helpers.rs +++ b/programs/drift/src/math/helpers.rs @@ -95,6 +95,7 @@ pub fn on_the_hour_update(now: i64, last_update_ts: i64, update_period: i64) -> Ok(time_remaining_until_update) } +#[cfg(test)] #[allow(clippy::comparison_chain)] pub fn log10(n: u128) -> u128 { if n < 10 { diff --git a/programs/drift/src/math/liquidation.rs b/programs/drift/src/math/liquidation.rs index 80d69453a..3ff900d2b 100644 --- a/programs/drift/src/math/liquidation.rs +++ b/programs/drift/src/math/liquidation.rs @@ -208,14 +208,6 @@ pub fn is_user_being_liquidated( Ok(is_being_liquidated) } -pub fn get_margin_requirement_plus_buffer( - margin_requirement: u128, - liquidation_margin_buffer_ratio: u8, -) -> DriftResult { - margin_requirement - .safe_add(margin_requirement.safe_div(liquidation_margin_buffer_ratio as u128)?) -} - pub fn validate_user_not_being_liquidated( user: &mut User, market_map: &PerpMarketMap, diff --git a/programs/drift/src/math/margin/tests.rs b/programs/drift/src/math/margin/tests.rs index 0519b4650..6b7e77e30 100644 --- a/programs/drift/src/math/margin/tests.rs +++ b/programs/drift/src/math/margin/tests.rs @@ -9,9 +9,7 @@ mod test { QUOTE_PRECISION_I64, SPOT_IMF_PRECISION, }; use crate::math::margin::{calculate_perp_position_value_and_pnl, MarginRequirementType}; - use crate::math::position::{ - calculate_base_asset_value_and_pnl_with_oracle_price, calculate_position_pnl, - }; + use crate::math::position::calculate_base_asset_value_and_pnl_with_oracle_price; use crate::state::oracle::{OraclePriceData, StrictOraclePrice}; use crate::state::perp_market::{ContractTier, PerpMarket, AMM}; use crate::state::spot_market::{AssetTier, SpotMarket}; @@ -226,16 +224,11 @@ mod test { let margin_requirement_type = MarginRequirementType::Initial; - let position_unrealized_pnl = - calculate_position_pnl(&market_position, &market.amm, false).unwrap(); - - assert_eq!(position_unrealized_pnl, 22699050905); - // sqrt of oracle price = 149 market.unrealized_pnl_imf_factor = market.imf_factor; let uaw = market - .get_unrealized_asset_weight(position_unrealized_pnl, MarginRequirementType::Initial) + .get_unrealized_asset_weight(22699050905, MarginRequirementType::Initial) .unwrap(); assert_eq!(uaw, 9559); @@ -251,7 +244,6 @@ mod test { .unwrap(); assert_eq!(upnl, 100000000); - assert!(upnl < position_unrealized_pnl); // margin system discounts assert!(pmr > 0); assert_eq!(pmr, 13555327867); diff --git a/programs/drift/src/math/orders.rs b/programs/drift/src/math/orders.rs index d348523f5..ee0e27028 100644 --- a/programs/drift/src/math/orders.rs +++ b/programs/drift/src/math/orders.rs @@ -7,7 +7,7 @@ use crate::controller::position::PositionDelta; use crate::controller::position::PositionDirection; use crate::error::{DriftResult, ErrorCode}; use crate::math::amm::calculate_amm_available_liquidity; -use crate::math::auction::{is_amm_available_liquidity_source, is_auction_complete}; +use crate::math::auction::is_amm_available_liquidity_source; use crate::math::casting::Cast; use crate::{ load, math, State, BASE_PRECISION_I128, OPEN_ORDER_MARGIN_REQUIREMENT, PERCENTAGE_PRECISION, @@ -19,7 +19,6 @@ use crate::math::constants::MARGIN_PRECISION_U128; use crate::math::margin::{ calculate_margin_requirement_and_total_collateral_and_liability_info, MarginRequirementType, }; -use crate::math::position::calculate_entry_price; use crate::math::safe_math::SafeMath; use crate::math::spot_balance::get_strict_token_value; use crate::math::spot_withdraw::get_max_withdraw_for_market_with_token_amount; @@ -118,30 +117,6 @@ pub fn calculate_base_asset_amount_to_fill_up_to_limit_price( ) } -pub fn limit_price_satisfied( - limit_price: u128, - quote_asset_amount: u128, - base_asset_amount: u128, - direction: PositionDirection, -) -> DriftResult { - let price = calculate_entry_price(quote_asset_amount, base_asset_amount)?; - - match direction { - PositionDirection::Long => { - if price > limit_price { - return Ok(false); - } - } - PositionDirection::Short => { - if price < limit_price { - return Ok(false); - } - } - } - - Ok(true) -} - pub fn calculate_quote_asset_amount_for_maker_order( base_asset_amount: u64, fill_price: u64, @@ -325,21 +300,6 @@ pub fn validate_perp_fill_possible( Ok(()) } -#[inline(always)] -pub fn should_cancel_market_order_after_fill( - user: &User, - user_order_index: usize, - slot: u64, -) -> DriftResult { - let order = &user.orders[user_order_index]; - if !order.is_market_order() || order.status != OrderStatus::Open { - return Ok(false); - } - - Ok(order.has_limit_price(slot)? - && is_auction_complete(order.slot, order.auction_duration, slot)?) -} - #[inline(always)] pub fn should_expire_order_before_fill( user: &User, @@ -582,24 +542,6 @@ pub fn order_satisfies_trigger_condition(order: &Order, oracle_price: u64) -> Dr } } -pub fn is_order_risk_decreasing( - order_direction: &PositionDirection, - order_base_asset_amount: u64, - position_base_asset_amount: i64, -) -> DriftResult { - Ok(match order_direction { - // User is short and order is long - PositionDirection::Long if position_base_asset_amount < 0 => { - order_base_asset_amount < position_base_asset_amount.unsigned_abs().safe_mul(2)? - } - // User is long and order is short - PositionDirection::Short if position_base_asset_amount > 0 => { - order_base_asset_amount < position_base_asset_amount.unsigned_abs().safe_mul(2)? - } - _ => false, - }) -} - pub fn is_new_order_risk_increasing( order: &Order, position_base_asset_amount: i64, @@ -767,54 +709,6 @@ fn get_max_fill_amounts_for_market( get_max_withdraw_for_market_with_token_amount(market, token_amount, is_leaving_drift) } -pub fn find_fallback_maker_order( - user: &User, - direction: &PositionDirection, - market_type: &MarketType, - market_index: u16, - valid_oracle_price: Option, - slot: u64, - tick_size: u64, -) -> DriftResult> { - let mut best_limit_price = match direction { - PositionDirection::Long => 0, - PositionDirection::Short => u64::MAX, - }; - let mut fallback_maker_order_index = None; - - for (order_index, order) in user.orders.iter().enumerate() { - if order.status != OrderStatus::Open { - continue; - } - - // if order direction is not same or market type is not same or market index is the same, skip - if order.direction != *direction - || order.market_type != *market_type - || order.market_index != market_index - { - continue; - } - - // if order is not limit order or must be triggered and not triggered, skip - if !order.is_limit_order() || (order.must_be_triggered() && !order.triggered()) { - continue; - } - - let limit_price = order.force_get_limit_price(valid_oracle_price, None, slot, tick_size)?; - - // if fallback maker order is not set, set it else check if this order is better - if fallback_maker_order_index.is_none() - || *direction == PositionDirection::Long && limit_price > best_limit_price - || *direction == PositionDirection::Short && limit_price < best_limit_price - { - best_limit_price = limit_price; - fallback_maker_order_index = Some(order_index); - } - } - - Ok(fallback_maker_order_index) -} - pub fn find_maker_orders( user: &User, direction: &PositionDirection, diff --git a/programs/drift/src/math/orders/tests.rs b/programs/drift/src/math/orders/tests.rs index 43c095764..f20945deb 100644 --- a/programs/drift/src/math/orders/tests.rs +++ b/programs/drift/src/math/orders/tests.rs @@ -702,331 +702,6 @@ mod get_max_fill_amounts { } } -mod find_fallback_maker_order { - use crate::controller::position::PositionDirection; - use crate::math::constants::{PRICE_PRECISION_I64, PRICE_PRECISION_U64}; - use crate::math::orders::find_fallback_maker_order; - use crate::state::user::{ - MarketType, Order, OrderStatus, OrderTriggerCondition, OrderType, User, - }; - - #[test] - fn no_open_orders() { - let user = User::default(); - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, None); - } - - #[test] - fn no_limit_orders() { - let user = User { - orders: [Order { - status: OrderStatus::Open, - order_type: OrderType::Market, - market_index: 0, - market_type: MarketType::Perp, - direction: PositionDirection::Long, - ..Order::default() - }; 32], - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, None); - } - - #[test] - fn no_triggered_trigger_limit_orders() { - let user = User { - orders: [Order { - status: OrderStatus::Open, - order_type: OrderType::TriggerLimit, - trigger_condition: OrderTriggerCondition::Above, - market_index: 0, - market_type: MarketType::Perp, - direction: PositionDirection::Long, - ..Order::default() - }; 32], - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, None); - } - - #[test] - fn wrong_direction() { - let user = User { - orders: [Order { - status: OrderStatus::Open, - order_type: OrderType::Limit, - market_index: 0, - market_type: MarketType::Perp, - direction: PositionDirection::Short, - price: PRICE_PRECISION_U64, - ..Order::default() - }; 32], - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, None); - } - - #[test] - fn wrong_market_index() { - let user = User { - orders: [Order { - status: OrderStatus::Open, - order_type: OrderType::Limit, - market_index: 1, - market_type: MarketType::Perp, - direction: PositionDirection::Long, - price: PRICE_PRECISION_U64, - ..Order::default() - }; 32], - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, None); - } - - #[test] - fn wrong_market_type() { - let user = User { - orders: [Order { - status: OrderStatus::Open, - order_type: OrderType::Limit, - market_index: 0, - market_type: MarketType::Spot, - direction: PositionDirection::Long, - price: PRICE_PRECISION_U64, - ..Order::default() - }; 32], - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, None); - } - - #[test] - fn only_one_fallback_bid() { - let mut orders = [Order::default(); 32]; - orders[0] = Order { - status: OrderStatus::Open, - order_type: OrderType::Limit, - market_index: 0, - market_type: MarketType::Perp, - direction: PositionDirection::Long, - price: PRICE_PRECISION_U64, - ..Order::default() - }; - - let user = User { - orders, - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, Some(0)); - } - - #[test] - fn find_best_bid() { - let mut orders = [Order::default(); 32]; - for (i, order) in orders.iter_mut().enumerate() { - *order = Order { - status: OrderStatus::Open, - order_type: OrderType::Limit, - market_index: 0, - market_type: MarketType::Perp, - direction: PositionDirection::Long, - price: (i as u64 + 1) * PRICE_PRECISION_U64, - ..Order::default() - } - } - - let user = User { - orders, - ..User::default() - }; - let direction = PositionDirection::Long; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, Some(31)); - } - - #[test] - fn find_best_ask() { - let mut orders = [Order::default(); 32]; - for (i, order) in orders.iter_mut().enumerate() { - *order = Order { - status: OrderStatus::Open, - order_type: OrderType::Limit, - market_index: 0, - market_type: MarketType::Perp, - direction: PositionDirection::Short, - price: (i as u64 + 1) * PRICE_PRECISION_U64, - ..Order::default() - } - } - - let user = User { - orders, - ..User::default() - }; - let direction = PositionDirection::Short; - let market_type = MarketType::Perp; - let market_index = 0; - let oracle_price = PRICE_PRECISION_I64; - let slot = 0; - let tick_size = 1; - - let order_index = find_fallback_maker_order( - &user, - &direction, - &market_type, - market_index, - Some(oracle_price), - slot, - tick_size, - ) - .unwrap(); - - assert_eq!(order_index, Some(0)); - } -} - mod find_maker_orders { use crate::controller::position::PositionDirection; use crate::math::constants::{PRICE_PRECISION_I64, PRICE_PRECISION_U64}; diff --git a/programs/drift/src/math/position.rs b/programs/drift/src/math/position.rs index 21df3e72e..449503ccb 100644 --- a/programs/drift/src/math/position.rs +++ b/programs/drift/src/math/position.rs @@ -1,12 +1,12 @@ use crate::controller::amm::SwapDirection; -use crate::controller::position::{PositionDelta, PositionDirection}; +use crate::controller::position::PositionDelta; use crate::error::DriftResult; use crate::math::amm; use crate::math::amm::calculate_quote_asset_amount_swapped; use crate::math::casting::Cast; use crate::math::constants::{ - AMM_RESERVE_PRECISION_I128, AMM_TO_QUOTE_PRECISION_RATIO, PRICE_PRECISION, - PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO, PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO_I128, + AMM_RESERVE_PRECISION_I128, PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO, + PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO_I128, }; use crate::math::helpers::get_proportion_u128; use crate::math::pnl::calculate_pnl; @@ -16,33 +16,6 @@ use crate::state::perp_market::AMM; use crate::state::user::PerpPosition; pub fn calculate_base_asset_value_and_pnl( - market_position: &PerpPosition, - amm: &AMM, - use_spread: bool, -) -> DriftResult<(u128, i128)> { - _calculate_base_asset_value_and_pnl( - market_position.base_asset_amount.cast()?, - market_position.quote_asset_amount.unsigned_abs().cast()?, - amm, - use_spread, - ) -} - -pub fn calculate_position_pnl( - market_position: &PerpPosition, - amm: &AMM, - use_spread: bool, -) -> DriftResult { - let (_, pnl) = _calculate_base_asset_value_and_pnl( - market_position.base_asset_amount.cast()?, - market_position.quote_asset_amount.unsigned_abs().cast()?, - amm, - use_spread, - )?; - Ok(pnl) -} - -pub fn _calculate_base_asset_value_and_pnl( base_asset_amount: i128, quote_asset_amount: u128, amm: &AMM, @@ -164,14 +137,6 @@ pub fn calculate_base_asset_value_with_expiry_price( .cast::() } -pub fn direction_to_close_position(base_asset_amount: i128) -> PositionDirection { - if base_asset_amount > 0 { - PositionDirection::Short - } else { - PositionDirection::Long - } -} - pub fn swap_direction_to_close_position(base_asset_amount: i128) -> SwapDirection { if base_asset_amount >= 0 { SwapDirection::Add @@ -180,17 +145,6 @@ pub fn swap_direction_to_close_position(base_asset_amount: i128) -> SwapDirectio } } -pub fn calculate_entry_price( - quote_asset_amount: u128, - base_asset_amount: u128, -) -> DriftResult { - let price = quote_asset_amount - .safe_mul(PRICE_PRECISION * AMM_TO_QUOTE_PRECISION_RATIO)? - .safe_div(base_asset_amount)?; - - Ok(price) -} - pub enum PositionUpdateType { Open, Increase, diff --git a/programs/drift/src/math/repeg.rs b/programs/drift/src/math/repeg.rs index 1c60603bc..bbec5c594 100644 --- a/programs/drift/src/math/repeg.rs +++ b/programs/drift/src/math/repeg.rs @@ -15,7 +15,7 @@ use crate::math::constants::{ use crate::math::cp_curve; use crate::math::oracle; use crate::math::oracle::OracleValidity; -use crate::math::position::_calculate_base_asset_value_and_pnl; +use crate::math::position::calculate_base_asset_value_and_pnl; use crate::math::safe_math::SafeMath; use crate::state::oracle::get_oracle_price; @@ -163,47 +163,6 @@ pub fn calculate_peg_from_target_price( Ok(new_peg.max(1)) } -pub fn calculate_amm_target_price( - amm: &AMM, - current_price: u64, - oracle_price_data: &OraclePriceData, -) -> DriftResult { - // calculates peg_multiplier that changing to would cost no more than budget - let oracle_price_normalised = - amm::normalise_oracle_price(amm, oracle_price_data, Some(current_price))?.cast::()?; - - let weight_denom = 100_u128; - - let delay_penalty = max( - 0, - oracle_price_data - .delay - .safe_mul(max(1, oracle_price_data.delay.safe_div(2)?))?, - ); - - let oracle_price_weight: u128 = max(0, 100_i64.safe_sub(delay_penalty)?).cast()?; - - let target_price = if oracle_price_weight > 0 { - let current_price_weight: u128 = weight_denom.safe_sub(oracle_price_weight)?; - - oracle_price_normalised - .cast::()? - .safe_mul(oracle_price_weight)? - .safe_div(weight_denom)? - .safe_add( - current_price - .cast::()? - .safe_mul(current_price_weight)? - .safe_div(weight_denom)?, - )? - .cast::()? - } else { - current_price - }; - - Ok(target_price) -} - pub fn adjust_peg_cost( market: &PerpMarket, new_peg_candidate: u128, @@ -212,7 +171,7 @@ pub fn adjust_peg_cost( let cost = if new_peg_candidate != market_clone.amm.peg_multiplier { // Find the net market value before adjusting peg - let (current_net_market_value, _) = _calculate_base_asset_value_and_pnl( + let (current_net_market_value, _) = calculate_base_asset_value_and_pnl( market_clone.amm.base_asset_amount_with_amm, 0, &market_clone.amm, @@ -221,7 +180,7 @@ pub fn adjust_peg_cost( market_clone.amm.peg_multiplier = new_peg_candidate; - let (_new_net_market_value, cost) = _calculate_base_asset_value_and_pnl( + let (_new_net_market_value, cost) = calculate_base_asset_value_and_pnl( market_clone.amm.base_asset_amount_with_amm, current_net_market_value, &market_clone.amm,