Skip to content

Commit

Permalink
sdk: priority fee subscriber (fork) (#590)
Browse files Browse the repository at this point in the history
* sdk: release v2.37.1-beta.7

* program: fix place_and_make/take_spot

* amm_spread.rs: add conf_component logic (#577)

* amm_spread.rs: add conf_component logic

* update CHANGELOG.md

* order subscriber event emitter

* renaming new to update

* checking for length > 0 before emitting

* fixing new orders bug

* sdk: release v2.37.1-beta.8

* program: add lp shares rebase (#568)

* start test

* improve lp_delta_quote

* improve per_lp_delta_quote

* init per_lp_base

* add rebase functions (wip)

* rm err msg

* add controller rebase to proper locations

* add rebase cargo test

* (wip) k out of wack

* fix rebase test and add more asserts

* format fix

* incorp basic example to typescript tests

* fix rebase math in position.rs (wip)

* wip continue

* working baseAssetAmountWithUnsettledLp

* mvp encapsulation of update_lp_market_position

* src/user.ts: add perLpBase to empty position

* remove logs

* simplify base unit logic more

* add get_per_lp_base_unit

* simplify per_lp_fee and add numbers to test

* properly set per_lp_base for lp_share=0 in mint_lp_shares (and add sdk/test)

* incorp feedback / format

* tests/liquidityProvider.ts: work with sdk change

* admin.rs: add constraint on per_lp_base range

* add apply_lp_rebase_to_perp_position to simulate_settled_lp_position

* use get_per_lp_base_unit consistently (wip sdk test for negative lp base)

* cut excess return values in calculate_lp_delta

* fix getPerpPositionWithLPSettle with negative perLpBase delta

---------

Co-authored-by: Chris Heaney <[email protected]>

* sdk: release v2.37.1-beta.9

* bigz/oracle-auction-oracle-validity-test (#584)

* sdk: fixes for getHealthComponents

* sdk: release v2.37.1-beta.10

* sdk: add option for marginCategory to getFreeCollateral (#573)

* sdk: release v2.37.1-beta.11

* wip save work

* sdk: updates to priorityfeesubscriber

* 25 default batch size

* tests: fix liquidateSpot health checks

* sdk: add debug for bulk account loader handleAccountCallbacks (#592)

* sdk: add debug for bulk account loader handleAccountCallbacks

* log callbacks individually

* sdk: release v2.37.1-beta.12

* configurable in polling config

* sdk: release v2.37.1-beta.13

* tests/driftClient.ts: add sleep

* bigz/fix-liquidatePerpAndLp-test (#593)

* bigz/fix-liquidatePerpAndLp-test

* uncomment out assert

* perpLpJit.ts: longer sleep for rc ts test

* perpLpJit.ts: longer sleep for rc ts test

* perpLpJit.ts: rm redundant check

* prepegMarketOrderBaseAssetAmount.ts: add sleep

* merge master

* v2.38.0

* sdk: release v2.38.1-beta.0

* feedback updates

* sdk: catch decoding error in polling drift client account subscriber

* sdk: release v2.38.1-beta.1

* Revert "sdk: catch decoding error in polling drift client account subscriber"

This reverts commit 36e0f0f.

* sdk: use decodeUnchecked in bulk account loader

* sdk: release v2.38.1-beta.2

* sdk: use decodeUnchecked in more places

* sdk: release v2.38.1-beta.3

* Revert "sdk: use decodeUnchecked in more places"

This reverts commit f11a3b0.

* sdk: use decodeUnchecked in PollingUserStatsAccountSubscriber

* sdk: fetchUserStatsAccount use decodeUnchecked

* sdk: update anchor to 0.28.1-beta.2 (#595)

* try 0.28.0

* try updating top dir anchor

* anchor 0.28.1-beta.2

* fix prettify

* CHANGELOG

* sdk: release v2.38.1-beta.4

---------

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Chris Heaney <[email protected]>
Co-authored-by: bigzPubkey <[email protected]>
Co-authored-by: Nour Alharithi <[email protected]>
Co-authored-by: Evan Pipta <[email protected]>
  • Loading branch information
6 people committed Aug 28, 2023
1 parent c84c2d4 commit f5d1acc
Show file tree
Hide file tree
Showing 52 changed files with 1,255 additions and 230 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- sdk: updated anchor to 0.28.1-beta.2

### Fixes

### Breaking

## [2.38.0] - 2023-08-25

### Features

- program: add reduce only user status ([#560](https://github.com/drift-labs/protocol-v2/pull/560))
- program: add conditionally smaller conf_component logic for amm spread ([#577](https://github.com/drift-labs/protocol-v2/pull/577))
- program: add per_lp_base on market/position ([#568](https://github.com/drift-labs/protocol-v2/pull/568))

### Fixes

Expand All @@ -24,7 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- program: add deposit_into_spot_market_revenue_pool ([#520](https://github.com/drift-labs/protocol-v2/pull/520))
- program: make users w excessive withdraws pay fees ([#547](https://github.com/drift-labs/protocol-v2/pull/547))
- program: allow settle pnl and spot fills via match when utilization is 100% ([#525](https://github.com/drift-labs/protocol-v2/pull/525))
- program: allow settle pnl and spot fills via match when utilization is 100% ([#525](https://github.com/drift-labs/protocol-v2/pull/525))
- program: new update_perp_bid_ask_twap ix ([#548](https://github.com/drift-labs/protocol-v2/pull/548))
- program: dont check price bands for place order ([#556](https://github.com/drift-labs/protocol-v2/pull/556))

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.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@coral-xyz/anchor": "0.26.0",
"@coral-xyz/anchor": "0.28.1-beta.2",
"@project-serum/common": "0.0.1-beta.3",
"@project-serum/serum": "^0.13.38",
"@pythnetwork/client": "^2.5.1",
Expand Down
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.37.0"
version = "2.38.0"
description = "Created with Anchor"
edition = "2018"

Expand Down
108 changes: 107 additions & 1 deletion programs/drift/src/controller/lp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,108 @@ use anchor_lang::prelude::Account;
#[cfg(test)]
mod tests;

pub fn apply_lp_rebase_to_perp_market(
perp_market: &mut PerpMarket,
expo_diff: i8,
) -> DriftResult<()> {
// target_base_asset_amount_per_lp is the only one that it doesnt get applied
// thus changing the base of lp and without changing target_base_asset_amount_per_lp
// causes an implied change

validate!(expo_diff != 0, ErrorCode::DefaultError, "expo_diff = 0")?;

perp_market.amm.per_lp_base = perp_market.amm.per_lp_base.safe_add(expo_diff)?;
let rebase_divisor: i128 = 10_i128.pow(expo_diff.abs().cast()?);

if expo_diff > 0 {
perp_market.amm.base_asset_amount_per_lp = perp_market
.amm
.base_asset_amount_per_lp
.safe_mul(rebase_divisor)?;

perp_market.amm.quote_asset_amount_per_lp = perp_market
.amm
.quote_asset_amount_per_lp
.safe_mul(rebase_divisor)?;

perp_market.amm.total_fee_earned_per_lp = perp_market
.amm
.total_fee_earned_per_lp
.safe_mul(rebase_divisor.cast()?)?;
} else {
perp_market.amm.base_asset_amount_per_lp = perp_market
.amm
.base_asset_amount_per_lp
.safe_div(rebase_divisor)?;

perp_market.amm.quote_asset_amount_per_lp = perp_market
.amm
.quote_asset_amount_per_lp
.safe_div(rebase_divisor)?;

perp_market.amm.total_fee_earned_per_lp = perp_market
.amm
.total_fee_earned_per_lp
.safe_div(rebase_divisor.cast()?)?;
}

msg!(
"rebasing perp market_index={} per_lp_base expo_diff={}",
perp_market.market_index,
expo_diff,
);

crate::validation::perp_market::validate_perp_market(perp_market)?;

Ok(())
}

pub fn apply_lp_rebase_to_perp_position(
perp_market: &PerpMarket,
perp_position: &mut PerpPosition,
) -> DriftResult<()> {
let expo_diff = perp_market
.amm
.per_lp_base
.safe_sub(perp_position.per_lp_base)?;

if expo_diff > 0 {
let rebase_divisor: i64 = 10_i64.pow(expo_diff.cast()?);

perp_position.last_base_asset_amount_per_lp = perp_position
.last_base_asset_amount_per_lp
.safe_mul(rebase_divisor)?;
perp_position.last_quote_asset_amount_per_lp = perp_position
.last_quote_asset_amount_per_lp
.safe_mul(rebase_divisor)?;

msg!(
"rebasing perp position for market_index={} per_lp_base by expo_diff={}",
perp_market.market_index,
expo_diff,
);
} else if expo_diff < 0 {
let rebase_divisor: i64 = 10_i64.pow(expo_diff.abs().cast()?);

perp_position.last_base_asset_amount_per_lp = perp_position
.last_base_asset_amount_per_lp
.safe_div(rebase_divisor)?;
perp_position.last_quote_asset_amount_per_lp = perp_position
.last_quote_asset_amount_per_lp
.safe_div(rebase_divisor)?;

msg!(
"rebasing perp position for market_index={} per_lp_base by expo_diff={}",
perp_market.market_index,
expo_diff,
);
}

perp_position.per_lp_base = perp_position.per_lp_base.safe_add(expo_diff)?;

Ok(())
}

pub fn mint_lp_shares(
position: &mut PerpPosition,
market: &mut PerpMarket,
Expand All @@ -40,6 +142,7 @@ pub fn mint_lp_shares(
} else {
position.last_base_asset_amount_per_lp = amm.base_asset_amount_per_lp.cast()?;
position.last_quote_asset_amount_per_lp = amm.quote_asset_amount_per_lp.cast()?;
position.per_lp_base = amm.per_lp_base;
}

// add share balance
Expand Down Expand Up @@ -78,6 +181,8 @@ pub fn settle_lp_position(
)?;
}

apply_lp_rebase_to_perp_position(market, position)?;

let mut lp_metrics: crate::math::lp::LPMetrics =
calculate_settle_lp_metrics(&market.amm, position)?;

Expand Down Expand Up @@ -184,9 +289,10 @@ pub fn burn_lp_shares(
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 {}: {}",
"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
Expand Down
4 changes: 3 additions & 1 deletion programs/drift/src/controller/lp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,8 @@ fn test_lp_margin_calc() {
market.amm.cumulative_funding_rate_long *= 2;
market.amm.cumulative_funding_rate_short *= 2;

apply_lp_rebase_to_perp_market(&mut market, 1).unwrap();

let sim_user_pos = user.perp_positions[0]
.simulate_settled_lp_position(&market, oracle_price_data.price)
.unwrap();
Expand All @@ -718,7 +720,7 @@ fn test_lp_margin_calc() {
);
assert_eq!(sim_user_pos.base_asset_amount, 101000000000);
assert_eq!(sim_user_pos.quote_asset_amount, -20000000000);
assert_eq!(sim_user_pos.last_cumulative_funding_rate, 0);
assert_eq!(sim_user_pos.last_cumulative_funding_rate, 16900000000);

// ensure margin calc doesnt incorrectly count funding rate (funding pnl MUST come before settling lp)
let (margin_requirement, weighted_unrealized_pnl, worse_case_base_asset_value) =
Expand Down
23 changes: 19 additions & 4 deletions programs/drift/src/controller/orders/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub mod fulfill_order_with_maker_order {
BID_ASK_SPREAD_PRECISION, PEG_PRECISION, PRICE_PRECISION, PRICE_PRECISION_I64,
PRICE_PRECISION_U64, QUOTE_PRECISION_I64, QUOTE_PRECISION_U64,
};
use crate::math::oracle::OracleValidity;
use crate::state::perp_market::{PerpMarket, AMM};
use crate::state::user::{Order, OrderType, PerpPosition, User, UserStats};

Expand Down Expand Up @@ -1586,8 +1587,8 @@ pub mod fulfill_order_with_maker_order {

#[test]
fn taker_oracle_bid_crosses_maker_ask() {
let now = 5_i64;
let slot = 5_u64;
let now = 50000_i64;
let slot = 50000_u64;

let mut maker = User {
orders: get_orders(Order {
Expand Down Expand Up @@ -1615,9 +1616,10 @@ pub mod fulfill_order_with_maker_order {
order_type: OrderType::Oracle,
direction: PositionDirection::Long,
base_asset_amount: BASE_PRECISION_U64,
auction_start_price: 0,
auction_start_price: 999 * PRICE_PRECISION_I64 / 10, // $99.9
auction_end_price: 100 * PRICE_PRECISION_I64,
auction_duration: 10,
auction_duration: 10, // auction is 1 cent per slot
slot: slot - 5,
..Order::default()
}),
perp_positions: get_positions(PerpPosition {
Expand All @@ -1630,6 +1632,7 @@ pub mod fulfill_order_with_maker_order {
};

let mut oracle_price = get_pyth_price(100, 6);
oracle_price.curr_slot = slot - 10000;
let oracle_price_key =
Pubkey::from_str("J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix").unwrap();
let pyth_program = crate::ids::pyth_program::id();
Expand All @@ -1642,8 +1645,20 @@ pub mod fulfill_order_with_maker_order {
let mut oracle_map = OracleMap::load_one(&oracle_account_info, slot, None).unwrap();

let mut market = PerpMarket::default_test();
market.amm.historical_oracle_data.last_oracle_price_twap = 999 * PRICE_PRECISION_I64 / 10;
market.amm.historical_oracle_data.last_oracle_price_twap_ts = now - 1;
market.amm.oracle = oracle_price_key;

let (opd, ov) = oracle_map
.get_price_data_and_validity(
&oracle_price_key,
market.amm.historical_oracle_data.last_oracle_price_twap,
)
.unwrap();

assert_eq!(opd.delay, 50000); // quite long time
assert_eq!(ov, OracleValidity::StaleForMargin);

let fee_structure = get_fee_structure();
let (maker_key, taker_key, filler_key) = get_user_keys();

Expand Down
70 changes: 14 additions & 56 deletions programs/drift/src/controller/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ use crate::controller;
use crate::controller::amm::SwapDirection;
use crate::error::{DriftResult, ErrorCode};
use crate::math::casting::Cast;
use crate::math::constants::{
AMM_RESERVE_PRECISION, AMM_RESERVE_PRECISION_I128, LP_FEE_SLICE_DENOMINATOR,
LP_FEE_SLICE_NUMERATOR, MAX_BASE_ASSET_AMOUNT_WITH_AMM, PERP_DECIMALS,
};
use crate::math::helpers::get_proportion_i128;
use crate::math::constants::{MAX_BASE_ASSET_AMOUNT_WITH_AMM, PERP_DECIMALS};
// use crate::math::helpers::get_proportion_i128;
use crate::math::orders::{
calculate_quote_asset_amount_for_maker_order, get_position_delta_for_fill,
is_multiple_of_step_size,
Expand Down Expand Up @@ -383,42 +380,21 @@ pub fn update_lp_market_position(
delta: &PositionDelta,
fee_to_market: i128,
liquidity_split: AMMLiquiditySplit,
) -> DriftResult<(i128, i128, i128)> {
let user_lp_shares = market.amm.user_lp_shares;

if user_lp_shares == 0 || liquidity_split == AMMLiquiditySplit::ProtocolOwned {
return Ok((0, 0, 0)); // no need to split with LP
) -> DriftResult<i128> {
if market.amm.user_lp_shares == 0 || liquidity_split == AMMLiquiditySplit::ProtocolOwned {
return Ok(0); // no need to split with LP
}

let total_lp_shares = if liquidity_split == AMMLiquiditySplit::LPOwned {
market.amm.user_lp_shares
} else {
market.amm.sqrt_k
};

// update Market per lp position
let per_lp_delta_base = get_proportion_i128(
delta.base_asset_amount.cast()?,
AMM_RESERVE_PRECISION,
total_lp_shares,
)?;
let base_unit: i128 = market.amm.get_per_lp_base_unit()?;

let mut per_lp_delta_quote = get_proportion_i128(
delta.quote_asset_amount.cast()?,
AMM_RESERVE_PRECISION,
total_lp_shares,
)?;
let (per_lp_delta_base, per_lp_delta_quote, per_lp_fee) =
market
.amm
.calculate_per_lp_delta(delta, fee_to_market, liquidity_split, base_unit)?;

// user position delta is short => lp position delta is long
if per_lp_delta_base < 0 {
// add one => lp subtract 1
per_lp_delta_quote = per_lp_delta_quote.safe_add(1)?;
}

let lp_delta_base =
get_proportion_i128(per_lp_delta_base, user_lp_shares, AMM_RESERVE_PRECISION)?;
let lp_delta_quote =
get_proportion_i128(per_lp_delta_quote, user_lp_shares, AMM_RESERVE_PRECISION)?;
let lp_delta_base = market
.amm
.calculate_lp_base_delta(per_lp_delta_base, base_unit)?;

market.amm.base_asset_amount_per_lp = market
.amm
Expand All @@ -430,24 +406,6 @@ pub fn update_lp_market_position(
.quote_asset_amount_per_lp
.safe_add(-per_lp_delta_quote)?;

// 1/5 of fee auto goes to market
// the rest goes to lps/market proportional
let lp_fee = get_proportion_i128(
fee_to_market,
LP_FEE_SLICE_NUMERATOR,
LP_FEE_SLICE_DENOMINATOR,
)?
.safe_mul(user_lp_shares.cast::<i128>()?)?
.safe_div(total_lp_shares.cast::<i128>()?)?;

let per_lp_fee: i128 = if lp_fee > 0 {
lp_fee
.safe_mul(AMM_RESERVE_PRECISION_I128)?
.safe_div(user_lp_shares.cast::<i128>()?)?
} else {
0
};

// track total fee earned by lps (to attribute breakdown of IL)
market.amm.total_fee_earned_per_lp = market
.amm
Expand All @@ -468,7 +426,7 @@ pub fn update_lp_market_position(
.base_asset_amount_with_unsettled_lp
.safe_add(lp_delta_base)?;

Ok((lp_delta_base, lp_delta_quote, lp_fee))
Ok(lp_delta_base)
}

pub fn update_position_with_base_asset_amount(
Expand Down
Loading

0 comments on commit f5d1acc

Please sign in to comment.