diff --git a/src/processor.rs b/src/processor.rs index b7c9d38..26ebc1a 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -444,15 +444,28 @@ fn process_init_pool( // pointing to it, and drain the vault via FlushToInsurance PDA-signer propagation. // The devnet program ID has no legitimate use on mainnet; gate it with the // "devnet" feature flag so it only compiles in when explicitly requested. + // + // #257: the legacy PERCOLATOR_DEVNET address above predates the v17 wrapper cutover. + // percolator-sdk's PROGRAM_IDS_V17.percolator ("69VUZ7a2BeXBTpRRManLamF5UWTaNR9B1hy5Se3cdXy9") + // is a SEPARATE, newer devnet-only deployment (SDK comment: "Mainnet addresses are + // pending the mainnet cutover (Phase 7 gate)" — there is no canonical v17 MAINNET + // address yet). Add it alongside, not in place of, the legacy devnet address, and + // keep it under the SAME "devnet" feature gate as PERCOLATOR_DEVNET for the same + // N-3 reason: it has no legitimate use on mainnet either. { const PERCOLATOR_MAINNET: Pubkey = solana_program::pubkey!("ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv"); #[cfg(feature = "devnet")] const PERCOLATOR_DEVNET: Pubkey = solana_program::pubkey!("FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD"); + #[cfg(feature = "devnet")] + const PERCOLATOR_V17_DEVNET: Pubkey = + solana_program::pubkey!("69VUZ7a2BeXBTpRRManLamF5UWTaNR9B1hy5Se3cdXy9"); let is_valid = *percolator_program.key == PERCOLATOR_MAINNET; #[cfg(feature = "devnet")] - let is_valid = is_valid || *percolator_program.key == PERCOLATOR_DEVNET; + let is_valid = is_valid + || *percolator_program.key == PERCOLATOR_DEVNET + || *percolator_program.key == PERCOLATOR_V17_DEVNET; if !is_valid { msg!( "Error: invalid percolator program {}", diff --git a/tests/unit.rs b/tests/unit.rs index 7aad44e..705ec7d 100644 --- a/tests/unit.rs +++ b/tests/unit.rs @@ -933,6 +933,29 @@ fn test_percolator_program_allowlist_constants_match_nft() { assert_ne!(devnet, Pubkey::default(), "devnet ID must not be zero"); } +#[test] +fn test_v17_devnet_wrapper_allowlist_constant_matches_sdk() { + // #257: percolator-sdk's PROGRAM_IDS_V17.percolator is a separate, newer + // devnet-only deployment from the legacy PERCOLATOR_DEVNET above (the SDK's + // own comment notes mainnet v17 addresses are "pending the mainnet cutover" — + // there is no canonical v17 MAINNET address yet, so only a devnet allowlist + // entry is correct here). This test encodes the expected value so drift is + // caught at test time, mirroring test_percolator_program_allowlist_constants_match_nft. + use solana_program::pubkey::Pubkey; + + let mainnet: Pubkey = solana_program::pubkey!("ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv"); + let legacy_devnet: Pubkey = + solana_program::pubkey!("FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD"); + let v17_devnet: Pubkey = solana_program::pubkey!("69VUZ7a2BeXBTpRRManLamF5UWTaNR9B1hy5Se3cdXy9"); + + assert_ne!(v17_devnet, mainnet, "v17 devnet wrapper must differ from mainnet"); + assert_ne!( + v17_devnet, legacy_devnet, + "v17 devnet wrapper must differ from the legacy (pre-v17) devnet wrapper" + ); + assert_ne!(v17_devnet, Pubkey::default(), "v17 devnet ID must not be zero"); +} + #[test] fn test_pool_stores_percolator_program() { // Verify that a StakePool's percolator_program field is a full 32-byte pubkey.