fix: force Token-2022 for pump suffix mints

This commit is contained in:
0xfnzero
2026-05-28 05:21:24 +08:00
parent 34f400e89d
commit 1d3c0ff5da
2 changed files with 29 additions and 9 deletions
+27 -8
View File
@@ -39,7 +39,10 @@ use solana_sdk::{
}; };
#[inline] #[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; let tp = protocol_params.token_program;
if tp == Pubkey::default() { if tp == Pubkey::default() {
TOKEN_PROGRAM_2022 TOKEN_PROGRAM_2022
@@ -190,7 +193,7 @@ fn build_buy_legacy(params: &SwapParams) -> Result<Vec<Instruction>> {
})?; })?;
let is_mayhem_mode = bonding_curve.is_mayhem_mode; 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, &params.output_mint);
let token_program_meta = if token_program == TOKEN_PROGRAM_2022 { let token_program_meta = if token_program == TOKEN_PROGRAM_2022 {
crate::constants::TOKEN_PROGRAM_2022_META crate::constants::TOKEN_PROGRAM_2022_META
} else { } else {
@@ -345,7 +348,7 @@ fn build_sell_legacy(params: &SwapParams) -> Result<Vec<Instruction>> {
})?; })?;
let is_mayhem_mode = bonding_curve.is_mayhem_mode; 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, &params.input_mint);
let token_program_meta = if token_program == TOKEN_PROGRAM_2022 { let token_program_meta = if token_program == TOKEN_PROGRAM_2022 {
crate::constants::TOKEN_PROGRAM_2022_META crate::constants::TOKEN_PROGRAM_2022_META
} else { } else {
@@ -463,7 +466,8 @@ fn build_buy_unified(params: &SwapParams) -> Result<Vec<Instruction>> {
})?; })?;
let is_mayhem_mode = bonding_curve.is_mayhem_mode; 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, &params.output_mint);
let base_token_program_meta = if base_token_program == TOKEN_PROGRAM_2022 { let base_token_program_meta = if base_token_program == TOKEN_PROGRAM_2022 {
crate::constants::TOKEN_PROGRAM_2022_META crate::constants::TOKEN_PROGRAM_2022_META
} else { } else {
@@ -694,7 +698,7 @@ fn build_sell_unified(params: &SwapParams) -> Result<Vec<Instruction>> {
})?; })?;
let is_mayhem_mode = bonding_curve.is_mayhem_mode; 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, &params.input_mint);
let base_token_program_meta = if base_token_program == TOKEN_PROGRAM_2022 { let base_token_program_meta = if base_token_program == TOKEN_PROGRAM_2022 {
crate::constants::TOKEN_PROGRAM_2022_META crate::constants::TOKEN_PROGRAM_2022_META
} else { } else {
@@ -939,18 +943,33 @@ mod tests {
} }
#[test] #[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(); crate::common::seed::set_default_rents();
let params = swap_params_for_buy(pump_mint(), TOKEN_PROGRAM); let params = swap_params_for_buy(pump_mint(), TOKEN_PROGRAM);
let instructions = build_buy(&params).unwrap(); let instructions = build_buy(&params).unwrap();
assert_eq!(instructions.len(), 3); assert_eq!(instructions.len(), 3);
assert_eq!(instructions[2].accounts[8].pubkey, TOKEN_PROGRAM); assert_eq!(instructions[2].accounts[8].pubkey, TOKEN_PROGRAM_2022);
assert_eq!(instructions[1].program_id, TOKEN_PROGRAM); assert_eq!(instructions[1].program_id, TOKEN_PROGRAM_2022);
assert_eq!(instructions[2].accounts.len(), 18); assert_eq!(instructions[2].accounts.len(), 18);
assert_eq!(instructions[2].data.len(), 25); 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(&params).unwrap();
let ix = instructions.last().unwrap();
assert_eq!(ix.accounts[9].pubkey, TOKEN_PROGRAM_2022);
}
#[test] #[test]
fn non_pump_buy_respects_explicit_legacy_token_program() { fn non_pump_buy_respects_explicit_legacy_token_program() {
crate::common::seed::set_default_rents(); crate::common::seed::set_default_rents();
+2 -1
View File
@@ -33,7 +33,8 @@ pub struct PumpFunParams {
pub fee_sharing_creator_vault_if_active: Option<Pubkey>, pub fee_sharing_creator_vault_if_active: Option<Pubkey>,
/// SPL Token or Token-2022 program id owning the **mint** (from gRPC / parser / cache). /// SPL Token or Token-2022 program id owning the **mint** (from gRPC / parser / cache).
/// **`Pubkey::default()`**ix 构建时使用 SDK 默认 **Token-2022**(与多数 Pump.fun 新发一致)。 /// **`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, pub token_program: Pubkey,
/// Whether to close token account when selling, only effective during sell operations /// Whether to close token account when selling, only effective during sell operations
pub close_token_account_when_sell: Option<bool>, pub close_token_account_when_sell: Option<bool>,