Skip to content

Commit 607a687

Browse files
committed
remove price bands logic
1 parent ddf3067 commit 607a687

File tree

4 files changed

+99
-53
lines changed

4 files changed

+99
-53
lines changed

programs/drift/src/controller/orders.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,7 @@ pub fn fill_perp_order(
13001300
let perp_market = perp_market_map.get_ref(&market_index)?;
13011301
validate_fill_price_within_price_bands(
13021302
fill_price,
1303+
order_direction,
13031304
oracle_price,
13041305
oracle_twap_5min,
13051306
perp_market.margin_ratio_initial,
@@ -4041,6 +4042,7 @@ pub fn fill_spot_order(
40414042
.last_oracle_price_twap_5min;
40424043
validate_fill_price_within_price_bands(
40434044
fill_price,
4045+
order_direction,
40444046
oracle_price,
40454047
oracle_twap_5min,
40464048
spot_market.get_margin_ratio(&MarginRequirementType::Initial)?,

programs/drift/src/math/orders.rs

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ use crate::controller::position::PositionDelta;
77
use crate::controller::position::PositionDirection;
88
use crate::error::{DriftResult, ErrorCode};
99
use crate::math::amm::calculate_amm_available_liquidity;
10+
use crate::math::auction::is_amm_available_liquidity_source;
1011
use crate::math::casting::Cast;
12+
use crate::state::fill_mode::FillMode;
1113
use crate::state::protected_maker_mode_config::ProtectedMakerParams;
1214
use crate::state::user::OrderBitFlag;
1315
use crate::{
14-
load, math, FeeTier, BASE_PRECISION_I128, FEE_ADJUSTMENT_MAX, MARGIN_PRECISION_I128,
16+
load, math, FeeTier, State, BASE_PRECISION_I128, FEE_ADJUSTMENT_MAX, MARGIN_PRECISION_I128,
1517
MAX_PREDICTION_MARKET_PRICE, MAX_PREDICTION_MARKET_PRICE_I64, OPEN_ORDER_MARGIN_REQUIREMENT,
1618
PERCENTAGE_PRECISION, PERCENTAGE_PRECISION_U64, PRICE_PRECISION_I128, PRICE_PRECISION_U64,
1719
QUOTE_PRECISION_I128, SPOT_WEIGHT_PRECISION, SPOT_WEIGHT_PRECISION_I128,
@@ -484,6 +486,7 @@ pub fn limit_price_breaches_maker_oracle_price_bands(
484486

485487
pub fn validate_fill_price_within_price_bands(
486488
fill_price: u64,
489+
direction: PositionDirection,
487490
oracle_price: i64,
488491
oracle_twap_5min: i64,
489492
margin_ratio_initial: u32,
@@ -508,37 +511,79 @@ pub fn validate_fill_price_within_price_bands(
508511
let max_oracle_diff = margin_ratio_initial.cast::<u128>()?;
509512
let max_oracle_twap_diff = oracle_twap_5min_percent_divergence.cast::<u128>()?; // 50%
510513

511-
let percent_diff: u128 = fill_price
512-
.abs_diff(oracle_price)
513-
.cast::<u128>()?
514-
.safe_mul(MARGIN_PRECISION_U128)?
515-
.safe_div(oracle_price.cast()?)?;
516-
517-
validate!(
518-
percent_diff < max_oracle_diff,
519-
ErrorCode::PriceBandsBreached,
520-
"Fill Price Breaches Oracle Price Bands: {} % <= {} % (fill: {} >= oracle: {})",
521-
max_oracle_diff,
522-
percent_diff,
523-
fill_price,
524-
oracle_price
525-
)?;
514+
if direction == PositionDirection::Long {
515+
if fill_price < oracle_price && fill_price < oracle_twap_5min {
516+
return Ok(());
517+
}
526518

527-
let percent_diff = fill_price
528-
.abs_diff(oracle_twap_5min)
529-
.cast::<u128>()?
530-
.safe_mul(PERCENTAGE_PRECISION)?
531-
.safe_div(oracle_twap_5min.cast()?)?;
532-
533-
validate!(
534-
percent_diff < max_oracle_twap_diff,
535-
ErrorCode::PriceBandsBreached,
536-
"Fill Price Breaches Oracle TWAP Price Bands: {} % <= {} % (fill: {} >= twap: {})",
537-
max_oracle_twap_diff,
538-
percent_diff,
539-
fill_price,
540-
oracle_twap_5min
541-
)?;
519+
let percent_diff: u128 = fill_price
520+
.saturating_sub(oracle_price)
521+
.cast::<u128>()?
522+
.safe_mul(MARGIN_PRECISION_U128)?
523+
.safe_div(oracle_price.cast()?)?;
524+
525+
validate!(
526+
percent_diff < max_oracle_diff,
527+
ErrorCode::PriceBandsBreached,
528+
"Fill Price Breaches Oracle Price Bands: {} % <= {} % (fill: {} >= oracle: {})",
529+
max_oracle_diff,
530+
percent_diff,
531+
fill_price,
532+
oracle_price
533+
)?;
534+
535+
let percent_diff = fill_price
536+
.saturating_sub(oracle_twap_5min)
537+
.cast::<u128>()?
538+
.safe_mul(PERCENTAGE_PRECISION)?
539+
.safe_div(oracle_twap_5min.cast()?)?;
540+
541+
validate!(
542+
percent_diff < max_oracle_twap_diff,
543+
ErrorCode::PriceBandsBreached,
544+
"Fill Price Breaches Oracle TWAP Price Bands: {} % <= {} % (fill: {} >= twap: {})",
545+
max_oracle_twap_diff,
546+
percent_diff,
547+
fill_price,
548+
oracle_twap_5min
549+
)?;
550+
} else {
551+
if fill_price > oracle_price && fill_price > oracle_twap_5min {
552+
return Ok(());
553+
}
554+
555+
let percent_diff: u128 = oracle_price
556+
.saturating_sub(fill_price)
557+
.cast::<u128>()?
558+
.safe_mul(MARGIN_PRECISION_U128)?
559+
.safe_div(oracle_price.cast()?)?;
560+
561+
validate!(
562+
percent_diff < max_oracle_diff,
563+
ErrorCode::PriceBandsBreached,
564+
"Fill Price Breaches Oracle Price Bands: {} % <= {} % (fill: {} <= oracle: {})",
565+
max_oracle_diff,
566+
percent_diff,
567+
fill_price,
568+
oracle_price
569+
)?;
570+
571+
let percent_diff = oracle_twap_5min
572+
.saturating_sub(fill_price)
573+
.cast::<u128>()?
574+
.safe_mul(PERCENTAGE_PRECISION)?
575+
.safe_div(oracle_twap_5min.cast()?)?;
576+
577+
validate!(
578+
percent_diff < max_oracle_twap_diff,
579+
ErrorCode::PriceBandsBreached,
580+
"Fill Price Breaches Oracle TWAP Price Bands: {} % <= {} % (fill: {} <= twap: {})",
581+
max_oracle_twap_diff,
582+
percent_diff,
583+
fill_price,
584+
oracle_twap_5min
585+
)?;
586+
}
542587

543588
Ok(())
544589
}

programs/drift/src/math/orders/tests.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,17 +3161,22 @@ mod calculate_max_perp_order_size {
31613161

31623162
pub mod validate_fill_price_within_price_bands {
31633163
use crate::math::orders::validate_fill_price_within_price_bands;
3164-
use crate::{MARGIN_PRECISION, PERCENTAGE_PRECISION, PRICE_PRECISION_I64, PRICE_PRECISION_U64};
3164+
use crate::{
3165+
PositionDirection, MARGIN_PRECISION, PERCENTAGE_PRECISION, PRICE_PRECISION_I64,
3166+
PRICE_PRECISION_U64,
3167+
};
31653168

31663169
#[test]
31673170
fn valid_long() {
31683171
let oracle_price = 100 * PRICE_PRECISION_I64;
31693172
let twap = oracle_price;
31703173
let fill_price = 105 * PRICE_PRECISION_U64;
3174+
let direction = PositionDirection::Long;
31713175
let margin_ratio_initial = MARGIN_PRECISION / 10;
31723176

31733177
assert!(validate_fill_price_within_price_bands(
31743178
fill_price,
3179+
direction,
31753180
oracle_price,
31763181
twap,
31773182
margin_ratio_initial,
@@ -3186,10 +3191,12 @@ pub mod validate_fill_price_within_price_bands {
31863191
let oracle_price = 100 * PRICE_PRECISION_I64;
31873192
let twap = oracle_price;
31883193
let fill_price = 95 * PRICE_PRECISION_U64;
3194+
let direction = PositionDirection::Short;
31893195
let margin_ratio_initial = MARGIN_PRECISION / 10;
31903196

31913197
assert!(validate_fill_price_within_price_bands(
31923198
fill_price,
3199+
direction,
31933200
oracle_price,
31943201
twap,
31953202
margin_ratio_initial,
@@ -3205,10 +3212,12 @@ pub mod validate_fill_price_within_price_bands {
32053212
let twap = oracle_price;
32063213
// 11% greater than oracle price
32073214
let fill_price = 111 * PRICE_PRECISION_U64;
3215+
let direction = PositionDirection::Long;
32083216
let margin_ratio_initial = MARGIN_PRECISION / 10; // 10x
32093217

32103218
assert!(validate_fill_price_within_price_bands(
32113219
fill_price,
3220+
direction,
32123221
oracle_price,
32133222
twap,
32143223
margin_ratio_initial,
@@ -3224,10 +3233,12 @@ pub mod validate_fill_price_within_price_bands {
32243233
let twap = oracle_price;
32253234
// 11% less than oracle price
32263235
let fill_price = 89 * PRICE_PRECISION_U64;
3236+
let direction = PositionDirection::Short;
32273237
let margin_ratio_initial = MARGIN_PRECISION / 10; // 10x
32283238

32293239
assert!(validate_fill_price_within_price_bands(
32303240
fill_price,
3241+
direction,
32313242
oracle_price,
32323243
twap,
32333244
margin_ratio_initial,
@@ -3243,10 +3254,12 @@ pub mod validate_fill_price_within_price_bands {
32433254
let twap = 100 * PRICE_PRECISION_I64;
32443255
// 50% greater than twap
32453256
let fill_price = 150 * PRICE_PRECISION_U64;
3257+
let direction = PositionDirection::Long;
32463258
let margin_ratio_initial = MARGIN_PRECISION / 10; // 10x
32473259

32483260
assert!(validate_fill_price_within_price_bands(
32493261
fill_price,
3262+
direction,
32503263
oracle_price,
32513264
twap,
32523265
margin_ratio_initial,
@@ -3262,29 +3275,12 @@ pub mod validate_fill_price_within_price_bands {
32623275
let twap = 100 * PRICE_PRECISION_I64;
32633276
// 50% less than twap
32643277
let fill_price = 50 * PRICE_PRECISION_U64;
3278+
let direction = PositionDirection::Short;
32653279
let margin_ratio_initial = MARGIN_PRECISION / 10; // 10x
32663280

32673281
assert!(validate_fill_price_within_price_bands(
32683282
fill_price,
3269-
oracle_price,
3270-
twap,
3271-
margin_ratio_initial,
3272-
(PERCENTAGE_PRECISION / 2) as u64,
3273-
false,
3274-
)
3275-
.is_err())
3276-
}
3277-
3278-
#[test]
3279-
fn invalid_long_too_volatile() {
3280-
let oracle_price = 100 * PRICE_PRECISION_I64;
3281-
let twap = 100 * PRICE_PRECISION_I64;
3282-
// 50% less than twap
3283-
let fill_price = 10 * PRICE_PRECISION_U64;
3284-
let margin_ratio_initial = MARGIN_PRECISION / 10; // 10x
3285-
3286-
assert!(validate_fill_price_within_price_bands(
3287-
fill_price,
3283+
direction,
32883284
oracle_price,
32893285
twap,
32903286
margin_ratio_initial,

programs/drift/src/math/spot_swap.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::math::safe_math::SafeMath;
66
use crate::math::spot_balance::{get_strict_token_value, get_token_value};
77
use crate::state::oracle::StrictOraclePrice;
88
use crate::state::spot_market::SpotMarket;
9-
use crate::{PRICE_PRECISION, SPOT_WEIGHT_PRECISION_U128};
9+
use crate::{PositionDirection, PRICE_PRECISION, SPOT_WEIGHT_PRECISION_U128};
1010

1111
#[cfg(test)]
1212
mod tests;
@@ -100,7 +100,7 @@ pub fn validate_price_bands_for_swap(
100100
out_price: i64,
101101
oracle_twap_5min_percent_divergence: u64,
102102
) -> DriftResult {
103-
let (fill_price, oracle_price, oracle_twap_5min, margin_ratio) = {
103+
let (fill_price, direction, oracle_price, oracle_twap_5min, margin_ratio) = {
104104
let in_market_margin_ratio = in_market.get_margin_ratio(&MarginRequirementType::Initial)?;
105105

106106
if in_market_margin_ratio != 0 {
@@ -113,6 +113,7 @@ pub fn validate_price_bands_for_swap(
113113

114114
(
115115
fill_price,
116+
PositionDirection::Short,
116117
in_price,
117118
in_market.historical_oracle_data.last_oracle_price_twap_5min,
118119
in_market_margin_ratio,
@@ -123,6 +124,7 @@ pub fn validate_price_bands_for_swap(
123124

124125
(
125126
fill_price,
127+
PositionDirection::Long,
126128
out_price,
127129
out_market
128130
.historical_oracle_data
@@ -134,6 +136,7 @@ pub fn validate_price_bands_for_swap(
134136

135137
validate_fill_price_within_price_bands(
136138
fill_price,
139+
direction,
137140
oracle_price,
138141
oracle_twap_5min,
139142
margin_ratio,

0 commit comments

Comments
 (0)