Skip to content

Commit c00ebb6

Browse files
committed
Merge branch 'master' into bigz/init-lp-pool
2 parents 7efab3e + 1fb12a6 commit c00ebb6

File tree

16 files changed

+720
-70
lines changed

16 files changed

+720
-70
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Fixes
1313

14+
- program: fix AMM reference price offset ([#1683](https://github.com/drift-labs/protocol-v2/pull/1683))
15+
1416
### Breaking
1517

1618
## [2.125.0] - 2025-06-24

programs/drift/src/controller/amm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ pub fn update_spreads(market: &mut PerpMarket, reserve_price: u64) -> DriftResul
184184
let liquidity_ratio = amm_spread::calculate_inventory_liquidity_ratio(
185185
market.amm.base_asset_amount_with_amm,
186186
market.amm.base_asset_reserve,
187-
market.amm.max_base_asset_reserve,
188187
market.amm.min_base_asset_reserve,
188+
market.amm.max_base_asset_reserve,
189189
)?;
190190

191191
let signed_liquidity_ratio =

programs/drift/src/controller/position/tests.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,9 @@ fn amm_perp_ref_offset() {
609609

610610
let reserve_price = perp_market.amm.reserve_price().unwrap();
611611
let (b1, a1) = perp_market.amm.bid_ask_price(reserve_price).unwrap();
612-
assert_eq!(b1, 7098048);
613-
assert_eq!(a1, 7105178);
612+
assert_eq!(reserve_price, 7101599);
613+
assert_eq!(b1, 7225876);
614+
assert_eq!(a1, 7233006);
614615
assert_eq!(
615616
perp_market.amm.historical_oracle_data.last_oracle_price,
616617
7101600
@@ -690,18 +691,18 @@ fn amm_perp_ref_offset() {
690691

691692
let r = perp_market.amm.reserve_price().unwrap();
692693
let (b, a) = perp_market.amm.bid_ask_price(r).unwrap();
693-
assert_eq!(b, 7098048);
694-
assert_eq!(a, 7105178);
694+
assert_eq!(b, 7098999);
695+
assert_eq!(a, 7106129);
695696
assert_eq!(
696697
perp_market.amm.historical_oracle_data.last_oracle_price,
697698
7101600
698699
);
699-
assert_eq!(perp_market.amm.reference_price_offset, 45000);
700+
assert_eq!(perp_market.amm.reference_price_offset, 134);
700701
assert_eq!(perp_market.amm.max_spread, 90000);
701702

702703
assert_eq!(r, 7101599);
703-
assert_eq!(perp_market.amm.bid_base_asset_reserve, 4570430670410018);
704-
assert_eq!(perp_market.amm.ask_base_asset_reserve, 4568069910766211);
704+
assert_eq!(perp_market.amm.bid_base_asset_reserve, 4675159724262455);
705+
assert_eq!(perp_market.amm.ask_base_asset_reserve, 4672813088646692);
705706

706707
crate::validation::perp_market::validate_perp_market(&perp_market).unwrap();
707708
}

programs/drift/src/state/perp_market.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ use crate::math::constants::{
1717
};
1818
use crate::math::constants::{
1919
AMM_RESERVE_PRECISION_I128, AMM_TO_QUOTE_PRECISION_RATIO, BID_ASK_SPREAD_PRECISION,
20-
BID_ASK_SPREAD_PRECISION_U128, DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT,
21-
LIQUIDATION_FEE_PRECISION, LIQUIDATION_FEE_TO_MARGIN_PRECISION_RATIO, LP_FEE_SLICE_DENOMINATOR,
22-
LP_FEE_SLICE_NUMERATOR, MARGIN_PRECISION, MARGIN_PRECISION_U128, MAX_LIQUIDATION_MULTIPLIER,
23-
PEG_PRECISION, PERCENTAGE_PRECISION, PERCENTAGE_PRECISION_I128, PERCENTAGE_PRECISION_I64,
20+
BID_ASK_SPREAD_PRECISION_I128, BID_ASK_SPREAD_PRECISION_U128,
21+
DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT, LIQUIDATION_FEE_PRECISION,
22+
LIQUIDATION_FEE_TO_MARGIN_PRECISION_RATIO, LP_FEE_SLICE_DENOMINATOR, LP_FEE_SLICE_NUMERATOR,
23+
MARGIN_PRECISION, MARGIN_PRECISION_U128, MAX_LIQUIDATION_MULTIPLIER, PEG_PRECISION,
24+
PERCENTAGE_PRECISION, PERCENTAGE_PRECISION_I128, PERCENTAGE_PRECISION_I64,
2425
PERCENTAGE_PRECISION_U64, PRICE_PRECISION, SPOT_WEIGHT_PRECISION, TWENTY_FOUR_HOUR,
2526
};
2627
use crate::math::helpers::get_proportion_i128;
@@ -1420,19 +1421,31 @@ impl AMM {
14201421
}
14211422

14221423
pub fn bid_price(&self, reserve_price: u64) -> DriftResult<u64> {
1424+
let adjusted_spread =
1425+
(-(self.short_spread.cast::<i32>()?)).safe_add(self.reference_price_offset)?;
1426+
1427+
let multiplier = BID_ASK_SPREAD_PRECISION_I128.safe_add(adjusted_spread.cast::<i128>()?)?;
1428+
14231429
reserve_price
14241430
.cast::<u128>()?
1425-
.safe_mul(BID_ASK_SPREAD_PRECISION_U128.safe_sub(self.short_spread.cast()?)?)?
1431+
.safe_mul(multiplier.cast::<u128>()?)?
14261432
.safe_div(BID_ASK_SPREAD_PRECISION_U128)?
14271433
.cast()
14281434
}
14291435

14301436
pub fn ask_price(&self, reserve_price: u64) -> DriftResult<u64> {
1437+
let adjusted_spread = self
1438+
.long_spread
1439+
.cast::<i32>()?
1440+
.safe_add(self.reference_price_offset)?;
1441+
1442+
let multiplier = BID_ASK_SPREAD_PRECISION_I128.safe_add(adjusted_spread.cast::<i128>()?)?;
1443+
14311444
reserve_price
14321445
.cast::<u128>()?
1433-
.safe_mul(BID_ASK_SPREAD_PRECISION_U128.safe_add(self.long_spread.cast()?)?)?
1446+
.safe_mul(multiplier.cast::<u128>()?)?
14341447
.safe_div(BID_ASK_SPREAD_PRECISION_U128)?
1435-
.cast::<u64>()
1448+
.cast()
14361449
}
14371450

14381451
pub fn bid_ask_price(&self, reserve_price: u64) -> DriftResult<(u64, u64)> {

sdk/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.126.0-beta.8
1+
2.126.0-beta.9

sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@drift-labs/sdk",
3-
"version": "2.126.0-beta.8",
3+
"version": "2.126.0-beta.9",
44
"main": "lib/node/index.js",
55
"types": "lib/node/index.d.ts",
66
"browser": "./lib/browser/index.js",

sdk/src/bankrun/bankrunConnection.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ export class BankrunContextWrapper {
121121
}
122122

123123
async moveTimeForward(increment: number): Promise<void> {
124+
const approxSlots = increment / 0.4;
125+
const slot = await this.connection.getSlot();
126+
this.context.warpToSlot(BigInt(Math.floor(Number(slot) + approxSlots)));
127+
124128
const currentClock = await this.context.banksClient.getClock();
125129
const newUnixTimestamp = currentClock.unixTimestamp + BigInt(increment);
126130
const newClock = new Clock(
@@ -130,6 +134,7 @@ export class BankrunContextWrapper {
130134
currentClock.leaderScheduleEpoch,
131135
newUnixTimestamp
132136
);
137+
133138
await this.context.setClock(newClock);
134139
}
135140

@@ -241,13 +246,31 @@ export class BankrunConnection {
241246
: await internal.tryProcessLegacyTransaction(serialized);
242247
const banksTransactionMeta = new BanksTransactionResultWithMeta(inner);
243248

244-
if (banksTransactionMeta.result) {
245-
throw new Error(banksTransactionMeta.result);
246-
}
247249
const signature = isVersioned
248250
? bs58.encode((tx as VersionedTransaction).signatures[0])
249251
: bs58.encode((tx as Transaction).signatures[0].signature);
250-
this.transactionToMeta.set(signature, banksTransactionMeta);
252+
253+
if (banksTransactionMeta.result) {
254+
if (
255+
!banksTransactionMeta.result
256+
.toString()
257+
.includes('This transaction has already been processed')
258+
) {
259+
throw new Error(banksTransactionMeta.result);
260+
} else {
261+
console.log(
262+
`Tx already processed (sig: ${signature}): ${JSON.stringify(
263+
banksTransactionMeta
264+
)}`,
265+
banksTransactionMeta,
266+
banksTransactionMeta.result
267+
);
268+
console.log(tx);
269+
}
270+
}
271+
if (!this.transactionToMeta.has(signature)) {
272+
this.transactionToMeta.set(signature, banksTransactionMeta);
273+
}
251274
let finalizedCount = 0;
252275
while (finalizedCount < 10) {
253276
const signatureStatus = (await this.getSignatureStatus(signature)).value
@@ -290,7 +313,7 @@ export class BankrunConnection {
290313
return signature;
291314
}
292315

293-
private async updateSlotAndClock() {
316+
async updateSlotAndClock() {
294317
const currentSlot = await this.getSlot();
295318
const nextSlot = currentSlot + BigInt(1);
296319
this.context.warpToSlot(nextSlot);
@@ -404,6 +427,9 @@ export class BankrunConnection {
404427
const transactionStatus = await this._banksClient.getTransactionStatus(
405428
signature
406429
);
430+
if (txMeta.meta === null) {
431+
throw new Error(`tx has no meta: ${JSON.stringify(txMeta)}`);
432+
}
407433
const meta: BankrunTransactionMetaNormalized = {
408434
logMessages: txMeta.meta.logMessages,
409435
err: txMeta.result,

sdk/src/driftClient.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,10 @@ export class DriftClient {
10851085
async getInitializeUserStatsIx(): Promise<TransactionInstruction> {
10861086
return await this.program.instruction.initializeUserStats({
10871087
accounts: {
1088-
userStats: this.getUserStatsAccountPublicKey(),
1088+
userStats: getUserStatsAccountPublicKey(
1089+
this.program.programId,
1090+
this.wallet.publicKey // only allow payer to initialize own user stats account
1091+
),
10891092
authority: this.wallet.publicKey,
10901093
payer: this.wallet.publicKey,
10911094
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
@@ -8389,19 +8392,24 @@ export class DriftClient {
83898392
marketIndex
83908393
);
83918394

8395+
const accounts = {
8396+
insuranceFundStake: ifStakeAccountPublicKey,
8397+
spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
8398+
userStats: getUserStatsAccountPublicKey(
8399+
this.program.programId,
8400+
this.wallet.publicKey // only allow payer to initialize own insurance fund stake account
8401+
),
8402+
authority: this.wallet.publicKey,
8403+
payer: this.wallet.publicKey,
8404+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
8405+
systemProgram: anchor.web3.SystemProgram.programId,
8406+
state: await this.getStatePublicKey(),
8407+
};
8408+
83928409
return await this.program.instruction.initializeInsuranceFundStake(
83938410
marketIndex,
83948411
{
8395-
accounts: {
8396-
insuranceFundStake: ifStakeAccountPublicKey,
8397-
spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
8398-
userStats: this.getUserStatsAccountPublicKey(),
8399-
authority: this.wallet.publicKey,
8400-
payer: this.wallet.publicKey,
8401-
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
8402-
systemProgram: anchor.web3.SystemProgram.programId,
8403-
state: await this.getStatePublicKey(),
8404-
},
8412+
accounts,
84058413
}
84068414
);
84078415
}
@@ -8429,7 +8437,10 @@ export class DriftClient {
84298437
state: await this.getStatePublicKey(),
84308438
spotMarket: spotMarket.pubkey,
84318439
insuranceFundStake: ifStakeAccountPublicKey,
8432-
userStats: this.getUserStatsAccountPublicKey(),
8440+
userStats: getUserStatsAccountPublicKey(
8441+
this.program.programId,
8442+
this.wallet.publicKey // only allow payer to add to own insurance fund stake account
8443+
),
84338444
authority: this.wallet.publicKey,
84348445
spotMarketVault: spotMarket.vault,
84358446
insuranceFundVault: spotMarket.insuranceFund.vault,
@@ -8551,7 +8562,12 @@ export class DriftClient {
85518562
let tokenAccount;
85528563

85538564
if (
8554-
!(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))
8565+
!(await this.checkIfAccountExists(
8566+
getUserStatsAccountPublicKey(
8567+
this.program.programId,
8568+
this.wallet.publicKey // only allow payer to initialize own user stats account
8569+
)
8570+
))
85558571
) {
85568572
addIfStakeIxs.push(await this.getInitializeUserStatsIx());
85578573
}

sdk/src/math/amm.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,7 @@ export function calculateSpreadReserves(
997997
amm.pegMultiplier
998998
);
999999

1000-
// always allow 10 bps of price offset, up to a fifth of the market's max_spread
1000+
// always allow 10 bps of price offset, up to a half of the market's max_spread
10011001
let maxOffset = 0;
10021002
let referencePriceOffset = ZERO;
10031003
if (amm.curveUpdateIntensity > 100) {

test-scripts/run-anchor-tests.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
#!/bin/bash
2+
3+
set -e
4+
trap 'echo -e "\nStopped by signal $? (SIGINT)"; exit 0' INT
5+
16
if [ "$1" != "--skip-build" ]; then
27
anchor build -- --features anchor-test && anchor test --skip-build &&
38
cp target/idl/drift.json sdk/src/idl/

0 commit comments

Comments
 (0)