Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

program: add update_lp_market_position test for big k #565

Merged
merged 7 commits into from
Aug 8, 2023
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 @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixes

- program: add update_lp_market_position test for big k ([#565](https://github.com/drift-labs/protocol-v2/pull/565))

### Breaking

## [2.37.0] - 2023-08-02
Expand Down
1 change: 1 addition & 0 deletions programs/drift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ solana-security-txt = "1.1.0"
[dev-dependencies]
bytes = "1.2.0"
pyth = { path = "../pyth", features = ["no-entrypoint"]}
base64 = "0.13.0"
2 changes: 1 addition & 1 deletion programs/drift/src/controller/orders/amm_jit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,7 @@ pub mod amm_jit {
);

assert_eq!(market.amm.quote_asset_amount_per_lp, 0);
assert_eq!(market_after.amm.quote_asset_amount_per_lp, -497271);
assert_eq!(market_after.amm.quote_asset_amount_per_lp, -497272);

assert_eq!(market.amm.base_asset_amount_per_lp, 0);
assert_eq!(market_after.amm.base_asset_amount_per_lp, 5000000);
Expand Down
8 changes: 7 additions & 1 deletion programs/drift/src/controller/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,12 +403,18 @@ pub fn update_lp_market_position(
total_lp_shares,
)?;

let per_lp_delta_quote = get_proportion_i128(
let mut per_lp_delta_quote = get_proportion_i128(
delta.quote_asset_amount.cast()?,
AMM_RESERVE_PRECISION,
total_lp_shares,
)?;

// 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 =
Expand Down
110 changes: 109 additions & 1 deletion programs/drift/src/controller/position/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ use crate::controller::position::{
update_lp_market_position, update_position_and_market, PositionDelta,
};
use crate::math::constants::{
AMM_RESERVE_PRECISION, AMM_RESERVE_PRECISION_I128, BASE_PRECISION_I64,
AMM_RESERVE_PRECISION, AMM_RESERVE_PRECISION_I128, BASE_PRECISION_I64, QUOTE_PRECISION_I128,
};
use crate::state::perp_market::{AMMLiquiditySplit, PerpMarket, AMM};
use crate::state::user::PerpPosition;
use crate::test_utils::create_account_info;
use anchor_lang::prelude::AccountLoader;
use solana_program::pubkey::Pubkey;
use std::str::FromStr;

#[test]
fn full_amm_split() {
Expand Down Expand Up @@ -34,6 +38,110 @@ fn full_amm_split() {
);
}

#[test]
fn amm_split_large_k() {
let perp_market_str = String::from("Ct8MLGv1N/dvAH3EF67yBqaUQerctpm4yqpK+QNSrXCQz76p+B+ka+8Ni2/aLOukHaFdQJXR2jkqDS+O0MbHvA9M+sjCgLVtQwhkAQAAAAAAAAAAAAAAAAIAAAAAAAAAkI1kAQAAAAB6XWQBAAAAAO8yzWQAAAAAnJ7I3f///////////////2dHvwAAAAAAAAAAAAAAAABGiVjX6roAAAAAAAAAAAAAAAAAAAAAAAB1tO47J+xiAAAAAAAAAAAAGD03Fis3mgAAAAAAAAAAAJxiDwAAAAAAAAAAAAAAAABxqRCIGRxiAAAAAAAAAAAAEy8wZfK9YwAAAAAAAAAAAGZeZCE+g3sAAAAAAAAAAAAKYeQAAAAAAAAAAAAAAAAAlIvoyyc3mgAAAAAAAAAAAADQdQKjbgAAAAAAAAAAAAAAwu8g05H/////////////E6tNHAIAAAAAAAAAAAAAAO3mFwd0AAAAAAAAAAAAAAAAgPQg5rUAAAAAAAAAAAAAGkDtXR4AAAAAAAAAAAAAAEv0WeZW/f////////////9kUidaqAIAAAAAAAAAAAAA0ZMEr1H9/////////////w5/U3uqAgAAAAAAAAAAAAAANfbqfCd3AAAAAAAAAAAAIhABAAAAAAAiEAEAAAAAACIQAQAAAAAAY1QBAAAAAAA5f3WMVAAAAAAAAAAAAAAAFhkiihsAAAAAAAAAAAAAAO2EfWc5AAAAAAAAAAAAAACM/5CAQgAAAAAAAAAAAAAAvenX0SsAAAAAAAAAAAAAALgPUogZAAAAAAAAAAAAAAC01x97AAAAAAAAAAAAAAAAOXzVbgAAAAAAAAAAAAAAAMG4+QwBAAAAAAAAAAAAAABwHI3fLeJiAAAAAAAAAAAABvigOblGmgAAAAAAAAAAALeRnZsi9mIAAAAAAAAAAAAqgs3ynCeaAAAAAAAAAAAAQwhkAQAAAAAAAAAAAAAAAJOMZAEAAAAAFKJkAQAAAABTl2QBAAAAALFuZAEAAAAAgrx7DAAAAAAUAwAAAAAAAAN1TAYAAAAAuC7NZAAAAAAQDgAAAAAAAADh9QUAAAAAZAAAAAAAAAAA4fUFAAAAAAAAAAAAAAAAn2HvyMABAADGV6rZFwAAAE5Qg2oPAAAA8zHNZAAAAAAdYAAAAAAAAE2FAAAAAAAA6zLNZAAAAAD6AAAAaEIAABQDAAAUAwAAAAAAANcBAABkADIAZGQAAcDIUt4AAAAA0QQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9qQbynsAAAAAAAAAAAAAAAAAAAAAAAAFNPTC1QRVJQICAgICAgICAgICAgICAgICAgICAgICAghuS1//////8A4fUFAAAAAAB0O6QLAAAAR7PdeQMAAAD+Mc1kAAAAAADKmjsAAAAAAAAAAAAAAAAAAAAAAAAAAOULDwAAAAAAUBkAAAAAAADtAQAAAAAAAMgAAAAAAAAAECcAAKhhAADoAwAA9AEAAAAAAAAQJwAAZAIAAGQCAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
let mut decoded_bytes = base64::decode(perp_market_str).unwrap();
let perp_market_bytes = decoded_bytes.as_mut_slice();

let key = Pubkey::default();
let owner = Pubkey::from_str("dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH").unwrap();
let mut lamports = 0;
let perp_market_account_info =
create_account_info(&key, true, &mut lamports, perp_market_bytes, &owner);

let perp_market_loader: AccountLoader<PerpMarket> =
AccountLoader::try_from(&perp_market_account_info).unwrap();
let mut perp_market = perp_market_loader.load_mut().unwrap();

assert_eq!(perp_market.amm.base_asset_amount_per_lp, -574054756);
assert_eq!(perp_market.amm.quote_asset_amount_per_lp, 12535655);

let og_baapl = perp_market.amm.base_asset_amount_per_lp;
let og_qaapl = perp_market.amm.quote_asset_amount_per_lp;

// msg!("perp_market: {:?}", perp_market);

// min long order for $2.3
let delta = PositionDelta {
base_asset_amount: BASE_PRECISION_I64 / 10,
quote_asset_amount: -2300000,
};

update_lp_market_position(&mut perp_market, &delta, 0, AMMLiquiditySplit::Shared).unwrap();

assert_eq!(perp_market.amm.base_asset_amount_per_lp, -574054758);
assert_eq!(perp_market.amm.quote_asset_amount_per_lp, 12535655);

// min short order for $2.3
let delta = PositionDelta {
base_asset_amount: -BASE_PRECISION_I64 / 10,
quote_asset_amount: 2300000,
};

update_lp_market_position(&mut perp_market, &delta, 0, AMMLiquiditySplit::Shared).unwrap();

assert_eq!(perp_market.amm.base_asset_amount_per_lp, -574054756);
assert_eq!(perp_market.amm.quote_asset_amount_per_lp, 12535654);

// long order for $230
let delta = PositionDelta {
base_asset_amount: BASE_PRECISION_I64 * 10,
quote_asset_amount: -230000000,
};

update_lp_market_position(&mut perp_market, &delta, 0, AMMLiquiditySplit::Shared).unwrap();

assert_eq!(perp_market.amm.base_asset_amount_per_lp, -574055043);
assert_eq!(perp_market.amm.quote_asset_amount_per_lp, 12535660);

assert_eq!(
(perp_market.amm.sqrt_k as i128) * (og_baapl - perp_market.amm.base_asset_amount_per_lp)
/ AMM_RESERVE_PRECISION_I128,
9977763076
);
// assert_eq!((perp_market.amm.sqrt_k as i128) * (og_baapl-perp_market.amm.base_asset_amount_per_lp) / AMM_RESERVE_PRECISION_I128, 104297175);
assert_eq!(
(perp_market.amm.sqrt_k as i128) * (og_qaapl - perp_market.amm.quote_asset_amount_per_lp)
/ QUOTE_PRECISION_I128,
-173828625034
);
assert_eq!(
(perp_market.amm.sqrt_k as i128)
* (og_qaapl - perp_market.amm.quote_asset_amount_per_lp - 1)
/ QUOTE_PRECISION_I128,
-208594350041
);
// assert_eq!(243360075047/9977763076 < 23, true); // ensure rounding in favor

// long order for $230
let delta = PositionDelta {
base_asset_amount: -BASE_PRECISION_I64 * 10,
quote_asset_amount: 230000000,
};

let og_baapl = perp_market.amm.base_asset_amount_per_lp;
let og_qaapl = perp_market.amm.quote_asset_amount_per_lp;

update_lp_market_position(&mut perp_market, &delta, 0, AMMLiquiditySplit::Shared).unwrap();

assert_eq!(perp_market.amm.base_asset_amount_per_lp, -574054756);
assert_eq!(perp_market.amm.quote_asset_amount_per_lp, 12535653);

assert_eq!(
(perp_market.amm.sqrt_k as i128) * (og_baapl - perp_market.amm.base_asset_amount_per_lp)
/ AMM_RESERVE_PRECISION_I128,
-9977763076
);
// assert_eq!((perp_market.amm.sqrt_k as i128) * (og_baapl-perp_market.amm.base_asset_amount_per_lp) / AMM_RESERVE_PRECISION_I128, 104297175);
assert_eq!(
(perp_market.amm.sqrt_k as i128) * (og_qaapl - perp_market.amm.quote_asset_amount_per_lp)
/ QUOTE_PRECISION_I128,
243360075047
);
// assert_eq!(243360075047/9977763076 < 23, true); // ensure rounding in favor
}

#[test]
fn full_lp_split() {
let delta = PositionDelta {
Expand Down
2 changes: 1 addition & 1 deletion tests/delistMarket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ describe('delist market', () => {
const userCostBasisBefore = marketBefore.amm.quoteAssetAmount;

console.log('userCostBasisBefore:', userCostBasisBefore.toString());
assert(userCostBasisBefore.eq(new BN(-1))); // from LP burn
assert(userCostBasisBefore.eq(new BN(-2))); // from LP burn

await liquidatorDriftClient.settlePNL(
await liquidatorDriftClient.getUserAccountPublicKey(),
Expand Down
12 changes: 6 additions & 6 deletions tests/liquidityProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,19 +494,19 @@ describe('liquidity providing', () => {
'=> net baa:',
driftClient.getPerpMarketAccount(0).amm.baseAssetAmountWithAmm.toString()
);
assert(user.perpPositions[0].quoteAssetAmount.eq(new BN(-1233600)));
assert(user.perpPositions[0].quoteAssetAmount.eq(new BN(-1233700)));
// assert(user.perpPositions[0].unsettledPnl.eq(new BN(900)));
// remainder goes into the last
assert(user.perpPositions[0].lastBaseAssetAmountPerLp.eq(new BN(12500000)));
assert(user.perpPositions[0].lastQuoteAssetAmountPerLp.eq(new BN(-12336)));
assert(user.perpPositions[0].lastQuoteAssetAmountPerLp.eq(new BN(-12337)));

market = await driftClient.getPerpMarketAccount(0);
console.log(
market.amm.quoteAssetAmountPerLp.toString(),
market.amm.baseAssetAmountPerLp.toString()
);
assert(market.amm.baseAssetAmountPerLp.eq(new BN(12500000)));
assert(market.amm.quoteAssetAmountPerLp.eq(new BN(-12336)));
assert(market.amm.quoteAssetAmountPerLp.eq(new BN(-12337)));

// remove
console.log('removing liquidity...');
Expand Down Expand Up @@ -934,7 +934,7 @@ describe('liquidity providing', () => {
console.log(user.perpPositions[0].baseAssetAmount.toString());
console.log(user.perpPositions[0].quoteAssetAmount.toString());
assert(user.perpPositions[0].baseAssetAmount.eq(new BN('10000000000'))); // lp is long
assert(user.perpPositions[0].quoteAssetAmount.eq(new BN(-9550785)));
assert(user.perpPositions[0].quoteAssetAmount.eq(new BN(-9550985)));

console.log('closing trader ...');
await adjustOraclePostSwap(tradeSize, SwapDirection.REMOVE, market);
Expand Down Expand Up @@ -1020,7 +1020,7 @@ describe('liquidity providing', () => {

assert(lpTokenAmount.eq(ZERO));
assert(user.perpPositions[0].baseAssetAmount.eq(new BN('-10000000000'))); // lp is short
assert(user.perpPositions[0].quoteAssetAmount.eq(new BN('11940740')));
assert(user.perpPositions[0].quoteAssetAmount.eq(new BN('11940540')));
assert(user.perpPositions[0].quoteEntryAmount.eq(new BN('11139500')));

console.log('closing trader...');
Expand Down Expand Up @@ -1125,7 +1125,7 @@ describe('liquidity providing', () => {
const baa = user.perpPositions[0].baseAssetAmount;
const qaa = user.perpPositions[0].quoteAssetAmount;
assert(baa.eq(new BN(10000000000)));
assert(qaa.eq(new BN(-6860362)));
assert(qaa.eq(new BN(-6860662)));

console.log('removing the other half of liquidity');
await driftClient.removePerpLpShares(market.marketIndex, otherHalfShares);
Expand Down
8 changes: 4 additions & 4 deletions tests/perpLpJit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ describe('lp jit', () => {
console.log(marketAfter.amm.baseAssetAmountWithAmm.toString());

assert(marketAfter.amm.baseAssetAmountPerLp.eq(new BN(-5000000)));
assert(marketAfter.amm.quoteAssetAmountPerLp.eq(new BN(144606790)));
assert(marketAfter.amm.quoteAssetAmountPerLp.eq(new BN(144606790 - 1)));
assert(marketAfter.amm.baseAssetAmountWithUnsettledLp.eq(new BN(-5000000)));
assert(marketAfter.amm.baseAssetAmountWithAmm.eq(new BN(5000000)));

Expand All @@ -1057,7 +1057,7 @@ describe('lp jit', () => {
console.log('lpPnl:', lpPnl.toString());

assert(dustPos.toString() == '0');
assert(lpPnl.toString() == '6134172');
assert(lpPnl.toString() == '6134171');

const _sig2 = await driftClient.settleLP(
await driftClient.getUserAccountPublicKey(),
Expand Down Expand Up @@ -1121,7 +1121,7 @@ describe('lp jit', () => {
console.log(marketAfter2.amm.baseAssetAmountWithAmm.toString());

assert(marketAfter2.amm.baseAssetAmountPerLp.eq(new BN(-2500000)));
assert(marketAfter2.amm.quoteAssetAmountPerLp.eq(new BN(78437568)));
assert(marketAfter2.amm.quoteAssetAmountPerLp.eq(new BN(78437566)));
assert(
marketAfter2.amm.baseAssetAmountWithUnsettledLp.eq(new BN(-2500000))
);
Expand All @@ -1140,7 +1140,7 @@ describe('lp jit', () => {
console.log('lpPnl:', lpPnl2.toString());

assert(dustPos2.toString() == '0');
assert(lpPnl2.toString() == '3067087');
assert(lpPnl2.toString() == '3067086');

await driftClient.settleLP(
await driftClient.getUserAccountPublicKey(),
Expand Down
Loading