diff --git a/src/instruction/pumpfun.rs b/src/instruction/pumpfun.rs index d5b97b8..c71e32a 100644 --- a/src/instruction/pumpfun.rs +++ b/src/instruction/pumpfun.rs @@ -39,7 +39,10 @@ use solana_sdk::{ }; #[inline] -fn effective_pump_mint_token_program(protocol_params: &PumpFunParams) -> Pubkey { +fn effective_pump_mint_token_program(protocol_params: &PumpFunParams, mint: &Pubkey) -> Pubkey { + if mint.to_string().ends_with("pump") { + return TOKEN_PROGRAM_2022; + } let tp = protocol_params.token_program; if tp == Pubkey::default() { TOKEN_PROGRAM_2022 @@ -190,7 +193,7 @@ fn build_buy_legacy(params: &SwapParams) -> Result> { })?; let is_mayhem_mode = bonding_curve.is_mayhem_mode; - let token_program = effective_pump_mint_token_program(protocol_params); + let token_program = effective_pump_mint_token_program(protocol_params, ¶ms.output_mint); let token_program_meta = if token_program == TOKEN_PROGRAM_2022 { crate::constants::TOKEN_PROGRAM_2022_META } else { @@ -345,7 +348,7 @@ fn build_sell_legacy(params: &SwapParams) -> Result> { })?; let is_mayhem_mode = bonding_curve.is_mayhem_mode; - let token_program = effective_pump_mint_token_program(protocol_params); + let token_program = effective_pump_mint_token_program(protocol_params, ¶ms.input_mint); let token_program_meta = if token_program == TOKEN_PROGRAM_2022 { crate::constants::TOKEN_PROGRAM_2022_META } else { @@ -463,7 +466,8 @@ fn build_buy_unified(params: &SwapParams) -> Result> { })?; let is_mayhem_mode = bonding_curve.is_mayhem_mode; - let base_token_program = effective_pump_mint_token_program(protocol_params); + let base_token_program = + effective_pump_mint_token_program(protocol_params, ¶ms.output_mint); let base_token_program_meta = if base_token_program == TOKEN_PROGRAM_2022 { crate::constants::TOKEN_PROGRAM_2022_META } else { @@ -694,7 +698,7 @@ fn build_sell_unified(params: &SwapParams) -> Result> { })?; let is_mayhem_mode = bonding_curve.is_mayhem_mode; - let base_token_program = effective_pump_mint_token_program(protocol_params); + let base_token_program = effective_pump_mint_token_program(protocol_params, ¶ms.input_mint); let base_token_program_meta = if base_token_program == TOKEN_PROGRAM_2022 { crate::constants::TOKEN_PROGRAM_2022_META } else { @@ -939,18 +943,33 @@ mod tests { } #[test] - fn pump_suffix_buy_respects_explicit_legacy_token_program() { + fn pump_suffix_buy_forces_token_2022_even_with_explicit_legacy_token_program() { crate::common::seed::set_default_rents(); let params = swap_params_for_buy(pump_mint(), TOKEN_PROGRAM); let instructions = build_buy(¶ms).unwrap(); assert_eq!(instructions.len(), 3); - assert_eq!(instructions[2].accounts[8].pubkey, TOKEN_PROGRAM); - assert_eq!(instructions[1].program_id, TOKEN_PROGRAM); + assert_eq!(instructions[2].accounts[8].pubkey, TOKEN_PROGRAM_2022); + assert_eq!(instructions[1].program_id, TOKEN_PROGRAM_2022); assert_eq!(instructions[2].accounts.len(), 18); assert_eq!(instructions[2].data.len(), 25); } + #[test] + fn pump_suffix_sell_forces_token_2022_even_with_explicit_legacy_token_program() { + crate::common::seed::set_default_rents(); + let mut params = swap_params_for_buy(pump_mint(), TOKEN_PROGRAM); + params.trade_type = crate::swqos::TradeType::Sell; + params.input_mint = pump_mint(); + params.output_mint = crate::constants::SOL_TOKEN_ACCOUNT; + params.create_output_mint_ata = false; + + let instructions = build_sell(¶ms).unwrap(); + let ix = instructions.last().unwrap(); + + assert_eq!(ix.accounts[9].pubkey, TOKEN_PROGRAM_2022); + } + #[test] fn non_pump_buy_respects_explicit_legacy_token_program() { crate::common::seed::set_default_rents(); diff --git a/src/trading/core/params/pumpfun.rs b/src/trading/core/params/pumpfun.rs index 0127741..528cfcf 100644 --- a/src/trading/core/params/pumpfun.rs +++ b/src/trading/core/params/pumpfun.rs @@ -33,7 +33,8 @@ pub struct PumpFunParams { pub fee_sharing_creator_vault_if_active: Option, /// SPL Token or Token-2022 program id owning the **mint** (from gRPC / parser / cache). /// **`Pubkey::default()`**:ix 构建时使用 SDK 默认 **Token-2022**(与多数 Pump.fun 新发一致)。 - /// 显式传入 Legacy 或 Token-2022 id 时严格按该值组装,不再用 mint 字符串后缀猜测。 + /// `*.pump` mint 在 Pump.fun 指令构造层会强制使用 Token-2022,避免陈旧 parser/cache + /// 传入 legacy Token Program 后创建出 owner 不匹配的临时 token account。 pub token_program: Pubkey, /// Whether to close token account when selling, only effective during sell operations pub close_token_account_when_sell: Option,