Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f30a47d
feat: option for custom oracle ws subscriber
LukasDeco Aug 13, 2025
aceaf6d
fix: pass custom oracle ws sub option in dc constructor
LukasDeco Aug 13, 2025
899f32b
sdk: add spot-market-index-57 to constants (#1815)
0xbigz Aug 13, 2025
336a40a
sdk: release v2.134.0-beta.2
github-actions[bot] Aug 13, 2025
5c37cce
lazer oracle migration (#1813)
moosecat2 Aug 13, 2025
1309349
sdk: release v2.134.0-beta.3
github-actions[bot] Aug 13, 2025
a0ded12
Merge pull request #1814 from drift-labs/lukas/oracle-ws-wubscribers-…
LukasDeco Aug 13, 2025
5fe346b
sdk: release v2.134.0-beta.4
github-actions[bot] Aug 13, 2025
04bfee3
program: settle pnl invariants (#1812)
crispheaney Aug 13, 2025
69ad09c
program: add_update_perp_pnl_pool (#1810)
crispheaney Aug 13, 2025
f74c938
sdk: release v2.134.0-beta.5
github-actions[bot] Aug 13, 2025
84bc55a
program: update-mark-twap-integer-bias (#1783)
0xbigz Aug 13, 2025
50547b8
program: update-fee-tier-determine-fix5 (#1800)
0xbigz Aug 13, 2025
bca72c4
program: update-mark-twap-crank-use-5min-basis (#1769)
0xbigz Aug 13, 2025
472d40b
program: update-min-margin-const-limit (#1802)
0xbigz Aug 13, 2025
c130b68
sdk: release v2.134.0-beta.6
github-actions[bot] Aug 13, 2025
4d5c479
program: rm-burn-lp-shares-invariant (#1816)
0xbigz Aug 13, 2025
66c10a2
fix test and cargo fmt
crispheaney Aug 13, 2025
bd5b8ae
fix anchor tests
crispheaney Aug 13, 2025
29e0058
yarn prettify:fix
crispheaney Aug 13, 2025
4035737
reenable settle_pnl mode test
wphan Aug 13, 2025
0fb3ec3
v2.134.0
wphan Aug 13, 2025
ff140d8
sdk: release v2.135.0-beta.0
github-actions[bot] Aug 13, 2025
0f4bb19
Merge pull request #1820 from drift-labs/chester/fix-zod
ChesterSim Aug 18, 2025
6e58c78
sdk: release v2.135.0-beta.1
github-actions[bot] Aug 18, 2025
bcb138d
mm oracle sdk change (#1806)
moosecat2 Aug 18, 2025
6189725
sdk: release v2.135.0-beta.2
github-actions[bot] Aug 18, 2025
6244cca
sdk: fix isHighLeverageMode
crispheaney Aug 18, 2025
35f72c4
sdk: release v2.135.0-beta.3
github-actions[bot] Aug 18, 2025
c4188d1
refactor(sdk): add update delegate ix method, ovrride authority for s…
ChesterSim Aug 19, 2025
4ffaa71
check in for z
moosecat2 Aug 19, 2025
ad49f76
more logging changes
moosecat2 Aug 19, 2025
0f7f0cc
mm oracle sdk additions (#1824)
moosecat2 Aug 19, 2025
7bc5ad4
sdk: release v2.135.0-beta.4
github-actions[bot] Aug 19, 2025
0fc52a3
init constituent bug fix and type change
moosecat2 Aug 19, 2025
7a2663f
add in invariant to be within 1 bp of balance before after
moosecat2 Aug 19, 2025
8bf70f3
add strict typing for getPrice and new auction trigger function (#1826)
moosecat2 Aug 20, 2025
59c678f
sdk: release v2.135.0-beta.5
github-actions[bot] Aug 20, 2025
634cb94
update tests and enforce atomic settles for withdraw
moosecat2 Aug 20, 2025
7638e5c
add failing withdraw test
moosecat2 Aug 20, 2025
601e332
Merge branch 'master' into nour/bl-branch
moosecat2 Aug 20, 2025
dfc7679
withdraw fix
moosecat2 Aug 21, 2025
588c85f
bring diff in validate back to 1
moosecat2 Aug 21, 2025
82f1c7d
make lp pool test fail
moosecat2 Aug 21, 2025
a066230
better failed test
moosecat2 Aug 22, 2025
a1d5bd7
only check after < before, do to spot precision limits
0xbigz Aug 22, 2025
c899777
add balance check to be < 1 cent
moosecat2 Aug 22, 2025
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
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking

## [2.134.0] - 2025-08-13

### Features

- program: add new settle pnl invariants ([#1812](https://github.com/drift-labs/protocol-v2/pull/1812))
- program: add update_perp_market_pnl_pool ([#1810](https://github.com/drift-labs/protocol-v2/pull/1810))
- program: increase min margin ratio invariant constant ([#1802](https://github.com/drift-labs/protocol-v2/pull/1802))
- program: update mark twap crank use 5min basis for bid/ask ([#1769](https://github.com/drift-labs/protocol-v2/pull/1769))

### Fixes

- program: remove burn lp shares invariant ([#1816](https://github.com/drift-labs/protocol-v2/pull/1816))
- program: correct fee tier 5 volume requirement ([#1800](https://github.com/drift-labs/protocol-v2/pull/1800))
- program: fix small number mark-twap-integer-bias ([#1783](https://github.com/drift-labs/protocol-v2/pull/1783))

### Breaking

## [2.133.0] - 2025-08-11

### Features
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,075 changes: 1,075 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"dependencies": {
"@ellipsis-labs/phoenix-sdk": "1.4.2",
"@pythnetwork/pyth-solana-receiver": "0.8.0",
"@switchboard-xyz/on-demand": "2.4.1",
"@switchboard-xyz/common": "3.0.14",
"@switchboard-xyz/on-demand": "2.4.1",
"anchor-bankrun": "0.3.0",
"chai-bn": "0.2.2",
"csvtojson": "2.0.10",
Expand All @@ -40,6 +40,7 @@
"nanoid": "3.3.4",
"rpc-websockets": "7.5.1",
"solana-bankrun": "0.3.0",
"zod": "4.0.17",
"zstddec": "0.1.0"
},
"scripts": {
Expand All @@ -54,4 +55,4 @@
"engines": {
"node": ">=12"
}
}
}
2 changes: 1 addition & 1 deletion programs/drift/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "drift"
version = "2.133.0"
version = "2.134.0"
description = "Created with Anchor"
edition = "2018"

Expand Down
9 changes: 0 additions & 9 deletions programs/drift/src/controller/lp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,6 @@ pub fn burn_lp_shares(
.base_asset_amount_with_unsettled_lp
.safe_add(position.remainder_base_asset_amount.cast()?)?;
if shares_to_burn as u128 == market.amm.user_lp_shares && unsettled_remainder != 0 {
crate::validate!(
unsettled_remainder.unsigned_abs() <= market.amm.order_step_size as u128,
ErrorCode::UnableToBurnLPTokens,
"unsettled baa on final burn too big rel to stepsize {}: {} (remainder:{})",
market.amm.order_step_size,
market.amm.base_asset_amount_with_unsettled_lp,
position.remainder_base_asset_amount
)?;

// sub bc lps take the opposite side of the user
position.remainder_base_asset_amount = position
.remainder_base_asset_amount
Expand Down
28 changes: 27 additions & 1 deletion programs/drift/src/controller/pnl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,20 @@ pub fn settle_pnl(
clock: &Clock,
state: &State,
meets_margin_requirement: Option<bool>,
mode: SettlePnlMode,
mut mode: SettlePnlMode,
) -> DriftResult {
validate!(!user.is_bankrupt(), ErrorCode::UserBankrupt)?;
let now = clock.unix_timestamp;
let tvl_before;
let deposits_balance_before;
let borrows_balance_before;
{
let spot_market = &mut spot_market_map.get_quote_spot_market_mut()?;
update_spot_market_cumulative_interest(spot_market, None, now)?;

tvl_before = spot_market.get_tvl()?;
deposits_balance_before = spot_market.deposit_balance;
borrows_balance_before = spot_market.borrow_balance;
}

let mut market = perp_market_map.get_ref_mut(&market_index)?;
Expand Down Expand Up @@ -281,6 +288,15 @@ pub fn settle_pnl(
now,
)?;

// if the spot market balance has changed, we have to fail if we are in try settle mode
if (spot_market.deposit_balance != deposits_balance_before
|| spot_market.borrow_balance != borrows_balance_before)
&& mode == SettlePnlMode::TrySettle
{
msg!("Spot market balance has changed, switch to MUST_SETTLE mode");
mode = SettlePnlMode::MustSettle;
}

if user_unsettled_pnl == 0 {
let msg = format!("User has no unsettled pnl for market {}", market_index);
return mode.result(ErrorCode::NoUnsettledPnl, market_index, &msg);
Expand Down Expand Up @@ -350,6 +366,16 @@ pub fn settle_pnl(
explanation: SettlePnlExplanation::None,
});

let tvl_after = spot_market.get_tvl()?;

validate!(
tvl_before.safe_sub(tvl_after)? <= 10,
ErrorCode::DefaultError,
"Settle Pnl TVL mismatch: before={}, after={}",
tvl_before,
tvl_after
)?;

Ok(())
}

Expand Down
23 changes: 16 additions & 7 deletions programs/drift/src/controller/spot_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::error::{DriftResult, ErrorCode};
use crate::math::amm::sanitize_new_price;
use crate::math::casting::Cast;
use crate::math::constants::{
FIVE_MINUTE, IF_FACTOR_PRECISION, ONE_HOUR, QUOTE_SPOT_MARKET_INDEX,
FIVE_MINUTE, IF_FACTOR_PRECISION, ONE_HOUR, ONE_MINUTE, QUOTE_SPOT_MARKET_INDEX,
SPOT_MARKET_TOKEN_TWAP_WINDOW,
};
use crate::math::spot_balance::{
Expand Down Expand Up @@ -55,6 +55,7 @@ pub fn update_spot_market_twap_stats(
spot_market.deposit_token_twap.cast()?,
since_last,
from_start,
None,
)?
.cast()?;

Expand All @@ -63,6 +64,7 @@ pub fn update_spot_market_twap_stats(
spot_market.borrow_token_twap.cast()?,
since_last,
from_start,
None,
)?
.cast()?;

Expand All @@ -73,6 +75,7 @@ pub fn update_spot_market_twap_stats(
spot_market.utilization_twap.cast()?,
since_last,
from_start,
None,
)?
.cast()?;

Expand Down Expand Up @@ -103,15 +106,19 @@ pub fn update_spot_market_twap_stats(
FIVE_MINUTE as i64,
)?;

spot_market.historical_oracle_data.last_oracle_price_twap = oracle_price_twap;
spot_market
.historical_oracle_data
.last_oracle_price_twap_5min = oracle_price_twap_5min;

spot_market.historical_oracle_data.last_oracle_price = oracle_price_data.price;
spot_market.historical_oracle_data.last_oracle_conf = oracle_price_data.confidence;
spot_market.historical_oracle_data.last_oracle_delay = oracle_price_data.delay;
spot_market.historical_oracle_data.last_oracle_price_twap_ts = now;

if oracle_price_twap != spot_market.historical_oracle_data.last_oracle_price_twap
|| since_last >= (ONE_MINUTE as i64)
{
spot_market.historical_oracle_data.last_oracle_price_twap = oracle_price_twap;
spot_market
.historical_oracle_data
.last_oracle_price_twap_5min = oracle_price_twap_5min;
spot_market.historical_oracle_data.last_oracle_price_twap_ts = now;
}
}

spot_market.last_twap_ts = now.cast()?;
Expand Down Expand Up @@ -243,10 +250,12 @@ pub fn update_spot_balances(
}

if token_amount > 0 {
msg!("token amount to transfer: {}", token_amount);
spot_balance.update_balance_type(*update_direction)?;
let round_up = update_direction == &SpotBalanceType::Borrow;
let balance_delta =
get_spot_balance(token_amount, spot_market, update_direction, round_up)?;
msg!("balance delta {}", balance_delta);
spot_balance.increase_balance(balance_delta)?;
increase_spot_balance(balance_delta, spot_market, update_direction)?;
}
Expand Down
14 changes: 10 additions & 4 deletions programs/drift/src/controller/spot_balance/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1743,12 +1743,18 @@ fn check_usdc_spot_market_twap() {
);

let wa_res =
calculate_weighted_average(PRICE_PRECISION_I64, PRICE_PRECISION_I64, 0, ONE_HOUR).unwrap();
calculate_weighted_average(PRICE_PRECISION_I64, PRICE_PRECISION_I64, 0, ONE_HOUR, None)
.unwrap();

assert_eq!(wa_res, PRICE_PRECISION_I64);
let wa_res2 =
calculate_weighted_average(PRICE_PRECISION_I64, PRICE_PRECISION_I64 + 1, 0, ONE_HOUR)
.unwrap();
let wa_res2 = calculate_weighted_average(
PRICE_PRECISION_I64,
PRICE_PRECISION_I64 + 1,
0,
ONE_HOUR,
None,
)
.unwrap();
assert_eq!(wa_res2, PRICE_PRECISION_I64 + 1);

assert_eq!(
Expand Down
63 changes: 63 additions & 0 deletions programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,36 @@ pub fn handle_deposit_into_perp_market_fee_pool<'c: 'info, 'info>(
Ok(())
}

#[access_control(
perp_market_valid(&ctx.accounts.perp_market)
)]
pub fn handle_update_perp_market_pnl_pool<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, UpdatePerpMarketPnlPool<'info>>,
amount: u64,
) -> Result<()> {
let perp_market = &mut load_mut!(ctx.accounts.perp_market)?;

let spot_market = &mut load_mut!(ctx.accounts.spot_market)?;

controller::spot_balance::update_spot_balances(
amount.cast::<u128>()?,
&SpotBalanceType::Deposit,
spot_market,
&mut perp_market.pnl_pool,
false,
)?;

validate_spot_market_vault_amount(spot_market, ctx.accounts.spot_market_vault.amount)?;

msg!(
"updating perp market {} pnl pool with amount {}",
perp_market.market_index,
amount
);

Ok(())
}

#[access_control(
deposit_not_paused(&ctx.accounts.state)
spot_market_valid(&ctx.accounts.spot_market)
Expand Down Expand Up @@ -5299,6 +5329,7 @@ pub fn handle_initialize_constituent<'info>(
constituent.volatility = volatility;
constituent.gamma_execution = gamma_execution;
constituent.gamma_inventory = gamma_inventory;
constituent.spot_balance.market_index = spot_market_index;
constituent.xi = xi;
lp_pool.constituents += 1;

Expand Down Expand Up @@ -5340,6 +5371,10 @@ pub fn handle_update_constituent_params<'info>(
constituent_params: ConstituentParams,
) -> Result<()> {
let mut constituent = ctx.accounts.constituent.load_mut()?;
if constituent.spot_balance.market_index != constituent.spot_market_index {
constituent.spot_balance.market_index = constituent.spot_market_index;
}

if constituent_params.max_weight_deviation.is_some() {
msg!(
"max_weight_deviation: {:?} -> {:?}",
Expand Down Expand Up @@ -5684,6 +5719,11 @@ pub fn handle_begin_lp_swap<'c: 'info, 'info>(
// Make sure we have enough balance to do the swap
let constituent_in_token_account = &ctx.accounts.constituent_in_token_account;

msg!("amount_in: {}", amount_in);
msg!(
"constituent_in_token_account.amount: {}",
constituent_in_token_account.amount
);
validate!(
amount_in <= constituent_in_token_account.amount,
ErrorCode::InvalidSwap,
Expand Down Expand Up @@ -6318,6 +6358,29 @@ pub struct SettleExpiredMarketPoolsToRevenuePool<'info> {
pub perp_market: AccountLoader<'info, PerpMarket>,
}

#[derive(Accounts)]
pub struct UpdatePerpMarketPnlPool<'info> {
#[account(
has_one = admin
)]
pub state: Box<Account<'info, State>>,
pub admin: Signer<'info>,
#[account(
seeds = [b"spot_market", 0_u16.to_le_bytes().as_ref()],
bump,
mut
)]
pub spot_market: AccountLoader<'info, SpotMarket>,
#[account(
mut,
seeds = [b"spot_market_vault".as_ref(), 0_u16.to_le_bytes().as_ref()],
bump,
)]
pub spot_market_vault: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut)]
pub perp_market: AccountLoader<'info, PerpMarket>,
}

#[derive(Accounts)]
pub struct DepositIntoMarketFeePool<'info> {
#[account(
Expand Down
33 changes: 25 additions & 8 deletions programs/drift/src/instructions/keeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2461,13 +2461,9 @@ pub fn handle_update_perp_bid_ask_twap<'c: 'info, 'info>(
msg!("skipping mark twap update for disabled amm prediction market");
return Ok(());
}

msg!(
"before amm bid twap = {} ask twap = {} ts = {}",
perp_market.amm.last_bid_price_twap,
perp_market.amm.last_ask_price_twap,
perp_market.amm.last_mark_price_twap_ts
);
let before_bid_price_twap = perp_market.amm.last_bid_price_twap;
let before_ask_price_twap = perp_market.amm.last_ask_price_twap;
let before_mark_twap_ts = perp_market.amm.last_mark_price_twap_ts;

let sanitize_clamp_denominator = perp_market.get_sanitize_clamp_denominator()?;
math::amm::update_mark_twap_crank(
Expand All @@ -2480,12 +2476,33 @@ pub fn handle_update_perp_bid_ask_twap<'c: 'info, 'info>(
)?;

msg!(
"after amm bid twap = {} ask twap = {} ts = {}",
"after amm bid twap = {} -> {}
ask twap = {} -> {}
ts = {} -> {}",
before_bid_price_twap,
perp_market.amm.last_bid_price_twap,
before_ask_price_twap,
perp_market.amm.last_ask_price_twap,
before_mark_twap_ts,
perp_market.amm.last_mark_price_twap_ts
);

if perp_market.amm.last_bid_price_twap == before_bid_price_twap
|| perp_market.amm.last_ask_price_twap == before_ask_price_twap
{
validate!(
perp_market
.amm
.last_mark_price_twap_ts
.safe_sub(before_mark_twap_ts)?
>= 60
|| estimated_bid.unwrap_or(0) == before_bid_price_twap
|| estimated_ask.unwrap_or(0) == before_ask_price_twap,
ErrorCode::CantUpdatePerpBidAskTwap,
"bid or ask twap unchanged from small ts delta update",
)?;
}

let funding_paused =
state.funding_paused()? || perp_market.is_operation_paused(PerpOperation::UpdateFunding);
controller::funding::update_funding_rate(
Expand Down
Loading