Skip to content

Commit

Permalink
program: handle fallback price when amm has no liquidity (#324)
Browse files Browse the repository at this point in the history
* program: handle fallback price when amm has no liquidity

* update CHANGELOG

* tweak get_fallback_price
  • Loading branch information
crispheaney committed Jan 13, 2023
1 parent 1fc9958 commit cb07de3
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixes

- program: handle fallback price when amm has no liquidity ([#324](https://github.com/drift-labs/protocol-v2/pull/324))
- sdk: add getRestingLimitBids/Asks to DLOB ([#325](https://github.com/drift-labs/protocol-v2/pull/325))
- program: tweak oracle price used for determine_perp_fulfillment_methods

Expand Down
10 changes: 9 additions & 1 deletion programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ 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::math::amm::calculate_amm_available_liquidity;
use crate::math::safe_unwrap::SafeUnwrap;
use crate::print_error;
use crate::state::events::{emit_stack, get_order_action_record, OrderActionRecord, OrderRecord};
Expand Down Expand Up @@ -1734,7 +1735,14 @@ pub fn fulfill_perp_order_with_match(

let oracle_price = oracle_map.get_price_data(&market.amm.oracle)?.price;
let taker_direction = taker.orders[taker_order_index].direction;
let taker_fallback_price = get_fallback_price(&taker_direction, bid_price, ask_price);
let amm_available_liquidity = calculate_amm_available_liquidity(&market.amm, &taker_direction)?;
let taker_fallback_price = get_fallback_price(
&taker_direction,
bid_price,
ask_price,
amm_available_liquidity,
oracle_price,
)?;
let mut taker_price = taker.orders[taker_order_index].force_get_limit_price(
Some(oracle_price),
Some(taker_fallback_price),
Expand Down
2 changes: 1 addition & 1 deletion programs/drift/src/controller/orders/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3132,7 +3132,7 @@ pub mod fulfill_order {

..HistoricalOracleData::default()
},

max_fill_reserve_fraction: 1,
..AMM::default()
},
margin_ratio_initial: 1000,
Expand Down
2 changes: 1 addition & 1 deletion programs/drift/src/math/amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ pub fn is_oracle_mark_too_divergent(
Ok(price_spread_pct.unsigned_abs() > max_divergence)
}

pub fn calculate_max_base_asset_amount_fillable(
pub fn calculate_amm_available_liquidity(
amm: &AMM,
order_direction: &PositionDirection,
) -> DriftResult<u64> {
Expand Down
24 changes: 18 additions & 6 deletions programs/drift/src/math/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::controller::position::PositionDelta;
use crate::controller::position::PositionDirection;
use crate::error::{DriftResult, ErrorCode};
use crate::math;
use crate::math::amm::calculate_max_base_asset_amount_fillable;
use crate::math::amm::calculate_amm_available_liquidity;
use crate::math::auction::is_auction_complete;
use crate::math::casting::Cast;

Expand Down Expand Up @@ -62,8 +62,7 @@ pub fn calculate_base_asset_amount_for_amm_to_fulfill(
limit_price,
Some(existing_base_asset_amount),
)?;
let max_base_asset_amount =
calculate_max_base_asset_amount_fillable(&market.amm, &order.direction)?;
let max_base_asset_amount = calculate_amm_available_liquidity(&market.amm, &order.direction)?;

Ok((min(base_asset_amount, max_base_asset_amount), limit_price))
}
Expand Down Expand Up @@ -517,10 +516,23 @@ pub fn validate_fill_price(
Ok(())
}

pub fn get_fallback_price(direction: &PositionDirection, bid_price: u64, ask_price: u64) -> u64 {
pub fn get_fallback_price(
direction: &PositionDirection,
bid_price: u64,
ask_price: u64,
amm_available_liquidity: u64,
oracle_price: i64,
) -> DriftResult<u64> {
let oracle_price = oracle_price.unsigned_abs();
match direction {
PositionDirection::Long => ask_price,
PositionDirection::Short => bid_price,
PositionDirection::Long if amm_available_liquidity > 0 => {
ask_price.safe_add(ask_price / 200)
}
PositionDirection::Long => oracle_price.safe_add(oracle_price / 20),
PositionDirection::Short if amm_available_liquidity > 0 => {
bid_price.safe_sub(bid_price / 200)
}
PositionDirection::Short => oracle_price.safe_sub(oracle_price / 20),
}
}

Expand Down
1 change: 1 addition & 0 deletions programs/drift/src/state/perp_market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ impl AMM {
min_base_asset_reserve: 0,
terminal_quote_asset_reserve: default_reserves,
peg_multiplier: crate::math::constants::PEG_PRECISION,
max_fill_reserve_fraction: 1,
max_spread: 1000,
historical_oracle_data: HistoricalOracleData {
last_oracle_price: PRICE_PRECISION_I64,
Expand Down

0 comments on commit cb07de3

Please sign in to comment.