From f247bcb3d9cd6798daf05a695e91419698628749 Mon Sep 17 00:00:00 2001 From: Jacques Alvarenga <100779979+alvarengao@users.noreply.github.com> Date: Wed, 11 Mar 2026 12:51:25 -0300 Subject: [PATCH 1/5] fix(sdk): update devnet USDC (spot/0) oracle to active Pyth feed --- sdk/src/constants/spotMarkets.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/src/constants/spotMarkets.ts b/sdk/src/constants/spotMarkets.ts index d5f965d39..5ecab5d3a 100644 --- a/sdk/src/constants/spotMarkets.ts +++ b/sdk/src/constants/spotMarkets.ts @@ -41,14 +41,13 @@ export const DevnetSpotMarkets: SpotMarketConfig[] = [ symbol: 'USDC', marketIndex: 0, poolId: 0, - oracle: new PublicKey('9VCioxmni2gDLv11qufWzT3RDERhQE4iY5Gf7NTfYyAV'), - oracleSource: OracleSource.PYTH_LAZER_STABLE_COIN, + oracle: new PublicKey('En8hkHLkRe9d9DraYmBTrus518BvmVH448YcvmrFM6Ce'), + oracleSource: OracleSource.PYTH_STABLE_COIN_PULL, mint: new PublicKey('8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2'), precision: new BN(10).pow(SIX), precisionExp: SIX, pythFeedId: '0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a', - pythLazerId: 7, }, { symbol: 'SOL', From ed4f651726d144a06916dbbee39b2a0156027080 Mon Sep 17 00:00:00 2001 From: Jacques Alvarenga <100779979+alvarengao@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:54:06 -0300 Subject: [PATCH 2/5] fix(contract): prevent withdrawal destination from being the vault itself --- programs/drift/src/instructions/user.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index a90a36ce1..6827cba76 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -4754,7 +4754,8 @@ pub struct Withdraw<'info> { pub drift_signer: AccountInfo<'info>, #[account( mut, - constraint = &spot_market_vault.mint.eq(&user_token_account.mint) + constraint = &spot_market_vault.mint.eq(&user_token_account.mint), + constraint = user_token_account.key() != spot_market_vault.key() @ ErrorCode::InvalidSpotPosition )] pub user_token_account: Box>, pub token_program: Interface<'info, TokenInterface>, From 6978542a2df2aa99dbf91f63679225f2be7e3d0a Mon Sep 17 00:00:00 2001 From: Jacques Alvarenga <100779979+alvarengao@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:22:16 -0300 Subject: [PATCH 3/5] fix: full protection against vault withdrawal routing --- sdk/src/driftClient.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index 54a6c636b..e98724639 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -3788,6 +3788,11 @@ export class DriftClient { txParams?: TxParams, updateFuel = false ): Promise { + // Ensure the destination account is not the vault itself to prevent state inconsistency + const spotMarket = this.getSpotMarketAccount(marketIndex); + if (spotMarket.vault.equals(associatedTokenAddress)) { + throw Error('Destination associatedTokenAddress cannot be the same as the spot market vault'); + } const additionalSigners: Array = []; const withdrawIxs = await this.getWithdrawalIxs( @@ -4371,6 +4376,12 @@ export class DriftClient { subAccountId?: number, txParams?: TxParams ): Promise { + // Ensure the destination account is not the vault itself to prevent state inconsistency + const spotMarket = this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX); + if (spotMarket.vault.equals(userTokenAccount)) { + throw Error('Destination userTokenAccount cannot be the same as the spot market vault'); + } + const instructions = await this.getWithdrawFromIsolatedPerpPositionIxsBundle( amount, From 0a3cdd1092b04908d89a621fbc2c9d3fff5d0d87 Mon Sep 17 00:00:00 2001 From: Jacques Alvarenga <100779979+alvarengao@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:06:21 -0300 Subject: [PATCH 4/5] fix(contract): add vault destination check for isolated perp withdrawals --- programs/drift/src/instructions/user.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/programs/drift/src/instructions/user.rs b/programs/drift/src/instructions/user.rs index 6827cba76..d514327a3 100644 --- a/programs/drift/src/instructions/user.rs +++ b/programs/drift/src/instructions/user.rs @@ -4962,9 +4962,10 @@ pub struct WithdrawIsolatedPerpPosition<'info> { )] /// CHECK: forced drift_signer pub drift_signer: AccountInfo<'info>, - #[account( + #[account( mut, - constraint = &spot_market_vault.mint.eq(&user_token_account.mint) + constraint = &spot_market_vault.mint.eq(&user_token_account.mint), + constraint = user_token_account.key() != spot_market_vault.key() @ ErrorCode::InvalidSpotPosition )] pub user_token_account: Box>, pub token_program: Interface<'info, TokenInterface>, From b8cf2644118841c7fbb5fe2e00ce7f0b3d8eebc1 Mon Sep 17 00:00:00 2001 From: Jacques Alvarenga <100779979+alvarengao@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:53:44 -0300 Subject: [PATCH 5/5] refactor: centralize vault validation and use dynamic derivation --- sdk/src/driftClient.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/src/driftClient.ts b/sdk/src/driftClient.ts index e98724639..4cf2ce77c 100644 --- a/sdk/src/driftClient.ts +++ b/sdk/src/driftClient.ts @@ -9477,6 +9477,7 @@ export class DriftClient { remainingAccounts: remainingAccounts, } ); + } public async getJupiterLiquidateSpotWithSwapIxV6({