Skip to content

Commit

Permalink
program: init pause_operations flag
Browse files Browse the repository at this point in the history
  • Loading branch information
crispheaney committed Jan 28, 2024
1 parent bb98eb4 commit 49501f1
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 71 deletions.
23 changes: 13 additions & 10 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ use crate::state::fulfillment::{PerpFulfillmentMethod, SpotFulfillmentMethod};
use crate::state::margin_calculation::{MarginCalculation, MarginContext};
use crate::state::oracle::{OraclePriceData, StrictOraclePrice};
use crate::state::oracle_map::OracleMap;
use crate::state::paused_operations::PausedOperations;
use crate::state::perp_market::{AMMLiquiditySplit, MarketStatus, PerpMarket};
use crate::state::perp_market_map::PerpMarketMap;
use crate::state::spot_fulfillment_params::{ExternalSpotFill, SpotFulfillmentParams};
Expand Down Expand Up @@ -178,7 +179,7 @@ pub fn place_perp_order(
)?;

validate!(
market.is_active(now)?,
!market.is_in_settlement(now),

Check warning on line 182 in programs/drift/src/controller/orders.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/controller/orders.rs#L182

Added line #L182 was not covered by tests
ErrorCode::MarketPlaceOrderPaused,
"Market is in settlement mode",
)?;
Expand Down Expand Up @@ -912,14 +913,16 @@ pub fn fill_perp_order(
validate!(
matches!(
market.status,
MarketStatus::Active
| MarketStatus::AmmPaused
| MarketStatus::FundingPaused
| MarketStatus::ReduceOnly
| MarketStatus::WithdrawPaused
MarketStatus::Active | MarketStatus::ReduceOnly
),
ErrorCode::MarketFillOrderPaused,
"Market unavailable for fills"
"Market not active",
)?;

validate!(

Check warning on line 922 in programs/drift/src/controller/orders.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/controller/orders.rs#L922

Added line #L922 was not covered by tests
!market.is_operation_paused(PausedOperations::Fill),
ErrorCode::MarketFillOrderPaused,

Check warning on line 924 in programs/drift/src/controller/orders.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/controller/orders.rs#L924

Added line #L924 was not covered by tests
"Market fills paused",
)?;

drop(market);
Expand Down Expand Up @@ -963,10 +966,10 @@ pub fn fill_perp_order(
let mut amm_is_available = !state.amm_paused()?;
{
let market = &mut perp_market_map.get_ref_mut(&market_index)?;
amm_is_available &= market.status != MarketStatus::AmmPaused;
amm_is_available &= !market.is_operation_paused(PausedOperations::AmmFills);
validation::perp_market::validate_perp_market(market)?;
validate!(
market.is_active(now)?,
!market.is_in_settlement(now),
ErrorCode::MarketFillOrderPaused,
"Market is in settlement mode",
)?;
Expand Down Expand Up @@ -1204,7 +1207,7 @@ pub fn fill_perp_order(
{
let market = &mut perp_market_map.get_ref_mut(&market_index)?;
let funding_paused =
state.funding_paused()? || matches!(market.status, MarketStatus::FundingPaused);
state.funding_paused()? || market.is_operation_paused(PausedOperations::Funding);

controller::funding::update_funding_rate(
market_index,
Expand Down
10 changes: 5 additions & 5 deletions programs/drift/src/controller/pnl/delisting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ pub mod delisting_test {
)
.is_err());
assert_eq!(market.is_reduce_only().unwrap(), false);
assert_eq!(market.is_active(clock.unix_timestamp).unwrap(), true);
assert_eq!(market.is_in_settlement(clock.unix_timestamp), false);

market.expiry_ts = clock.unix_timestamp + 100;
assert_eq!(clock.unix_timestamp, 1662065595);

assert_eq!(market.is_active(clock.unix_timestamp).unwrap(), true);
assert_eq!(market.is_in_settlement(clock.unix_timestamp), false);
assert_eq!(market.is_reduce_only().unwrap(), false); // isnt set like in update expiry ix

market.status = MarketStatus::ReduceOnly;
Expand Down Expand Up @@ -255,7 +255,7 @@ pub mod delisting_test {
assert_eq!(market.expiry_ts < clock.unix_timestamp, true);
assert_eq!(market.status, MarketStatus::Initialized);
assert_eq!(market.expiry_price, 0);
assert_eq!(market.is_active(clock.unix_timestamp).unwrap(), false);
assert_eq!(market.is_in_settlement(clock.unix_timestamp), true);

// put in settlement mode
settle_expired_market(
Expand Down Expand Up @@ -1906,7 +1906,7 @@ pub mod delisting_test {

assert_eq!(total_collateral_short, 17_000_000_000);
assert_eq!(margin_requirement_short, 16002510000);
assert_eq!(market.is_active(clock.unix_timestamp).unwrap(), false);
assert_eq!(market.is_in_settlement(clock.unix_timestamp), true);
assert_eq!(market.is_reduce_only().unwrap(), false);

// put in settlement mode
Expand All @@ -1920,7 +1920,7 @@ pub mod delisting_test {
)
.unwrap();
assert_eq!(market.is_reduce_only().unwrap(), false);
assert_eq!(market.is_active(clock.unix_timestamp).unwrap(), false);
assert_eq!(market.is_in_settlement(clock.unix_timestamp), true);

let market = market_map.get_ref_mut(&0).unwrap();
assert_eq!(market.expiry_price != 0, true);
Expand Down
4 changes: 2 additions & 2 deletions programs/drift/src/controller/spot_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ 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;
use crate::state::spot_market::{SpotBalance, SpotBalanceType, SpotMarket};
use crate::validate;

use crate::math::oracle::{is_oracle_valid_for_action, DriftAction};
use crate::math::safe_math::SafeMath;
use crate::state::paused_operations::PausedOperations;

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -124,7 +124,7 @@ pub fn update_spot_market_cumulative_interest(
oracle_price_data: Option<&OraclePriceData>,
now: i64,
) -> DriftResult {
if spot_market.status == MarketStatus::FundingPaused {
if spot_market.is_operation_paused(PausedOperations::Funding) {
update_spot_market_twap_stats(spot_market, oracle_price_data, now)?;
return Ok(());
}
Expand Down
9 changes: 2 additions & 7 deletions programs/drift/src/controller/spot_position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,10 @@ pub fn update_spot_balances_and_cumulative_deposits_with_limits(
validate!(
matches!(
spot_market.status,
MarketStatus::Active
| MarketStatus::AmmPaused
| MarketStatus::FundingPaused
| MarketStatus::FillPaused
| MarketStatus::ReduceOnly
| MarketStatus::Settlement
MarketStatus::Active | MarketStatus::ReduceOnly | MarketStatus::Settlement
),
ErrorCode::MarketWithdrawPaused,
"Spot Market {} withdraws are currently paused",
"Spot Market {} withdraws are currently paused, market not active or in settlement",
spot_market.market_index
)?;

Expand Down
5 changes: 3 additions & 2 deletions programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ pub fn handle_initialize_spot_market(
spot_fee_pool: PoolBalance::default(), // in quote asset
total_spot_fee: 0,
orders_enabled: spot_market_index != 0,
padding1: [0; 6],
paused_operations: 0,
padding1: [0; 5],

Check warning on line 270 in programs/drift/src/instructions/admin.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/admin.rs#L270

Added line #L270 was not covered by tests
flash_loan_amount: 0,
flash_loan_initial_token_amount: 0,
total_swap_fee: 0,
Expand Down Expand Up @@ -632,7 +633,7 @@ pub fn handle_initialize_perp_market(
unrealized_pnl_max_imbalance: 0,
liquidator_fee,
if_liquidation_fee: LIQUIDATION_FEE_PRECISION / 100, // 1%
padding1: 0,
paused_operations: 0,
quote_spot_market_index: 0,
fee_adjustment: 0,
padding: [0; 46],
Expand Down
2 changes: 1 addition & 1 deletion programs/drift/src/instructions/keeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ pub fn handle_resolve_perp_pnl_deficit(
}

validate!(
perp_market.is_active(now)?,
!perp_market.is_in_settlement(now),

Check warning on line 890 in programs/drift/src/instructions/keeper.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/keeper.rs#L890

Added line #L890 was not covered by tests
ErrorCode::MarketActionPaused,
"Market is in settlement mode",
)?;
Expand Down
42 changes: 19 additions & 23 deletions programs/drift/src/instructions/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use crate::state::oracle::StrictOraclePrice;
use crate::state::order_params::{
ModifyOrderParams, OrderParams, PlaceOrderOptions, PostOnlyParam,
};
use crate::state::paused_operations::PausedOperations;
use crate::state::perp_market::MarketStatus;
use crate::state::perp_market_map::{get_writable_perp_market_set, MarketSet};
use crate::state::spot_fulfillment_params::SpotFulfillmentParams;
Expand Down Expand Up @@ -342,16 +343,9 @@ pub fn handle_deposit(

if spot_position.balance_type == SpotBalanceType::Deposit && spot_position.scaled_balance > 0 {
validate!(
matches!(
spot_market.status,
MarketStatus::Active
| MarketStatus::FundingPaused
| MarketStatus::AmmPaused
| MarketStatus::FillPaused
| MarketStatus::WithdrawPaused
),
matches!(spot_market.status, MarketStatus::Active),

Check warning on line 346 in programs/drift/src/instructions/user.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/user.rs#L346

Added line #L346 was not covered by tests
ErrorCode::MarketActionPaused,
"spot_market in reduce only mode",
"spot_market not active",
)?;
}

Expand Down Expand Up @@ -650,18 +644,20 @@ pub fn handle_transfer_deposit(
validate!(
matches!(
spot_market.status,
MarketStatus::Active
| MarketStatus::AmmPaused
| MarketStatus::FundingPaused
| MarketStatus::FillPaused
| MarketStatus::ReduceOnly
| MarketStatus::Settlement
MarketStatus::Active | MarketStatus::ReduceOnly | MarketStatus::Settlement
),
ErrorCode::MarketWithdrawPaused,
"Spot Market {} withdraws are currently paused",
spot_market.market_index
)?;

validate!(
spot_market.is_operation_paused(PausedOperations::Withdraw),
ErrorCode::MarketWithdrawPaused,

Check warning on line 656 in programs/drift/src/instructions/user.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/user.rs#L654-L656

Added lines #L654 - L656 were not covered by tests
"Spot Market {} withdraws are currently paused",
spot_market.market_index

Check warning on line 658 in programs/drift/src/instructions/user.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/user.rs#L658

Added line #L658 was not covered by tests
)?;

from_user.increment_total_withdraws(
amount,
oracle_price,
Expand Down Expand Up @@ -1661,17 +1657,17 @@ pub fn handle_add_perp_lp_shares<'info>(
let mut market = perp_market_map.get_ref_mut(&market_index)?;

validate!(
matches!(
market.status,
MarketStatus::Active
| MarketStatus::FundingPaused
| MarketStatus::FillPaused
| MarketStatus::WithdrawPaused
),
matches!(market.status, MarketStatus::Active),

Check warning on line 1660 in programs/drift/src/instructions/user.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/user.rs#L1660

Added line #L1660 was not covered by tests
ErrorCode::MarketStatusInvalidForNewLP,
"Market Status doesn't allow for new LP liquidity"
)?;

validate!(
market.is_operation_paused(PausedOperations::AmmFills),
ErrorCode::MarketStatusInvalidForNewLP,

Check warning on line 1667 in programs/drift/src/instructions/user.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/user.rs#L1665-L1667

Added lines #L1665 - L1667 were not covered by tests
"Market amm fills paused"
)?;

validate!(
n_shares >= market.amm.order_step_size,
ErrorCode::NewLPSizeTooSmall,
Expand Down Expand Up @@ -1960,7 +1956,7 @@ pub fn handle_deposit_into_spot_market_revenue_pool(
let mut spot_market = load_mut!(ctx.accounts.spot_market)?;

validate!(
spot_market.is_active(Clock::get()?.unix_timestamp)?,
!spot_market.is_in_settlement(Clock::get()?.unix_timestamp),

Check warning on line 1959 in programs/drift/src/instructions/user.rs

View check run for this annotation

Codecov / codecov/patch

programs/drift/src/instructions/user.rs#L1959

Added line #L1959 was not covered by tests
ErrorCode::DefaultError,
"spot market {} not active",
spot_market.market_index
Expand Down
5 changes: 3 additions & 2 deletions programs/drift/src/math/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use crate::math::constants::BID_ASK_SPREAD_PRECISION;
use crate::math::safe_math::SafeMath;

use crate::state::oracle::OraclePriceData;
use crate::state::perp_market::{MarketStatus, PerpMarket, AMM};
use crate::state::paused_operations::PausedOperations;
use crate::state::perp_market::{PerpMarket, AMM};
use crate::state::state::{OracleGuardRails, ValidityGuardRails};

#[cfg(test)]
Expand Down Expand Up @@ -123,7 +124,7 @@ pub fn block_operation(

let slots_since_amm_update = slot.saturating_sub(market.amm.last_update_slot);

let funding_paused_on_market = market.status == MarketStatus::FundingPaused;
let funding_paused_on_market = market.is_operation_paused(PausedOperations::Funding);

let block = slots_since_amm_update > 10
|| !is_oracle_valid
Expand Down
1 change: 1 addition & 0 deletions programs/drift/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod margin_calculation;
pub mod oracle;
pub mod oracle_map;
pub mod order_params;
pub mod paused_operations;
pub mod perp_market;
pub mod perp_market_map;
pub mod spot_fulfillment_params;
Expand Down
17 changes: 17 additions & 0 deletions programs/drift/src/state/paused_operations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#[derive(Clone, Copy, PartialEq, Debug, Eq)]
pub enum PausedOperations {
/// funding rate updates are paused
Funding = 0b00000001,
/// amm fills are prevented/blocked
AmmFills = 0b00000010,
/// fills are blocked
Fill = 0b00000100,
/// perp: pause settling negative pnl | spot: pause depositing asset
Withdraw = 0b00001000,
}

impl PausedOperations {
pub fn is_operation_paused(current: u8, operation: PausedOperations) -> bool {
current & operation as u8 != 0
}
}
17 changes: 11 additions & 6 deletions programs/drift/src/state/perp_market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::state::traits::{MarketIndexOffset, Size};
use crate::{AMM_TO_QUOTE_PRECISION_RATIO, PRICE_PRECISION};
use borsh::{BorshDeserialize, BorshSerialize};

use crate::state::paused_operations::PausedOperations;
use drift_macros::assert_no_slop;
use static_assertions::const_assert_eq;

Expand Down Expand Up @@ -202,7 +203,7 @@ pub struct PerpMarket {
/// The contract tier determines how much insurance a market can receive, with more speculative markets receiving less insurance
/// It also influences the order perp markets can be liquidated, with less speculative markets being liquidated first
pub contract_tier: ContractTier,
pub padding1: u8,
pub paused_operations: u8,
/// The spot market that pnl is settled in
pub quote_spot_market_index: u16,
/// Between -100 and 100, represents what % to increase/decrease the fee by
Expand Down Expand Up @@ -240,7 +241,7 @@ impl Default for PerpMarket {
status: MarketStatus::default(),
contract_type: ContractType::default(),
contract_tier: ContractTier::default(),
padding1: 0,
paused_operations: 0,
quote_spot_market_index: 0,
fee_adjustment: 0,
padding: [0; 46],
Expand All @@ -257,19 +258,23 @@ impl MarketIndexOffset for PerpMarket {
}

impl PerpMarket {
pub fn is_active(&self, now: i64) -> DriftResult<bool> {
let status_ok = !matches!(
pub fn is_in_settlement(&self, now: i64) -> bool {
let in_settlement = matches!(
self.status,
MarketStatus::Settlement | MarketStatus::Delisted
);
let not_expired = self.expiry_ts == 0 || now < self.expiry_ts;
Ok(status_ok && not_expired)
let expired = self.expiry_ts != 0 && now >= self.expiry_ts;
in_settlement || expired
}

pub fn is_reduce_only(&self) -> DriftResult<bool> {
Ok(self.status == MarketStatus::ReduceOnly)
}

pub fn is_operation_paused(&self, operation: PausedOperations) -> bool {
PausedOperations::is_operation_paused(self.paused_operations, operation)
}

pub fn get_sanitize_clamp_denominator(self) -> DriftResult<Option<i64>> {
Ok(match self.contract_tier {
ContractTier::A => Some(10_i64), // 10%
Expand Down
Loading

0 comments on commit 49501f1

Please sign in to comment.