Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- program: new median price for trigger orders ([#1716](https://github.com/drift-labs/protocol-v2/pull/1716))

### Fixes

### Breaking
Expand Down
1 change: 1 addition & 0 deletions programs/drift/src/controller/funding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ pub fn update_funding_rate(
.safe_add(funding_rate_short)?;

market.amm.last_funding_rate = funding_rate;
market.amm.last_funding_oracle_twap = oracle_price_twap;
market.amm.last_funding_rate_long = funding_rate_long.cast()?;
market.amm.last_funding_rate_short = funding_rate_short.cast()?;
market.amm.last_24h_avg_funding_rate = calculate_new_twap(
Expand Down
1 change: 1 addition & 0 deletions programs/drift/src/controller/liquidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,7 @@ pub fn liquidate_perp(
taker_existing_base_asset_amount: taker_existing_base_asset_amount,
maker_existing_quote_entry_amount: maker_existing_quote_entry_amount,
maker_existing_base_asset_amount: maker_existing_base_asset_amount,
trigger_price: None,
};
emit!(fill_record);

Expand Down
29 changes: 19 additions & 10 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ pub fn place_perp_order(
None,
None,
None,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;

Expand Down Expand Up @@ -721,6 +722,7 @@ pub fn cancel_order(
None,
None,
None,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;
}
Expand Down Expand Up @@ -1324,7 +1326,7 @@ pub fn fill_perp_order(
let fill_price =
calculate_fill_price(quote_asset_amount, base_asset_amount, BASE_PRECISION_U64)?;

let perp_market = perp_market_map.get_ref(&market_index)?;
let mut perp_market = perp_market_map.get_ref_mut(&market_index)?;
validate_fill_price_within_price_bands(
fill_price,
oracle_price,
Expand All @@ -1335,6 +1337,8 @@ pub fn fill_perp_order(
.max_oracle_twap_5min_percent_divergence(),
perp_market.is_prediction_market(),
)?;

perp_market.last_fill_price = fill_price;
}

let base_asset_amount_after = user.perp_positions[position_index].base_asset_amount;
Expand Down Expand Up @@ -2449,6 +2453,7 @@ pub fn fulfill_perp_order_with_amm(
taker_existing_base_asset_amount,
maker_existing_quote_entry_amount,
maker_existing_base_asset_amount,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;

Expand Down Expand Up @@ -2897,6 +2902,7 @@ pub fn fulfill_perp_order_with_match(
taker_existing_base_asset_amount,
maker_existing_quote_entry_amount,
maker_existing_base_asset_amount,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;

Expand Down Expand Up @@ -2989,11 +2995,10 @@ pub fn trigger_order(
"Order is not triggerable"
)?;

validate!(
!user.orders[order_index].triggered(),
ErrorCode::OrderNotTriggerable,
"Order is already triggered"
)?;
if user.orders[order_index].triggered() {
msg!("Order is already triggered");
return Ok(());
}

validate!(
market_type == MarketType::Perp,
Expand Down Expand Up @@ -3049,10 +3054,9 @@ pub fn trigger_order(
"oracle price vs twap too divergent"
)?;

let can_trigger = order_satisfies_trigger_condition(
&user.orders[order_index],
oracle_price.unsigned_abs().cast()?,
)?;
let trigger_price =
perp_market.get_trigger_price(oracle_price, now, state.use_median_trigger_price())?;
let can_trigger = order_satisfies_trigger_condition(&user.orders[order_index], trigger_price)?;
validate!(can_trigger, ErrorCode::OrderDidNotSatisfyTriggerCondition)?;

let (_, worst_case_liability_value_before) = user
Expand Down Expand Up @@ -3125,6 +3129,7 @@ pub fn trigger_order(
None,
None,
None,
Some(trigger_price),
)?;
emit!(order_action_record);

Expand Down Expand Up @@ -3810,6 +3815,7 @@ pub fn place_spot_order(
None,
None,
None,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;

Expand Down Expand Up @@ -5046,6 +5052,7 @@ pub fn fulfill_spot_order_with_match(
None,
None,
None,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;

Expand Down Expand Up @@ -5319,6 +5326,7 @@ pub fn fulfill_spot_order_with_external_market(
None,
None,
None,
None,
)?;
emit_stack::<_, { OrderActionRecord::SIZE }>(order_action_record)?;

Expand Down Expand Up @@ -5522,6 +5530,7 @@ pub fn trigger_spot_order(
None,
None,
None,
Some(oracle_price.unsigned_abs()),
)?;

emit!(order_action_record);
Expand Down
52 changes: 40 additions & 12 deletions programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::convert::{identity, TryInto};
use std::mem::size_of;

use crate::msg;
use crate::{msg, FeatureBitFlags};
use anchor_lang::prelude::*;
use anchor_spl::token_2022::Token2022;
use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface};
Expand Down Expand Up @@ -114,7 +114,7 @@ pub fn handle_initialize(ctx: Context<Initialize>) -> Result<()> {
initial_pct_to_liquidate: 0,
max_number_of_sub_accounts: 0,
max_initialize_user_fee: 0,
disable_bit_flags: 0,
feature_bit_flags: 0,
padding: [0; 9],
};

Expand Down Expand Up @@ -965,7 +965,9 @@ pub fn handle_initialize_perp_market(
high_leverage_margin_ratio_maintenance: 0,
protected_maker_limit_price_divisor: 0,
protected_maker_dynamic_divisor: 0,
padding: [0; 36],
padding1: 0,
last_fill_price: 0,
padding: [0; 24],
amm: AMM {
oracle: *ctx.accounts.oracle.key,
oracle_source,
Expand Down Expand Up @@ -1061,7 +1063,8 @@ pub fn handle_initialize_perp_market(
quote_asset_amount_with_unsettled_lp: 0,
reference_price_offset: 0,
amm_inventory_spread_adjustment: 0,
padding: [0; 11],
padding: [0; 3],
last_funding_oracle_twap: 0,
},
};

Expand Down Expand Up @@ -4853,7 +4856,7 @@ pub fn handle_zero_mm_oracle_fields(ctx: Context<HotAdminUpdatePerpMarket>) -> R
pub fn handle_update_mm_oracle_native(accounts: &[AccountInfo], data: &[u8]) -> Result<()> {
// Verify this ix is allowed
let state = &accounts[3].data.borrow();
assert!(state[982] & 1 == 0, "ix disabled by admin state");
assert!(state[982] & 1 > 0, "ix disabled by admin state");

let signer_account = &accounts[1];
#[cfg(not(feature = "anchor-test"))]
Expand Down Expand Up @@ -4898,22 +4901,47 @@ pub fn handle_update_amm_spread_adjustment_native(
Ok(())
}

pub fn handle_update_disable_bitflags_mm_oracle(
pub fn handle_update_feature_bit_flags_mm_oracle(
ctx: Context<HotAdminUpdateState>,
disable: bool,
enable: bool,
) -> Result<()> {
let state = &mut ctx.accounts.state;
if disable {
msg!("Setting first bit to 1, disabling mm oracle update");
state.disable_bit_flags = state.disable_bit_flags | 1;
if enable {
validate!(
ctx.accounts.admin.key().eq(&state.admin),
ErrorCode::DefaultError,
"Only state admin can re-enable after kill switch"
)?;

msg!("Setting first bit to 1, enabling mm oracle update");
state.feature_bit_flags = state.feature_bit_flags | (FeatureBitFlags::MmOracleUpdate as u8);
} else {
msg!("Setting first bit to 0, disabling mm oracle update");
state.feature_bit_flags =
state.feature_bit_flags & !(FeatureBitFlags::MmOracleUpdate as u8);
}
Ok(())
}

pub fn handle_update_feature_bit_flags_median_trigger_price(
ctx: Context<HotAdminUpdateState>,
enable: bool,
) -> Result<()> {
let state = &mut ctx.accounts.state;
if enable {
validate!(
ctx.accounts.admin.key().eq(&state.admin),
ErrorCode::DefaultError,
"Only state admin can re-enable after kill switch"
)?;
msg!("Setting first bit to 0, enabling mm oracle update");
state.disable_bit_flags = state.disable_bit_flags & !1;

msg!("Setting second bit to 1, enabling median trigger price");
state.feature_bit_flags =
state.feature_bit_flags | (FeatureBitFlags::MedianTriggerPrice as u8);
} else {
msg!("Setting second bit to 0, disabling median trigger price");
state.feature_bit_flags =
state.feature_bit_flags & !(FeatureBitFlags::MedianTriggerPrice as u8);
}
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions programs/drift/src/instructions/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1888,6 +1888,7 @@ pub fn handle_transfer_perp_position<'c: 'info, 'info>(
taker_existing_base_asset_amount: to_existing_base_asset_amount,
maker_existing_quote_entry_amount: from_existing_quote_entry_amount,
maker_existing_base_asset_amount: from_existing_base_asset_amount,
trigger_price: None,
};

emit_stack::<_, { OrderActionRecord::SIZE }>(fill_record)?;
Expand Down
13 changes: 10 additions & 3 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1810,16 +1810,23 @@ pub mod drift {
handle_update_if_rebalance_config(ctx, params)
}

pub fn update_disable_bitflags_mm_oracle(
pub fn update_feature_bit_flags_mm_oracle(
ctx: Context<HotAdminUpdateState>,
disable: bool,
enable: bool,
) -> Result<()> {
handle_update_disable_bitflags_mm_oracle(ctx, disable)
handle_update_feature_bit_flags_mm_oracle(ctx, enable)
}

pub fn zero_mm_oracle_fields(ctx: Context<HotAdminUpdatePerpMarket>) -> Result<()> {
handle_zero_mm_oracle_fields(ctx)
}

pub fn update_feature_bit_flags_median_trigger_price(
ctx: Context<HotAdminUpdateState>,
enable: bool,
) -> Result<()> {
handle_update_feature_bit_flags_median_trigger_price(ctx, enable)
}
}

#[cfg(not(feature = "no-entrypoint"))]
Expand Down
2 changes: 2 additions & 0 deletions programs/drift/src/math/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ pub const DEFAULT_QUOTE_ASSET_AMOUNT_TICK_SIZE: u64 =

// FUNDING
pub const FUNDING_RATE_OFFSET_DENOMINATOR: i64 = 5000; // 5000 => 7.3% annualized rate for hourly funding
pub const FUNDING_RATE_OFFSET_PERCENTAGE: i64 =
FUNDING_RATE_PRECISION_I64 / FUNDING_RATE_OFFSET_DENOMINATOR;

// ORDERS
pub const AUCTION_DERIVE_PRICE_FRACTION: i64 = 200;
Expand Down
6 changes: 5 additions & 1 deletion programs/drift/src/state/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,12 @@ pub struct OrderActionRecord {
/// precision: BASE_PRECISION
/// Only Some if the maker flipped position direction
pub maker_existing_base_asset_amount: Option<u64>,
/// precision: PRICE_PRECISION
pub trigger_price: Option<u64>,
}

impl Size for OrderActionRecord {
const SIZE: usize = 448;
const SIZE: usize = 464;
}

pub fn get_order_action_record(
Expand Down Expand Up @@ -285,6 +287,7 @@ pub fn get_order_action_record(
taker_existing_base_asset_amount: Option<u64>,
maker_existing_quote_entry_amount: Option<u64>,
maker_existing_base_asset_amount: Option<u64>,
trigger_price: Option<u64>,
) -> DriftResult<OrderActionRecord> {
Ok(OrderActionRecord {
ts,
Expand Down Expand Up @@ -337,6 +340,7 @@ pub fn get_order_action_record(
taker_existing_base_asset_amount,
maker_existing_quote_entry_amount,
maker_existing_base_asset_amount,
trigger_price,
})
}

Expand Down
Loading
Loading