fix(nft): the burn holder is the rent recipient — mark it writable (#376) - #377
fix(nft): the burn holder is the rent recipient — mark it writable (#376)#3770x-SquidSol wants to merge 1 commit into
Conversation
|
Warning Review limit reachedNext included review available in 56 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (1)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe NFT burn and emergency burn templates now mark the holder as signer and writable. Tests validate account counts, account permissions, permissionless reconciliation, and rejection of mismatched key counts. ChangesNFT ABI validation
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to The burn account metadata now correctly marks the rent recipient as both signer and writable, preventing the affected burn transactions from being rejected. No actionable merge-blocking risk remains after normal checks and review. Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Full details: Docstring CoverageExplanation No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
`ACCOUNTS_NFT_BURN` and `ACCOUNTS_NFT_EMERGENCY_BURN` marked account 0, the NFT
holder, as "s": signer but NOT writable. The program requires signer AND
writable, because the holder receives the rent from every account those
instructions close — the ATA, the mint, the PositionNft PDA and the
ExtraAccountMetaList.
percolator-nft rejects a read-only holder outright:
fn require_writable_rent_recipient(holder: &AccountInfo) -> ProgramResult {
if !holder.is_writable { return Err(ProgramError::InvalidAccountData); }
Ok(())
}
called from BurnPositionNft (processor.rs:825) and EmergencyBurn (:1000). The
program's own ABI table documents account 0 as `[signer, writable]`
(instruction.rs:44 and :99).
So every burn instruction built from these templates via buildNftAccountMetas
went on the wire with isWritable: false and was rejected with
InvalidAccountData. This is a live break against the deployed programs.
It went unnoticed because nothing in this repo consumes the templates — there is
no in-repo call site of buildNftAccountMetas or of any ACCOUNTS_NFT_* array, so
only external callers ever exercised them. The existing drift tests could not
have caught it either: they assert the shorthand string codes, and the defect is
only visible once those become {isSigner, isWritable} booleans.
Add account-list tests that round-trip through the real builder and assert those
booleans. That is the assertion that makes this class visible, and it also covers
the historical wrong-builder bug documented above buildNftAccountMetas, where
every flag silently became `undefined`.
Closes dcccrypto#376
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
796464a to
8b50f11
Compare
Closes #376.
Problem
ACCOUNTS_NFT_BURNandACCOUNTS_NFT_EMERGENCY_BURNmarked account 0 — the NFT holder — as"s": signer but not writable. The program requires signer and writable, because the holder receives the rent from every account those instructions close: the ATA, the mint, the PositionNft PDA and the ExtraAccountMetaList.percolator-nft rejects a read-only holder outright:
called from
BurnPositionNft(processor.rs:825) andEmergencyBurn(:1000). The program's own ABI table documents account 0 as[signer, writable](instruction.rs:44and:99).So every burn built from these templates via
buildNftAccountMetaswent on the wire withisWritable: falseand was rejected withInvalidAccountData. This is a live break against the deployed programs, not a latent one.Why nothing caught it
Two reasons, and the second is the more useful one:
buildNftAccountMetas, and no consumer of anyACCOUNTS_NFT_*array. Only external callers exercise them.{isSigner, isWritable}booleans, which is the object that actually goes into the transaction.That second point is the same failure mode the long comment above
buildNftAccountMetasalready records: the earlier bug there was passing these arrays to the wrong builder, silently yieldingisSigner: undefined/isWritable: undefined, described as failing with "InvalidAccountDataat ~2.4k CU, before any CPI". Same symptom, different cause — and the same blind spot in the tests.Fix
"s"→"sw"in both templates, plus the doc lines above them.Tests
New
percolator-nft account-list ABIblock intest/drift-check.test.ts, which already tracks this surface. The assertions round-trip each template through the real builder and check the booleans rather than the codes:Before this change they fail exactly where the bug is:
The block also covers
MintPositionNft's two signers,extra_metaswritability on both burn paths (#102), that Reconcile is permissionless (no account may be a signer), and thatbuildNftAccountMetasthrows on a key-count mismatch rather than truncating.npx tsc --noEmitclean; full suite 1013 passing across 29 files.Scope
Deliberately narrow — this is a live break and should be able to merge on its own.
A second, separate change is coming for
ACCOUNTS_NFT_RECONCILE, which must grow from 7 to 9 accounts to match dcccrypto/percolator-nft#183. That one is not mergeable yet: both the mainnet and devnet programs still expect seven accounts, so it has to wait until the program change is merged and deployed. Keeping them apart so this fix is not held behind that gate.🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests