Skip to content

fix(programs): add MintCloseAuthority as restricted extension (M-03)#2263

Merged
ananas-block merged 2 commits intomainfrom
jorrit/fix-certora-m03-mint-close-authority
Feb 10, 2026
Merged

fix(programs): add MintCloseAuthority as restricted extension (M-03)#2263
ananas-block merged 2 commits intomainfrom
jorrit/fix-certora-m03-mint-close-authority

Conversation

@ananas-block
Copy link
Contributor

@ananas-block ananas-block commented Feb 9, 2026

Summary

  • Certora audit M-03: MintCloseAuthority was not in the restricted extensions list. A mint with this extension could be compressed without CompressedOnly mode, allowing the mint authority to close the mint and strand compressed tokens.
  • Fix: Add MintCloseAuthority to RESTRICTED_EXTENSION_TYPES.

Changes

  • token_2022_extensions.rs: Added MintCloseAuthority to restricted list, added has_mint_close_authority flag to MintExtensionFlags.
  • check_mint_extensions.rs: Added detection for MintCloseAuthority in has_mint_extensions().

Summary by CodeRabbit

  • New Features
    • Added support for detecting and tracking the MintCloseAuthority extension. This restricted extension type is now included in validation checks for token mints.

A mint with MintCloseAuthority can be closed and re-opened with
different extensions. Treating it as restricted ensures compressed
tokens from such mints require CompressedOnly mode.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • program-tests/compressed-token-test/tests/compress_only/restricted_required.rs is excluded by none and included by none

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request extends support for the MintCloseAuthority extension type across the token interface and compressed token program. It adds the extension to the restricted types list, introduces a new tracking field has_mint_close_authority to MintExtensionFlags, and integrates this flag into both extension detection and restricted extension validation.

Changes

Cohort / File(s) Summary
Restricted extension type registration
program-libs/token-interface/src/token_2022_extensions.rs
Added MintCloseAuthority to the RESTRICTED_EXTENSION_TYPES array, expanded from 5 to 6 types. Updated is_restricted_extension() to match on the new type, and incorporated has_mint_close_authority into the has_restricted_extensions() calculation.
Extension detection and tracking
programs/compressed-token/program/src/extensions/check_mint_extensions.rs
Added has_mint_close_authority: bool field to MintExtensionFlags struct. Updated has_mint_extensions() function to detect ExtensionType::MintCloseAuthority, track it in a local variable, and include it in the returned MintExtensionFlags struct.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

🔐 A new authority arrives on the scene,
Mint closure now joins the restricted machine,
Fields track its presence, both far and between,
Extensions grow stronger, the logic pristine,
Security blooms in a token-based dream! 🌱

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding MintCloseAuthority to the restricted extensions list to address a security audit finding.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 70.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jorrit/fix-certora-m03-mint-close-authority

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 and usage tips.

@ananas-block ananas-block changed the title fix(M-03): add MintCloseAuthority as restricted extension fix(programs): add MintCloseAuthority as restricted extension (M-03) Feb 9, 2026
@ananas-block
Copy link
Contributor Author

@CodeRabbit

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Tip

For best results, initiate chat on the files or code changes.

@ananas-block: Hello! How can I assist you with this PR? I can help with:

  • Reviewing the changes in detail
  • Answering questions about the implementation
  • Generating tests or documentation
  • Running scripts to analyze the codebase
  • Any other specific requests you have

Just let me know what you need!


🧠 Learnings used
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/mint_action/**/*.rs : MintAction instruction must support exactly 10 action types: CreateCompressedMint, MintTo, UpdateMintAuthority, UpdateFreezeAuthority, MintToCToken, UpdateMetadataField, UpdateMetadataAuthority, RemoveMetadataKey, DecompressMint, and CompressAndCloseCMint

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2026-01-12T14:27:56.326Z
Learning: Applies to programs/compressed-token/program/docs/**/RESTRICTED_T22_EXTENSIONS.md : Documentation files should include RESTRICTED_T22_EXTENSIONS.md for SPL Token-2022 behavior for 5 restricted extensions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/account/README.md:0-0
Timestamp: 2026-02-04T00:56:37.405Z
Learning: Applies to sdk-libs/account/**/*.rs : Include optional `mint::authority_seeds`, `mint::authority_bump`, `mint::name`, `mint::symbol`, `mint::uri`, `mint::update_authority`, and `mint::additional_metadata` fields when creating a Light Mint

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: airdrop-implementations/simple-claim/README.md:0-0
Timestamp: 2026-01-10T19:24:56.367Z
Learning: Applies to airdrop-implementations/simple-claim/**/*.rs : Tokens must be minted as compressed tokens to PDAs derived from `[claimant, mint, unlock_slot, bump]`

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/transfer2/**/*.rs : Transfer2 instruction must perform sum checks when supporting multi-mint Compress, Decompress, and CompressAndClose operations

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Compressed mint accounts support only one extension: TokenMetadata

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2026-01-12T14:27:56.326Z
Learning: Applies to programs/compressed-token/program/docs/**/EXTENSIONS.md : Documentation files should include EXTENSIONS.md for Token-2022 extension validation across ctoken instructions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : When validating owner and delegate authority, use shared utilities from `shared/owner_validation.rs`

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressible/*.rs : Rent authority can compress accounts only when `is_compressible()` returns true, as documented in program-libs/compressible/docs/RENT.md

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/token-interface/README.md:0-0
Timestamp: 2026-01-29T22:54:05.595Z
Learning: Applies to program-libs/token-interface/**/*.rs : Organize Rust modules with clear separation of concerns: `instructions` for mint, transfer, wrap, unwrap operations; `state` for token account and mint state structs; `discriminator` for instruction discriminator constants; `hash_cache` for precomputed hashes; `pool_derivation` for SPL/T22 pool account PDA derivation; `token_2022_extensions` for Token-2022 extension data types; `error` for TokenInterfaceError variants

@ananas-block
Copy link
Contributor Author

ananas-block commented Feb 9, 2026

@CodeRabbit please review this pr, specifically check that all places where restricted extensions are checked include close authority now

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

@ananas-block: I'll review the changes in this PR right away. This looks like an important security fix addressing the MintCloseAuthority extension risk identified in the Certora audit.


🧠 Learnings used
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/mint_action/**/*.rs : MintAction instruction must support exactly 10 action types: CreateCompressedMint, MintTo, UpdateMintAuthority, UpdateFreezeAuthority, MintToCToken, UpdateMetadataField, UpdateMetadataAuthority, RemoveMetadataKey, DecompressMint, and CompressAndCloseCMint

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: airdrop-implementations/simple-claim/README.md:0-0
Timestamp: 2026-01-10T19:24:56.367Z
Learning: Applies to airdrop-implementations/simple-claim/**/*.rs : Tokens must be minted as compressed tokens to PDAs derived from `[claimant, mint, unlock_slot, bump]`

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/token-interface/README.md:0-0
Timestamp: 2026-01-29T22:54:05.595Z
Learning: Applies to program-libs/token-interface/**/*.rs : Organize Rust modules with clear separation of concerns: `instructions` for mint, transfer, wrap, unwrap operations; `state` for token account and mint state structs; `discriminator` for instruction discriminator constants; `hash_cache` for precomputed hashes; `pool_derivation` for SPL/T22 pool account PDA derivation; `token_2022_extensions` for Token-2022 extension data types; `error` for TokenInterfaceError variants

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: account-comparison/CLAUDE.md:0-0
Timestamp: 2026-01-10T19:26:01.412Z
Learning: Applies to account-comparison/programs/**/tests/test_compressed_account.rs : Include Light Protocol tests in test_compressed_account.rs to verify compressed account operations using LightAccount primitives

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/transfer2/**/*.rs : Transfer2 instruction must perform sum checks when supporting multi-mint Compress, Decompress, and CompressAndClose operations

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-light-token-pinocchio/README.md:0-0
Timestamp: 2026-02-04T00:57:01.583Z
Learning: Applies to sdk-tests/sdk-light-token-pinocchio/**/*.rs : Use `MintToCTokenCpi::invoke()` to mint tokens to compressed accounts

Learnt from: CR
Repo: Lightprotocol/distributor PR: 0
File: programs/merkle-distributor/CLAUDE.md:0-0
Timestamp: 2026-01-11T01:05:19.378Z
Learning: Applies to programs/merkle-distributor/**/instructions/{new_claim,claim_locked}.rs : Use Light SDK v2 CPI via `LightSystemProgramCpi::new_cpi` for compressed account interactions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/CLAUDE.md:0-0
Timestamp: 2026-01-31T16:39:11.741Z
Learning: Applies to sdk-libs/macros/**/*.rs : Use `#[light_account(init)]` attribute for compressed PDAs, `#[light_account(init, mint::...)]` for compressed mints, `#[light_account([init,] token::...)]` for token accounts, and `#[light_account([init,] associated_token::...)]` for associated token accounts

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/**/*.rs : Claim and WithdrawFundingPool instructions must validate that CompressibleConfig state is not inactive (active or deprecated OK)

Learnt from: CR
Repo: Lightprotocol/distributor PR: 0
File: README.md:0-0
Timestamp: 2026-01-11T01:05:03.142Z
Learning: Applies to programs/merkle-distributor/src/**/*.rs : Use compressed accounts (compressed PDAs) instead of regular PDAs for ClaimStatus accounts in the Solana merkle-distributor program to reduce cost per claim (~0.00005 SOL vs ~0.002 SOL per claim)

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2026-01-12T14:27:56.326Z
Learning: Applies to programs/compressed-token/program/docs/**/RESTRICTED_T22_EXTENSIONS.md : Documentation files should include RESTRICTED_T22_EXTENSIONS.md for SPL Token-2022 behavior for 5 restricted extensions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/account/README.md:0-0
Timestamp: 2026-02-04T00:56:37.405Z
Learning: Applies to sdk-libs/account/**/*.rs : Include optional `mint::authority_seeds`, `mint::authority_bump`, `mint::name`, `mint::symbol`, `mint::uri`, `mint::update_authority`, and `mint::additional_metadata` fields when creating a Light Mint

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Compressed mint accounts support only one extension: TokenMetadata

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2026-01-12T14:27:56.326Z
Learning: Applies to programs/compressed-token/program/docs/**/EXTENSIONS.md : Documentation files should include EXTENSIONS.md for Token-2022 extension validation across ctoken instructions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : When validating owner and delegate authority, use shared utilities from `shared/owner_validation.rs`

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressible/*.rs : Rent authority can compress accounts only when `is_compressible()` returns true, as documented in program-libs/compressible/docs/RENT.md
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's find and read the token_2022_extensions.rs file to see the RESTRICTED_EXTENSION_TYPES definition
fd -t f "token_2022_extensions.rs" --exec cat {}

Length of output: 6135


🏁 Script executed:

#!/bin/bash
# Search for all occurrences of RESTRICTED_EXTENSION_TYPES to see where it's used
rg -n "RESTRICTED_EXTENSION_TYPES" -C3

Length of output: 2384


🏁 Script executed:

#!/bin/bash
# Search for check_mint_extensions and related validation functions
rg -n "check_mint_extensions|has_mint_extensions|restricted.extension" -i -C3

Length of output: 123252


🏁 Script executed:

#!/bin/bash
# Find the check_mint_extensions.rs file
fd -t f "check_mint_extensions.rs" --exec cat {}

Length of output: 9865


🏁 Script executed:

#!/bin/bash
# Search for documentation files about restricted extensions
fd -t f "RESTRICTED" -e md --exec cat {}

Length of output: 13027


🏁 Script executed:

#!/bin/bash
# Search for any tests related to restricted extensions or MintCloseAuthority
rg -n "MintCloseAuthority|mint_close_authority" -C2

Length of output: 6203


@ananas-block: I've reviewed the PR and verified that MintCloseAuthority is properly included in all code paths that check for restricted extensions. Here's my analysis:

✅ Code Implementation - Complete

All critical code paths correctly include MintCloseAuthority:

  1. RESTRICTED_EXTENSION_TYPES constant (token_2022_extensions.rs:9-16)

    • ✅ Now has 6 elements including ExtensionType::MintCloseAuthority
  2. is_restricted_extension() function (token_2022_extensions.rs:49-58)

    • ✅ Matches on ExtensionType::MintCloseAuthority
  3. MintExtensionFlags struct (token_2022_extensions.rs:76-77)

    • ✅ Has has_mint_close_authority field
  4. has_restricted_extensions() method (token_2022_extensions.rs:153-160)

    • ✅ Checks self.has_mint_close_authority in the return expression
  5. has_mint_extensions() function (check_mint_extensions.rs:193, 206, 229)

    • ✅ Detects MintCloseAuthority and sets the flag correctly
  6. All validation entry points:

    • restricted_seed() - uses is_restricted_extension()
    • pool_derivation::has_restricted_extensions() - uses is_restricted_extension()
    • parse_mint_extensions() - uses is_restricted_extension()
    • Account creation validation - uses has_restricted_extensions() method ✓

📝 Documentation Gaps

However, I found some documentation that needs updating:

  1. CREATE_TOKEN_POOL.md:49 - Says "Restricted extensions (5 types)" should be "6 types"

  2. EXTENSIONS.md - MintCloseAuthority is listed as extension #8 but not clearly marked as restricted in the quick reference table at the top

  3. RESTRICTED_T22_EXTENSIONS.md - Missing a section documenting MintCloseAuthority behavior (the file documents the other 5 restricted extensions but not this one)

Recommendation

The code implementation is solid and complete. I recommend updating the documentation to:

  • Update the count from 5 to 6 restricted extensions
  • Add MintCloseAuthority to RESTRICTED_T22_EXTENSIONS.md explaining why it's restricted (preventing mint closure while compressed tokens exist)
  • Mark it as "restricted" in EXTENSIONS.md quick reference table

Would you like me to help generate the documentation updates?


🧠 Learnings used
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/transfer2/**/*.rs : Transfer2 instruction must perform sum checks when supporting multi-mint Compress, Decompress, and CompressAndClose operations

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: create-and-update/README.md:0-0
Timestamp: 2026-01-10T19:25:28.052Z
Learning: Applies to create-and-update/**/*.rs : Verify ownership before allowing updates to compressed accounts

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: airdrop-implementations/simple-claim/README.md:0-0
Timestamp: 2026-01-10T19:24:56.367Z
Learning: Applies to airdrop-implementations/simple-claim/**/*.rs : Tokens must be minted as compressed tokens to PDAs derived from `[claimant, mint, unlock_slot, bump]`

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: account-comparison/CLAUDE.md:0-0
Timestamp: 2026-01-10T19:26:01.412Z
Learning: Applies to account-comparison/programs/**/tests/test_compressed_account.rs : Include Light Protocol tests in test_compressed_account.rs to verify compressed account operations using LightAccount primitives

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: basic-operations/CLAUDE.md:0-0
Timestamp: 2026-01-10T19:26:21.240Z
Learning: Applies to basic-operations/**/{anchor,native}/**/src/**/*.rs : Verify current state matches on-chain data before executing close, update, or burn operations

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/mint_action/**/*.rs : MintAction instruction must support exactly 10 action types: CreateCompressedMint, MintTo, UpdateMintAuthority, UpdateFreezeAuthority, MintToCToken, UpdateMetadataField, UpdateMetadataAuthority, RemoveMetadataKey, DecompressMint, and CompressAndCloseCMint

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressed_token/**/*.rs : Claim and WithdrawFundingPool instructions must validate that CompressibleConfig state is not inactive (active or deprecated OK)

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: counter/CLAUDE.md:0-0
Timestamp: 2026-01-10T19:26:31.226Z
Learning: Applies to counter/**/{anchor,native,pinocchio}/src/**/*.rs : Include owner binding validation in all mutations to verify owner is reconstructed from signer and matches account hash

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/DISCRIMINATOR.md:0-0
Timestamp: 2025-11-24T17:59:36.701Z
Learning: Applies to program-libs/account-checks/docs/**/account-checks/**/*.rs : Ensure discriminator validation is Anchor-compatible by using sha256 hashing for consistency with Anchor accounts

Learnt from: CR
Repo: Lightprotocol/program-examples PR: 0
File: account-comparison/CLAUDE.md:0-0
Timestamp: 2026-01-10T19:26:01.412Z
Learning: Applies to account-comparison/programs/**/src/**/*.rs : Verify user ownership by asserting `compressed_account.user == ctx.accounts.user.key()` in `update_compressed_account` instruction before state modifications

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2026-01-12T14:27:56.326Z
Learning: Applies to programs/compressed-token/program/docs/**/RESTRICTED_T22_EXTENSIONS.md : Documentation files should include RESTRICTED_T22_EXTENSIONS.md for SPL Token-2022 behavior for 5 restricted extensions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/account/README.md:0-0
Timestamp: 2026-02-04T00:56:37.405Z
Learning: Applies to sdk-libs/account/**/*.rs : Include optional `mint::authority_seeds`, `mint::authority_bump`, `mint::name`, `mint::symbol`, `mint::uri`, `mint::update_authority`, and `mint::additional_metadata` fields when creating a Light Mint

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Compressed mint accounts support only one extension: TokenMetadata

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2026-01-12T14:27:56.326Z
Learning: Applies to programs/compressed-token/program/docs/**/EXTENSIONS.md : Documentation files should include EXTENSIONS.md for Token-2022 extension validation across ctoken instructions

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : When validating owner and delegate authority, use shared utilities from `shared/owner_validation.rs`

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2026-01-14T00:06:46.444Z
Learning: Applies to programs/compressed-token/program/src/compressible/*.rs : Rent authority can compress accounts only when `is_compressible()` returns true, as documented in program-libs/compressible/docs/RENT.md

Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/token-interface/README.md:0-0
Timestamp: 2026-01-29T22:54:05.595Z
Learning: Applies to program-libs/token-interface/**/*.rs : Organize Rust modules with clear separation of concerns: `instructions` for mint, transfer, wrap, unwrap operations; `state` for token account and mint state structs; `discriminator` for instruction discriminator constants; `hash_cache` for precomputed hashes; `pool_derivation` for SPL/T22 pool account PDA derivation; `token_2022_extensions` for Token-2022 extension data types; `error` for TokenInterfaceError variants

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
program-libs/token-interface/src/token_2022_extensions.rs (1)

150-160: ⚠️ Potential issue | 🟡 Minor

Same stale-doc issue on has_restricted_extensions.

The doc comment on line 151–152 lists five extensions but doesn't mention MintCloseAuthority, even though line 159 now checks for it. Keeping these in sync avoids confusing the next person reading the code.

📝 Suggested fix
     /// Returns true if mint has any restricted extensions.
-    /// Restricted extensions (Pausable, PermanentDelegate, TransferFee, TransferHook,
-    /// DefaultAccountState) require compression_only mode when compressing tokens.
+    /// Restricted extensions (Pausable, PermanentDelegate, TransferFee, TransferHook,
+    /// DefaultAccountState, MintCloseAuthority) require compression_only mode when compressing tokens.
programs/compressed-token/program/src/extensions/check_mint_extensions.rs (1)

26-27: ⚠️ Potential issue | 🟡 Minor

Doc comment on MintExtensionChecks::has_restricted_extensions field is also stale.

Line 26 mentions "Pausable, PermanentDelegate, TransferFee, TransferHook, DefaultAccountState" — same pattern as the other file. Worth updating for consistency.

📝 Suggested fix
-    /// Whether the mint has restricted extensions (Pausable, PermanentDelegate, TransferFee, TransferHook, DefaultAccountState)
+    /// Whether the mint has restricted extensions (Pausable, PermanentDelegate, TransferFee, TransferHook, DefaultAccountState, MintCloseAuthority)
🤖 Fix all issues with AI agents
In `@program-libs/token-interface/src/token_2022_extensions.rs`:
- Around line 6-16: Update the stale doc comment above
RESTRICTED_EXTENSION_TYPES to include "mint close authority"
(ExtensionType::MintCloseAuthority) among the listed restricted behaviors so the
comment matches the array and is_restricted_extension logic; revise the sentence
that lists pausable, permanent delegate, fees, hooks, default frozen state to
also mention mint close authority (or "mint close authority (mint close)") for
clarity.

Comment on lines 6 to 16
/// Restricted extension types that require compression_only mode.
/// These extensions have special behaviors (pausable, permanent delegate, fees, hooks,
/// default frozen state) that are incompatible with standard compressed token transfers.
pub const RESTRICTED_EXTENSION_TYPES: [ExtensionType; 5] = [
pub const RESTRICTED_EXTENSION_TYPES: [ExtensionType; 6] = [
ExtensionType::Pausable,
ExtensionType::PermanentDelegate,
ExtensionType::TransferFeeConfig,
ExtensionType::TransferHook,
ExtensionType::DefaultAccountState,
ExtensionType::MintCloseAuthority,
];
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Stale doc comment — MintCloseAuthority not listed among restricted extensions.

The comment on lines 7–8 enumerates the restricted behaviors but omits MintCloseAuthority (mint close authority). Since you've added it to the array and is_restricted_extension, the comment should stay in sync.

📝 Suggested fix
 /// Restricted extension types that require compression_only mode.
-/// These extensions have special behaviors (pausable, permanent delegate, fees, hooks,
-/// default frozen state) that are incompatible with standard compressed token transfers.
+/// These extensions have special behaviors (pausable, permanent delegate, fees, hooks,
+/// default frozen state, mint close authority) that are incompatible with standard compressed token transfers.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Restricted extension types that require compression_only mode.
/// These extensions have special behaviors (pausable, permanent delegate, fees, hooks,
/// default frozen state) that are incompatible with standard compressed token transfers.
pub const RESTRICTED_EXTENSION_TYPES: [ExtensionType; 5] = [
pub const RESTRICTED_EXTENSION_TYPES: [ExtensionType; 6] = [
ExtensionType::Pausable,
ExtensionType::PermanentDelegate,
ExtensionType::TransferFeeConfig,
ExtensionType::TransferHook,
ExtensionType::DefaultAccountState,
ExtensionType::MintCloseAuthority,
];
/// Restricted extension types that require compression_only mode.
/// These extensions have special behaviors (pausable, permanent delegate, fees, hooks,
/// default frozen state, mint close authority) that are incompatible with standard compressed token transfers.
pub const RESTRICTED_EXTENSION_TYPES: [ExtensionType; 6] = [
ExtensionType::Pausable,
ExtensionType::PermanentDelegate,
ExtensionType::TransferFeeConfig,
ExtensionType::TransferHook,
ExtensionType::DefaultAccountState,
ExtensionType::MintCloseAuthority,
];
🤖 Prompt for AI Agents
In `@program-libs/token-interface/src/token_2022_extensions.rs` around lines 6 -
16, Update the stale doc comment above RESTRICTED_EXTENSION_TYPES to include
"mint close authority" (ExtensionType::MintCloseAuthority) among the listed
restricted behaviors so the comment matches the array and
is_restricted_extension logic; revise the sentence that lists pausable,
permanent delegate, fees, hooks, default frozen state to also mention mint close
authority (or "mint close authority (mint close)") for clarity.

Add test coverage for MintCloseAuthority requiring compression_only mode,
complementing the fix in f2da063.
@ananas-block ananas-block merged commit 80705a4 into main Feb 10, 2026
33 of 41 checks passed
@ananas-block ananas-block deleted the jorrit/fix-certora-m03-mint-close-authority branch February 10, 2026 01:12
SwenSchaeferjohann pushed a commit that referenced this pull request Feb 11, 2026
…2263)

* fix: add MintCloseAuthority as restricted extension (M-03)

A mint with MintCloseAuthority can be closed and re-opened with
different extensions. Treating it as restricted ensures compressed
tokens from such mints require CompressedOnly mode.

* test: add MintCloseAuthority compression_only requirement tests

Add test coverage for MintCloseAuthority requiring compression_only mode,
complementing the fix in f2da063.
SwenSchaeferjohann added a commit that referenced this pull request Feb 11, 2026
refactor

remove fetch-accounts

renaming, simplify trait

fomat

excl photon-api submodule

fix: multi-pass cold account lookup in test indexer RPC

Align get_account_interface and get_multiple_account_interfaces with
Photon's lookup strategy: search compressed_accounts by onchain_pubkey,
then by PDA seed derivation, then token_compressed_accounts, then by
token_data.owner. Also fix as_mint() to accept ColdContext::Account
since Photon returns mints as generic compressed accounts.

Co-authored-by: Cursor <cursoragent@cursor.com>

lint

fix lint

fix: reject rent sponsor self-referencing the token account (#2257)

* fix: reject rent sponsor self-referencing the token account

Audit issue #9 (INFO): The rent payer could be the same account as
the target token account being created. Add a check that rejects
this self-reference to prevent accounting issues.

* test: add failing test rent sponsor self reference

fix: process metadata add/remove actions in sequential order (#2256)

* fix: process metadata add/remove actions in sequential order

Audit issue #16 (LOW): should_add_key checked for any add and any
remove independently, ignoring action ordering. An add-remove-add
sequence would incorrectly remove the key. Process actions
sequentially so the final state reflects the actual order.

* chore: format

* test: add randomized test for metadata action processing

Validates that process_extensions_config_with_actions produces correct
AdditionalMetadataConfig for random sequences of UpdateMetadataField
and RemoveMetadataKey actions, covering the add-remove-add bug from
audit issue #16.

* test: add integration test for audit issue #13 (no double rent charge)

Verifies that two compress operations targeting the same compressible
CToken account in a single Transfer2 instruction do not double-charge
the rent top-up budget.

* chore: format extensions_metadata test

fix: validate authority on self-transfer early return (#2252)

* fix: handle self-transfer in ctoken transfer and transfer_checked

Validate that the authority is a signer and is the owner or delegate
before allowing self-transfer early return. Previously the self-transfer
path returned Ok(()) without any authority validation.

* fix: simplify map_or to is_some_and per clippy

* fix: use pubkey_eq for self-transfer check

* refactor: extract self-transfer validation into shared function

Extract duplicate self-transfer check from default.rs and checked.rs
into validate_self_transfer() in shared.rs with cold path for authority
validation.

* chore: format

* fix: deduplicate random metadata keys in test_random_mint_action

Random key generation could produce duplicate keys, causing
DuplicateMetadataKey error (18040) with certain seeds.

fix: enforce mint extension checks in cToken-to-cToken decompress (#2246)

* fix: enforce mint extension checks in cToken-to-cToken decompress hot path

Add enforce_extension_state() to MintExtensionChecks and call it in the
Decompress branch when decompress_inputs is None (hot-path, not
CompressedOnly restore). This prevents cToken-to-cToken transfers from
bypassing pause, transfer fee, and transfer hook restrictions.

* fix test

chore: reject compress for mints with restricted extensions in build_mint_extension_cache (#2240)

* chore: reject compress for mints with restricted extensions in mint check

* Update programs/compressed-token/program/src/compressed_token/transfer2/check_extensions.rs

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

* fix: format else-if condition for lint

---------

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

fix: token-pool index 0 check (#2239)

fix(programs): add MintCloseAuthority as restricted extension (M-03) (#2263)

* fix: add MintCloseAuthority as restricted extension (M-03)

A mint with MintCloseAuthority can be closed and re-opened with
different extensions. Treating it as restricted ensures compressed
tokens from such mints require CompressedOnly mode.

* test: add MintCloseAuthority compression_only requirement tests

Add test coverage for MintCloseAuthority requiring compression_only mode,
complementing the fix in f2da063.

refactor: light program pinocchio macro (#2247)

* refactor: light program pinocchio macro

* fix: address CodeRabbit review comments on macro codegen

- Fix account order bug in process_update_config (config=0, authority=1)
- Use backend-provided serialize/deserialize derives in LightAccountData
- Remove redundant is_pinocchio() branch for has_le_bytes unpack fields
- DRY doc attribute generation across 4 struct generation methods
- Unify unpack_data path using account_crate re-export for both backends

chore(libs): bump versions (#2272)

fix(programs): allow account-level delegate to compress CToken (M-02) (#2262)

* fix: allow account-level delegate to compress tokens from CToken (M-02)

check_ctoken_owner() only checked owner and permanent delegate.
An account-level delegate (approved via CTokenApprove) could not
compress tokens. Added delegate check after permanent delegate.

* test: compress by delegate

fix: accumulate delegated amount at decompression (#2242)

* fix: accumulate delegated amount at decompression

* fix lint

* refactor: simplify apply_delegate to single accumulation path

* fix: ignore delegated_amount without delegate

* restore decompress amount check

fix programtest, wallet owner tracking for ata

fmt and lint
SwenSchaeferjohann added a commit that referenced this pull request Feb 11, 2026
refactor

remove fetch-accounts

renaming, simplify trait

fomat

excl photon-api submodule

fix: multi-pass cold account lookup in test indexer RPC

Align get_account_interface and get_multiple_account_interfaces with
Photon's lookup strategy: search compressed_accounts by onchain_pubkey,
then by PDA seed derivation, then token_compressed_accounts, then by
token_data.owner. Also fix as_mint() to accept ColdContext::Account
since Photon returns mints as generic compressed accounts.

Co-authored-by: Cursor <cursoragent@cursor.com>

lint

fix lint

fix: reject rent sponsor self-referencing the token account (#2257)

* fix: reject rent sponsor self-referencing the token account

Audit issue #9 (INFO): The rent payer could be the same account as
the target token account being created. Add a check that rejects
this self-reference to prevent accounting issues.

* test: add failing test rent sponsor self reference

fix: process metadata add/remove actions in sequential order (#2256)

* fix: process metadata add/remove actions in sequential order

Audit issue #16 (LOW): should_add_key checked for any add and any
remove independently, ignoring action ordering. An add-remove-add
sequence would incorrectly remove the key. Process actions
sequentially so the final state reflects the actual order.

* chore: format

* test: add randomized test for metadata action processing

Validates that process_extensions_config_with_actions produces correct
AdditionalMetadataConfig for random sequences of UpdateMetadataField
and RemoveMetadataKey actions, covering the add-remove-add bug from
audit issue #16.

* test: add integration test for audit issue #13 (no double rent charge)

Verifies that two compress operations targeting the same compressible
CToken account in a single Transfer2 instruction do not double-charge
the rent top-up budget.

* chore: format extensions_metadata test

fix: validate authority on self-transfer early return (#2252)

* fix: handle self-transfer in ctoken transfer and transfer_checked

Validate that the authority is a signer and is the owner or delegate
before allowing self-transfer early return. Previously the self-transfer
path returned Ok(()) without any authority validation.

* fix: simplify map_or to is_some_and per clippy

* fix: use pubkey_eq for self-transfer check

* refactor: extract self-transfer validation into shared function

Extract duplicate self-transfer check from default.rs and checked.rs
into validate_self_transfer() in shared.rs with cold path for authority
validation.

* chore: format

* fix: deduplicate random metadata keys in test_random_mint_action

Random key generation could produce duplicate keys, causing
DuplicateMetadataKey error (18040) with certain seeds.

fix: enforce mint extension checks in cToken-to-cToken decompress (#2246)

* fix: enforce mint extension checks in cToken-to-cToken decompress hot path

Add enforce_extension_state() to MintExtensionChecks and call it in the
Decompress branch when decompress_inputs is None (hot-path, not
CompressedOnly restore). This prevents cToken-to-cToken transfers from
bypassing pause, transfer fee, and transfer hook restrictions.

* fix test

chore: reject compress for mints with restricted extensions in build_mint_extension_cache (#2240)

* chore: reject compress for mints with restricted extensions in mint check

* Update programs/compressed-token/program/src/compressed_token/transfer2/check_extensions.rs

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

* fix: format else-if condition for lint

---------

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

fix: token-pool index 0 check (#2239)

fix(programs): add MintCloseAuthority as restricted extension (M-03) (#2263)

* fix: add MintCloseAuthority as restricted extension (M-03)

A mint with MintCloseAuthority can be closed and re-opened with
different extensions. Treating it as restricted ensures compressed
tokens from such mints require CompressedOnly mode.

* test: add MintCloseAuthority compression_only requirement tests

Add test coverage for MintCloseAuthority requiring compression_only mode,
complementing the fix in f2da063.

refactor: light program pinocchio macro (#2247)

* refactor: light program pinocchio macro

* fix: address CodeRabbit review comments on macro codegen

- Fix account order bug in process_update_config (config=0, authority=1)
- Use backend-provided serialize/deserialize derives in LightAccountData
- Remove redundant is_pinocchio() branch for has_le_bytes unpack fields
- DRY doc attribute generation across 4 struct generation methods
- Unify unpack_data path using account_crate re-export for both backends

chore(libs): bump versions (#2272)

fix(programs): allow account-level delegate to compress CToken (M-02) (#2262)

* fix: allow account-level delegate to compress tokens from CToken (M-02)

check_ctoken_owner() only checked owner and permanent delegate.
An account-level delegate (approved via CTokenApprove) could not
compress tokens. Added delegate check after permanent delegate.

* test: compress by delegate

fix: accumulate delegated amount at decompression (#2242)

* fix: accumulate delegated amount at decompression

* fix lint

* refactor: simplify apply_delegate to single accumulation path

* fix: ignore delegated_amount without delegate

* restore decompress amount check

fix programtest, wallet owner tracking for ata

fmt and lint
SwenSchaeferjohann added a commit that referenced this pull request Feb 11, 2026
refactor

remove fetch-accounts

renaming, simplify trait

fomat

excl photon-api submodule

fix: multi-pass cold account lookup in test indexer RPC

Align get_account_interface and get_multiple_account_interfaces with
Photon's lookup strategy: search compressed_accounts by onchain_pubkey,
then by PDA seed derivation, then token_compressed_accounts, then by
token_data.owner. Also fix as_mint() to accept ColdContext::Account
since Photon returns mints as generic compressed accounts.

Co-authored-by: Cursor <cursoragent@cursor.com>

lint

fix lint

fix: reject rent sponsor self-referencing the token account (#2257)

* fix: reject rent sponsor self-referencing the token account

Audit issue #9 (INFO): The rent payer could be the same account as
the target token account being created. Add a check that rejects
this self-reference to prevent accounting issues.

* test: add failing test rent sponsor self reference

fix: process metadata add/remove actions in sequential order (#2256)

* fix: process metadata add/remove actions in sequential order

Audit issue #16 (LOW): should_add_key checked for any add and any
remove independently, ignoring action ordering. An add-remove-add
sequence would incorrectly remove the key. Process actions
sequentially so the final state reflects the actual order.

* chore: format

* test: add randomized test for metadata action processing

Validates that process_extensions_config_with_actions produces correct
AdditionalMetadataConfig for random sequences of UpdateMetadataField
and RemoveMetadataKey actions, covering the add-remove-add bug from
audit issue #16.

* test: add integration test for audit issue #13 (no double rent charge)

Verifies that two compress operations targeting the same compressible
CToken account in a single Transfer2 instruction do not double-charge
the rent top-up budget.

* chore: format extensions_metadata test

fix: validate authority on self-transfer early return (#2252)

* fix: handle self-transfer in ctoken transfer and transfer_checked

Validate that the authority is a signer and is the owner or delegate
before allowing self-transfer early return. Previously the self-transfer
path returned Ok(()) without any authority validation.

* fix: simplify map_or to is_some_and per clippy

* fix: use pubkey_eq for self-transfer check

* refactor: extract self-transfer validation into shared function

Extract duplicate self-transfer check from default.rs and checked.rs
into validate_self_transfer() in shared.rs with cold path for authority
validation.

* chore: format

* fix: deduplicate random metadata keys in test_random_mint_action

Random key generation could produce duplicate keys, causing
DuplicateMetadataKey error (18040) with certain seeds.

fix: enforce mint extension checks in cToken-to-cToken decompress (#2246)

* fix: enforce mint extension checks in cToken-to-cToken decompress hot path

Add enforce_extension_state() to MintExtensionChecks and call it in the
Decompress branch when decompress_inputs is None (hot-path, not
CompressedOnly restore). This prevents cToken-to-cToken transfers from
bypassing pause, transfer fee, and transfer hook restrictions.

* fix test

chore: reject compress for mints with restricted extensions in build_mint_extension_cache (#2240)

* chore: reject compress for mints with restricted extensions in mint check

* Update programs/compressed-token/program/src/compressed_token/transfer2/check_extensions.rs

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

* fix: format else-if condition for lint

---------

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

fix: token-pool index 0 check (#2239)

fix(programs): add MintCloseAuthority as restricted extension (M-03) (#2263)

* fix: add MintCloseAuthority as restricted extension (M-03)

A mint with MintCloseAuthority can be closed and re-opened with
different extensions. Treating it as restricted ensures compressed
tokens from such mints require CompressedOnly mode.

* test: add MintCloseAuthority compression_only requirement tests

Add test coverage for MintCloseAuthority requiring compression_only mode,
complementing the fix in f2da063.

refactor: light program pinocchio macro (#2247)

* refactor: light program pinocchio macro

* fix: address CodeRabbit review comments on macro codegen

- Fix account order bug in process_update_config (config=0, authority=1)
- Use backend-provided serialize/deserialize derives in LightAccountData
- Remove redundant is_pinocchio() branch for has_le_bytes unpack fields
- DRY doc attribute generation across 4 struct generation methods
- Unify unpack_data path using account_crate re-export for both backends

chore(libs): bump versions (#2272)

fix(programs): allow account-level delegate to compress CToken (M-02) (#2262)

* fix: allow account-level delegate to compress tokens from CToken (M-02)

check_ctoken_owner() only checked owner and permanent delegate.
An account-level delegate (approved via CTokenApprove) could not
compress tokens. Added delegate check after permanent delegate.

* test: compress by delegate

fix: accumulate delegated amount at decompression (#2242)

* fix: accumulate delegated amount at decompression

* fix lint

* refactor: simplify apply_delegate to single accumulation path

* fix: ignore delegated_amount without delegate

* restore decompress amount check

fix programtest, wallet owner tracking for ata

fmt and lint

upd amm test

simplify client usage, remove unnecessary endpoints

clean

cleanup

lint
SwenSchaeferjohann added a commit that referenced this pull request Feb 11, 2026
refactor

remove fetch-accounts

renaming, simplify trait

fomat

excl photon-api submodule

fix: multi-pass cold account lookup in test indexer RPC

Align get_account_interface and get_multiple_account_interfaces with
Photon's lookup strategy: search compressed_accounts by onchain_pubkey,
then by PDA seed derivation, then token_compressed_accounts, then by
token_data.owner. Also fix as_mint() to accept ColdContext::Account
since Photon returns mints as generic compressed accounts.

Co-authored-by: Cursor <cursoragent@cursor.com>

lint

fix lint

fix: reject rent sponsor self-referencing the token account (#2257)

* fix: reject rent sponsor self-referencing the token account

Audit issue #9 (INFO): The rent payer could be the same account as
the target token account being created. Add a check that rejects
this self-reference to prevent accounting issues.

* test: add failing test rent sponsor self reference

fix: process metadata add/remove actions in sequential order (#2256)

* fix: process metadata add/remove actions in sequential order

Audit issue #16 (LOW): should_add_key checked for any add and any
remove independently, ignoring action ordering. An add-remove-add
sequence would incorrectly remove the key. Process actions
sequentially so the final state reflects the actual order.

* chore: format

* test: add randomized test for metadata action processing

Validates that process_extensions_config_with_actions produces correct
AdditionalMetadataConfig for random sequences of UpdateMetadataField
and RemoveMetadataKey actions, covering the add-remove-add bug from
audit issue #16.

* test: add integration test for audit issue #13 (no double rent charge)

Verifies that two compress operations targeting the same compressible
CToken account in a single Transfer2 instruction do not double-charge
the rent top-up budget.

* chore: format extensions_metadata test

fix: validate authority on self-transfer early return (#2252)

* fix: handle self-transfer in ctoken transfer and transfer_checked

Validate that the authority is a signer and is the owner or delegate
before allowing self-transfer early return. Previously the self-transfer
path returned Ok(()) without any authority validation.

* fix: simplify map_or to is_some_and per clippy

* fix: use pubkey_eq for self-transfer check

* refactor: extract self-transfer validation into shared function

Extract duplicate self-transfer check from default.rs and checked.rs
into validate_self_transfer() in shared.rs with cold path for authority
validation.

* chore: format

* fix: deduplicate random metadata keys in test_random_mint_action

Random key generation could produce duplicate keys, causing
DuplicateMetadataKey error (18040) with certain seeds.

fix: enforce mint extension checks in cToken-to-cToken decompress (#2246)

* fix: enforce mint extension checks in cToken-to-cToken decompress hot path

Add enforce_extension_state() to MintExtensionChecks and call it in the
Decompress branch when decompress_inputs is None (hot-path, not
CompressedOnly restore). This prevents cToken-to-cToken transfers from
bypassing pause, transfer fee, and transfer hook restrictions.

* fix test

chore: reject compress for mints with restricted extensions in build_mint_extension_cache (#2240)

* chore: reject compress for mints with restricted extensions in mint check

* Update programs/compressed-token/program/src/compressed_token/transfer2/check_extensions.rs

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

* fix: format else-if condition for lint

---------

Co-authored-by: 0xa5df-c <172008956+0xa5df-c@users.noreply.github.com>

fix: token-pool index 0 check (#2239)

fix(programs): add MintCloseAuthority as restricted extension (M-03) (#2263)

* fix: add MintCloseAuthority as restricted extension (M-03)

A mint with MintCloseAuthority can be closed and re-opened with
different extensions. Treating it as restricted ensures compressed
tokens from such mints require CompressedOnly mode.

* test: add MintCloseAuthority compression_only requirement tests

Add test coverage for MintCloseAuthority requiring compression_only mode,
complementing the fix in f2da063.

refactor: light program pinocchio macro (#2247)

* refactor: light program pinocchio macro

* fix: address CodeRabbit review comments on macro codegen

- Fix account order bug in process_update_config (config=0, authority=1)
- Use backend-provided serialize/deserialize derives in LightAccountData
- Remove redundant is_pinocchio() branch for has_le_bytes unpack fields
- DRY doc attribute generation across 4 struct generation methods
- Unify unpack_data path using account_crate re-export for both backends

chore(libs): bump versions (#2272)

fix(programs): allow account-level delegate to compress CToken (M-02) (#2262)

* fix: allow account-level delegate to compress tokens from CToken (M-02)

check_ctoken_owner() only checked owner and permanent delegate.
An account-level delegate (approved via CTokenApprove) could not
compress tokens. Added delegate check after permanent delegate.

* test: compress by delegate

fix: accumulate delegated amount at decompression (#2242)

* fix: accumulate delegated amount at decompression

* fix lint

* refactor: simplify apply_delegate to single accumulation path

* fix: ignore delegated_amount without delegate

* restore decompress amount check

fix programtest, wallet owner tracking for ata

fmt and lint

upd amm test

simplify client usage, remove unnecessary endpoints

clean

cleanup

lint
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.

2 participants