Skip to content

fix(stake): #257 — add v17 devnet wrapper to the feature-gated devnet allowlist - #263

Open
Morenikeoa wants to merge 1 commit into
dcccrypto:mainfrom
Morenikeoa:fix/stake-257-v17-devnet-wrapper-allowlist
Open

fix(stake): #257 — add v17 devnet wrapper to the feature-gated devnet allowlist#263
Morenikeoa wants to merge 1 commit into
dcccrypto:mainfrom
Morenikeoa:fix/stake-257-v17-devnet-wrapper-allowlist

Conversation

@Morenikeoa

@Morenikeoa Morenikeoa commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Problem

InitPool's percolator_program allowlist only recognized the legacy (pre-v17) devnet address (PERCOLATOR_DEVNET, gated behind the devnet feature). It did not recognize percolator-sdk's PROGRAM_IDS_V17.percolator (69VUZ7a2BeXBTpRRManLamF5UWTaNR9B1hy5Se3cdXy9), a separate devnet-only deployment from the v17 cutover (2026-06-24, per the SDK source). Initializing a pool against the canonical v17 SDK config fails with InvalidPercolatorProgram.

Correcting the original issue's framing

I verified the SDK source (percolator-sdk/src/config/program-ids.ts) before touching anything, since the issue's claim didn't fully match what's actually there:

  • The SDK's own comment states: "v17 program IDs — live devnet addresses deployed 2026-06-24... Mainnet addresses are pending the mainnet cutover (Phase 7 gate) — mainnet fields will be filled then." There is no canonical v17 mainnet address yetPROGRAM_IDS_V17 has no devnet/mainnet split at all, it's devnet-only. So this is a devnet integration gap blocking v17 testing today, not "full staking/vault liveness failure" for a live mainnet deployment as the issue described — mainnet v17 doesn't exist yet to be blocked.
  • The issue's suggested fix (let is_valid = *percolator_program.key == PERCOLATOR_MAINNET || *percolator_program.key == PERCOLATOR_V17;, unconditional, no feature gate) would have been a regression: PERCOLATOR_DEVNET was deliberately moved behind the devnet feature flag in a recent PR (N-3 fix, fix(stake): gate PERCOLATOR_DEVNET in program allowlist behind devnet feature flag #235) specifically because "if the devnet deploy keypair is compromised an attacker can deploy a malicious binary at the devnet address on mainnet... and drain the vault." The same reasoning applies to this new devnet-only address — it has no legitimate use on mainnet either.

Fix

Added PERCOLATOR_V17_DEVNET alongside the existing PERCOLATOR_DEVNET, inside the same #[cfg(feature = "devnet")] gate, so it's available for devnet integration testing without ever compiling into a mainnet build.

Proof of Fix

  • Verified cargo build/cargo test --lib pass both with and without --features devnet — CI (.github/workflows/ci.yml) only ever runs the default (no-devnet) build, so this is the only way to confirm the gated branch isn't broken by this change.
  • Added test_v17_devnet_wrapper_allowlist_constant_matches_sdk in tests/unit.rs, mirroring the existing test_percolator_program_allowlist_constants_match_nft constants-drift-detection pattern.
  • Full cargo test --lib (142 tests) and non-SBF-dependent integration/proptest files (198 more tests, 340 total) pass with no regressions, in both feature configurations.

Related

Closes #257

Summary by CodeRabbit

  • Bug Fixes
    • Expanded program allowlist validation to accept an additional supported devnet program ID, while preserving existing mainnet and legacy devnet checks.
    • Requests using unsupported program IDs still return the same validation error.
  • Tests
    • Added coverage to verify the new devnet program ID is distinct from existing supported IDs and is a valid non-default value.

…ist (dcccrypto#257)

InitPool's percolator_program allowlist only recognized the legacy
(pre-v17) PERCOLATOR_DEVNET address, not percolator-sdk's
PROGRAM_IDS_V17.percolator ("69VUZ7a2BeXBTpRRManLamF5UWTaNR9B1hy5Se3cdXy9"),
a separate devnet-only deployment from the v17 cutover (2026-06-24).
Initializing a pool against the canonical v17 SDK config failed with
InvalidPercolatorProgram.

Note on scope, correcting dcccrypto#257's framing: the SDK's own comment states
mainnet v17 addresses are "pending the mainnet cutover (Phase 7 gate)" --
there is no canonical v17 MAINNET address yet, so this is a devnet
integration gap, not a live mainnet liveness failure as the issue
described. It's also why the fix adds PERCOLATOR_V17_DEVNET inside the
EXISTING "devnet" feature gate (alongside the legacy PERCOLATOR_DEVNET)
rather than the issue's suggested unconditional addition to the mainnet
check -- the existing devnet gating was added deliberately (N-3) because
a compromised devnet deploy keypair has no legitimate mainnet use; an
unconditional addition would have reintroduced exactly that regression
for a second address.

Verified the fix compiles and the full test suite passes both with and
without --features devnet (CI only runs the default/no-devnet build, so
this is the only way to confirm the gated branch isn't broken). Added a
constants-drift test mirroring the existing
test_percolator_program_allowlist_constants_match_nft pattern.
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a devnet-gated PERCOLATOR_V17_DEVNET program ID to process_init_pool validation and adds a unit test covering the new wrapper constant.

Changes

Percolator wrapper allowlist

Layer / File(s) Summary
InitPool allowlist and test coverage
src/processor.rs, tests/unit.rs
process_init_pool accepts PERCOLATOR_V17_DEVNET in addition to the existing mainnet and legacy devnet IDs, and the unit test checks the new wrapper constant against the other wrapper IDs.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • dcccrypto/percolator-stake issue 257 — Updates the process_init_pool wrapper allowlist to accept the v17 devnet program ID, which matches the change made here.

Poem

🐇 I hopped through the allowlist lane,
With v17 keys in my soft little brain.
Mainnet, legacy, and new ID too,
The pool says “yes” to the wrapper crew.
Thump! Thump! All checked anew.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: adding the v17 devnet wrapper to the feature-gated allowlist.
Description check ✅ Passed The description covers the problem, fix, test evidence, and related issue, though it doesn't follow the template headings exactly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unit.rs`:
- Around line 937-956: The v17 devnet wrapper test only compares hardcoded
Pubkeys against each other, so it can miss drift from the SDK. Update
test_v17_devnet_wrapper_allowlist_constant_matches_sdk to assert the wrapper
value matches the SDK-exported source of truth (for example the percolator-sdk
PROGRAM_IDS_V17.percolator constant) instead of another literal, while keeping
the existing sanity checks that it differs from mainnet/legacy and is
non-default.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6c67fda-2fb1-44e6-845a-ef512e7293d5

📥 Commits

Reviewing files that changed from the base of the PR and between c3edb7f and 72b81f1.

📒 Files selected for processing (2)
  • src/processor.rs
  • tests/unit.rs

Comment thread tests/unit.rs
Comment on lines +937 to +956
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");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find SDK dependency and any direct use of PROGRAM_IDS_V17 =="
fd 'Cargo.toml|Cargo.lock' . -x sh -c 'echo "--- $1"; rg -n "percolator-sdk|PROGRAM_IDS_V17" "$1" || true' sh {}

echo
echo "== Inspect current test/production references =="
rg -n -C2 'PROGRAM_IDS_V17|69VUZ7a2BeXBTpRRManLamF5UWTaNR9B1hy5Se3cdXy9|PERCOLATOR_V17_DEVNET' src tests

Repository: dcccrypto/percolator-stake

Length of output: 2387


Compare against the SDK-exported constant

These literals only prove the addresses differ; the test still passes if percolator-sdk changes PROGRAM_IDS_V17.percolator. Compare against the SDK constant or a shared source of truth instead of another hardcoded string.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit.rs` around lines 937 - 956, The v17 devnet wrapper test only
compares hardcoded Pubkeys against each other, so it can miss drift from the
SDK. Update test_v17_devnet_wrapper_allowlist_constant_matches_sdk to assert the
wrapper value matches the SDK-exported source of truth (for example the
percolator-sdk PROGRAM_IDS_V17.percolator constant) instead of another literal,
while keeping the existing sanity checks that it differs from mainnet/legacy and
is non-default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant