From 35bfa935164ce127c24f2811275b18098eb51d90 Mon Sep 17 00:00:00 2001 From: 0xfnzero <0xfnzero@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:53:36 +0800 Subject: [PATCH] fix: add slippage clamping and improve WSOL wrap logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to src/utils/calc/common.rs: - Add MAX_SLIPPAGE_BASIS_POINTS constant (9999 = 99.99%) - Clamp basis_points in calculate_with_slippage_buy to prevent amount doubling Changes to src/instruction/pumpswap.rs: - Fix WSOL wrap amount calculation for exact vs non-exact input modes - Use input_amount for exact mode, sol_amount for non-exact mode 🤖 Generated with [Qoder][https://qoder.com] --- src/instruction/pumpswap.rs | 12 +++++++++++- src/utils/calc/common.rs | 15 ++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/instruction/pumpswap.rs b/src/instruction/pumpswap.rs index a5fb596..1aa49b6 100755 --- a/src/instruction/pumpswap.rs +++ b/src/instruction/pumpswap.rs @@ -139,8 +139,18 @@ impl InstructionBuilder for PumpSwapInstructionBuilder { let mut instructions = Vec::with_capacity(6); if create_wsol_ata { + // Determine wrap amount based on instruction type: + // - buy_exact_quote_in: program spends exactly input_amount, wrap input_amount + // - buy: program may spend up to max_quote, wrap max_quote + let wrap_amount = if quote_is_wsol_or_usdc + && params.use_exact_sol_amount.unwrap_or(true) + { + params.input_amount.unwrap_or(0) + } else { + sol_amount + }; instructions - .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), sol_amount)); + .extend(crate::trading::common::handle_wsol(¶ms.payer.pubkey(), wrap_amount)); } if params.create_output_mint_ata { diff --git a/src/utils/calc/common.rs b/src/utils/calc/common.rs index 32b65a0..e833acc 100644 --- a/src/utils/calc/common.rs +++ b/src/utils/calc/common.rs @@ -28,6 +28,10 @@ pub const fn ceil_div(a: u128, b: u128) -> u128 { (a + b - 1) / b } +/// Maximum slippage in basis points (99.99% = 9999 bps) +/// This prevents the wrap amount from doubling when slippage is 100% +pub const MAX_SLIPPAGE_BASIS_POINTS: u64 = 9999; + /// Calculate buy amount with slippage protection /// Add slippage percentage to the amount to ensure successful purchase /// @@ -40,9 +44,18 @@ pub const fn ceil_div(a: u128, b: u128) -> u128 { /// * basis_points = 10 -> 0.1% slippage /// * basis_points = 100 -> 1% slippage /// * basis_points = 500 -> 5% slippage +/// +/// # Note +/// Basis points are clamped to MAX_SLIPPAGE_BASIS_POINTS (9999 = 99.99%) +/// to prevent the amount from doubling when basis_points = 10000. #[inline(always)] pub const fn calculate_with_slippage_buy(amount: u64, basis_points: u64) -> u64 { - amount + (amount * basis_points / 10000) + let bps = if basis_points > MAX_SLIPPAGE_BASIS_POINTS { + MAX_SLIPPAGE_BASIS_POINTS + } else { + basis_points + }; + amount + (amount * bps / 10000) } /// Calculate sell amount with slippage protection