Skip to content

fix: prevent compressible account funding with 1 epoch#1993

Merged
ananas-block merged 18 commits intomainfrom
jorrit/fix-pre-funding-compressible-account
Oct 16, 2025
Merged

fix: prevent compressible account funding with 1 epoch#1993
ananas-block merged 18 commits intomainfrom
jorrit/fix-pre-funding-compressible-account

Conversation

@ananas-block
Copy link
Contributor

@ananas-block ananas-block commented Oct 15, 2025

Summary by CodeRabbit

  • Bug Fixes

    • New runtime guards and error responses for prefunding, initialization, delegate use, account counts, duplicate mints, and rent top‑up handling.
  • Documentation

    • Updated guidance on prefunding rules, transfer padding/discriminators, compress-and-close validation, and rent/exemption examples.
  • Tests

    • Major test reorganization: expanded integration suites (creation, ATA, transfer, compress/close, SPL compatibility), updated baselines and inputs, and removed/added several test modules.
  • Chores

    • CI matrix/workflow added; public SDK/input sizes and rent-exemption constants adjusted.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 15, 2025

Walkthrough

Removes legacy compressed-token account tests and adds a modular ctoken test suite with shared helpers; forbids exactly 1‑epoch rent prefunding; introduces DuplicateMint and OneEpochPrefundingNotAllowed errors; migrates many ArrayVec usages to ArrayMap/tinyvec/fixed arrays; adjusts rent constants, discriminators, Transfer2/CToken layouts, SDK types, and CI/workspace deps.

Changes

Cohort / File(s) Summary
Prefunding validation & errors
programs/compressed-token/anchor/src/lib.rs, programs/compressed-token/program/src/create_token_account.rs, programs/compressed-token/program/src/create_associated_token_account.rs, programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
Add OneEpochPrefundingNotAllowed error and pre-validate/reject compressible rent_payment == 1; cast rent_payment when calling rent helpers; docs updated.
Duplicate‑mint & sum‑check
programs/compressed-token/program/src/transfer2/sum_check.rs, programs/compressed-token/program/src/transfer2/processor.rs, programs/compressed-token/program/docs/instructions/TRANSFER2.md, programs/compressed-token/program/tests/multi_sum_check.rs
Replace ArrayVec with ArrayMap, return mint_map from sum_check_multi_mint, add validate_mint_uniqueness and DuplicateMint error; tests added/updated.
Compress‑and‑close ownership & delegate rules
programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs, sdk-libs/token-client/src/instructions/transfer2.rs, programs/compressed-token/program/docs/instructions/TRANSFER2.md, program-tests/utils/src/assert_transfer2.rs, sdk-libs/token-client/src/actions/transfer2.rs
Reject compress-and-close when a delegate exists; factor compress_to_pubkey into owner/destination resolution; client and assertion paths updated to honor compress_to_pubkey.
CToken transfer layout & guards
programs/compressed-token/program/src/lib.rs, programs/compressed-token/program/src/ctoken_transfer.rs, sdk-libs/token-client/src/actions/ctoken_transfer.rs, programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
Adjust instruction discriminant offsets and parsing; enforce minimum account count guard; remove duplicate discriminator in client payloads; document padding.
Rent exemption constant & top‑up adjustments
program-libs/ctoken-types/src/constants.rs, programs/compressed-token/program/src/ctoken_transfer.rs, programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs, program-tests/utils/src/assert_ctoken_transfer.rs, program-libs/compressible/tests/{compression_info.rs,rent.rs}
Add COMPRESSIBLE_TOKEN_RENT_EXEMPTION constant; replace hardcoded rent-exemption values in calculations and tests; adjust top‑up assertions and test constants (260 bytes).
Initialize guard
programs/compressed-token/program/src/shared/initialize_ctoken_account.rs
Add pre-init guard rejecting already-initialized accounts (AlreadyInitialized) before initialization.
SDK/types: epoch width & Transfer2 output_queue
program-libs/ctoken-types/src/instructions/extensions/compressible.rs, sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs, sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs, sdk-libs/token-client/src/actions/create_compressible_token_account.rs, sdk-libs/compressed-token-sdk/src/instructions/transfer2/instruction.rs, program-libs/ctoken-types/src/instructions/transfer2/instruction_data.rs, sdk-libs/compressed-token-sdk/src/account2.rs
Change rent_payment / pre_pay_num_epochs from u64 → u8; add output_queue field to Transfer2Inputs and wire through SDK/client; remove per-account output_merkle_tree_index from CTokenAccount2 constructors.
Test suite restructure & shared helpers
program-tests/compressed-token-test/tests/ctoken.rs, program-tests/compressed-token-test/tests/ctoken/*, program-tests/compressed-token-test/tests/transfer2/*, program-tests/compressed-token-test/tests/ctoken/shared.rs
Delete legacy account.rs; add modular ctoken tests (create, create_ata, transfer, close, compress_and_close, functional, functional_ata, spl_instruction_compat) and a comprehensive shared helper module exposing AccountTestContext and helpers.
Removed legacy account tests
program-tests/compressed-token-test/tests/account.rs
Entire legacy test module deleted.
Assertions & helper updates
program-tests/utils/src/assert_create_token_account.rs, program-tests/utils/src/assert_close_token_account.rs, program-tests/utils/src/assert_ctoken_transfer.rs, program-tests/utils/src/assert_transfer2.rs, sdk-libs/program-test/src/utils/assert.rs
Use LightProgramTest, add idempotent ATA handling, nuanced payer/tx-fee logic, compress_to_pubkey-aware checks, refine top-up assertions, and exhaustive InstructionError/BanksClientError mapping in assert_rpc_error.
Tests: unwraps & error-code fallbacks
program-tests/registry-test/tests/compressible.rs, program-tests/system-cpi-test/tests/test.rs, program-tests/system-test/tests/test.rs, program-tests/compressed-token-test/tests/v1.rs
Replace many Result-propagating flows with unwraps in tests; add fallback assertions matching literal error code 21 for panic/verification cases.
CI workflow
.github/workflows/programs.yml
Add matrix-driven "programs" CI workflow with Redis service, concurrency group, sub-test iteration, flaky-test retry, and RUSTFLAGS treating warnings as errors.
Dev/test deps & workspace bump
program-tests/compressed-token-test/Cargo.toml, program-tests/registry-test/Cargo.toml, Cargo.toml, programs/compressed-token/program/Cargo.toml, program-libs/ctoken-types/Cargo.toml
Add dev/test deps (light-zero-copy, light-compressed-token-sdk, light-compressible, light-token-client, light-ctoken-types), add tinyvec & light-array-map workspace deps, and bump pinocchio-token-program git revision.
Hash cache & ArrayMap migrations
program-libs/ctoken-types/src/hash_cache.rs, programs/compressed-token/program/src/transfer2/processor.rs, programs/compressed-token/program/src/transfer2/sum_check.rs, tests...
Migrate ArrayVec-backed caches/maps to ArrayMap; change lookup/insert patterns; expose validate_mint_uniqueness; update callers/tests.
ArrayVec → tinyvec / fixed-array local changes
programs/compressed-token/program/src/extensions/mod.rs, programs/compressed-token/program/src/mint_action/*, programs/compressed-token/program/src/shared/*, tests...
Replace arrayvec::ArrayVec usages with tinyvec::ArrayVec or fixed arrays for seed/seed_inputs and local accumulators; adapt create_pda_account seed parameter.
Misc docs & constants
program-libs/compressible/docs/RENT.md, programs/compressed-token/program/docs/instructions/TRANSFER2.md, programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md, various CLAUDE.md/files
Update examples/account sizes (261→260), document CTOKEN_TRANSFER padding, TRANSFER2 notes and DuplicateMint; update discriminators in docs.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Program as Compressed Token Program

  rect rgba(230,245,255,0.6)
  note right of Program: Create / Init (compressible)
  Client->>Program: CreateTokenAccount{compressible_config.rent_payment = N}
  Program->>Program: if rent_payment == 1 -> log & Err(OneEpochPrefundingNotAllowed)
  alt rent_payment != 1
    Program->>Program: check already-initialized -> proceed init
    Program-->>Client: Ok
  end
  end
Loading
sequenceDiagram
  autonumber
  actor Client
  participant Program as Compressed Token Program
  participant Ledger as Token Account

  rect rgba(240,255,240,0.6)
  note right of Program: Compress-and-Close
  Client->>Program: Transfer2: CompressAndClose(source, ...)
  Program->>Ledger: Read source account
  alt source.delegate != None
    Program-->>Client: Err(CompressAndCloseDelegateNotAllowed)
  else
    Program->>Program: determine owner = compress_to_pubkey ? source_pubkey : owner_pubkey
    Program->>Program: perform compress & close -> outputs/destination handling
    Program-->>Client: Ok
  end
  end
Loading
sequenceDiagram
  autonumber
  actor SDK
  participant Program as Compressed Token Program

  rect rgba(255,245,230,0.6)
  note right of Program: CToken Transfer layout & parsing
  SDK->>SDK: build_instruction(data = [3u8 | padding? | amount_le])
  SDK-->>Program: invoke(instruction_data)
  Program->>Program: parse starting at byte 1 (expect >=3 accounts) else Err(NotEnoughAccountKeys)
  Program-->>SDK: Ok / logs
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

I nibbled bytes by lamport light, one epoch I hopped away,
I sniffed out duplicate mints and told the delegates “nay.”
Tests sprouted helpers, CI learned retries at night,
Seed arrays grew tidy, and errors now refuse one‑epoch slight.
Rabbit applause — green checks glow, I munch on code delight. 🥕🐇

Pre-merge checks and finishing touches

✅ 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 clearly summarizes the primary change of the pull request: adding validation to disallow compressible account funding for exactly one epoch and preventing rent_payment=1. It is concise, specific, and accurately reflects the adjustments to error codes, documentation, and test updates centered on this fix. Team members scanning history will understand the main intent without extra details.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jorrit/fix-pre-funding-compressible-account

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 15, 2025

Walkthrough

Introduces a new validation rejecting exactly 1-epoch prefunding for compressible accounts, adds a corresponding error code, updates documentation, and adjusts tests to use 2-epoch prefunding with updated epoch warps. Test code also switches many async error propagations to unwraps and removes a Result return from one test.

Changes

Cohort / File(s) Summary
Core program validation
programs/compressed-token/program/src/create_token_account.rs, programs/compressed-token/program/src/create_associated_token_account.rs
Add early check to reject rent_payment == 1 when using compressible config; return ErrorCode::OneEpochPrefundingNotAllowed with a log and short-circuit.
Error codes
programs/compressed-token/anchor/src/lib.rs
Add new enum variant OneEpochPrefundingNotAllowed to ErrorCode.
Docs
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
Document new preflight validation disallowing 1-epoch prefunding for compressible flows; add error mapping (6116) in relevant sections.
Program tests: epochs and control-flow tweaks
program-tests/compressed-token-test/tests/account.rs, program-tests/compressed-token-test/tests/transfer2/*.rs, program-tests/compressed-token-test/tests/compressible.rs
Change pre_pay_num_epochs from 1 to 2; adjust epoch advancement/warp targets and comments; replace many ? with .unwrap(); update one test signature to no longer return Result.
SDK tests and helpers
sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs, sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs, sdk-tests/sdk-token-test/tests/pda_ctoken.rs
Update pre_pay_num_epochs from 1 to 2 in test/setup inputs; no control-flow changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant P as Compressed Token Program
  participant V as Prefund Validator
  participant F as Account Creation Flow

  rect rgba(230,240,255,0.6)
  note right of C: Create (associated) token account with compressible config
  C->>P: Instruction (compressible_config, rent_payment)
  P->>V: Validate compressible_config
  V-->>P: rent_payment == 1 ?
  alt New check: exactly 1 epoch
    P-->>C: Error: OneEpochPrefundingNotAllowed
  else Allowed
    P->>F: Proceed with existing creation/compression logic
    F-->>C: Success (account created)
  end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

A hare with a stopwatch and ledger in paw,
Counts epochs: “Not one! Two’s the law.”
New checks hop in, with errors well-named,
Docs burrow deeper, tests re-aimed.
With unwraps aplenty and timelines true—
Thump goes the tail: we’re ready with two. 🥕🐇

Pre-merge checks and finishing touches

✅ 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 clearly summarizes the primary change—preventing one-epoch prefunding for compressible accounts. It is concise and specific, directly reflecting the added validation logic and associated error code. Therefore, it meets the clarity and relevance criteria.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jorrit/fix-pre-funding-compressible-account

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.

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: 0

🧹 Nitpick comments (2)
programs/compressed-token/program/src/create_associated_token_account.rs (1)

152-156: Early validation prevents footgun scenario.

The validation correctly rejects exactly 1 epoch prefunding before expensive operations. The error message is helpful and actionable.

Consider extracting validation to shared helper.

This validation logic is duplicated in create_token_account.rs (lines 159-163). Consider extracting to a shared function to maintain consistency and reduce duplication:

// In shared module
pub fn validate_rent_payment(rent_payment: u64) -> Result<(), ProgramError> {
    if rent_payment == 1 {
        msg!("Prefunding for exactly 1 epoch is not allowed. If the account is created near an epoch boundary, it could become immediately compressible. Use 0 or 2+ epochs.");
        return Err(anchor_compressed_token::ErrorCode::OneEpochPrefundingNotAllowed.into());
    }
    Ok(())
}
programs/compressed-token/program/src/create_token_account.rs (1)

159-163: Early validation prevents epoch boundary issues.

The validation correctly rejects exactly 1 epoch prefunding with a clear, actionable error message. The early return prevents unnecessary processing.

Note: This validation logic is duplicated from create_associated_token_account.rs (lines 152-156). The suggestion to extract to a shared helper applies here as well.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19842c7 and 61e7f94.

📒 Files selected for processing (11)
  • program-tests/compressed-token-test/tests/account.rs (6 hunks)
  • program-tests/compressed-token-test/tests/compressible.rs (27 hunks)
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs (1 hunks)
  • programs/compressed-token/anchor/src/lib.rs (1 hunks)
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (5 hunks)
  • programs/compressed-token/program/src/create_associated_token_account.rs (1 hunks)
  • programs/compressed-token/program/src/create_token_account.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs (1 hunks)
  • sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs (1 hunks)
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs}

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/docs/instructions/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
programs/compressed-token/program/docs/**/instructions/**/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Keep detailed instruction documentation files under the instructions/ directory; add additional instruction docs as needed

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
sdk-tests/sdk-token-test/**/tests/**/*.rs

📄 CodeRabbit inference engine (sdk-tests/sdk-token-test/CLAUDE.md)

Every test should only contain functional integration tests

Files:

  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
🧠 Learnings (24)
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/account.rs
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{claim/**,withdraw_funding_pool.rs} : Enforce Not Inactive config validation for Claim and Withdraw Funding Pool instructions

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/{CREATE_TOKEN_ACCOUNT,MINT_ACTION,TRANSFER2,CLAIM,CLOSE_TOKEN_ACCOUNT,DECOMPRESSED_TRANSFER,WITHDRAW_FUNDING_POOL}.md : Every instruction description must include sections: path, description, instruction_data, Accounts, instruction logic and checks, Errors

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/ACCOUNTS.md : Accounts documentation must include: description, discriminator, state layout, serialization example, hashing (only for compressed accounts), derivation (only for PDAs), and associated instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/instructions/*.md : Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/**/ACCOUNTS.md : Provide complete account layouts and data structures in ACCOUNTS.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/DECOMPRESSED_TRANSFER.md : Document SPL-compatible transfers between decompressed accounts in instructions/DECOMPRESSED_TRANSFER.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/error.rs : Provide ProgramError conversions compatible with Anchor, Pinocchio, and Solana error types

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/error.rs : Maintain stable mapping of AccountError to ProgramError, including Pinocchio code mapping (1–11), in error.rs

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Return errors as ProgramError::Custom(error_code as u32) on-chain

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : Return AccountError variants (codes 12006–12021) and rely on automatic ProgramError conversions; avoid returning raw ProgramError directly

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent curve algorithms via rent_curve_per_epoch

Applied to files:

  • program-tests/compressed-token-test/tests/account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • program-tests/compressed-token-test/tests/account.rs
  • program-tests/compressed-token-test/tests/compressible.rs
🧬 Code graph analysis (1)
program-tests/compressed-token-test/tests/compressible.rs (2)
program-tests/utils/src/spl.rs (1)
  • create_mint_helper (260-263)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-56)
🪛 LanguageTool
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

[grammar] ~76-~76: There might be a mistake here.
Context: ...is not exactly 1 epoch - Check: compressible_config.rent_payment != 1 - Error: `ErrorCode::OneEpochPrefundingNot...

(QB_NEW_EN)


[grammar] ~180-~180: There might be a mistake here.
Context: ...epoch (see create ctoken account errors)

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.18.1)
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

112-112: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


180-180: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: stateless-js-v1
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: stateless-js-v2
  • GitHub Check: cli-v2
  • GitHub Check: cli-v1
  • GitHub Check: lint
  • GitHub Check: Forester e2e test
🔇 Additional comments (15)
programs/compressed-token/anchor/src/lib.rs (1)

415-416: LGTM! Clear error message for prefunding validation.

The new error variant is well-documented with a clear message explaining the epoch boundary timing risk and providing actionable guidance (use 0 or 2+ epochs).

sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs (1)

35-35: LGTM! Test updated for new validation.

Correctly updates pre_pay_num_epochs from 1 to 2 to align with the new validation that disallows exactly 1 epoch prefunding.

program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs (1)

102-102: LGTM! Test setup aligned with new validation.

sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs (1)

40-40: LGTM! Test input updated correctly.

sdk-tests/sdk-token-test/tests/pda_ctoken.rs (1)

216-216: LGTM! Test setup updated appropriately.

program-tests/compressed-token-test/tests/transfer2/compress_failing.rs (1)

98-98: LGTM! Test setup updated consistently.

program-tests/compressed-token-test/tests/compressible.rs (4)

71-71: LGTM! Acceptable test pattern for explicit success-path handling.

The conversion from ? error propagation to .unwrap() is appropriate for tests, as it provides clear panic messages on failure while simplifying the test logic.

Also applies to: 84-86, 111-112, 115-117, 123-125


143-143: LGTM! Consistent with the unwrap() pattern.

The removal of the Result return type aligns with the shift from error propagation to panicking on failure, which is acceptable in test code.


154-154: LGTM! Correctly avoids 1-epoch prefunding.

The loop range shift from 1..=10 to 2..=11 ensures all test accounts comply with the new validation rule that forbids exactly 1 epoch of rent prefunding, while maintaining the same test coverage of 10 accounts with varying prepaid epochs.


443-443: LGTM! Complies with new 1-epoch prefunding restriction.

The update of pre_pay_num_epochs from 1 to 2 across all test scenarios correctly implements the new validation rule that forbids exactly 1 epoch of rent prefunding, ensuring tests reflect the intended behavior.

Also applies to: 565-565, 600-600, 714-714

program-tests/compressed-token-test/tests/account.rs (2)

403-403: LGTM! Enforces minimum 2-epoch prefunding.

The update from 1 to 2 prepaid epochs correctly implements the new validation rule that prevents exactly 1 epoch of rent prefunding, ensuring these test cases comply with the updated constraints.

Also applies to: 574-574


827-827: LGTM! Clear test progression with updated epoch accounting.

The changes correctly:

  1. Update pre_pay_num_epochs from 1 to 2 to comply with the new validation rule
  2. Adjust comments to reflect the new total of 3 epochs (2 prepaid + 1 topped up)
  3. Update epoch progression expectations to match the new timing (epoch 3 instead of previous values)

The updated comments enhance test readability by clearly documenting the rent funding timeline.

Also applies to: 845-883

programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (3)

39-43: LGTM! Clear rationale for the validation rule.

The documentation effectively explains:

  1. The forbidden value (rent_payment = 1)
  2. Allowed values (0 or 2+ epochs)
  3. The rationale: preventing accounts from becoming immediately compressible due to epoch boundary timing

This helps developers understand why the restriction exists and how to comply with it.

As per coding guidelines


75-78: LGTM! Well-positioned early validation.

The addition of step 3.0 as an early validation check is appropriate:

  • Fails fast before resource allocation
  • Clear check condition and error code
  • Explains the purpose of preventing epoch boundary timing issues

As per coding guidelines


112-112: LGTM! Consistent error documentation across instruction types.

The error documentation:

  1. Includes the error code (6116) and name (OneEpochPrefundingNotAllowed)
  2. Explains the cause (rent_payment is exactly 1 epoch)
  3. Is consistently documented for both create_token_account and create_associated_token_account
  4. Follows the required schema of including error codes with descriptions

As per coding guidelines

Also applies to: 162-165, 180-180

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)
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (1)

18-18: Fix instruction path (missing /program/)

Current path points to programs/compressed-token/src/create_token_account.rs; repository uses programs/compressed-token/program/src/create_token_account.rs.

Apply:

-  **path:** programs/compressed-token/src/create_token_account.rs
+  **path:** programs/compressed-token/program/src/create_token_account.rs

As per coding guidelines

program-tests/compressed-token-test/tests/account.rs (1)

291-298: Fix assertion: hardcoded rent delta and mismatched message

Test still assumes 1-epoch constants and inconsistent numbers. Compute rent via RentConfig to match num_prepaid_epochs.

Apply:

-    let tx_fee = 10_000; // Standard transaction fee
-    assert_eq!(
-        payer_balance_before - payer_balance_after,
-        11_776 + tx_fee,
-        "Payer should have paid exactly 14,830 lamports for additional rent (1 epoch) plus {} tx fee",
-        tx_fee
-    );
+    let rent = RentConfig::default()
+        .get_rent_with_compression_cost(COMPRESSIBLE_TOKEN_ACCOUNT_SIZE, num_prepaid_epochs);
+    let tx_fee = 10_000; // Standard transaction fee
+    assert_eq!(
+        payer_balance_before - payer_balance_after,
+        rent + tx_fee,
+        "Payer should have paid {} lamports for additional rent ({} epochs) plus {} tx fee",
+        rent,
+        num_prepaid_epochs,
+        tx_fee
+    );
🧹 Nitpick comments (9)
sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs (1)

35-35: Consider adding a comment explaining the epoch count.

The hardcoded value of 2 epochs is now required due to the new validation that rejects exactly 1 epoch. A brief inline comment would help future maintainers understand this constraint.

-        pre_pay_num_epochs: 2,    // Pre-pay for 2 epochs
+        pre_pay_num_epochs: 2,    // Pre-pay for 2 epochs (1 epoch is disallowed due to epoch boundary timing risk)
programs/compressed-token/program/src/create_associated_token_account.rs (1)

152-156: Consider extracting shared validation logic.

This validation is duplicated in create_token_account.rs (lines 159-163). Consider extracting to a shared helper function to maintain consistency and reduce duplication.

Example location: src/shared/mod.rs or a new src/shared/rent_validation.rs:

pub fn validate_rent_payment(rent_payment: u16) -> Result<(), ProgramError> {
    if rent_payment == 1 {
        msg!("Prefunding for exactly 1 epoch is not allowed. If the account is created near an epoch boundary, it could become immediately compressible. Use 0 or 2+ epochs.");
        return Err(anchor_compressed_token::ErrorCode::OneEpochPrefundingNotAllowed.into());
    }
    Ok(())
}
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (4)

112-112: Fix list indentation (markdownlint MD007)

Unordered list item should be top-level aligned like other Errors.

-  - `ErrorCode::OneEpochPrefundingNotAllowed` (error code: 6116) - rent_payment is exactly 1 epoch, which is forbidden due to epoch boundary timing edge case
+- `ErrorCode::OneEpochPrefundingNotAllowed` (error code: 6116) - rent_payment is exactly 1 epoch, which is forbidden due to epoch boundary timing edge case

As per coding guidelines


10-10: Typo: “instruciton” → “instruction”

Minor docs nit.

-    - **instruciton logic and checks**
+    - **instruction logic and checks**

As per coding guidelines


162-164: ATA docs: validation noted; fix list indentation

  • Validation lines look good and mirror Create flow.
  • Also fix MD007 indentation for the Errors bullet like above.
-  - `ErrorCode::OneEpochPrefundingNotAllowed` (error code: 6116) - rent_payment is exactly 1 epoch (see create ctoken account errors)
+- `ErrorCode::OneEpochPrefundingNotAllowed` (error code: 6116) - rent_payment is exactly 1 epoch (see create ctoken account errors)

As per coding guidelines

Also applies to: 180-180


64-68: Unify account naming: rent_payer_pda vs. fee_payer_pda

Docs mix “rent_payer_pda” (Create) and “fee_payer_pda” (ATA) for the same role. Pick one term and define it once to avoid confusion.

As per coding guidelines

Also applies to: 148-153

program-tests/compressed-token-test/tests/account.rs (1)

472-477: Minor: Message refers to “Pool PDA” while using a custom rent payer

Since rent_sponsor is the custom payer, tweak the message to avoid “Pool PDA” phrasing.

program-tests/compressed-token-test/tests/compressible.rs (2)

150-153: Update comment to match new range (2..=11)

Loop now creates 2..=11 prepaid epochs; fix the stale “1 to 10” comment.

-// Create 10 token accounts with varying prepaid epochs (1 to 10)
+// Create 10 token accounts with varying prepaid epochs (2 to 11)
-for i in 2..=11 {
+for i in 2..=11 {

Also applies to: 154-156


142-147: Add a negative test for 1‑epoch prefunding

Please add a test that attempts num_prepaid_epochs = 1 and asserts ErrorCode::OneEpochPrefundingNotAllowed (6116). This locks in the new rule.

Example:

#[tokio::test]
async fn test_reject_one_epoch_prefunding() {
    let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(false, None)).await.unwrap();
    let payer = rpc.get_payer().insecure_clone();
    let owner = Keypair::new();
    let mint = create_mint_helper(&mut rpc, &payer).await;

    let result = create_compressible_token_account(
        &mut rpc,
        CreateCompressibleTokenAccountInputs {
            owner: owner.pubkey(),
            mint,
            num_prepaid_epochs: 1,
            payer: &payer,
            token_account_keypair: None,
            lamports_per_write: Some(100),
            token_account_version: light_ctoken_types::state::TokenDataVersion::ShaFlat,
        },
    )
    .await;

    // Expect custom error 6116 on instruction 0
    assert_rpc_error(result, 0, 6116).unwrap();
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19842c7 and 61e7f94.

📒 Files selected for processing (11)
  • program-tests/compressed-token-test/tests/account.rs (6 hunks)
  • program-tests/compressed-token-test/tests/compressible.rs (27 hunks)
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs (1 hunks)
  • programs/compressed-token/anchor/src/lib.rs (1 hunks)
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (5 hunks)
  • programs/compressed-token/program/src/create_associated_token_account.rs (1 hunks)
  • programs/compressed-token/program/src/create_token_account.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs (1 hunks)
  • sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs (1 hunks)
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs}

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/docs/instructions/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
programs/compressed-token/program/docs/**/instructions/**/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Keep detailed instruction documentation files under the instructions/ directory; add additional instruction docs as needed

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
sdk-tests/sdk-token-test/**/tests/**/*.rs

📄 CodeRabbit inference engine (sdk-tests/sdk-token-test/CLAUDE.md)

Every test should only contain functional integration tests

Files:

  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
🧠 Learnings (24)
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • program-tests/compressed-token-test/tests/account.rs
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/error.rs : Maintain stable mapping of AccountError to ProgramError, including Pinocchio code mapping (1–11), in error.rs

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/error.rs : Provide ProgramError conversions compatible with Anchor, Pinocchio, and Solana error types

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Return errors as ProgramError::Custom(error_code as u32) on-chain

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : Return AccountError variants (codes 12006–12021) and rely on automatic ProgramError conversions; avoid returning raw ProgramError directly

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/{CREATE_TOKEN_ACCOUNT,MINT_ACTION,TRANSFER2,CLAIM,CLOSE_TOKEN_ACCOUNT,DECOMPRESSED_TRANSFER,WITHDRAW_FUNDING_POOL}.md : Every instruction description must include sections: path, description, instruction_data, Accounts, instruction logic and checks, Errors

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/ACCOUNTS.md : Accounts documentation must include: description, discriminator, state layout, serialization example, hashing (only for compressed accounts), derivation (only for PDAs), and associated instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/instructions/*.md : Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/**/ACCOUNTS.md : Provide complete account layouts and data structures in ACCOUNTS.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/DECOMPRESSED_TRANSFER.md : Document SPL-compatible transfers between decompressed accounts in instructions/DECOMPRESSED_TRANSFER.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent curve algorithms via rent_curve_per_epoch

Applied to files:

  • program-tests/compressed-token-test/tests/account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • program-tests/compressed-token-test/tests/account.rs
  • program-tests/compressed-token-test/tests/compressible.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : Validate account type with 8-byte discriminators using check_discriminator before deserialization

Applied to files:

  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs
🧬 Code graph analysis (1)
program-tests/compressed-token-test/tests/compressible.rs (2)
program-tests/utils/src/spl.rs (1)
  • create_mint_helper (260-263)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-56)
🪛 LanguageTool
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

[grammar] ~76-~76: There might be a mistake here.
Context: ...is not exactly 1 epoch - Check: compressible_config.rent_payment != 1 - Error: `ErrorCode::OneEpochPrefundingNot...

(QB_NEW_EN)


[grammar] ~180-~180: There might be a mistake here.
Context: ...epoch (see create ctoken account errors)

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.18.1)
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

112-112: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


180-180: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: stateless-js-v1
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: stateless-js-v2
  • GitHub Check: cli-v2
  • GitHub Check: cli-v1
  • GitHub Check: lint
  • GitHub Check: Forester e2e test
🔇 Additional comments (8)
programs/compressed-token/program/src/create_associated_token_account.rs (1)

152-156: LGTM! Well-placed footgun prevention.

The early validation correctly prevents exactly 1-epoch prefunding before account creation. The error message clearly explains the risk and provides alternative options.

As per coding guidelines (based on learnings).

programs/compressed-token/anchor/src/lib.rs (1)

415-416: LGTM! Clear error code definition.

The error code is well-defined with a descriptive message that explains both the constraint and the rationale. The conversion to ProgramError::Custom follows the established pattern.

As per coding guidelines (based on learnings).

programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (3)

39-43: Good: Clear rent_payment policy documented

Explicitly forbidding 1 epoch and allowing 0 or 2+ is clear and matches the new validation intent.

As per coding guidelines


75-79: Good: Validation and error surfaced in logic

The check and error mapping are documented in the right place. Please also verify the numeric error code matches the program (6116).

Run a quick grep to confirm the compiled/custom error code value for OneEpochPrefundingNotAllowed matches 6116 in programs/compressed-token/anchor/src/lib.rs and any anchor-generated IDL. As per coding guidelines


16-18: Verify discriminators

Please confirm discriminator values (Create: 18; ATA: 103/101) reflect current program enum/dispatch.

As per coding guidelines

Also applies to: 117-119

program-tests/compressed-token-test/tests/account.rs (2)

403-403: LGTM: Bumped pre_pay_num_epochs to 2

Matches the new “no 1-epoch” rule across tests.

Also applies to: 574-574, 827-827


845-858: LGTM: Epoch warp updates align with 2+1 top-up timeline

Advancing to epochs 1 and 3 matches the 2-prepaid + 1 top-up flow.

Also applies to: 880-884

program-tests/compressed-token-test/tests/compressible.rs (1)

84-86: Tests: unwraps are fine here

Switching to unwrap() for success paths simplifies tests and is acceptable.

Also applies to: 198-201, 412-415, 501-503, 536-539, 619-622, 662-664, 769-771, 71-71, 331-331, 365-365, 399-399

Comment on lines +159 to +163
// Validate that rent_payment is not exactly 1 epoch (footgun prevention)
if compressible_config.rent_payment == 1 {
msg!("Prefunding for exactly 1 epoch is not allowed. If the account is created near an epoch boundary, it could become immediately compressible. Use 0 or 2+ epochs.");
return Err(anchor_compressed_token::ErrorCode::OneEpochPrefundingNotAllowed.into());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

❓ Verification inconclusive

LGTM! Consistent validation with ATA creation.

The validation correctly prevents exactly 1-epoch prefunding and mirrors the logic in create_associated_token_account.rs. The error message is clear and actionable.

Verify that test coverage exists for the new error path. From the provided files, I don't see explicit tests that attempt to create a compressible account with pre_pay_num_epochs: 1 and assert the OneEpochPrefundingNotAllowed error.

As per coding guidelines (based on learnings).


🏁 Script executed:

#!/bin/bash
# Search for tests that explicitly validate the OneEpochPrefundingNotAllowed error
rg -n -C3 'OneEpochPrefundingNotAllowed|6116' --type=rs -g '**/*test*.rs'

Length of output: 26


🏁 Script executed:

#!/bin/bash
# Search for tests referencing the OneEpochPrefundingNotAllowed error code or its numeric value 6116
rg -n -C3 'OneEpochPrefundingNotAllowed|6116' -g '*test*.rs' -g 'tests/*.rs'

Length of output: 0


Add missing tests for OneEpochPrefundingNotAllowed error

Add unit tests for both create_token_account and create_associated_token_account that set pre_pay_num_epochs (or rent_payment) to 1 and assert the OneEpochPrefundingNotAllowed error is returned.

🤖 Prompt for AI Agents
In programs/compressed-token/program/src/create_token_account.rs around lines
159-163, the code returns OneEpochPrefundingNotAllowed when rent_payment == 1
but there are no unit tests covering this; add two unit tests: one for
create_token_account and one for create_associated_token_account that set
pre_pay_num_epochs (or rent_payment) to 1 and assert the program returns
anchor_compressed_token::ErrorCode::OneEpochPrefundingNotAllowed. Each test
should build the minimum required accounts, call the respective instruction with
rent_payment/pre_pay_num_epochs = 1, capture the error result, and assert the
error matches OneEpochPrefundingNotAllowed (with proper conversion to Anchor
error type).

Comment on lines +34 to +119
name: programs
if: github.event.pull_request.draft == false
runs-on: warp-ubuntu-latest-x64-4x
timeout-minutes: 90

services:
redis:
image: redis:8.0.1
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

env:
REDIS_URL: redis://localhost:6379

strategy:
matrix:
include:
- program: account-compression-and-registry
sub-tests: '["cargo-test-sbf -p account-compression-test", "cargo-test-sbf -p registry-test"]'
- program: light-system-program-address
sub-tests: '["cargo-test-sbf -p system-test -- test_with_address"]'
- program: light-system-program-compression
sub-tests: '["cargo-test-sbf -p system-test -- test_with_compression", "cargo-test-sbf -p system-test --test test_re_init_cpi_account"]'
- program: compressed-token-and-e2e
sub-tests: '["cargo-test-sbf -p compressed-token-test -- --skip test_transfer_with_photon_and_batched_tree", "cargo-test-sbf -p e2e-test"]'
- program: compressed-token-batched-tree
sub-tests: '["cargo-test-sbf -p compressed-token-test -- test_transfer_with_photon_and_batched_tree"]'
- program: system-cpi-test
sub-tests:
'["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-program-pinocchio",
"cargo-test-sbf -p system-cpi-v2-test -- --skip functional_ --skip event::parse", "cargo-test-sbf -p system-cpi-v2-test -- event::parse"
]'
- program: system-cpi-test-v2-functional-read-only
sub-tests: '["cargo-test-sbf -p system-cpi-v2-test -- functional_read_only"]'
- program: system-cpi-test-v2-functional-account-infos
sub-tests: '["cargo-test-sbf -p system-cpi-v2-test -- functional_account_infos"]'
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Setup and build
uses: ./.github/actions/setup-and-build
with:
skip-components: "redis,disk-cleanup"
cache-suffix: "system-programs"

- name: Build CLI
run: |
npx nx build @lightprotocol/zk-compression-cli

- name: ${{ matrix.program }}
run: |

IFS=',' read -r -a sub_tests <<< "${{ join(fromJSON(matrix['sub-tests']), ', ') }}"
for subtest in "${sub_tests[@]}"
do
echo "$subtest"

# Retry logic for flaky batched-tree test
if [[ "$subtest" == *"test_transfer_with_photon_and_batched_tree"* ]]; then
echo "Running flaky test with retry logic (max 3 attempts)..."
attempt=1
max_attempts=3
until RUSTFLAGS="-D warnings" eval "$subtest"; do
attempt=$((attempt + 1))
if [ $attempt -gt $max_attempts ]; then
echo "Test failed after $max_attempts attempts"
exit 1
fi
echo "Attempt $attempt/$max_attempts failed, retrying..."
sleep 5
done
echo "Test passed on attempt $attempt"
else
RUSTFLAGS="-D warnings" eval "$subtest"
if [ "$subtest" == "cargo-test-sbf -p e2e-test" ]; then
pnpm --filter @lightprotocol/programs run build-compressed-token-small
RUSTFLAGS="-D warnings" eval "$subtest -- --test test_10_all"
fi
fi
done

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 5 months ago

To fix this problem, explicitly set the permissions key for the workflow. Since none of the workflow steps write to the repo or interact with issues or PRs, the safest minimum is contents: read. This should be added at the root of the workflow YAML (before jobs:), to apply to all jobs unless overridden.
You should add:

permissions:
  contents: read

directly after the name: programs key (line 27).

Suggested changeset 1
.github/workflows/programs.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/programs.yml b/.github/workflows/programs.yml
--- a/.github/workflows/programs.yml
+++ b/.github/workflows/programs.yml
@@ -25,6 +25,9 @@
 
 name: programs
 
+permissions:
+  contents: read
+
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
EOF
@@ -25,6 +25,9 @@

name: programs

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Copilot is powered by AI and may make mistakes. Always verify output.
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: 11

Caution

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

⚠️ Outside diff range comments (1)
program-tests/utils/src/assert_create_token_account.rs (1)

75-116: Idempotent mode check happens too late; skip deep equality before it

You assert full CToken equality (Line 110) and lamports (Lines 57-74) before detecting idempotent mode (Lines 112-116). If the account already existed, fields like last_claimed_slot or prepaid layout may differ, causing false failures. Guard and early-return before deep checks.

Apply this diff to insert an early idempotent branch and remove the late one:

@@
-            // Calculate expected lamports balance
-            let rent_exemption = rpc
-                .get_minimum_balance_for_rent_exemption(COMPRESSIBLE_TOKEN_ACCOUNT_SIZE as usize)
-                .await
-                .expect("Failed to get rent exemption");
-
-            let rent_with_compression = RentConfig::default().get_rent_with_compression_cost(
-                COMPRESSIBLE_TOKEN_ACCOUNT_SIZE,
-                compressible_info.num_prepaid_epochs,
-            );
-            let expected_lamports = rent_exemption + rent_with_compression;
-
-            assert_eq!(
-                account_info.lamports, expected_lamports,
-                "Account should have rent-exempt balance ({}) plus prepaid rent with compression cost ({}) = {} lamports, but has {}",
-                rent_exemption, rent_with_compression, expected_lamports, account_info.lamports
-            );
+            // Check if account existed before transaction (for idempotent mode)
+            let account_existed_before = rpc
+                .get_pre_transaction_account(&token_account_pubkey)
+                .is_some();
+
+            // Transaction fee: 5000 lamports per signature
+            // For ATA: 1 signer (payer only), else: 2 signers (token_account_keypair + payer)
+            let tx_fee = if is_ata { 5_000 } else { 10_000 };
+
+            // Assert payer and rent sponsor balance changes
+            let payer_balance_before = rpc
+                .get_pre_transaction_account(&compressible_info.payer)
+                .expect("Payer should exist in pre-transaction context")
+                .lamports;
+            let payer_balance_after = rpc
+                .get_account(compressible_info.payer)
+                .await
+                .expect("Failed to get payer account")
+                .expect("Payer should exist")
+                .lamports;
+
+            if account_existed_before {
+                // In idempotent mode, account already existed, so only tx fee is paid
+                assert_eq!(
+                    payer_balance_before - payer_balance_after,
+                    tx_fee,
+                    "In idempotent mode (account already existed), payer should only pay tx fee ({} lamports), but paid {}",
+                    tx_fee,
+                    payer_balance_before - payer_balance_after
+                );
+                return;
+            }
+
+            // Calculate expected lamports balance (non-idempotent path)
+            let rent_exemption = rpc
+                .get_minimum_balance_for_rent_exemption(COMPRESSIBLE_TOKEN_ACCOUNT_SIZE as usize)
+                .await
+                .expect("Failed to get rent exemption");
+            let rent_with_compression = RentConfig::default().get_rent_with_compression_cost(
+                COMPRESSIBLE_TOKEN_ACCOUNT_SIZE,
+                compressible_info.num_prepaid_epochs,
+            );
+            let expected_lamports = rent_exemption + rent_with_compression;
+            assert_eq!(
+                account_info.lamports, expected_lamports,
+                "Account should have rent-exempt balance ({}) plus prepaid rent with compression cost ({}) = {} lamports, but has {}",
+                rent_exemption, rent_with_compression, expected_lamports, account_info.lamports
+            );
@@
-            assert_eq!(actual_token_account, expected_token_account);
-
-            // Check if account existed before transaction (for idempotent mode)
-            let account_existed_before = rpc
-                .get_pre_transaction_account(&token_account_pubkey)
-                .is_some();
-
-            // Assert payer and rent sponsor balance changes
-            let payer_balance_before = rpc
-                .get_pre_transaction_account(&compressible_info.payer)
-                .expect("Payer should exist in pre-transaction context")
-                .lamports;
-            let payer_balance_after = rpc
-                .get_account(compressible_info.payer)
-                .await
-                .expect("Failed to get payer account")
-                .expect("Payer should exist")
-                .lamports;
-            let rent_sponsor_balance_before = rpc
-                .get_pre_transaction_account(&compressible_info.rent_sponsor)
-                .expect("Rent sponsor should exist in pre-transaction context")
-                .lamports;
-            let rent_sponsor_balance_after = rpc
-                .get_account(compressible_info.rent_sponsor)
-                .await
-                .expect("Failed to get rent sponsor account")
-                .expect("Rent sponsor should exist")
-                .lamports;
-            // Transaction fee: 5000 lamports per signature
-            // For ATA: 1 signer (payer only) = 5,000 lamports
-            // For regular token account: 2 signers (token_account_keypair + payer) = 10,000 lamports
-            let tx_fee = if is_ata { 5_000 } else { 10_000 };
+            assert_eq!(actual_token_account, expected_token_account);
+
+            // Balances (non-idempotent path)
+            let rent_sponsor_balance_before = rpc
+                .get_pre_transaction_account(&compressible_info.rent_sponsor)
+                .expect("Rent sponsor should exist in pre-transaction context")
+                .lamports;
+            let rent_sponsor_balance_after = rpc
+                .get_account(compressible_info.rent_sponsor)
+                .await
+                .expect("Failed to get rent sponsor account")
+                .expect("Rent sponsor should exist")
+                .lamports;
@@
-            // If account existed before (idempotent mode), only tx fee is charged
-            if account_existed_before {
-                // In idempotent mode, account already existed, so only tx fee is paid
-                assert_eq!(
-                    payer_balance_before - payer_balance_after,
-                    tx_fee,
-                    "In idempotent mode (account already existed), payer should only pay tx fee ({} lamports), but paid {}",
-                    tx_fee,
-                    payer_balance_before - payer_balance_after
-                );
-                return;
-            }
+            // Non-idempotent path continues…
♻️ Duplicate comments (2)
programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs (1)

130-130: Extract magic number into a shared constant.

This is the same hardcoded value 2700480 that appears in ctoken_transfer.rs:81 and assert_ctoken_transfer.rs:109. Consolidate this into a shared constant to improve maintainability.

See the comment on programs/compressed-token/program/src/ctoken_transfer.rs:81 for the suggested refactor.

program-tests/utils/src/assert_ctoken_transfer.rs (1)

109-109: Extract magic number into a shared constant.

This hardcoded value 2700480 is duplicated across ctoken_transfer.rs:81, compress_or_decompress_ctokens.rs:130, and here. Consolidate into a shared constant.

See the comment on programs/compressed-token/program/src/ctoken_transfer.rs:81 for the suggested refactor.

🧹 Nitpick comments (17)
sdk-libs/program-test/src/utils/assert.rs (1)

89-131: Duplicate mapping logic; extract and reuse a single helper

The BanksClientError path repeats the same large match. Use a shared helper (see above) for both branches to reduce drift and maintenance.

.github/workflows/programs.yml (3)

35-37: Guard skips pushes; allow push runs too

On push events, github.event.pull_request is null, so the job always skips. Make the guard PR-only or allow pushes:

-    if: github.event.pull_request.draft == false
+    if: github.event_name != 'pull_request' || github.event.pull_request.draft == false

26-31: Add least-privilege GITHUB_TOKEN permissions

Set explicit permissions as recommended.

 name: programs
+
+permissions:
+  contents: read

41-49: Pin Redis Docker image to a digest
redis:8.0.1 exists, but pinning to its digest ensures immutable, reproducible builds.

program-tests/compressed-token-test/Cargo.toml (1)

52-52: Scope features to what tests actually need

If “mut” or “derive” isn’t used in this crate’s tests, drop it to speed builds.

programs/compressed-token/program/docs/instructions/TRANSFER2.md (2)

5-14: Avoid line-number navigation; use anchors only

Line numbers rot quickly. Replace “(line …)” with in-doc anchors.


289-314: Stabilize error references

Numeric codes for Solana built-ins can drift across versions. Prefer symbolic names (e.g., ProgramError::ArithmeticOverflow) or note the Solana version these map to.

As per coding guidelines

program-tests/utils/src/assert_close_token_account.rs (1)

155-159: Consider extracting transaction fee into a test constant.

The hardcoded tx_fee = 10_000 value is used throughout the assertions. While the comment explains the calculation (5000 lamports per signature × 2 signers), consider extracting this into a named constant for clarity and reusability across test utilities.

// At module level or in a shared test constants module
const TX_FEE_TWO_SIGNERS: u64 = 10_000; // 5000 lamports per signature * 2 signers

Then use:

-    // Transaction fee: 5000 lamports per signature * 2 signers = 10,000 lamports
-    let tx_fee = 10_000;
+    // Transaction fee: 5000 lamports per signature * 2 signers
+    let tx_fee = TX_FEE_TWO_SIGNERS;
program-tests/compressed-token-test/tests/ctoken/close.rs (1)

105-107: Replace magic error numbers with named constants and fix mismatched comments

Tests use raw integers (e.g., 75, 4, 11, 74, 76) while comments reference 607x variants. This is brittle and confusing. Centralize with named constants (or derive from program errors) and keep comments aligned with the actual assertion semantics.

Example at Lines 165–216 and 272–323: comments say 6074/6076 but assertions pass 74/76. Unify by:

  • Using a helper to assert by error variant, or
  • Defining constants that reflect your assert mapping (e.g., ANCHOR_BASE + variant), or
  • Referencing the SDK/util’s exported mapping if available.

This avoids silent drift when codes change and improves readability.

Also applies to: 118-119, 138-139, 160-161, 213-214, 267-268, 320-321

program-tests/compressed-token-test/tests/ctoken/functional_ata.rs (1)

177-181: Assert specific error code instead of just is_err()

Make the failure deterministic by asserting the expected error code (e.g., IllegalOwner or the mapped InstructionError) using your assert helper, not just is_err().

Example:

-    assert!(
-        result.is_err(),
-        "Non-idempotent ATA creation should fail when account already exists"
-    );
+    light_program_test::utils::assert::assert_rpc_error(result, 0, /* expected */ 29).unwrap();
program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1)

218-219: Replace magic error numbers with named constants or helper mapping

Use named constants (or a single source of truth from the program/SDK) for error codes instead of raw integers (101, 29, 1, 2, 21/19, 20001, 20000). This makes tests resilient to code shifts and easier to read. If your assert helper supports variant-based matching, prefer that.

Also applies to: 255-256, 297-299, 363-365, 431-434, 473-474, 509-510

program-tests/utils/src/assert_create_token_account.rs (2)

95-105: Avoid hard-coding config_account_version = 1 in expected extension

Config version can change across environments. Either (a) fetch and assert against the actual extension’s config_account_version, or (b) compare fields selectively instead of full struct equality to reduce brittleness.


142-146: Hard-coded fee (5_000/signature) risks brittleness

Prefer deriving the fee from the test harness (e.g., a helper or rpc/context-provided constant) to avoid coupling to a magic number.

program-tests/compressed-token-test/tests/ctoken/shared.rs (4)

214-268: Avoid manual discriminator (18) when initializing non-compressible accounts

Building the instruction by hand with a magic discriminator is fragile. Prefer the SDK helper (create_token_account) or a typed constructor from light_ctoken_types to construct the instruction and required accounts.


570-576: Make warp_to_slot relative to current slot

Using absolute SLOTS_PER_EPOCH * epochs can move time backwards or not far enough depending on current slot. Derive from current slot.

-        context
-            .rpc
-            .warp_to_slot((SLOTS_PER_EPOCH * epochs) + 1)
-            .unwrap();
+        let current = context.rpc.get_slot().await.unwrap_or(0);
+        context
+            .rpc
+            .warp_to_slot(current + (SLOTS_PER_EPOCH * epochs))
+            .unwrap();

680-710: Optional: compute is_compressible instead of hard-coding true

For negative-path tests, deriving is_compressible from the account avoids false positives if called with a non-compressible account.


784-787: Compute current_epoch dynamically

Avoid hard-coding 0; derive from slot for correctness across runs.

-    let current_epoch = 0;
+    let current_epoch = context.rpc.get_slot().await.unwrap_or(0) / SLOTS_PER_EPOCH;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61e7f94 and c911c0d.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • .github/workflows/programs.yml (1 hunks)
  • Cargo.toml (1 hunks)
  • program-libs/compressible/tests/compression_info.rs (1 hunks)
  • program-libs/compressible/tests/rent.rs (1 hunks)
  • program-tests/compressed-token-test/Cargo.toml (1 hunks)
  • program-tests/compressed-token-test/tests/account.rs (0 hunks)
  • program-tests/compressed-token-test/tests/ctoken.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/close.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/functional.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/functional_ata.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/shared.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/mod.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs (1 hunks)
  • program-tests/registry-test/Cargo.toml (1 hunks)
  • program-tests/registry-test/tests/compressible.rs (28 hunks)
  • program-tests/utils/src/assert_close_token_account.rs (5 hunks)
  • program-tests/utils/src/assert_create_token_account.rs (4 hunks)
  • program-tests/utils/src/assert_ctoken_transfer.rs (1 hunks)
  • program-tests/utils/src/assert_transfer2.rs (2 hunks)
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md (1 hunks)
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md (1 hunks)
  • programs/compressed-token/program/src/ctoken_transfer.rs (3 hunks)
  • programs/compressed-token/program/src/shared/initialize_ctoken_account.rs (1 hunks)
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs (1 hunks)
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs (1 hunks)
  • sdk-libs/program-test/src/compressible.rs (1 hunks)
  • sdk-libs/program-test/src/utils/assert.rs (1 hunks)
  • sdk-libs/token-client/src/actions/ctoken_transfer.rs (1 hunks)
  • sdk-libs/token-client/src/instructions/transfer2.rs (3 hunks)
💤 Files with no reviewable changes (1)
  • program-tests/compressed-token-test/tests/account.rs
✅ Files skipped from review due to trivial changes (2)
  • sdk-libs/program-test/src/compressible.rs
  • program-libs/compressible/tests/compression_info.rs
🧰 Additional context used
📓 Path-based instructions (5)
programs/compressed-token/program/src/transfer2/**

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
  • programs/compressed-token/program/src/ctoken_transfer.rs
  • programs/compressed-token/program/src/shared/initialize_ctoken_account.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
programs/compressed-token/program/src/ctoken_transfer.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Files:

  • programs/compressed-token/program/src/ctoken_transfer.rs
programs/compressed-token/program/docs/instructions/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
programs/compressed-token/program/docs/**/instructions/**/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Keep detailed instruction documentation files under the instructions/ directory; add additional instruction docs as needed

Files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
🧠 Learnings (29)
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
  • programs/compressed-token/program/src/ctoken_transfer.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • program-tests/utils/src/assert_transfer2.rs
  • program-tests/compressed-token-test/tests/ctoken/functional.rs
  • program-tests/utils/src/assert_close_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs
  • program-tests/compressed-token-test/tests/ctoken/close.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
  • programs/compressed-token/program/src/shared/initialize_ctoken_account.rs
  • program-tests/compressed-token-test/tests/ctoken/create.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Applied to files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
  • programs/compressed-token/program/src/ctoken_transfer.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • sdk-libs/token-client/src/actions/ctoken_transfer.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • program-tests/utils/src/assert_transfer2.rs
  • program-tests/compressed-token-test/tests/ctoken/functional.rs
  • program-tests/compressed-token-test/tests/transfer2/mod.rs
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
  • program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/transfer2/native_compression/** : For Compress & Close via registry paths, enforce Not Inactive config validation

Applied to files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • program-tests/utils/src/assert_ctoken_transfer.rs
  • program-libs/compressible/tests/rent.rs
  • program-tests/utils/src/assert_close_token_account.rs
  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : On account initialization, call account_info_init to set the 8-byte discriminator

Applied to files:

  • programs/compressed-token/program/src/shared/initialize_ctoken_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs
  • program-tests/compressed-token-test/tests/ctoken/close.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/TRANSFER2.md : Document the batch transfer instruction supporting compressed/decompressed operations in instructions/TRANSFER2.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/DECOMPRESSED_TRANSFER.md : Document SPL-compatible transfers between decompressed accounts in instructions/DECOMPRESSED_TRANSFER.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/transfer2/** : Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • program-tests/utils/src/assert_transfer2.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • program-libs/compressible/tests/rent.rs
  • program-tests/utils/src/assert_close_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • program-libs/compressible/tests/rent.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • program-tests/utils/src/assert_close_token_account.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • program-libs/compressible/tests/rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Compute close lamport distribution with calculate_close_lamports

Applied to files:

  • program-libs/compressible/tests/rent.rs
  • program-tests/utils/src/assert_close_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent curve algorithms via rent_curve_per_epoch

Applied to files:

  • program-libs/compressible/tests/rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/docs/RENT.md : Document rent calculation functions and compressibility checks in docs/RENT.md

Applied to files:

  • program-libs/compressible/tests/rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • program-libs/compressible/tests/rent.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: CToken account layout matches SPL token accounts with a custom Compressible extension; compressed mint accounts support the TokenMetadata extension

Applied to files:

  • sdk-libs/token-client/src/instructions/transfer2.rs
  • program-tests/utils/src/assert_transfer2.rs
  • program-tests/compressed-token-test/tests/ctoken/functional.rs
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/mod.rs : Export each new operation module by adding pub mod <operation>; and re-export with pub use <operation>::*.

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken.rs
  • program-tests/compressed-token-test/tests/transfer2/mod.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/error.rs : Maintain stable mapping of AccountError to ProgramError, including Pinocchio code mapping (1–11), in error.rs

Applied to files:

  • sdk-libs/program-test/src/utils/assert.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Return errors as ProgramError::Custom(error_code as u32) on-chain

Applied to files:

  • sdk-libs/program-test/src/utils/assert.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/create.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/create.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • program-tests/registry-test/tests/compressible.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/program-libs/ctoken-types/{state/**,instructions/**,state/extensions/**} : Define all state and instruction data structures (including extensions like Compressible and TokenMetadata) in the light-ctoken-types crate

Applied to files:

  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/account_info/{solana.rs,pinocchio.rs,test_account_info.rs} : Gate SDK-specific implementations with #[cfg(feature = "solana"|"pinocchio"|"test-only")]

Applied to files:

  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/{CREATE_TOKEN_ACCOUNT,MINT_ACTION,TRANSFER2,CLAIM,CLOSE_TOKEN_ACCOUNT,DECOMPRESSED_TRANSFER,WITHDRAW_FUNDING_POOL}.md : Every instruction description must include sections: path, description, instruction_data, Accounts, instruction logic and checks, Errors

Applied to files:

  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
🧬 Code graph analysis (11)
program-tests/compressed-token-test/tests/ctoken/functional_ata.rs (3)
program-tests/utils/src/assert_create_token_account.rs (2)
  • assert_create_token_account (236-252)
  • assert_create_associated_token_account (258-291)
program-tests/compressed-token-test/tests/ctoken/shared.rs (1)
  • setup_account_test (40-63)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/compressed-token-test/tests/ctoken/functional.rs (4)
program-tests/compressed-token-test/tests/ctoken/shared.rs (2)
  • setup_account_test (40-63)
  • setup_destination_account (66-80)
program-tests/utils/src/assert_create_token_account.rs (1)
  • assert_create_token_account (236-252)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/utils/src/assert_transfer2.rs (1)
  • assert_transfer2_compress (576-590)
sdk-libs/program-test/src/utils/assert.rs (1)
js/stateless.js/src/errors.ts (1)
  • RpcError (79-79)
program-tests/compressed-token-test/tests/ctoken/shared.rs (6)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/utils/src/assert_create_token_account.rs (2)
  • assert_create_token_account (236-252)
  • assert_create_associated_token_account (258-291)
sdk-libs/program-test/src/compressible.rs (1)
  • new (44-64)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
sdk-libs/token-client/src/instructions/transfer2.rs (1)
  • create_generic_transfer2_instruction (145-640)
js/stateless.js/src/utils/instruction.ts (1)
  • PackedAccounts (5-99)
program-tests/compressed-token-test/tests/ctoken/create_ata.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_ata (400-461)
  • create_and_assert_ata_fails (464-514)
sdk-libs/program-test/src/compressible.rs (1)
  • new (44-64)
program-tests/utils/src/assert_create_token_account.rs (1)
  • assert_create_associated_token_account (258-291)
program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (2)
program-tests/compressed-token-test/tests/ctoken/shared.rs (7)
  • setup_compress_and_close_test (530-579)
  • compress_and_close_owner_and_assert (587-662)
  • setup_account_test (40-63)
  • create_non_compressible_token_account (210-278)
  • create_and_assert_ata (400-461)
  • compress_and_close_and_assert_fails (672-729)
  • compress_and_close_forester_with_invalid_output (750-902)
program-tests/utils/src/assert_transfer2.rs (2)
  • assert_transfer2 (550-552)
  • assert_transfer2_compress_and_close (594-628)
program-tests/compressed-token-test/tests/ctoken/close.rs (1)
program-tests/compressed-token-test/tests/ctoken/shared.rs (4)
  • setup_account_test_with_created_account (178-207)
  • close_and_assert_token_account (281-353)
  • close_and_assert_token_account_fails (356-396)
  • create_and_assert_token_account (82-127)
program-tests/compressed-token-test/tests/ctoken/create.rs (2)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_and_assert_token_account_fails (130-172)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/compressed-token-test/tests/ctoken/transfer.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_non_compressible_token_account (210-278)
program-tests/utils/src/assert_ctoken_transfer.rs (1)
  • assert_ctoken_transfer (150-201)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/registry-test/tests/compressible.rs (2)
program-tests/utils/src/spl.rs (1)
  • create_mint_helper (260-263)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs (2)
program-tests/utils/src/spl.rs (3)
  • create_mint_helper (260-263)
  • create_token_2022_account (435-488)
  • mint_spl_tokens (69-105)
js/stateless.js/src/errors.ts (1)
  • RpcError (79-79)
🪛 GitHub Actions: Lint GitHub Actions workflows
.github/workflows/programs.yml

[error] 83-83: Input 'cache-suffix' is not defined for action "Setup and build". Available inputs are "cache-key", "skip-components". The workflow failed with exit code 1.

🪛 GitHub Check: CodeQL
.github/workflows/programs.yml

[warning] 34-119: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}

🪛 LanguageTool
programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md

[grammar] ~21-~21: There might be a mistake here.
Context: ...riminator (3) - Second byte: 0 (padding) - Remaining bytes: SPL TokenInstruction::T...

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: cli-v2
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: lint
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address"])
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: Test program-libs-slow
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip test_tran...
  • GitHub Check: Forester e2e test
  • GitHub Check: cli-v1
  • GitHub Check: stateless-js-v2
  • GitHub Check: Test program-libs-fast
  • GitHub Check: stateless-js-v1
🔇 Additional comments (12)
programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md (1)

21-21: LGTM! Documentation accurately reflects the instruction data format change.

The update from "SPL Token Transfer instruction discriminator (3)" to "0 (padding)" correctly documents the new instruction data layout, which aligns with the implementation changes in sdk-libs/token-client/src/actions/ctoken_transfer.rs.

program-tests/compressed-token-test/tests/transfer2/mod.rs (1)

7-7: LGTM! New test module added.

The addition of the spl_ctoken module expands test coverage for cross-token transfer scenarios.

programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs (1)

76-81: LGTM! Appropriate validation for compress-and-close operations.

The validation correctly prevents compress-and-close operations on accounts with delegates, since compressed tokens don't support delegation. The error message and error code (CompressAndCloseDelegateNotAllowed) clearly communicate the constraint.

sdk-libs/token-client/src/actions/ctoken_transfer.rs (1)

71-71: LGTM! Instruction data format updated to use padding byte.

The change from the SPL transfer discriminator (3) to padding (0) aligns with the documented instruction format in CTOKEN_TRANSFER.md and the on-chain implementation.

program-tests/utils/src/assert_ctoken_transfer.rs (2)

107-107: LGTM! Correct parameter for calculating expected top-up.

The change from lamports_after to lamports_before is correct. The function should calculate what the top-up should be based on the pre-transaction state, then verify that the post-transaction state matches expectations.


113-127: LGTM! Improved clarity in top-up verification logic.

The rewritten logic explicitly handles both cases (top-up applied vs. no top-up needed) with clear assertions and error messages, making test failures easier to diagnose.

program-tests/utils/src/assert_close_token_account.rs (1)

89-104: LGTM! Transaction fee handling improves test accuracy.

The additions correctly account for transaction fees in lamport distribution assertions, distinguishing between cases where:

  • Authority is/isn't the destination
  • Payer is/isn't involved in rent recipient or authority payments
  • Rent authority is/isn't the signer

This makes the test assertions more robust and accurate.

Also applies to: 247-338

program-tests/compressed-token-test/tests/ctoken/functional.rs (1)

35-39: Verify the extra padding byte on initialize account

Pushing an extra 0 byte onto the initialize-account instruction data seems unrelated to the documented CTOKEN_TRANSFER padding change. Please confirm this is required for the init path; otherwise drop it or add a clarifying comment with a reference.

program-tests/compressed-token-test/tests/ctoken.rs (1)

4-27: Module wiring LGTM

Submodule paths are clear and correctly scoped.

program-tests/utils/src/assert_create_token_account.rs (2)

234-252: Wrapper refactor LGTM

Public wrappers delegating to the internal impl (with is_ata flag) simplify call sites and match the new API.


268-291: ATA assertion helper LGTM

Deriving the ATA and asserting existence before delegating is clean and explicit.

program-tests/compressed-token-test/tests/ctoken/shared.rs (1)

398-461: ATA helpers LGTM

Creation and assertion (including idempotent path) are clear and match the updated API.

Comment on lines +223 to +231
// Test 2: Account already initialized (non-idempotent)
// Creating the same ATA twice with non-idempotent mode should fail.
// Error: 18 (IllegalOwner - account is no longer owned by system program)
{
// Use a different mint for this test
context.mint_pubkey = solana_sdk::pubkey::Pubkey::new_unique();

let compressible_data = CompressibleData {
compression_authority: context.compression_authority,
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

Fix comment/code mismatch for IllegalOwner

Comment says “Error: 18 (IllegalOwner)”, but assertion uses 29. Align the expected code or the comment to avoid confusion.

Also applies to: 255-256

🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/ctoken/create_ata.rs around lines
223-231 (and similarly at lines 255-256), the inline comment states the expected
error is 18 (IllegalOwner) but the test assertion checks for error code 29;
update either the comment or the assertion so they match: change the comment to
reflect error 29 if that is the correct expected error, or change the asserted
error code to 18 if IllegalOwner is the intended expectation; ensure both
occurrences (223-231 and 255-256) are updated consistently.

Comment on lines +93 to +101
/// Test:
/// 1. SUCCESS: Create system account with compressible token size
/// 2. SUCCESS: Initialize compressible token account with rent authority and recipient
/// 3. SUCCESS: Verify compressible account structure using existing assertion helper
/// 4. SUCCESS: Close account using rent authority
/// 5. SUCCESS: Verify lamports transferred to rent recipient using existing assertion helper
#[tokio::test]
#[serial]
async fn test_compressible_account_with_compression_authority_lifecycle() {
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

Doc mismatch: authority used for close is the owner, not the rent authority

Comments say “Close account using rent authority,” but the instruction signs with owner. Update the doc to “owner,” or switch the authority if you intended rent-authority closure.

Also applies to: 266-273

🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/ctoken/functional.rs around lines
93-101 (and also apply same change at lines 266-273), the test documentation
says “Close account using rent authority” but the test signs the close with the
owner; update the documentation to accurately reflect the code by changing “rent
authority” to “owner” in the doc comments, or if you intended to use the rent
authority instead, modify the test to sign the close with the rent authority
keypair and adjust any assertions accordingly so doc and implementation match.

Comment on lines +209 to +216
// Calculate transaction fee from the transaction result
let tx_fee = 10_000; // Standard transaction fee
assert_eq!(
payer_balance_before - payer_balance_after,
11_776 + tx_fee,
"Payer should have paid exactly 14,830 lamports for additional rent (1 epoch) plus {} tx fee",
tx_fee
);
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 | 🟠 Major

Avoid hard-coded lamport deltas; compute or rely on existing helpers

The assertion uses a hard-coded 11_776 + tx_fee while the message claims 14,830 and “1 epoch” even though pre_pay_num_epochs = 2. This is fragile and inconsistent.

Prefer:

  • Deriving the expected delta programmatically (from prepay params and rent math), or
  • Relying solely on assert_create_token_account which already validates lamport flows.

At minimum, fix the message to match the actual expectation.

🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/ctoken/functional.rs around lines
209 to 216, the test asserts a hard-coded lamport delta (11_776 + tx_fee) while
the assertion message references 14,830 and “1 epoch” despite pre_pay_num_epochs
= 2, making it fragile and inconsistent; update the assertion to compute the
expected lamport change programmatically (derive the prepay rent amount from the
same pre_pay_num_epochs and rent calculation used elsewhere or call the existing
helper that computes expected rent) and then assert payer_balance_before -
payer_balance_after == expected_rent + tx_fee, or if you prefer the helper
route, remove the manual delta and call assert_create_token_account (or the
appropriate helper) that already validates lamport flows; if you cannot refactor
now, at minimum update the assertion message to match the computed expectation
(correct amount and epoch count).

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

♻️ Duplicate comments (2)
program-tests/compressed-token-test/tests/ctoken/transfer.rs (1)

118-122: Pass the real system program, not the zero pubkey.

AccountMeta::new_readonly(Pubkey::default(), …) hands the transfer CPI a zeroed program id. As soon as a transfer hits the rent top-up path, the CPI into the system program will fail with IncorrectProgramId, so tests test_ctoken_transfer_compressible_with_topup (line 227) and test_ctoken_transfer_mixed_compressible_non_compressible (line 441) cannot succeed.

Apply this diff:

-            AccountMeta::new_readonly(Pubkey::default(), false), // System program for lamport transfers during top-up
+            AccountMeta::new_readonly(solana_sdk::system_program::ID, false), // System program for lamport transfers during top-up
programs/compressed-token/program/src/create_token_account.rs (1)

165-169: Verify error conversion follows coding guidelines.

The validation logic correctly prevents 1-epoch prefunding with a clear error message. However, per the coding guidelines, errors should be returned as ProgramError::Custom(error_code as u32) on-chain.

Verify that anchor_compressed_token::ErrorCode::OneEpochPrefundingNotAllowed.into() properly converts to ProgramError::Custom(...):

#!/bin/bash
# Description: Check the ErrorCode implementation to verify it converts to ProgramError::Custom

# Find the ErrorCode enum definition and its Into<ProgramError> implementation
ast-grep --pattern $'impl From<ErrorCode> for $_ {
  $$$
}'

# Also search for the OneEpochPrefundingNotAllowed error code definition
rg -nP --type=rs -C5 'OneEpochPrefundingNotAllowed\s*[=,]'

As per coding guidelines.


Note: As flagged in the previous review, test coverage for this error path is still missing. Please add unit tests that set rent_payment to 1 and assert the OneEpochPrefundingNotAllowed error is returned.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c911c0d and 89619aa.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/spl_instruction_compat.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs (1 hunks)
  • programs/compressed-token/program/src/create_token_account.rs (2 hunks)
  • programs/compressed-token/program/src/lib.rs (1 hunks)
  • sdk-libs/token-client/src/actions/ctoken_transfer.rs (0 hunks)
💤 Files with no reviewable changes (1)
  • sdk-libs/token-client/src/actions/ctoken_transfer.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • program-tests/compressed-token-test/tests/ctoken.rs
🧰 Additional context used
📓 Path-based instructions (2)
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/lib.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs}

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Files:

  • programs/compressed-token/program/src/create_token_account.rs
🧠 Learnings (13)
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Applied to files:

  • programs/compressed-token/program/src/lib.rs
  • program-tests/compressed-token-test/tests/ctoken/spl_instruction_compat.rs
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • programs/compressed-token/program/src/lib.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/transfer2/** : Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: CToken account layout matches SPL token accounts with a custom Compressible extension; compressed mint accounts support the TokenMetadata extension

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
🧬 Code graph analysis (3)
programs/compressed-token/program/src/lib.rs (1)
programs/compressed-token/program/src/ctoken_transfer.rs (1)
  • process_ctoken_transfer (19-35)
program-tests/compressed-token-test/tests/ctoken/spl_instruction_compat.rs (1)
program-tests/compressed-token-test/tests/ctoken/shared.rs (1)
  • setup_account_test (40-63)
program-tests/compressed-token-test/tests/ctoken/transfer.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_non_compressible_token_account (210-278)
program-tests/utils/src/assert_ctoken_transfer.rs (1)
  • assert_ctoken_transfer (150-201)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip test_tran...
  • GitHub Check: Test program-libs-slow
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address"])
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: lint
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: cli-v1
  • GitHub Check: stateless-js-v2
  • GitHub Check: Forester e2e test
  • GitHub Check: cli-v2
  • GitHub Check: stateless-js-v1
🔇 Additional comments (8)
Cargo.toml (1)

221-221: Thanks for reverting to the shared git source.

Pointing pinocchio-token-program back to the git dependency keeps the workspace portable and fixes the CI breakage from the absolute local path. Looks good.

programs/compressed-token/program/src/lib.rs (1)

115-115: This is a bug fix—approve as-is.

The change from [2..] to [1..] corrects an incorrect offset. Git history confirms the prior value was [2..], which was wrong. All nine instructions in the file now consistently use [1..] after the single-byte discriminator (line 108). Tests already expect this format: transfer.rs line 111 constructs instruction data as vec![3] (discriminator only) + amount, confirming [1..] is correct.

If the old code with [2..] was ever deployed, it would have been parsing instruction data incorrectly by skipping an extra byte. This is a correctness fix.

program-tests/compressed-token-test/tests/ctoken/transfer.rs (5)

1-98: LGTM: Test setup correctly uses 2 prepaid epochs.

The setup_transfer_test helper properly creates compressible accounts with 2 prepaid epochs (not 1), aligning with the PR's objective to prohibit single-epoch prefunding. The setup logic for creating source/destination accounts and minting tokens is sound.


127-181: LGTM: Transfer helpers correctly use assertion utilities.

The transfer_and_assert and transfer_and_assert_fails helpers properly execute transfers and validate outcomes using shared assertion utilities from light_test_utils and light_program_test.


187-274: Tests correctly use 2 prepaid epochs, but top-up test will fail.

The successful transfer tests properly use 2 prepaid epochs for compressible accounts, aligning with the PR objective. However, test_ctoken_transfer_compressible_with_topup (line 227) will fail due to the system program issue at line 121. Once that's fixed, this test should pass.


280-414: LGTM: Comprehensive failure scenario coverage.

The failing transfer tests correctly validate critical error modes (insufficient balance, frozen accounts, wrong authority, mint mismatch) with appropriate error codes. Using non-compressible accounts avoids the system program issue at line 121.


420-500: Edge cases well covered, but mixed test will fail.

The zero-amount transfer test correctly validates SPL token behavior. The mixed compressible/non-compressible test properly uses 2 prepaid epochs and funds the owner for top-ups, but will fail due to the system program issue at line 121 until that's resolved.

programs/compressed-token/program/src/create_token_account.rs (1)

61-67: Ignore call-site verification for create_token_account
The process_create_token_account handler is only invoked via on-chain dispatch and has no internal callers to update.

Likely an incorrect or invalid review comment.

Comment on lines +49 to +117
// Step 2: Initialize using SPL token initialize_account3 instruction
// Note: initialize_account3 doesn't require account to be signer (SPL compatibility)
let mut init_ix = spl_token_2022::instruction::initialize_account3(
&spl_token_2022::ID,
&account1_keypair.pubkey(),
&context.mint_pubkey,
&context.owner_keypair.pubkey(),
)
.unwrap();

// Change program_id to ctoken program for compatibility test
init_ix.program_id = light_compressed_token::ID;

context
.rpc
.create_and_send_transaction(&[init_ix], &payer_pubkey, &[&context.payer])
.await
.unwrap();

println!("First token account created successfully");
}

println!("Creating second token account...");

// Create second account using SPL token instruction format
{
// Step 1: Create account via system program with ctoken program as owner
let rent = context
.rpc
.get_minimum_balance_for_rent_exemption(165)
.await
.unwrap();

let create_account_ix = solana_sdk::system_instruction::create_account(
&payer_pubkey,
&account2_keypair.pubkey(),
rent,
165,
&light_compressed_token::ID, // Use ctoken program as owner
);

context
.rpc
.create_and_send_transaction(
&[create_account_ix],
&payer_pubkey,
&[&context.payer, &account2_keypair],
)
.await
.unwrap();

// Step 2: Initialize using SPL token initialize_account3 instruction
// Note: initialize_account3 doesn't require account to be signer (SPL compatibility)
let mut init_ix = spl_token_2022::instruction::initialize_account3(
&spl_token_2022::ID,
&account2_keypair.pubkey(),
&context.mint_pubkey,
&context.owner_keypair.pubkey(),
)
.unwrap();

// Change program_id to ctoken program for compatibility test
init_ix.program_id = light_compressed_token::ID;

context
.rpc
.create_and_send_transaction(&[init_ix], &payer_pubkey, &[&context.payer])
.await
.unwrap();
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 | 🔴 Critical

Missing mint account initialization prevents every instruction from succeeding

setup_account_test() only hands back a random mint_pubkey; it never creates a Mint account on chain. The very first initialize_account3 (and every later transfer/close) therefore references a non-existent mint, so the transaction aborts with InstructionError::MissingAccount/AccountNotFound. Please create and initialize the mint (e.g., system create_account + spl_token_2022::instruction::initialize_mint2 through the ctoken program) before issuing the account/move/close instructions.

🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/ctoken/spl_instruction_compat.rs
around lines 49–117, the test uses a random mint_pubkey but never
creates/initializes the Mint account on-chain, so subsequent initialize_account3
calls fail with AccountNotFound; fix by creating and initializing the mint
before creating token accounts: allocate a mint Keypair, call system
create_account with correct rent-exempt lamports, space and owner =
light_compressed_token::ID (using the test payer as payer), then call
spl_token_2022::instruction::initialize_mint2 (with desired decimals and
mint/authority params), change that instruction’s program_id to
light_compressed_token::ID for compatibility, include the mint Keypair (and
payer) in the transaction signers, and await/unwrap the RPC call before
proceeding to initialize token accounts.

@ananas-block ananas-block force-pushed the jorrit/fix-pre-funding-compressible-account branch from 89619aa to 165f5d4 Compare October 16, 2025 01:48
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: 5

Caution

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

⚠️ Outside diff range comments (2)
sdk-libs/token-client/src/instructions/transfer2.rs (1)

525-586: Fix compress_to_pubkey handling

compress_to_pubkey in the compressible extension is the target pubkey, not a boolean flag. Conflating it with true/false and, when “true”, reusing source_index (the Solana token account being closed) means the packed owner meta no longer points at the intended Pubkey. For accounts where compress_to_pubkey is Some(pubkey), this will surface as instruction failures because the owner index references the wrong account key. Please deserialize compress_to_pubkey as the Pubkey it encodes and insert that key into packed_tree_accounts (falling back to the original owner when it is None), rather than reusing the source account index.

program-tests/utils/src/assert_create_token_account.rs (1)

198-229: Remove magic number 165; rely on BASE_TOKEN_ACCOUNT_SIZE only.

Two size assertions; one uses hard‑coded 165. Keep a single assertion with the constant to avoid drift.

Apply:

-            assert_eq!(account_info.data.len(), 165); // SPL token account size
+            // SPL token account size
+            assert_eq!(account_info.data.len(), BASE_TOKEN_ACCOUNT_SIZE as usize);
...
-            assert_eq!(actual_spl_token_account, expected_spl_token_account);
-            assert_eq!(account_info.data.len(), BASE_TOKEN_ACCOUNT_SIZE as usize);
+            assert_eq!(actual_spl_token_account, expected_spl_token_account);
♻️ Duplicate comments (10)
program-tests/registry-test/tests/compressible.rs (2)

151-157: Update comment to reflect actual epoch range (2-11).

The comment states "1 to 10" but the loop creates accounts with prepaid epochs ranging from 2 to 11. This mismatch should be corrected.

Apply this diff to fix the comment:

-    // Create 10 token accounts with varying prepaid epochs (1 to 10)
+    // Create 10 token accounts with varying prepaid epochs (2 to 11)
     let mut token_accounts = Vec::new();
     let mut owners = Vec::new();
 
     for i in 2..=11 {

185-187: Align comment with actual epoch warp count (11).

The comment says "Warp forward 10 epochs" but the code warps forward 11 epochs. Update the comment to match the code.

Apply this diff to fix the comment:

-    // Warp forward 10 epochs using the new wrapper method
+    // Warp forward 11 epochs using the new wrapper method
     rpc.warp_epoch_forward(11).await.unwrap();
sdk-libs/program-test/src/utils/assert.rs (3)

44-87: Critical: Hardcoded discriminants don't match standard Solana SDK and reference non-existent variants.

Based on previous analysis, the numeric discriminants are offset by 1 and several variants don't exist in solana-sdk:

  • Line 53: AccountDataTooSmall is 4 in SDK, not 5
  • Line 54: InsufficientFunds is 5 in SDK, not 6
  • Lines 61-62, 66: MaxSeedLengthExceeded, InvalidSeeds, ComputationalBudgetExceeded don't exist in standard SDK
  • All subsequent mappings are similarly offset

This will cause:

  1. Compile errors if these variants don't exist in solana_instruction::error::InstructionError
  2. Logic errors if the discriminants are wrong, causing tests to fail or pass incorrectly

Refactor to:

  1. Match on the variant directly instead of hardcoding numbers
  2. Extract shared logic into a helper function to eliminate duplication with lines 89-130
  3. Add explicit discriminant conversion if needed: err as u32 == expected_error_code

Example refactor:

-        Err(RpcError::TransactionError(TransactionError::InstructionError(index, ref err)))
-            if index == index_instruction =>
-        {
-            match (err, expected_error_code) {
-                (InstructionError::GenericError, 0) => Ok(()),
-                (InstructionError::InvalidArgument, 1) => Ok(()),
-                // ... 30+ more lines
-                _ => Err(RpcError::AssertRpcError(format!(
-                    "Expected error code {}, but got {:?}",
-                    expected_error_code, err
-                ))),
-            }
-        }
+        Err(RpcError::TransactionError(TransactionError::InstructionError(index, ref err)))
+            if index == index_instruction =>
+        {
+            if matches_instruction_error(err, expected_error_code) {
+                Ok(())
+            } else {
+                Err(RpcError::AssertRpcError(format!(
+                    "Expected error code {}, but got {:?}",
+                    expected_error_code, err
+                )))
+            }
+        }

Add helper function before assert_rpc_error:

fn matches_instruction_error(err: &InstructionError, expected_code: u32) -> bool {
    match err {
        InstructionError::Custom(code) => *code == expected_code,
        _ => {
            // For built-in variants, cast the discriminant directly
            // This avoids hardcoding and keeps in sync with the enum definition
            let discriminant = unsafe { *(err as *const InstructionError as *const u32) };
            discriminant == expected_code
        }
    }
}

Or use a simpler approach if the crate has serialization:

fn matches_instruction_error(err: &InstructionError, expected_code: u32) -> bool {
    match err {
        InstructionError::Custom(code) => *code == expected_code,
        other => std::mem::discriminant(other) == std::mem::discriminant(&(expected_code as InstructionError)),
    }
}

89-130: Critical: Exact duplication of lines 44-87 with different error source.

This block duplicates the same hardcoded discriminant logic from lines 44-87, only wrapped in BanksClientError instead of direct TransactionError. All the same issues apply:

  • Incorrect discriminants
  • Non-existent variants
  • Maintenance burden

Replace with the same helper function approach:

-        Err(RpcError::BanksError(BanksClientError::TransactionError(
-            TransactionError::InstructionError(index, ref err),
-        ))) if index == index_instruction => match (err, expected_error_code) {
-            (InstructionError::GenericError, 0) => Ok(()),
-            // ... 30+ more duplicated lines
-            _ => Err(RpcError::AssertRpcError(format!(
-                "Expected error code {}, but got {:?}",
-                expected_error_code, err
-            ))),
-        },
+        Err(RpcError::BanksError(BanksClientError::TransactionError(
+            TransactionError::InstructionError(index, ref err),
+        ))) if index == index_instruction =>
+        {
+            if matches_instruction_error(err, expected_error_code) {
+                Ok(())
+            } else {
+                Err(RpcError::AssertRpcError(format!(
+                    "Expected error code {}, but got {:?}",
+                    expected_error_code, err
+                )))
+            }
+        }

44-130: Add handling for index mismatch on non-Custom errors.

Currently, only Custom errors (lines 16-24, 27-35) check for index mismatch. Non-Custom errors at lines 44-130 don't have a symmetric branch for index != index_instruction, causing them to fall through to the generic "Unexpected error type" message on line 136-139.

Add branches before lines 45 and 90:

+        // Index mismatch for non-Custom TransactionError
+        Err(RpcError::TransactionError(TransactionError::InstructionError(index, ref err)))
+            if index != index_instruction =>
+        {
+            Err(RpcError::AssertRpcError(format!(
+                "Expected error at instruction {}, but got at {} with error {:?}",
+                index_instruction, index, err
+            )))
+        }
+
         // Handle built-in Solana errors (non-Custom) - TransactionError variants
         Err(RpcError::TransactionError(TransactionError::InstructionError(index, ref err)))
             if index == index_instruction =>

And before line 90:

+        // Index mismatch for non-Custom BanksClientError  
+        Err(RpcError::BanksError(BanksClientError::TransactionError(
+            TransactionError::InstructionError(index, ref err),
+        ))) if index != index_instruction =>
+        {
+            Err(RpcError::AssertRpcError(format!(
+                "Expected error at instruction {}, but got at {} with error {:?}",
+                index_instruction, index, err
+            )))
+        }
+
         // Handle built-in Solana errors (non-Custom) - BanksClientError variants
         Err(RpcError::BanksError(BanksClientError::TransactionError(
programs/compressed-token/program/src/create_token_account.rs (1)

165-169: This is the same validation issue flagged in the past review comment. The validation logic is correct and consistent with create_associated_token_account.rs, but tests explicitly exercising the OneEpochPrefundingNotAllowed error path are still missing.

Based on the test files provided, all tests use valid epoch values (0, 2+) and none attempt to set rent_payment = 1 to verify the error is returned.

program-tests/compressed-token-test/tests/ctoken/functional.rs (1)

209-216: Assertion message inconsistent with test parameters.

The assertion message claims "14,830 lamports for additional rent (1 epoch)" but the test uses num_prepaid_epochs = 2 (line 121), and the hard-coded delta is 11_776 + tx_fee, not 14,830. This makes the test fragile and confusing.

As noted in the previous review, either:

  1. Compute the expected delta programmatically from pre_pay_num_epochs and rent calculations, or
  2. Rely on assert_create_token_account which already validates lamport flows

At minimum, fix the message to accurately reflect the actual values and epoch count.

.github/workflows/programs.yml (1)

34-119: Add explicit permissions block to limit GITHUB_TOKEN scope.

The workflow does not specify permissions for the GITHUB_TOKEN, granting it default permissions which may be overly broad. As a security best practice, explicitly limit the token's permissions to the minimum required.

Add this block at the job level (after line 33):

 jobs:
   system-programs:
     name: programs
+    permissions:
+      contents: read
     if: github.event.pull_request.draft == false

Based on static analysis.

program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1)

223-256: Align the IllegalOwner comment with the asserted code

Inline comment still says “Error: 18 (IllegalOwner)” while the assertion expects 29. Please update one or the other so the narrative matches the behavior.

program-tests/compressed-token-test/tests/ctoken/transfer.rs (1)

118-122: Wire the actual system program into transfer CPI

AccountMeta::new_readonly(Pubkey::default(), …) feeds a zero program id to the CPI, so any rent top-up immediately trips IncorrectProgramId. Please pass the real system program id instead.

-            AccountMeta::new_readonly(Pubkey::default(), false), // System program for lamport transfers during top-up
+            AccountMeta::new_readonly(solana_sdk::system_program::ID, false), // System program for lamport transfers during top-up
🧹 Nitpick comments (16)
program-tests/registry-test/tests/compressible.rs (2)

4-4: TODO: Refactor into directory structure.

This organizational task is flagged. The test file could benefit from being split into multiple modules within a directory.

Would you like me to generate a proposed directory structure and migration plan, or open a new issue to track this refactoring task?


144-147: Consider preserving error context with Result return types.

The function signature changed from returning Result<(), RpcError> to a unit return, and error handling throughout the test now uses .unwrap() instead of the ? operator. While tests will still fail appropriately through panics, this reduces error context visibility when debugging failures.

If detailed error messages are important for debugging, consider keeping the Result return type and using ? for error propagation:

-async fn test_claim_multiple_accounts_different_epochs() {
-    let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(false, None))
-        .await
-        .unwrap();
+async fn test_claim_multiple_accounts_different_epochs() -> Result<(), RpcError> {
+    let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(false, None))
+        .await?;

Apply similar changes throughout the function where .unwrap() is used on operations that return Result<_, RpcError>.

program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs (4)

44-47: Consider removing debug print statement.

This debug print appears to be a development artifact. Consider removing it or converting to a proper test log if the output is needed for debugging.

Apply this diff to remove the debug print:

-    println!(
-        "spl_token_account_keypair {:?}",
-        spl_token_account_keypair.pubkey()
-    );

128-128: Consider removing debug print statement.

This debug print appears to be a development artifact. Consider removing it or converting to a proper test log if the output is needed for debugging.

Apply this diff to remove the debug print:

-    println!("Testing reverse transfer: ctoken to SPL");

73-76: Reduce code duplication and document magic number.

The parsing logic for PodAccount is duplicated five times throughout the test. Additionally, the hardcoded slice [..165] used for compressed token accounts (lines 114, 171) is a magic number that should be documented or extracted as a constant.

Consider refactoring the parsing logic into helper functions:

fn parse_spl_account(data: &[u8]) -> Result<PodAccount, RpcError> {
    spl_pod::bytemuck::pod_from_bytes::<PodAccount>(data)
        .map(|acc| *acc)
        .map_err(|e| RpcError::AssertRpcError(format!("Failed to parse SPL token account: {}", e)))
}

fn parse_ctoken_account(data: &[u8]) -> Result<PodAccount, RpcError> {
    const CTOKEN_ACCOUNT_POD_SIZE: usize = 165;
    spl_pod::bytemuck::pod_from_bytes::<PodAccount>(&data[..CTOKEN_ACCOUNT_POD_SIZE])
        .map(|acc| *acc)
        .map_err(|e| RpcError::AssertRpcError(format!("Failed to parse compressed token account: {}", e)))
}

Then use these helpers throughout the test to reduce duplication and improve maintainability.

Also applies to: 98-103, 114-118, 151-156, 171-178


91-125: Consider flattening nested blocks for improved readability.

The nested blocks (lines 91-125 and 144-184) are used to scope variables but add unnecessary nesting. Consider flattening these blocks to improve readability, as the variable names don't conflict.

Example refactoring for the first verification block:

-    {
-        // Verify SPL token balance decreased
-        let spl_account_data = rpc
-            .get_account(spl_token_account_keypair.pubkey())
-            .await
-            .unwrap()
-            .unwrap();
-        let spl_account = spl_pod::bytemuck::pod_from_bytes::<PodAccount>(&spl_account_data.data)
-            .map_err(|e| {
-                RpcError::AssertRpcError(format!("Failed to parse SPL token account: {}", e))
-            })
-            .unwrap();
-        let final_spl_balance: u64 = spl_account.amount.into();
-        assert_eq!(final_spl_balance, amount - transfer_amount);
-    }
-    {
-        // Verify compressed token balance increased
-        let spl_account_data = rpc
-            .get_account(associated_token_account)
-            .await
-            .unwrap()
-            .unwrap();
-        let spl_account =
-            spl_pod::bytemuck::pod_from_bytes::<PodAccount>(&spl_account_data.data[..165])
-                .map_err(|e| {
-                    RpcError::AssertRpcError(format!("Failed to parse SPL token account: {}", e))
-                })
-                .unwrap();
-        assert_eq!(
-            u64::from(spl_account.amount),
-            transfer_amount,
-            "Recipient should have {} compressed tokens",
-            transfer_amount
-        );
-    }
+    // Verify SPL token balance decreased
+    let spl_account_data = rpc
+        .get_account(spl_token_account_keypair.pubkey())
+        .await
+        .unwrap()
+        .unwrap();
+    let spl_account = spl_pod::bytemuck::pod_from_bytes::<PodAccount>(&spl_account_data.data)
+        .map_err(|e| {
+            RpcError::AssertRpcError(format!("Failed to parse SPL token account: {}", e))
+        })
+        .unwrap();
+    let final_spl_balance: u64 = spl_account.amount.into();
+    assert_eq!(final_spl_balance, amount - transfer_amount);
+
+    // Verify compressed token balance increased
+    let ctoken_account_data = rpc
+        .get_account(associated_token_account)
+        .await
+        .unwrap()
+        .unwrap();
+    let ctoken_account =
+        spl_pod::bytemuck::pod_from_bytes::<PodAccount>(&ctoken_account_data.data[..165])
+            .map_err(|e| {
+                RpcError::AssertRpcError(format!("Failed to parse SPL token account: {}", e))
+            })
+            .unwrap();
+    assert_eq!(
+        u64::from(ctoken_account.amount),
+        transfer_amount,
+        "Recipient should have {} compressed tokens",
+        transfer_amount
+    );

Also applies to: 144-184

program-tests/utils/src/assert_create_token_account.rs (4)

2-2: Remove unused import.

use light_client::rpc::Rpc; is not used.

Apply:

-use light_client::rpc::Rpc;

75-111: Avoid brittle full-struct equality on CToken; assert stable fields only.

last_claimed_slot == current_slot and config_account_version = 1 can drift and cause flaky tests. Prefer asserting invariant fields (mint, owner, amount=0, state, extension core values), and check last_claimed_slot <= current_slot.

Example approach (sketch):

  • Extract CompressionInfo from actual_token_account.
  • Assert:
    • mint/owner/amount/state as today
    • compression_authority/rent_sponsor/lamports_per_write/compress_to_pubkey/account_version
    • rent_config equals expected default (or compare relevant fields)
    • last_claimed_slot <= current_slot
  • Drop expected_token_account construction and assert_eq!(actual, expected).

Based on learnings.


142-146: Don’t hard‑code fee per signature (5_000).

Fee can change; hard‑coding risks flakes. Derive fee dynamically and multiply by signer count.

Consider:

  • Query lamports per signature via the test RPC (e.g., fees endpoint) and compute tx_fee = lamports_per_sig * (is_ata ? 1 : 2).
  • If not available, thread expected lamports_per_sig into this helper from the caller.

267-279: Redundant ATA existence pre‑check.

assert_create_token_account_internal immediately fetches and asserts existence; this extra fetch/assert duplicates work.

Apply:

-    // Verify the account exists at the derived address
-    let account = rpc
-        .get_account(ata_pubkey)
-        .await
-        .expect("Failed to get ATA account");
-
-    assert!(
-        account.is_some(),
-        "ATA should exist at derived address {} for owner {} and mint {}",
-        ata_pubkey,
-        owner_pubkey,
-        mint_pubkey
-    );
program-tests/utils/src/assert_transfer2.rs (1)

389-414: Avoid magic 165; use BASE_TOKEN_ACCOUNT_SIZE

Use the shared base token account size constant for length checks to avoid brittle literals.

-                let compress_to_pubkey = if pre_account_data.data.len() > 165 {
+                let compress_to_pubkey = if pre_account_data.data.len()
+                    > light_ctoken_types::BASE_TOKEN_ACCOUNT_SIZE as usize
+                {

Add import near the top of this file:

use light_ctoken_types::BASE_TOKEN_ACCOUNT_SIZE;

Apply similarly anywhere else 165 is used for SPL account header sizing in this helper.

Also applies to: 422-427

program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (3)

67-75: Replace repeated 165 byte constants with BASE_TOKEN_ACCOUNT_SIZE

Referencing SPL account header size via a shared constant improves clarity and avoids drift.

  • Import and use light_ctoken_types::BASE_TOKEN_ACCOUNT_SIZE for:
    • unpack/pack slices: &data[..BASE_TOKEN_ACCOUNT_SIZE as usize]
    • length checks comparing against 165
      Apply across this file for all occurrences shown and similar ones.

Also applies to: 117-125, 609-613, 810-817


457-465: Clarify payer vs pool variables and assertion message

Variable pool_balance_before actually holds the payer’s balance. Rename to payer_balance_before and update the assertion message to avoid confusion.

-    let pool_balance_before = context
+    let payer_balance_before = context
         .rpc
-        .get_account(payer_pubkey)
+        .get_account(payer_pubkey)
         .await
         .unwrap()
-        .expect("Pool PDA should exist")
+        .expect("Payer should exist")
         .lamports;
...
-    assert_eq!(
-        pool_balance_before - payer_balance_after,
+    assert_eq!(
+        payer_balance_before - payer_balance_after,
         rent_exemption + rent + tx_fee,
-        "Pool PDA should have paid {} lamports for account creation (rent-exempt), and the additional rent",
+        "Payer should have covered rent-exempt + additional rent + fee",
         rent_exemption
     );

Also applies to: 495-511


237-239: Use get_output_pubkey consistently for output queue

Some tests use get_output_pubkey() while others read .queue. For consistency and to avoid packing mismatches, prefer get_output_pubkey() everywhere in these tests.

Also applies to: 290-291

programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (1)

112-112: Fix markdown list indentation.

The error list items have incorrect indentation (2 spaces instead of 0), which violates markdown linting rules.

Apply this fix to both locations:

-  - `ErrorCode::OneEpochPrefundingNotAllowed` (error code: 6116) - rent_payment is exactly 1 epoch...
+- `ErrorCode::OneEpochPrefundingNotAllowed` (error code: 6116) - rent_payment is exactly 1 epoch...

Based on static analysis.

Also applies to: 180-180

program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1)

441-473: Keep the InvalidAccountOwner commentary in sync with the assertion

The prose calls out error 14, but the check asserts 20001. Adjust the comment (or the expectation) so readers don’t chase the wrong code.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89619aa and 165f5d4.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (47)
  • .github/workflows/programs.yml (1 hunks)
  • Cargo.toml (1 hunks)
  • program-libs/compressible/tests/compression_info.rs (1 hunks)
  • program-libs/compressible/tests/rent.rs (1 hunks)
  • program-libs/ctoken-types/src/constants.rs (1 hunks)
  • program-tests/compressed-token-test/Cargo.toml (1 hunks)
  • program-tests/compressed-token-test/tests/account.rs (0 hunks)
  • program-tests/compressed-token-test/tests/ctoken.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/close.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/functional.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/functional_ata.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/shared.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/spl_instruction_compat.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/mod.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs (1 hunks)
  • program-tests/compressed-token-test/tests/v1.rs (5 hunks)
  • program-tests/registry-test/Cargo.toml (1 hunks)
  • program-tests/registry-test/tests/compressible.rs (28 hunks)
  • program-tests/system-cpi-test/tests/test.rs (2 hunks)
  • program-tests/system-test/tests/test.rs (1 hunks)
  • program-tests/utils/src/assert_close_token_account.rs (5 hunks)
  • program-tests/utils/src/assert_create_token_account.rs (4 hunks)
  • program-tests/utils/src/assert_ctoken_transfer.rs (1 hunks)
  • program-tests/utils/src/assert_transfer2.rs (2 hunks)
  • programs/compressed-token/anchor/src/lib.rs (1 hunks)
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (5 hunks)
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md (1 hunks)
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md (1 hunks)
  • programs/compressed-token/program/src/create_associated_token_account.rs (1 hunks)
  • programs/compressed-token/program/src/create_token_account.rs (2 hunks)
  • programs/compressed-token/program/src/ctoken_transfer.rs (3 hunks)
  • programs/compressed-token/program/src/lib.rs (1 hunks)
  • programs/compressed-token/program/src/shared/initialize_ctoken_account.rs (1 hunks)
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs (1 hunks)
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs (1 hunks)
  • sdk-libs/program-test/src/utils/assert.rs (1 hunks)
  • sdk-libs/token-client/src/actions/ctoken_transfer.rs (0 hunks)
  • sdk-libs/token-client/src/instructions/transfer2.rs (3 hunks)
  • sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs (1 hunks)
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs (1 hunks)
💤 Files with no reviewable changes (2)
  • sdk-libs/token-client/src/actions/ctoken_transfer.rs
  • program-tests/compressed-token-test/tests/account.rs
✅ Files skipped from review due to trivial changes (1)
  • program-tests/compressed-token-test/tests/transfer2/mod.rs
🚧 Files skipped from review as they are similar to previous changes (14)
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • sdk-tests/sdk-token-test/tests/pda_ctoken.rs
  • programs/compressed-token/program/src/lib.rs
  • program-libs/compressible/tests/rent.rs
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • programs/compressed-token/program/src/shared/initialize_ctoken_account.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_and_close.rs
  • program-tests/compressed-token-test/tests/ctoken/spl_instruction_compat.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • programs/compressed-token/program/src/ctoken_transfer.rs
  • Cargo.toml
  • sdk-tests/sdk-token-test/src/process_create_ctoken_with_compress_to_pubkey.rs
  • program-tests/registry-test/Cargo.toml
  • program-tests/compressed-token-test/tests/ctoken/shared.rs
🧰 Additional context used
📓 Path-based instructions (6)
programs/compressed-token/program/docs/instructions/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
programs/compressed-token/program/docs/**/instructions/**/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Keep detailed instruction documentation files under the instructions/ directory; add additional instruction docs as needed

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs}

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/src/transfer2/**

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Files:

  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
🧠 Learnings (32)
📓 Common learnings
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/error.rs : Maintain stable mapping of AccountError to ProgramError, including Pinocchio code mapping (1–11), in error.rs

Applied to files:

  • sdk-libs/program-test/src/utils/assert.rs
  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Return errors as ProgramError::Custom(error_code as u32) on-chain

Applied to files:

  • sdk-libs/program-test/src/utils/assert.rs
  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/ctoken/functional.rs
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs
  • program-tests/compressed-token-test/tests/ctoken/close.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/ctoken/functional.rs
  • program-tests/utils/src/assert_transfer2.rs
  • program-libs/ctoken-types/src/constants.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs
  • program-tests/utils/src/assert_close_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/close.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: CToken account layout matches SPL token accounts with a custom Compressible extension; compressed mint accounts support the TokenMetadata extension

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/utils/src/assert_transfer2.rs
  • program-libs/ctoken-types/src/constants.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/create.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/ctoken/create.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/ACCOUNTS.md : Accounts documentation must include: description, discriminator, state layout, serialization example, hashing (only for compressed accounts), derivation (only for PDAs), and associated instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/{CREATE_TOKEN_ACCOUNT,MINT_ACTION,TRANSFER2,CLAIM,CLOSE_TOKEN_ACCOUNT,DECOMPRESSED_TRANSFER,WITHDRAW_FUNDING_POOL}.md : Every instruction description must include sections: path, description, instruction_data, Accounts, instruction logic and checks, Errors

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/instructions/*.md : Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/**/ACCOUNTS.md : Provide complete account layouts and data structures in ACCOUNTS.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/DECOMPRESSED_TRANSFER.md : Document SPL-compatible transfers between decompressed accounts in instructions/DECOMPRESSED_TRANSFER.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/ctoken/create.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-libs/ctoken-types/src/constants.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • program-tests/utils/src/assert_close_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-libs/ctoken-types/src/constants.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • program-tests/utils/src/assert_close_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-libs/ctoken-types/src/constants.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/compressible/tests/compression_info.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/functional.rs
  • program-tests/utils/src/assert_transfer2.rs
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs
  • program-tests/compressed-token-test/tests/ctoken.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/transfer2/** : Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Applied to files:

  • program-tests/utils/src/assert_transfer2.rs
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
  • sdk-libs/token-client/src/instructions/transfer2.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Include default initialization for CToken V1 config in CompressibleConfig

Applied to files:

  • program-libs/ctoken-types/src/constants.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/docs/RENT.md : Document rent calculation functions and compressibility checks in docs/RENT.md

Applied to files:

  • program-libs/ctoken-types/src/constants.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • program-libs/ctoken-types/src/constants.rs
  • program-libs/compressible/tests/compression_info.rs
  • programs/compressed-token/program/src/transfer2/compression/ctoken/compress_or_decompress_ctokens.rs
  • program-tests/registry-test/tests/compressible.rs
  • program-tests/utils/src/assert_close_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-tests/system-cpi-test/tests/test.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • program-tests/registry-test/tests/compressible.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Compute close lamport distribution with calculate_close_lamports

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-tests/utils/src/assert_close_token_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/account_info/{solana.rs,pinocchio.rs,test_account_info.rs} : Gate SDK-specific implementations with #[cfg(feature = "solana"|"pinocchio"|"test-only")]

Applied to files:

  • program-tests/system-cpi-test/tests/test.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/program-libs/ctoken-types/{state/**,instructions/**,state/extensions/**} : Define all state and instruction data structures (including extensions like Compressible and TokenMetadata) in the light-ctoken-types crate

Applied to files:

  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • program-tests/registry-test/tests/compressible.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/error.rs : Provide ProgramError conversions compatible with Anchor, Pinocchio, and Solana error types

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : Return AccountError variants (codes 12006–12021) and rely on automatic ProgramError conversions; avoid returning raw ProgramError directly

Applied to files:

  • programs/compressed-token/anchor/src/lib.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/TRANSFER2.md : Document the batch transfer instruction supporting compressed/decompressed operations in instructions/TRANSFER2.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md
🧬 Code graph analysis (12)
sdk-libs/program-test/src/utils/assert.rs (1)
js/stateless.js/src/errors.ts (1)
  • RpcError (79-79)
program-tests/compressed-token-test/tests/ctoken/functional.rs (4)
program-tests/compressed-token-test/tests/ctoken/shared.rs (2)
  • setup_account_test (40-63)
  • setup_destination_account (66-80)
program-tests/utils/src/assert_create_token_account.rs (1)
  • assert_create_token_account (236-252)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/utils/src/assert_transfer2.rs (1)
  • assert_transfer2_compress (576-590)
program-tests/compressed-token-test/tests/ctoken/transfer.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_non_compressible_token_account (210-278)
program-tests/utils/src/assert_ctoken_transfer.rs (1)
  • assert_ctoken_transfer (150-201)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/compressed-token-test/tests/ctoken/functional_ata.rs (3)
program-tests/utils/src/assert_create_token_account.rs (2)
  • assert_create_token_account (236-252)
  • assert_create_associated_token_account (258-291)
program-tests/compressed-token-test/tests/ctoken/shared.rs (1)
  • setup_account_test (40-63)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (7)
  • setup_compress_and_close_test (530-579)
  • compress_and_close_owner_and_assert (587-662)
  • setup_account_test (40-63)
  • create_non_compressible_token_account (210-278)
  • create_and_assert_ata (400-461)
  • compress_and_close_and_assert_fails (672-729)
  • compress_and_close_forester_with_invalid_output (750-902)
program-tests/utils/src/assert_transfer2.rs (2)
  • assert_transfer2 (550-552)
  • assert_transfer2_compress_and_close (594-628)
sdk-libs/token-client/src/instructions/transfer2.rs (1)
  • create_generic_transfer2_instruction (145-640)
program-tests/registry-test/tests/compressible.rs (2)
program-tests/utils/src/spl.rs (1)
  • create_mint_helper (260-263)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/compressed-token-test/tests/ctoken/create_ata.rs (4)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_ata (400-461)
  • create_and_assert_ata_fails (464-514)
sdk-libs/program-test/src/compressible.rs (1)
  • new (44-64)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/utils/src/assert_create_token_account.rs (1)
  • assert_create_associated_token_account (258-291)
program-tests/compressed-token-test/tests/ctoken/create.rs (2)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_and_assert_token_account_fails (130-172)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/compressed-token-test/tests/ctoken/close.rs (1)
program-tests/compressed-token-test/tests/ctoken/shared.rs (4)
  • setup_account_test_with_created_account (178-207)
  • close_and_assert_token_account (281-353)
  • close_and_assert_token_account_fails (356-396)
  • create_and_assert_token_account (82-127)
program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs (1)
program-tests/utils/src/spl.rs (3)
  • create_mint_helper (260-263)
  • create_token_2022_account (435-488)
  • mint_spl_tokens (69-105)
program-tests/compressed-token-test/tests/ctoken.rs (1)
programs/registry/src/lib.rs (1)
  • compress_and_close (765-778)
program-tests/system-test/tests/test.rs (1)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
🪛 GitHub Check: CodeQL
.github/workflows/programs.yml

[warning] 34-119: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}

🪛 LanguageTool
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

[grammar] ~76-~76: There might be a mistake here.
Context: ...is not exactly 1 epoch - Check: compressible_config.rent_payment != 1 - Error: `ErrorCode::OneEpochPrefundingNot...

(QB_NEW_EN)


[grammar] ~180-~180: There might be a mistake here.
Context: ...epoch (see create ctoken account errors)

(QB_NEW_EN)

programs/compressed-token/program/docs/instructions/CTOKEN_TRANSFER.md

[grammar] ~21-~21: There might be a mistake here.
Context: ...riminator (3) - Second byte: 0 (padding) - Remaining bytes: SPL TokenInstruction::T...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.18.1)
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

112-112: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


180-180: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: cli-v1
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: cli-v2
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: lint
  • GitHub Check: Forester e2e test
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: stateless-js-v2
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip test_tran...
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address"])
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: stateless-js-v1
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...

Comment on lines +28 to +43
// Create SPL token account and mint tokens
let spl_token_account_keypair = Keypair::new();
create_token_2022_account(&mut rpc, &mint, &spl_token_account_keypair, &sender, false)
.await
.unwrap();
mint_spl_tokens(
&mut rpc,
&mint,
&spl_token_account_keypair.pubkey(),
&payer.pubkey(),
&payer,
amount,
false,
)
.await
.unwrap();
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 | 🔴 Critical

Fix token owner mismatch in mint operation.

The SPL token account is created with sender as the owner (line 30), but mint_spl_tokens is called with payer.pubkey() as the token_owner parameter (line 37). This mismatch could cause the mint operation to fail or behave incorrectly.

Apply this diff to fix the token owner:

     mint_spl_tokens(
         &mut rpc,
         &mint,
         &spl_token_account_keypair.pubkey(),
-        &payer.pubkey(),
+        &sender.pubkey(),
         &payer,
         amount,
         false,
     )
📝 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
// Create SPL token account and mint tokens
let spl_token_account_keypair = Keypair::new();
create_token_2022_account(&mut rpc, &mint, &spl_token_account_keypair, &sender, false)
.await
.unwrap();
mint_spl_tokens(
&mut rpc,
&mint,
&spl_token_account_keypair.pubkey(),
&payer.pubkey(),
&payer,
amount,
false,
)
.await
.unwrap();
// Create SPL token account and mint tokens
let spl_token_account_keypair = Keypair::new();
create_token_2022_account(&mut rpc, &mint, &spl_token_account_keypair, &sender, false)
.await
.unwrap();
mint_spl_tokens(
&mut rpc,
&mint,
&spl_token_account_keypair.pubkey(),
&sender.pubkey(),
&payer,
amount,
false,
)
.await
.unwrap();
🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/transfer2/spl_ctoken.rs around
lines 28 to 43, the SPL token account was created with sender as the owner but
mint_spl_tokens is called with payer.pubkey() as the token_owner; change the
token_owner argument in the mint_spl_tokens call to sender.pubkey() so the mint
operation uses the actual account owner and removes the mismatch.

result,
0,
anchor_lang::error::ErrorCode::ConstraintSeeds.into(),
result, 0, 21, //anchor_lang::error::ErrorCode::ConstraintSeeds.into(),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Replace magic number with semantic error constant.

Using the hard-coded error code 21 reduces test readability and maintainability. If this represents the new OneEpochPrefundingNotAllowed error mentioned in the PR, consider defining and using a semantic constant.

-                result, 0, 21, //anchor_lang::error::ErrorCode::ConstraintSeeds.into(),
+                result, 0, ErrorCode::OneEpochPrefundingNotAllowed.into(),

If ErrorCode::OneEpochPrefundingNotAllowed is not accessible in this test file's scope, import it or define a test constant like ONE_EPOCH_PREFUNDING_NOT_ALLOWED_ERROR_CODE at the module level with a clear comment explaining its value.

📝 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
result, 0, 21, //anchor_lang::error::ErrorCode::ConstraintSeeds.into(),
// … previous lines …
result, 0, ErrorCode::OneEpochPrefundingNotAllowed.into(),
// … following lines …
🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/v1.rs around line 1174, replace the
hard-coded magic number 21 with a semantic error constant (e.g.,
ErrorCode::OneEpochPrefundingNotAllowed.into() or a test-level constant
ONE_EPOCH_PREFUNDING_NOT_ALLOWED_ERROR_CODE) to improve readability; if the enum
variant isn't in scope, import the ErrorCode enum or add a module-level const
with a comment clarifying it equals 21, then use that constant in the assertion.

Comment on lines +911 to +912
result, 0,
21, // Panic AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch.into(),
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 | 🟠 Major

Inconsistent error handling approach and unclear comment.

This change directly expects error code 21 (panic), while program-tests/system-test/tests/test.rs (lines 862-868) uses a fallback mechanism that tries the specific error first, then falls back to error code 21. This inconsistency suggests:

  1. Different failure modes: Are these two cases failing differently, or should they use the same pattern?
  2. Unclear intent: The comment "Panic AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch.into()" is ambiguous - does it mean "this panics instead of returning AddressMerkleTreeAccountDiscriminatorMismatch" or "this is a panic case related to AddressMerkleTreeAccountDiscriminatorMismatch"?

Recommendations:

  1. Use the same fallback pattern as in program-tests/system-test/tests/test.rs for consistency:
         assert_rpc_error(
-            result, 0,
-            21, // Panic AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch.into(),
+            result.clone(),
+            0,
+            AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch.into(),
         )
+        .or_else(|_| {
+            // Fallback: program panics instead of returning specific error code
+            assert_rpc_error(result, 0, 21)
+        })
         .unwrap();
  1. If panic is always expected here (not a fallback), clarify the comment:
         assert_rpc_error(
             result, 0,
-            21, // Panic AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch.into(),
+            21, // Program panics with invalid batch tree account instead of returning
+                // AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch
         )
         .unwrap();
  1. Investigate why this specific test case always panics while others (in system-test) require a fallback. Document the findings.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In program-tests/system-cpi-test/tests/test.rs around lines 911-912 the test
unconditionally expects error code 21 (a panic) and leaves an ambiguous comment
about
AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch;
change this to the same two-step fallback pattern used in
program-tests/system-test/tests/test.rs (try to match the specific
AccountCompressionErrorCode::AddressMerkleTreeAccountDiscriminatorMismatch error
first, and if that fails, assert error code 21), replace the ambiguous inline
comment with a clear comment stating "expect specific
AddressMerkleTreeAccountDiscriminatorMismatch or panic fallback (code 21)" and
add a short TODO to investigate and document why this case panics here while the
system-test uses a fallback.

Comment on lines +862 to +868
if assert_rpc_error(result.clone(), 0, expected_error_code).is_err() {
// In case program panics instead of returning an error code.
// This can happen if proof verification fails and debug print runs oom.
assert_rpc_error(result, 0, 21)
} else {
Ok(())
}
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 | 🟠 Major

Fallback to generic panic error weakens test precision.

Accepting error code 21 (ProgramFailedToComplete) as a fallback makes this test less strict and could mask regressions. When proof verification fails, the test should ideally verify the specific failure mode rather than accepting any panic.

Consider one of these approaches:

  1. Fix the root cause: If debug printing causes OOM during proof verification, increase memory limits or reduce debug output rather than accepting panics.
  2. Make the fallback explicit: If panic is the expected behavior for certain inputs, document which test scenarios require this fallback and why.
  3. Add validation: Before falling back to error 21, verify that the failure truly occurred during proof verification (e.g., by checking transaction logs).

Apply this diff to add a clear comment documenting when the fallback is expected:

     let result = rpc
         .create_and_send_transaction(&[instruction], &payer.pubkey(), &[payer])
         .await;
-    if assert_rpc_error(result.clone(), 0, expected_error_code).is_err() {
-        // In case program panics instead of returning an error code.
-        // This can happen if proof verification fails and debug print runs oom.
-        assert_rpc_error(result, 0, 21)
-    } else {
-        Ok(())
-    }
+    // Primary assertion: verify the expected error code
+    if assert_rpc_error(result.clone(), 0, expected_error_code).is_err() {
+        // Fallback: In production, proof verification failures may panic (error code 21)
+        // instead of returning a specific error code when debug assertions run OOM.
+        // TODO: Investigate if memory limits can be increased to avoid this fallback.
+        assert_rpc_error(result, 0, 21)
+    } else {
+        Ok(())
+    }
📝 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
if assert_rpc_error(result.clone(), 0, expected_error_code).is_err() {
// In case program panics instead of returning an error code.
// This can happen if proof verification fails and debug print runs oom.
assert_rpc_error(result, 0, 21)
} else {
Ok(())
}
// Primary assertion: verify the expected error code
if assert_rpc_error(result.clone(), 0, expected_error_code).is_err() {
// Fallback: In production, proof verification failures may panic (error code 21)
// instead of returning a specific error code when debug assertions run OOM.
// TODO: Investigate if memory limits can be increased to avoid this fallback.
assert_rpc_error(result, 0, 21)
} else {
Ok(())
}

Comment on lines +89 to +104
// For non-compressible accounts, authority balance check depends on if they're also the destination
if authority_pubkey == destination {
// Authority is the destination, they receive the lamports
assert_eq!(
final_authority_lamports,
initial_authority_lamports + account_lamports_before_close,
"Authority (as destination) should receive all {} lamports for non-compressible account closure",
account_lamports_before_close
);
} else {
// Authority is not the destination, shouldn't receive anything
assert_eq!(
final_authority_lamports, initial_authority_lamports,
"Authority (not destination) should not receive any lamports for non-compressible account closure"
);
}
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 | 🟠 Major

Missing transaction fee adjustment for non-compressible accounts.

The authority balance checks do not account for transaction fees when the authority is also the payer. This is inconsistent with the compressible account path (lines 312-317, 326-331), which correctly adjusts for tx_fee when authority_pubkey == payer_pubkey.

Apply this diff to add tx_fee handling:

 // For non-compressible accounts, authority balance check depends on if they're also the destination
 if authority_pubkey == destination {
     // Authority is the destination, they receive the lamports
+    let expected_authority_lamports = if authority_pubkey == payer_pubkey {
+        initial_authority_lamports + account_lamports_before_close - tx_fee
+    } else {
+        initial_authority_lamports + account_lamports_before_close
+    };
+
     assert_eq!(
-        final_authority_lamports,
-        initial_authority_lamports + account_lamports_before_close,
+        final_authority_lamports, expected_authority_lamports,
         "Authority (as destination) should receive all {} lamports for non-compressible account closure",
         account_lamports_before_close
     );
 } else {
     // Authority is not the destination, shouldn't receive anything
+    let expected_authority_lamports = if authority_pubkey == payer_pubkey {
+        initial_authority_lamports - tx_fee
+    } else {
+        initial_authority_lamports
+    };
+
     assert_eq!(
-        final_authority_lamports, initial_authority_lamports,
+        final_authority_lamports, expected_authority_lamports,
         "Authority (not destination) should not receive any lamports for non-compressible account closure"
     );
 }
🤖 Prompt for AI Agents
In program-tests/utils/src/assert_close_token_account.rs around lines 89 to 104,
the authority balance assertions for non-compressible account closure don't
account for transaction fees when the authority is also the payer; update the
branch where authority_pubkey == destination to subtract tx_fee from the
expected final_authority_lamports if authority_pubkey == payer_pubkey (i.e.,
expected = initial_authority_lamports + account_lamports_before_close - tx_fee),
and ensure the other branch (authority not destination) similarly subtracts
tx_fee from the expected balance when authority_pubkey == payer_pubkey (i.e.,
expected = initial_authority_lamports - tx_fee); follow the same tx_fee
conditional pattern used in the compressible account checks at lines ~312-331.

process_transfer(accounts, instruction_data)
.map_err(|e| ProgramError::Custom(u64::from(e) as u32))?;

msg!("CToken transfer: transfer processed");
Copy link
Contributor

Choose a reason for hiding this comment

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

msg leftover?

Copy link
Contributor

@SwenSchaeferjohann SwenSchaeferjohann left a comment

Choose a reason for hiding this comment

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

lgtm

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: 3

♻️ Duplicate comments (4)
program-tests/registry-test/tests/compressible.rs (2)

151-156: Fix comment to match epoch range

Comment still says “1 to 10” while the loop actually iterates 2..=11. Please sync the comment with the code.

-    // Create 10 token accounts with varying prepaid epochs (1 to 10)
+    // Create 10 token accounts with varying prepaid epochs (2 to 11)

185-186: Align warp comment with actual epoch count

The comment claims we warp 10 epochs, but the call is warp_epoch_forward(11). Update the comment so it reflects the 11-epoch warp.

-    // Warp forward 10 epochs using the new wrapper method
+    // Warp forward 11 epochs using the new wrapper method
program-tests/compressed-token-test/tests/ctoken/shared.rs (1)

103-105: Wire compress_to_pubkey into create instruction

Set compress_to_account_pubkey to Some(token_account_pubkey) when compressible_data.compress_to_pubkey is true.

-                payer: payer_pubkey,
-                compress_to_account_pubkey: None,
+                payer: payer_pubkey,
+                compress_to_account_pubkey: if compressible_data.compress_to_pubkey {
+                    Some(token_account_pubkey)
+                } else {
+                    None
+                },
                 token_account_version: compressible_data.account_version,

Also applies to: 155-157

program-tests/compressed-token-test/tests/ctoken/transfer.rs (1)

118-122: Pass the real system program ID, not Pubkey::default()

Using Pubkey::default() will make any CPI to system program fail (IncorrectProgramId) during top-ups. Replace with the real system program id.

-            AccountMeta::new_readonly(Pubkey::default(), false), // System program for lamport transfers during top-up
+            AccountMeta::new_readonly(solana_sdk::system_program::ID, false), // System program for lamport transfers during top-up
🧹 Nitpick comments (9)
program-tests/utils/src/assert_create_token_account.rs (1)

142-145: Consider extracting hardcoded fee values to named constants.

The transaction fees (5,000 and 10,000 lamports) are hardcoded. For better maintainability and clarity, consider extracting these to named constants.

+const TX_FEE_PER_SIGNATURE: u64 = 5_000;
+
 // Transaction fee: 5000 lamports per signature
 // For ATA: 1 signer (payer only) = 5,000 lamports
 // For regular token account: 2 signers (token_account_keypair + payer) = 10,000 lamports
-let tx_fee = if is_ata { 5_000 } else { 10_000 };
+let num_signers = if is_ata { 1 } else { 2 };
+let tx_fee = TX_FEE_PER_SIGNATURE * num_signers;
programs/compressed-token/program/tests/multi_sum_check.rs (1)

120-130: Trim iteration/log noise to speed CI (optional).

3000 scenarios with printlns can slow CI. Consider reducing to ~500 and remove prints except on failure.

program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (2)

237-245: Use consistent output queue accessor.

Elsewhere you use get_output_pubkey(); here you use .queue. Prefer a single accessor to avoid API drift:

-    let output_queue = context.rpc.get_random_state_tree_info().unwrap().queue;
+    let output_queue = context
+        .rpc
+        .get_random_state_tree_info()
+        .unwrap()
+        .get_output_pubkey()
+        .unwrap();

Also applies to: 348-356


457-511: Rename var and fix comment: this is payer balance, not pool PDA.

The variable tracks payer balance. Rename and update message for clarity:

-    let pool_balance_before = context
+    let payer_balance_before = context
         .rpc
         .get_account(payer_pubkey)
         .await
         .unwrap()
         .expect("Pool PDA should exist")
         .lamports;
@@
-    assert_eq!(
-        pool_balance_before - payer_balance_after,
+    assert_eq!(
+        payer_balance_before - payer_balance_after,
         rent_exemption + rent + tx_fee,
-        "Pool PDA should have paid {} lamports for account creation (rent-exempt), and the additional rent",
+        "Payer should have paid {} lamports for account creation (rent-exempt) and the additional rent",
         rent_exemption
     );
program-tests/compressed-token-test/tests/ctoken/create.rs (1)

32-47: Comment nit: label says “Three epoch” but uses 2.

Update the test label to avoid confusion.

-    // Test 2: Three epoch prefunding
+    // Test 2: Two epoch prefunding
sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs (1)

29-31: Add doc hint for allowed pre_pay_num_epochs values

-    /// Number of epochs of rent to prepay
+    /// Number of epochs of rent to prepay (0 or ≥ 2; 1 is rejected on-chain)
     pub pre_pay_num_epochs: u8,

Optional: implement an SDK-level check to reject 1 early (negative tests that set 1 will need updating).

program-tests/compressed-token-test/tests/ctoken/transfer.rs (2)

307-312: Avoid hardcoded byte offsets for freezing; use the SPL Account struct

Directly mutating data[108] is brittle. Unpack, set state to Frozen, and repack via spl_token_2022::state::Account for stability across versions.

Also applies to: 336-340


110-113: Prefer a named constant or SDK builder for the discriminator

Hardcoding 3 is error-prone. If available, use a constant or the SDK’s instruction builder to construct the transfer payload.

programs/compressed-token/program/src/transfer2/sum_check.rs (1)

137-140: Don’t conflate “missing mint account” with DuplicateMint

Mapping a missing packed mint account to DuplicateMint is misleading. Prefer a sum-check/validation error (e.g., SumCheckFailed or a specific MissingMint/InvalidMintIndex variant if available).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 165f5d4 and 58dca7f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • program-libs/compressible/docs/RENT.md (2 hunks)
  • program-libs/compressible/src/compression_info.rs (1 hunks)
  • program-libs/compressible/tests/compression_info.rs (1 hunks)
  • program-libs/compressible/tests/rent.rs (3 hunks)
  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/shared.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs (1 hunks)
  • program-tests/registry-test/tests/compressible.rs (29 hunks)
  • program-tests/utils/src/assert_create_token_account.rs (4 hunks)
  • program-tests/utils/src/assert_ctoken_transfer.rs (1 hunks)
  • programs/compressed-token/anchor/src/lib.rs (1 hunks)
  • programs/compressed-token/program/Cargo.toml (1 hunks)
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md (2 hunks)
  • programs/compressed-token/program/src/create_associated_token_account.rs (2 hunks)
  • programs/compressed-token/program/src/create_token_account.rs (3 hunks)
  • programs/compressed-token/program/src/ctoken_transfer.rs (2 hunks)
  • programs/compressed-token/program/src/transfer2/processor.rs (5 hunks)
  • programs/compressed-token/program/src/transfer2/sum_check.rs (5 hunks)
  • programs/compressed-token/program/tests/multi_sum_check.rs (3 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (2 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs (1 hunks)
  • sdk-libs/token-client/src/actions/create_compressible_token_account.rs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • program-libs/compressible/docs/RENT.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • programs/compressed-token/anchor/src/lib.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-tests/compressed-token-test/tests/ctoken/create_ata.rs
  • program-libs/compressible/tests/rent.rs
🧰 Additional context used
📓 Path-based instructions (6)
programs/compressed-token/program/src/ctoken_transfer.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Files:

  • programs/compressed-token/program/src/ctoken_transfer.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/ctoken_transfer.rs
  • programs/compressed-token/program/src/transfer2/sum_check.rs
  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/src/create_token_account.rs
programs/compressed-token/program/src/transfer2/**

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Files:

  • programs/compressed-token/program/src/transfer2/sum_check.rs
  • programs/compressed-token/program/src/transfer2/processor.rs
programs/compressed-token/program/docs/instructions/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
programs/compressed-token/program/docs/**/instructions/**/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Keep detailed instruction documentation files under the instructions/ directory; add additional instruction docs as needed

Files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs}

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Files:

  • programs/compressed-token/program/src/create_token_account.rs
🧠 Learnings (26)
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Applied to files:

  • programs/compressed-token/program/src/ctoken_transfer.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • programs/compressed-token/program/src/ctoken_transfer.rs
  • sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs
  • program-libs/compressible/src/compression_info.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • program-tests/compressed-token-test/tests/ctoken/shared.rs
  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/DECOMPRESSED_TRANSFER.md : Document SPL-compatible transfers between decompressed accounts in instructions/DECOMPRESSED_TRANSFER.md

Applied to files:

  • programs/compressed-token/program/src/ctoken_transfer.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs
  • program-libs/compressible/src/compression_info.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs
  • program-libs/compressible/src/compression_info.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • program-tests/compressed-token-test/tests/ctoken/create.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
  • program-tests/compressed-token-test/tests/ctoken/shared.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • program-libs/compressible/src/compression_info.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • program-tests/utils/src/assert_ctoken_transfer.rs
  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • program-libs/compressible/src/compression_info.rs
  • program-tests/utils/src/assert_create_token_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent curve algorithms via rent_curve_per_epoch

Applied to files:

  • program-libs/compressible/src/compression_info.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/docs/RENT.md : Document rent calculation functions and compressibility checks in docs/RENT.md

Applied to files:

  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Compute close lamport distribution with calculate_close_lamports

Applied to files:

  • program-libs/compressible/src/compression_info.rs
  • program-tests/utils/src/assert_create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/transfer2/** : Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Applied to files:

  • programs/compressed-token/program/src/transfer2/sum_check.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/TRANSFER2.md : Document the batch transfer instruction supporting compressed/decompressed operations in instructions/TRANSFER2.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/MINT_ACTION.md : Document Mint operations and compressed mint management (9 actions) in instructions/MINT_ACTION.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/error.rs : Provide ProgramError conversions compatible with Anchor, Pinocchio, and Solana error types

Applied to files:

  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Return errors as ProgramError::Custom(error_code as u32) on-chain

Applied to files:

  • programs/compressed-token/program/src/transfer2/processor.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • programs/compressed-token/program/src/transfer2/processor.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
  • program-tests/registry-test/tests/compressible.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: CToken account layout matches SPL token accounts with a custom Compressible extension; compressed mint accounts support the TokenMetadata extension

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • program-tests/compressed-token-test/tests/ctoken/create.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/checks.rs : Expose and maintain account validation helpers (check_owner, check_program, check_mut/non_mut, check_signer, check_discriminator, set_discriminator, check_pda_seeds, check_account_balance_is_rent_exempt, account_info_init) in checks.rs

Applied to files:

  • programs/compressed-token/program/tests/multi_sum_check.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/account_info/{solana.rs,pinocchio.rs,test_account_info.rs} : Gate SDK-specific implementations with #[cfg(feature = "solana"|"pinocchio"|"test-only")]

Applied to files:

  • programs/compressed-token/program/tests/multi_sum_check.rs
🧬 Code graph analysis (8)
program-tests/compressed-token-test/tests/ctoken/compress_and_close.rs (2)
program-tests/compressed-token-test/tests/ctoken/shared.rs (5)
  • compress_and_close_owner_and_assert (587-662)
  • create_non_compressible_token_account (210-278)
  • create_and_assert_ata (400-461)
  • compress_and_close_and_assert_fails (672-729)
  • compress_and_close_forester_with_invalid_output (750-902)
sdk-libs/token-client/src/instructions/transfer2.rs (1)
  • create_generic_transfer2_instruction (145-640)
program-tests/utils/src/assert_create_token_account.rs (1)
sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (1)
  • derive_ctoken_ata (226-235)
programs/compressed-token/program/src/transfer2/processor.rs (1)
programs/compressed-token/program/src/transfer2/sum_check.rs (3)
  • sum_check_multi_mint (92-121)
  • sum_compressions (34-63)
  • validate_mint_uniqueness (127-161)
program-tests/compressed-token-test/tests/ctoken/create.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_and_assert_token_account_fails (130-172)
sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs (1)
  • create_compressible_token_account (38-88)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
programs/compressed-token/program/tests/multi_sum_check.rs (1)
programs/compressed-token/program/src/transfer2/sum_check.rs (2)
  • sum_check_multi_mint (92-121)
  • validate_mint_uniqueness (127-161)
program-tests/compressed-token-test/tests/ctoken/shared.rs (8)
sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (5)
  • create_associated_token_account (98-104)
  • derive_ctoken_ata (226-235)
  • create_compressible_associated_token_account_idempotent (48-52)
  • create_compressible_associated_token_account (41-45)
  • create_associated_token_account_idempotent (107-113)
sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs (2)
  • create_token_account (90-116)
  • create_compressible_token_account (38-88)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/utils/src/assert_create_token_account.rs (2)
  • assert_create_token_account (236-252)
  • assert_create_associated_token_account (258-291)
sdk-libs/program-test/src/compressible.rs (1)
  • new (44-64)
sdk-libs/token-client/src/actions/create_compressible_token_account.rs (1)
  • create_compressible_token_account (29-95)
sdk-libs/token-client/src/instructions/transfer2.rs (1)
  • create_generic_transfer2_instruction (145-640)
programs/registry/src/utils.rs (1)
  • get_forester_epoch_pda_from_authority (13-16)
program-tests/compressed-token-test/tests/ctoken/transfer.rs (3)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_token_account (82-127)
  • create_non_compressible_token_account (210-278)
program-tests/utils/src/assert_ctoken_transfer.rs (1)
  • assert_ctoken_transfer (150-201)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/registry-test/tests/compressible.rs (2)
program-tests/utils/src/spl.rs (1)
  • create_mint_helper (260-263)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: cli-v1
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: Test program-libs-fast
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address"])
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: stateless-js-v2
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip test_tran...
  • GitHub Check: lint
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: cli-v2
  • GitHub Check: stateless-js-v1
  • GitHub Check: Forester e2e test
🔇 Additional comments (19)
programs/compressed-token/program/src/create_token_account.rs (1)

165-168: Clear guard against 1-epoch prefunding

Nice job adding the explicit check and error to stop the 1-epoch footgun while preserving the informative log message. Fully aligned with the associated ATA flow.

program-tests/utils/src/assert_create_token_account.rs (7)

29-48: LGTM! Well-structured function signature and validation.

The addition of the is_ata parameter to distinguish between ATA (1 signer) and regular token accounts (2 signers) is a good design choice that enables more accurate fee validation. The basic account validation is correct.


63-110: LGTM! Compressible account validation is thorough and correct.

The rent calculation, lamports balance verification, and zero-copy deserialization are all properly implemented. The type casts (u8→u64 at line 65, bool→u8 at line 103) are appropriate conversions for the underlying data structures.


112-158: Excellent idempotent mode handling!

The detection of existing accounts via get_pre_transaction_account and the special handling to only validate transaction fees in idempotent mode is well-designed and prevents false positives when accounts are created idempotently.


160-194: LGTM! Fee handling logic is precise and well-documented.

The distinction between custom fee payer (where payer pays everything) and split payment scenarios (where rent sponsor pays rent exemption and payer pays compression cost + tx fee) is correctly implemented with comprehensive assertions and clear error messages.


234-252: LGTM! Clean public API wrapper.

The separation of the public API wrapper from the internal implementation provides good encapsulation and makes the distinction between ATA and regular token accounts clear to callers.


254-291: LGTM! ATA wrapper with helpful validation.

The explicit existence check at lines 267-279 provides clear, contextual error messages when the ATA doesn't exist at the derived address, improving the debugging experience. The wrapper correctly derives the ATA address and delegates to the internal function.


17-17: Verify u8 limit for num_prepaid_epochs
Ensure narrowing from u64 to u8 (0–255) covers all current and future use cases; confirm no scenario requires more than 255 prepaid epochs.

programs/compressed-token/program/src/ctoken_transfer.rs (2)

23-34: Guarding SPL transfer preconditions looks solid.

process_transfer always expects source, destination, and authority; failing fast with NotEnoughAccountKeys keeps us SPL-compatible and avoids later panics.


75-82: Thanks for removing the hard-coded rent exemption.

Routing through COMPRESSIBLE_TOKEN_RENT_EXEMPTION keeps this logic aligned with the shared rent policy and resolves the prior duplication.

sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (1)

32-33: Type change keeps client and instruction in sync.

Limiting pre_pay_num_epochs to u8 mirrors the on-chain struct and blocks accidental oversized prefunding requests.

programs/compressed-token/program/docs/instructions/TRANSFER2.md (1)

275-307: Error matrix update is comprehensive.

Documenting DuplicateMint alongside the existing sum-check failures keeps operators aligned with the new invariant.

program-libs/ctoken-types/src/instructions/extensions/compressible.rs (1)

18-23: rent_payment downcast matches new validation limits.

Switching to u8 aligns serialization with the SDK and enforces the max-epoch policy directly in the instruction payload.

program-libs/compressible/src/compression_info.rs (1)

113-125: Switching to available_balance clarifies the funding window.

Deriving epochs_funded_ahead from get_available_rent_balance mirrors the rent helpers and should prevent the negative-balance edge cases we saw with the previous heuristic.

program-tests/utils/src/assert_ctoken_transfer.rs (1)

105-127: Test now mirrors the on-chain top-up inputs.

Using the pre-transfer lamports together with COMPRESSIBLE_TOKEN_RENT_EXEMPTION makes the assertion match calculate_and_execute_top_up_transfers, so any drift will surface immediately.

programs/compressed-token/program/src/transfer2/processor.rs (1)

191-197: Nice: multi‑mint sum check integrated pre‑CPI with mint_map.

Returning the mint_map and following with a uniqueness check aligns with Transfer2 requirements.

programs/compressed-token/program/tests/multi_sum_check.rs (1)

382-421: Good coverage for duplicate mint index scenarios.

Validates allowed same-index aggregation across inputs/compressions and different mints. LGTM.

programs/compressed-token/program/src/transfer2/sum_check.rs (1)

92-121: On-chain error mapping is correctly implemented
Errors returned as ErrorCode by sum checks are mapped to ProgramError::Custom(e as u32 + 6000) in programs/compressed-token/program/src/transfer2/processor.rs.

program-tests/compressed-token-test/tests/ctoken/transfer.rs (1)

187-205: Review comment is incorrect—assert_ctoken_transfer tolerates non-compressible accounts.

The helper only validates compressible extensions if they existed before the transfer (lines 57–83). For non-compressible accounts without extensions, the validation block is skipped and the function returns successfully. The test will not encounter false failures.

Comment on lines +216 to +257
// Error: 1 (InsufficientFunds from system program)
{
// Create a payer with insufficient funds (only enough for tx fees + account creation)
let poor_payer = Keypair::new();
context
.rpc
.airdrop_lamports(&poor_payer.pubkey(), 10000) // Not enough for additional rent
.await
.unwrap();

let poor_payer_pubkey = poor_payer.pubkey();
let token_account_pubkey = Keypair::new();

let create_token_account_ix =
light_compressed_token_sdk::instructions::create_compressible_token_account(
light_compressed_token_sdk::instructions::CreateCompressibleTokenAccount {
account_pubkey: token_account_pubkey.pubkey(),
mint_pubkey: context.mint_pubkey,
owner_pubkey: context.owner_keypair.pubkey(),
compressible_config: context.compressible_config,
rent_sponsor: context.rent_sponsor,
pre_pay_num_epochs: 10, // High number to require more lamports
lamports_per_write: Some(1000),
payer: poor_payer_pubkey,
compress_to_account_pubkey: None,
token_account_version: light_ctoken_types::state::TokenDataVersion::ShaFlat,
},
)
.unwrap();

let result = context
.rpc
.create_and_send_transaction(
&[create_token_account_ix],
&poor_payer_pubkey,
&[&poor_payer, &token_account_pubkey],
)
.await;

// Should fail with InsufficientFunds (1) from system program
light_program_test::utils::assert::assert_rpc_error(result, 0, 1).unwrap();
}
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 | 🔴 Critical

Fix expected error code for InsufficientFunds (should be 6).

Solana InstructionError::InsufficientFunds is 6, not 1. Update comment and assertion:

-    // Error: 1 (InsufficientFunds from system program)
+    // Error: 6 (InsufficientFunds from system program)
@@
-        // Should fail with InsufficientFunds (1) from system program
-        light_program_test::utils::assert::assert_rpc_error(result, 0, 1).unwrap();
+        // Should fail with InsufficientFunds (6) from system program
+        light_program_test::utils::assert::assert_rpc_error(result, 0, 6).unwrap();
📝 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
// Error: 1 (InsufficientFunds from system program)
{
// Create a payer with insufficient funds (only enough for tx fees + account creation)
let poor_payer = Keypair::new();
context
.rpc
.airdrop_lamports(&poor_payer.pubkey(), 10000) // Not enough for additional rent
.await
.unwrap();
let poor_payer_pubkey = poor_payer.pubkey();
let token_account_pubkey = Keypair::new();
let create_token_account_ix =
light_compressed_token_sdk::instructions::create_compressible_token_account(
light_compressed_token_sdk::instructions::CreateCompressibleTokenAccount {
account_pubkey: token_account_pubkey.pubkey(),
mint_pubkey: context.mint_pubkey,
owner_pubkey: context.owner_keypair.pubkey(),
compressible_config: context.compressible_config,
rent_sponsor: context.rent_sponsor,
pre_pay_num_epochs: 10, // High number to require more lamports
lamports_per_write: Some(1000),
payer: poor_payer_pubkey,
compress_to_account_pubkey: None,
token_account_version: light_ctoken_types::state::TokenDataVersion::ShaFlat,
},
)
.unwrap();
let result = context
.rpc
.create_and_send_transaction(
&[create_token_account_ix],
&poor_payer_pubkey,
&[&poor_payer, &token_account_pubkey],
)
.await;
// Should fail with InsufficientFunds (1) from system program
light_program_test::utils::assert::assert_rpc_error(result, 0, 1).unwrap();
}
// Error: 6 (InsufficientFunds from system program)
{
// Create a payer with insufficient funds (only enough for tx fees + account creation)
let poor_payer = Keypair::new();
context
.rpc
.airdrop_lamports(&poor_payer.pubkey(), 10000) // Not enough for additional rent
.await
.unwrap();
let poor_payer_pubkey = poor_payer.pubkey();
let token_account_pubkey = Keypair::new();
let create_token_account_ix =
light_compressed_token_sdk::instructions::create_compressible_token_account(
light_compressed_token_sdk::instructions::CreateCompressibleTokenAccount {
account_pubkey: token_account_pubkey.pubkey(),
mint_pubkey: context.mint_pubkey,
owner_pubkey: context.owner_keypair.pubkey(),
compressible_config: context.compressible_config,
rent_sponsor: context.rent_sponsor,
pre_pay_num_epochs: 10, // High number to require more lamports
lamports_per_write: Some(1000),
payer: poor_payer_pubkey,
compress_to_account_pubkey: None,
token_account_version: light_ctoken_types::state::TokenDataVersion::ShaFlat,
},
)
.unwrap();
let result = context
.rpc
.create_and_send_transaction(
&[create_token_account_ix],
&poor_payer_pubkey,
&[&poor_payer, &token_account_pubkey],
)
.await;
// Should fail with InsufficientFunds (6) from system program
light_program_test::utils::assert::assert_rpc_error(result, 0, 6).unwrap();
}
🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/ctoken/create.rs around lines 216
to 257, the test expects InsufficientFunds error code 1 but Solana's
InstructionError::InsufficientFunds is 6; update the inline comment to reflect
the correct code and change the assert_rpc_error call to expect 6 instead of 1
(i.e., replace the asserted error code value and update the comment text
accordingly).

Comment on lines +129 to 135
let mut mint_map: ArrayMap<u8, u64, 5> = ArrayMap::new();
sum_compressions(compressions, &mut mint_map)?;

// Validate mint uniqueness
validate_mint_uniqueness(&mint_map, &validated_accounts.packed_accounts)
.map_err(|e| ProgramError::Custom(e as u32 + 6000))?;

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 | 🟠 Major

Do not offset custom error codes; return ProgramError::Custom(e as u32).

Per guidelines, on-chain must map to ProgramError::Custom(error_code as u32). The +6000 offset breaks consistency and downstream assertions.

Apply:

-    validate_mint_uniqueness(&mint_map, &validated_accounts.packed_accounts)
-        .map_err(|e| ProgramError::Custom(e as u32 + 6000))?;
+    validate_mint_uniqueness(&mint_map, &validated_accounts.packed_accounts)
+        .map_err(|e| ProgramError::Custom(e as u32))?;
@@
-    let mint_map = sum_check_multi_mint(
+    let mint_map = sum_check_multi_mint(
         &inputs.in_token_data,
         &inputs.out_token_data,
         inputs.compressions.as_deref(),
     )
-    .map_err(|e| ProgramError::Custom(e as u32 + 6000))?;
+    .map_err(|e| ProgramError::Custom(e as u32))?;
@@
-    validate_mint_uniqueness(&mint_map, &validated_accounts.packed_accounts)
-        .map_err(|e| ProgramError::Custom(e as u32 + 6000))?;
+    validate_mint_uniqueness(&mint_map, &validated_accounts.packed_accounts)
+        .map_err(|e| ProgramError::Custom(e as u32))?;

As per coding guidelines

Also applies to: 191-202

🤖 Prompt for AI Agents
In programs/compressed-token/program/src/transfer2/processor.rs around lines
129-135 (and also apply the same change at lines 191-202), the review points out
that custom error codes are being offset by +6000 when converted to
ProgramError::Custom; remove the +6000 offset so the function maps errors
directly using ProgramError::Custom(e as u32). Update both call sites to return
ProgramError::Custom(e as u32) instead of ProgramError::Custom(e as u32 + 6000),
ensuring the error type casts to u32 as before.

Comment on lines +143 to +156
if let Some(existing_index) = seen_pubkeys.get_by_pubkey(mint_pubkey) {
// Same pubkey referenced by different index - this is an attack
if *existing_index != *mint_index {
msg!(
"Duplicate mint detected: index {} and {} both reference the same mint pubkey",
existing_index,
mint_index
);
return Err(ErrorCode::DuplicateMint);
}
} else {
// First time seeing this pubkey, record it
seen_pubkeys.insert(*mint_pubkey, *mint_index, ErrorCode::TooManyMints)?;
}
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 | 🔴 Critical

Fix invalid method call on ArrayMap: use get_by_key

ArrayMap doesn’t expose get_by_pubkey. This won’t compile. Use get_by_key with the same key type as the map.

-            if let Some(existing_index) = seen_pubkeys.get_by_pubkey(mint_pubkey) {
+            if let Some(existing_index) = seen_pubkeys.get_by_key(mint_pubkey) {
                 // Same pubkey referenced by different index - this is an attack
                 if *existing_index != *mint_index {
                     msg!(
                         "Duplicate mint detected: index {} and {} both reference the same mint pubkey",
                         existing_index,
                         mint_index
                     );
                     return Err(ErrorCode::DuplicateMint);
                 }
             } else {
                 // First time seeing this pubkey, record it
                 seen_pubkeys.insert(*mint_pubkey, *mint_index, ErrorCode::TooManyMints)?;
             }
🤖 Prompt for AI Agents
In programs/compressed-token/program/src/transfer2/sum_check.rs around lines
143–156, the code calls seen_pubkeys.get_by_pubkey(mint_pubkey) which doesn't
exist on ArrayMap; replace that call with seen_pubkeys.get_by_key(...) using the
exact key type the map expects (e.g., pass *mint_pubkey if the map keys are
Pubkey or &mint_pubkey if it expects a reference) so the lookup compiles; leave
the insert logic as-is but ensure the key/value types you pass to get_by_key and
insert match the ArrayMap's key/value types.

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: 3

♻️ Duplicate comments (3)
program-tests/compressed-token-test/tests/v1.rs (2)

1174-1174: Conflating distinct error types to generic error code reduces test precision.

Multiple semantically different error checks (ConstraintSeeds, StateMerkleTreeAccountDiscriminatorMismatch, ProofVerificationFailed) are now standardized to the hard-coded error code 21 (InstructionError::ProgramFailedToComplete). This generic built-in Solana error is far less specific than the original custom error codes, resulting in:

  1. Loss of semantic information - tests can no longer distinguish between different failure modes (e.g., invalid seeds vs. account discriminator mismatch)
  2. Reduced test coverage - a single error code now covers multiple distinct program error paths, potentially masking regressions
  3. Poor maintainability - the magic number 21 requires consulting comments or external references to understand its meaning

If the underlying program behavior has changed to emit ProgramFailedToComplete in these scenarios, consider:

  • Defining test-level constants like PROGRAM_FAILED_TO_COMPLETE_ERROR_CODE = 21 with explanatory comments
  • Documenting why these previously distinct errors now map to the same code
  • Verifying whether this conflation is intentional or if more specific error codes should be restored

Based on past review comments.

Also applies to: 1239-1240, 2284-2285, 2329-2330, 2761-2762


5962-5962: Replace magic number with semantic constant.

Error code 21 lacks clarity. Define a test-level constant or use a descriptive identifier to improve readability:

-        assert_rpc_error(result, 0, 21).unwrap();
+        // ProgramFailedToComplete when no sender account is provided
+        const PROGRAM_FAILED_TO_COMPLETE: u32 = 21;
+        assert_rpc_error(result, 0, PROGRAM_FAILED_TO_COMPLETE).unwrap();

Alternatively, if this maps to a specific custom error like OneEpochPrefundingNotAllowed mentioned in the PR, use that error code instead.

Based on past review comments.

.github/workflows/programs.yml (1)

32-120: Add an explicit permissions block.

The workflow still runs with default write-all token permissions. Please add the minimal block (permissions: contents: read) at the job or workflow level to close out the CodeQL warning.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58dca7f and 918cccf.

📒 Files selected for processing (5)
  • .github/workflows/programs.yml (1 hunks)
  • program-libs/compressible/src/compression_info.rs (1 hunks)
  • program-libs/compressible/src/rent/account_rent.rs (3 hunks)
  • program-libs/compressible/tests/compression_info.rs (2 hunks)
  • program-tests/compressed-token-test/tests/v1.rs (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • program-libs/compressible/src/compression_info.rs
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Implement rent curve algorithms via rent_curve_per_epoch

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Compute close lamport distribution with calculate_close_lamports

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
🧬 Code graph analysis (1)
program-tests/compressed-token-test/tests/v1.rs (1)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
🪛 GitHub Check: CodeQL
.github/workflows/programs.yml

[warning] 34-120: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: stateless-js-v2
  • GitHub Check: stateless-js-v1
  • GitHub Check: lint
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: Test program-libs-fast
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: Test program-libs-slow
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test --test v1", "cargo-...
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address", "c...
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...
  • GitHub Check: Forester e2e test
  • GitHub Check: cli-v2
  • GitHub Check: cli-v1
🔇 Additional comments (4)
program-libs/compressible/tests/compression_info.rs (3)

334-564: Excellent comprehensive test coverage!

The new test_calculate_top_up_lamports test function is well-structured with:

  • Clear organization using TestCase struct
  • Systematic coverage of three main paths (compressible, not compressible, well-funded)
  • Thorough edge case testing
  • Descriptive test case names and documentation
  • Detailed assertion messages for debugging

The test cases effectively verify the rent calculation logic across various scenarios including epoch boundaries, partial epochs, and extreme gaps.


526-533: Verify the invalid state edge case is intentionally supported.

This test case explicitly sets up an invalid state where current_lamports is missing the required FULL_COMPRESSION_COSTS. While testing saturating_sub behavior is good defensive programming, confirm that your implementation should gracefully handle this invalid state rather than rejecting it with an error.

If accounts should never reach this state in practice, consider whether an explicit validation error would be more appropriate than silently handling it with saturating subtraction.

Based on learnings


9-10: Constants are verified as consistent across the codebase.

All values check out:

  • TEST_BYTES = 260 matches in both test files
  • RENT_PER_EPOCH = 260 + 128 is consistent everywhere
  • Rent exemption value 2700480 matches COMPRESSIBLE_TOKEN_RENT_EXEMPTION defined in program-libs/ctoken-types/src/constants.rs:22 and is used consistently throughout the codebase
program-libs/compressible/src/rent/account_rent.rs (1)

81-82: LGTM: Good defensive overflow protection.

Using saturating_mul instead of direct multiplication prevents potential integer overflow in rent calculations. The comment accurately notes it's cheaper than checked_mul since it avoids conditional branching. In the extremely unlikely event of overflow with unrealistic epoch or rent values, saturation provides sensible fallback behavior:

  • is_compressible correctly identifies the account as compressible with a large deficit
  • calculate_claimable_rent caps at u64::MAX (only called after passing compressibility check)
  • get_unused_lamports returns 0, correctly indicating no unused lamports if rent due is massive

For production blockchain code, graceful degradation via saturation is preferable to panicking.

Also applies to: 115-116, 156-157

Comment on lines +33 to +76
system-programs:
name: programs
if: github.event.pull_request.draft == false
runs-on: warp-ubuntu-latest-x64-4x
timeout-minutes: 90

services:
redis:
image: redis:8.0.1
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

env:
REDIS_URL: redis://localhost:6379

strategy:
matrix:
include:
- program: account-compression-and-registry
sub-tests: '["cargo-test-sbf -p account-compression-test", "cargo-test-sbf -p registry-test"]'
- program: light-system-program-address
sub-tests: '["cargo-test-sbf -p system-test -- test_with_address", "cargo-test-sbf -p e2e-test", "cargo-test-sbf -p compressed-token-test --test ctoken"]'
- program: light-system-program-compression
sub-tests: '["cargo-test-sbf -p system-test -- test_with_compression", "cargo-test-sbf -p system-test --test test_re_init_cpi_account"]'
- program: compressed-token-and-e2e
sub-tests: '["cargo-test-sbf -p compressed-token-test --test v1", "cargo-test-sbf -p compressed-token-test --test mint"]'
- program: compressed-token-batched-tree
sub-tests: '["cargo-test-sbf -p compressed-token-test -- test_transfer_with_photon_and_batched_tree"]'
- program: system-cpi-test
sub-tests:
'["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-program-pinocchio",
"cargo-test-sbf -p system-cpi-v2-test -- --skip functional_ --skip event::parse", "cargo-test-sbf -p system-cpi-v2-test -- event::parse"
"cargo-test-sbf -p compressed-token-test --test transfer2"
]'
- program: system-cpi-test-v2-functional-read-only
sub-tests: '["cargo-test-sbf -p system-cpi-v2-test -- functional_read_only"]'
- program: system-cpi-test-v2-functional-account-infos
sub-tests: '["cargo-test-sbf -p system-cpi-v2-test -- functional_account_infos"]'
steps:
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 | 🟠 Major

Allow push workflows to run.

if: github.event.pull_request.draft == false short-circuits every push build because github.event.pull_request is null on push events, leaving main without coverage. Gate only pull_request events (e.g., if: github.event_name != 'pull_request' || github.event.pull_request.draft == false') so pushes still execute.

-    if: github.event.pull_request.draft == false
+    if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
🤖 Prompt for AI Agents
In .github/workflows/programs.yml around lines 33 to 76 the current if:
github.event.pull_request.draft == false will be null on push events and
short-circuit those runs; change the conditional to only gate draft pull
requests by using a compound check such as: if: github.event_name !=
'pull_request' || github.event.pull_request.draft == false so that
non-pull_request events (pushes) still run while draft PRs remain blocked.

Comment on lines +93 to +118
IFS=',' read -r -a sub_tests <<< "${{ join(fromJSON(matrix['sub-tests']), ', ') }}"
for subtest in "${sub_tests[@]}"
do
echo "$subtest"

# Retry logic for flaky batched-tree test
if [[ "$subtest" == *"test_transfer_with_photon_and_batched_tree"* ]]; then
echo "Running flaky test with retry logic (max 3 attempts)..."
attempt=1
max_attempts=3
until RUSTFLAGS="-D warnings" eval "$subtest"; do
attempt=$((attempt + 1))
if [ $attempt -gt $max_attempts ]; then
echo "Test failed after $max_attempts attempts"
exit 1
fi
echo "Attempt $attempt/$max_attempts failed, retrying..."
sleep 5
done
echo "Test passed on attempt $attempt"
else
RUSTFLAGS="-D warnings" eval "$subtest"
if [ "$subtest" == "cargo-test-sbf -p e2e-test" ]; then
pnpm --filter @lightprotocol/programs run build-compressed-token-small
RUSTFLAGS="-D warnings" eval "$subtest -- --test test_10_all"
fi
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 | 🟠 Major

Trim subtest strings before comparisons.

Splitting on commas leaves each element with a leading space, so the literal comparison on Line 115 never matches "cargo-test-sbf -p e2e-test". As a result, the extra CLI build and --test test_10_all run are silently skipped. Strip the whitespace (e.g., subtest="${subtest## }") or iterate the JSON array directly to ensure the equality check fires.

-          for subtest in "${sub_tests[@]}"
+          for subtest in "${sub_tests[@]}"
           do
-            echo "$subtest"
+            subtest="${subtest## }"
+            echo "$subtest"
🤖 Prompt for AI Agents
In .github/workflows/programs.yml around lines 93 to 118, the elements produced
by splitting the JSON string contain leading spaces so the equality check for
"cargo-test-sbf -p e2e-test" never matches; fix this by trimming
leading/trailing whitespace from each subtest before any comparisons or evals
(or iterate the JSON array directly), and use the trimmed value for the
retry/eval and the subsequent equality branch so the extra build and the `--test
test_10_all` invocation run as intended.

@ananas-block ananas-block force-pushed the jorrit/fix-pre-funding-compressible-account branch from 3422afc to a0c9ae0 Compare October 16, 2025 04:53
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: 2

♻️ Duplicate comments (1)
programs/compressed-token/program/src/create_token_account.rs (1)

164-168: Consistent validation with ATA creation.

The 1-epoch prefunding validation correctly prevents the footgun scenario and mirrors the logic in create_associated_token_account.rs. The error message clearly explains the issue and suggests alternatives.

However, as noted in the previous review, explicit test coverage for this error path is still missing.

As per coding guidelines (based on learnings).

🧹 Nitpick comments (5)
programs/compressed-token/program/tests/allocation_test.rs (1)

21-29: LGTM! Clean migration to tinyvec.

The replacement of arrayvec::ArrayVec with tinyvec::ArrayVec is correct. Element types satisfy the Default requirement, and capacities (35 for outputs, 8 for inputs) are appropriate for these test cases.

Optional: Consider using the array_vec! macro for cleaner construction.

Based on learnings, tinyvec provides the array_vec! macro for more concise initialization:

-    let mut outputs_no_ext = tinyvec::ArrayVec::<[(bool, u32); 35]>::new();
-    outputs_no_ext.push((true, expected_mint_size_no_ext as u32));
+    let mut outputs_no_ext = tinyvec::array_vec![(bool, u32); 35 => (true, expected_mint_size_no_ext as u32)];

However, the current explicit form is also perfectly fine and may be clearer for readers unfamiliar with the macro.

Also applies to: 54-62

programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs (1)

34-43: Consider removing commented-out code.

The commented-out PDA verification logic is no longer in use and leaves the _program_id parameter (line 16) unused. Consider either removing this dead code and the unused parameter, or uncommenting and completing the verification if it's needed.

program-tests/compressed-token-test/tests/mint/random.rs (1)

320-349: Simpler filtering approach improves maintainability.

The state-based filtering using a HashSet to track removed keys is correct and more maintainable than complex reordering logic. The manual index manipulation handles the removal case properly by not incrementing when an action is dropped.

For a more idiomatic Rust pattern, consider using retain or filter to avoid manual index management:

-        let mut removed_keys: HashSet<Vec<u8>> = HashSet::new();
-        let mut i = 0;
-
-        while i < actions.len() {
-            match &actions[i] {
-                MintActionType::RemoveMetadataKey { key, .. } => {
-                    // Track that this key has been removed
-                    removed_keys.insert(key.clone());
-                    i += 1;
-                }
-                MintActionType::UpdateMetadataField {
-                    key, field_type: 3, ..
-                } => {
-                    // If trying to update a key that was already removed, remove this action
-                    if removed_keys.contains(key) {
-                        actions.remove(i);
-                        // Don't increment i, check the same position again
-                    } else {
-                        i += 1;
-                    }
-                }
-                _ => {
-                    i += 1;
-                }
-            }
-        }
+        // First pass: collect all removed keys
+        let removed_keys: HashSet<Vec<u8>> = actions
+            .iter()
+            .filter_map(|action| match action {
+                MintActionType::RemoveMetadataKey { key, .. } => Some(key.clone()),
+                _ => None,
+            })
+            .collect();
+
+        // Second pass: filter out updates for removed keys
+        actions.retain(|action| {
+            !matches!(
+                action,
+                MintActionType::UpdateMetadataField {
+                    key,
+                    field_type: 3,
+                    ..
+                } if removed_keys.contains(key)
+            )
+        });

This two-pass approach separates concerns (collecting removed keys, then filtering) and avoids manual index management, though both implementations are functionally correct.

programs/compressed-token/program/src/extensions/mod.rs (1)

125-126: Clarify the mixed usage of arrayvec and tinyvec.

The code uses arrayvec::ArrayVec for configs (line 125) and tinyvec::ArrayVec for processed_keys (line 126). While both serve similar purposes, mixing two different crate implementations in the same function can reduce maintainability and increase cognitive load.

Consider standardizing on one crate throughout this module. Based on the retrieved learnings, tinyvec 1.10.0 is 100% safe Rust and actively maintained. If the broader codebase is migrating to tinyvec, complete the migration here; otherwise, document why both are needed.

Based on learnings.

programs/compressed-token/program/src/create_associated_token_account.rs (1)

151-155: Consider extracting the validation to a shared helper.

This validation is identical to the one in create_token_account.rs (lines 164-168). While the duplication is minimal, extracting it to a shared validation function would ensure consistency and make future policy changes easier to maintain.

Example:

// In shared module:
pub fn validate_rent_payment(rent_payment: u32) -> Result<(), ProgramError> {
    if rent_payment == 1 {
        msg!("Prefunding for exactly 1 epoch is not allowed. If the account is created near an epoch boundary, it could become immediately compressible. Use 0 or 2+ epochs.");
        return Err(anchor_compressed_token::ErrorCode::OneEpochPrefundingNotAllowed.into());
    }
    Ok(())
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3422afc and a0c9ae0.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .github/workflows/programs.yml (1 hunks)
  • program-libs/ctoken-types/Cargo.toml (1 hunks)
  • program-libs/ctoken-types/src/hash_cache.rs (2 hunks)
  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs (3 hunks)
  • program-tests/compressed-token-test/tests/mint/random.rs (1 hunks)
  • programs/compressed-token/program/Cargo.toml (1 hunks)
  • programs/compressed-token/program/src/create_associated_token_account.rs (3 hunks)
  • programs/compressed-token/program/src/create_token_account.rs (4 hunks)
  • programs/compressed-token/program/src/extensions/mod.rs (1 hunks)
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs (1 hunks)
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs (1 hunks)
  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs (1 hunks)
  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs (2 hunks)
  • programs/compressed-token/program/src/shared/create_pda_account.rs (2 hunks)
  • programs/compressed-token/program/src/transfer2/cpi.rs (2 hunks)
  • programs/compressed-token/program/tests/allocation_test.rs (3 hunks)
  • programs/compressed-token/program/tests/exact_allocation_test.rs (2 hunks)
  • programs/compressed-token/program/tests/token_input.rs (1 hunks)
  • programs/compressed-token/program/tests/token_output.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/programs.yml
  • program-libs/ctoken-types/Cargo.toml
  • programs/compressed-token/program/Cargo.toml
  • program-libs/ctoken-types/src/hash_cache.rs
🧰 Additional context used
📓 Path-based instructions (4)
programs/compressed-token/program/src/transfer2/**

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Files:

  • programs/compressed-token/program/src/transfer2/cpi.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/transfer2/cpi.rs
  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/extensions/mod.rs
  • programs/compressed-token/program/src/shared/create_pda_account.rs
  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
programs/compressed-token/program/src/mint_action/**

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

MintAction must implement the 9 listed actions and handle both compressed and decompressed minting flows

Files:

  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs
programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs}

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
🧠 Learnings (26)
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/**/*.rs : Pass the data Vec<u8> through unchanged from the wrapper to the target program CPI; the target program performs deserialization.

Applied to files:

  • programs/compressed-token/program/src/transfer2/cpi.rs
  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/tests/token_output.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs
  • programs/compressed-token/program/tests/token_input.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/shared/create_pda_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/error.rs : Provide ProgramError conversions compatible with Anchor, Pinocchio, and Solana error types

Applied to files:

  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/shared/create_pda_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Return errors as ProgramError::Custom(error_code as u32) on-chain

Applied to files:

  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs
  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs
  • programs/compressed-token/program/src/shared/create_pda_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement CompressibleConfig account with Anchor, Borsh, and Pod serialization for Light Registry integration

Applied to files:

  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/tests/token_output.rs
  • programs/compressed-token/program/tests/token_input.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Applied to files:

  • programs/compressed-token/program/src/mint_action/zero_copy_config.rs
  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/**/*.rs : CPI processing functions must derive PDA signer seeds as [CPI_AUTHORITY_PDA_SEED, bump] and use CpiContext::new_with_signer with cpi_authority as the authority account and mapped target accounts.

Applied to files:

  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs
  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • programs/compressed-token/program/src/shared/create_pda_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: CToken account layout matches SPL token accounts with a custom Compressible extension; compressed mint accounts support the TokenMetadata extension

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/*.rs : Context structs for wrapper instructions must include standard accounts: optional registered_forester_pda (mut), authority Signer, cpi_authority with seeds/bump for CPI_AUTHORITY_PDA_SEED, registered_program_pda, target program handle, log_wrapper, and mutable target_account.

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/checks.rs : Expose and maintain account validation helpers (check_owner, check_program, check_mut/non_mut, check_signer, check_discriminator, set_discriminator, check_pda_seeds, check_account_balance_is_rent_exempt, account_info_init) in checks.rs

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
  • programs/compressed-token/program/src/create_associated_token_account.rs
  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Expose claimable rent computation via claimable_lamports

Applied to files:

  • programs/compressed-token/program/src/create_token_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/error.rs : Maintain stable mapping of AccountError to ProgramError, including Pinocchio code mapping (1–11), in error.rs

Applied to files:

  • programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs
  • programs/compressed-token/program/src/shared/create_pda_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/account_iterator.rs : Use AccountIterator for sequential account retrieval to get precise file:line:column error locations; avoid manual index handling

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Provide PDA derivation helpers derive_pda and derive_v1_config_pda for CompressibleConfig

Applied to files:

  • programs/compressed-token/program/src/create_associated_token_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/account_info/{solana.rs,pinocchio.rs,test_account_info.rs} : Gate SDK-specific implementations with #[cfg(feature = "solana"|"pinocchio"|"test-only")]

Applied to files:

  • programs/compressed-token/program/src/shared/create_pda_account.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/discriminator.rs : Define and keep discriminator constants and the Discriminator trait in discriminator.rs for compile-time verification

Applied to files:

  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : Validate account type with 8-byte discriminators using check_discriminator before deserialization

Applied to files:

  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
📚 Learning: 2025-10-11T21:59:52.702Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/docs/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:52.702Z
Learning: Applies to program-libs/account-checks/docs/**/DISCRIMINATOR.md : DISCRIMINATOR.md must document 8-byte discriminators, the Discriminator trait, constant arrays for compile-time checks, and integration with account initialization

Applied to files:

  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : On account initialization, call account_info_init to set the 8-byte discriminator

Applied to files:

  • programs/compressed-token/program/src/shared/cpi_bytes_size.rs
🧬 Code graph analysis (4)
programs/compressed-token/program/tests/token_output.rs (1)
programs/compressed-token/program/src/shared/cpi_bytes_size.rs (1)
  • compressed_token_data_len (30-36)
programs/compressed-token/program/src/create_token_account.rs (1)
programs/compressed-token/anchor/src/lib.rs (1)
  • from (422-424)
programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs (1)
js/compressed-token/src/constants.ts (1)
  • POOL_SEED (2-2)
programs/compressed-token/program/src/create_associated_token_account.rs (1)
programs/compressed-token/anchor/src/lib.rs (1)
  • from (422-424)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: stateless-js-v1
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...
  • GitHub Check: cli-v1
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test --test v1", "cargo-...
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address", "c...
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: stateless-js-v2
  • GitHub Check: cli-v2
  • GitHub Check: Forester e2e test
  • GitHub Check: lint
🔇 Additional comments (19)
programs/compressed-token/program/tests/exact_allocation_test.rs (2)

47-51: LGTM: Correct tinyvec migration.

The migration from arrayvec to tinyvec::ArrayVec is correct and maintains identical semantics. The capacities (35 for outputs, 8 for input accounts) are adequate for the test scenarios, and tinyvec's panic-on-overflow behavior matches the original arrayvec implementation.


302-306: LGTM: Consistent migration pattern.

The tinyvec migration here mirrors the changes at lines 47-51, maintaining consistency across both test functions. The allocations correctly support the various metadata size test cases.

programs/compressed-token/program/tests/allocation_test.rs (1)

167-175: LGTM! Consistent with the tinyvec migration.

The container type changes here mirror those in test_extension_allocation_only, maintaining consistency across the test suite. The migration correctly preserves test logic while adopting the new container type.

programs/compressed-token/program/tests/token_input.rs (1)

92-97: LGTM! ArrayVec migration to tinyvec is correct.

The migration from arrayvec::ArrayVec to tinyvec::ArrayVec for both input_accounts and output_accounts is implemented correctly. Both element types (bool and (bool, u32)) implement Default as required by tinyvec, and the capacities (8 and 35) are appropriate for the test workload. The tinyvec library provides equivalent functionality with the added benefit of being implemented in 100% safe Rust.

Based on learnings.

programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_token_pool.rs (2)

47-53: LGTM! Clean migration to fixed-size array.

The refactor from ArrayVec to a fixed-size array for seed construction is efficient and aligns with the broader codebase migration pattern. The seed order (POOL_SEED, mint_key, bump) is correct for PDA derivation.


95-98: Correct error handling per guidelines.

The error conversion to ProgramError::Custom correctly follows the on-chain error handling pattern specified in the coding guidelines.

programs/compressed-token/program/src/shared/cpi_bytes_size.rs (1)

40-41: Type syntax correctly updated for tinyvec API.

The field types have been properly migrated from ArrayVec<T, N> (arrayvec const generic syntax) to ArrayVec<[T; N]> (tinyvec array-backed syntax). All usages within the file (lines 54, 57, 61, 65, 78-79, 81-82) are compatible with the new API.

programs/compressed-token/program/src/transfer2/cpi.rs (1)

5-5: LGTM: Consistent migration to tinyvec.

The import and type annotation changes are consistent with the migration in cpi_bytes_size.rs. The ArrayVec::new() initialization and subsequent push() operations (line 22) are fully compatible with tinyvec's API.

Also applies to: 19-20

programs/compressed-token/program/src/mint_action/zero_copy_config.rs (1)

10-10: Tinyvec migration verified—sufficient capacity confirmed.

The CpiConfigInput struct defines:

  • input_accounts: ArrayVec<[bool; 8]> → supports max 1 element required ✓
  • output_accounts: ArrayVec<[(bool, u32); 35]> → supports max 30 elements required ✓

Capacities are adequate. The migration to tinyvec is sound and consistent with usage elsewhere in the codebase (e.g., transfer2/cpi.rs).

programs/compressed-token/program/tests/token_output.rs (1)

71-77: Test file changes are compatible, but broader migration is incomplete.

The replacement of arrayvec::ArrayVec with tinyvec::ArrayVec in lines 71 and 77 is correct—capacities are safe and the API is compatible. However, verification reveals that arrayvec is still actively used in five other files in the same program:

  • programs/compressed-token/program/src/extensions/mod.rs:125
  • programs/compressed-token/program/src/shared/create_pda_account.rs:60
  • programs/compressed-token/program/src/transfer2/compression/mod.rs:3
  • programs/compressed-token/program/src/convert_account_infos.rs:16
  • programs/compressed-token/program/src/convert_account_infos.rs:35

Both dependencies remain in Cargo.toml. Clarify whether this PR is intended as a complete migration across the codebase or targeted only at test files. If the latter, document why the partial approach is acceptable.

program-libs/ctoken-types/src/instructions/extensions/compressible.rs (2)

6-6: Migration to tinyvec confirmed.

The import change to tinyvec::ArrayVec aligns with the broader codebase migration. Per the library documentation, tinyvec 1.10.0 is 100% safe Rust with no unsafe code, which improves memory safety guarantees.

Note: tinyvec's ArrayVec panics on capacity overflow rather than returning errors. Ensure all usage sites validate input lengths before pushing elements (see comment on lines 38-41).

Based on learnings.


20-20: Verify serialization compatibility and domain constraints.

Changing rent_payment from u64 to u8 breaks the previous serialization format and caps rent pre-payment at 255 epochs. Inputs are already u8 (so no overflow risk) and the 1-epoch footgun check remains. Please confirm:

  • 255 epochs is sufficient for all expected use cases
  • A migration path exists for any on-chain data still using the old u64 format
programs/compressed-token/program/src/create_token_account.rs (2)

60-66: LGTM! Correct signer requirement for compressible accounts.

The conditional logic correctly requires token_account to be a signer when creating compressible accounts (via CPI), while maintaining SPL compatibility for non-compressible accounts. This aligns with the CPI account creation flow and the parallel changes in create_associated_token_account.rs.


207-213: LGTM! Simplified seed handling.

The refactor from dynamic ArrayVec to fixed-size arrays reduces allocations and simplifies the code. The seeds_inputs array construction is straightforward and maintains the same functional behavior.

programs/compressed-token/program/src/create_associated_token_account.rs (2)

109-116: LGTM! Clean seed refactor for non-compressible path.

The conversion to fixed-size arrays is straightforward and maintains the same PDA derivation logic while reducing allocations.


181-209: Seed construction logic is correct and safely handles empty elements.

The create_pda_account function properly processes both scenarios:

  1. Custom rent payer (true): When seeds_inputs = [ata_seeds.as_slice(), &[]], the loop at line 61–65 iterates both elements and skips the empty slice via the if !seeds.is_empty() check (line 62), resulting in only ATA seeds being used. ✓

  2. Rent sponsor scenario (false): Both rent_sponsor_seeds and ata_seeds slices are non-empty and both are added to the signers in the correct order. ✓

  3. Empty slice handling: The conditional check at line 62 (if !seeds.is_empty()) explicitly filters out empty seed sets before building the signer array, making the dual-array pattern safe and intentional. ✓

programs/compressed-token/program/src/shared/create_pda_account.rs (2)

41-41: Breaking API change simplifies seed handling.

The parameter type change from ArrayVec<&[Seed], N> to [&[Seed]; N] is a breaking change that simplifies the API by requiring callers to provide fixed-size arrays. This reduces allocations and aligns with the broader refactor across create_token_account, create_associated_token_account, and create_mint_account.

Ensure all callers have been updated to the new signature. Based on the provided files, the major callers appear to have been updated.

As per coding guidelines.


60-65: LGTM! Correct handling of empty seed sets.

The loop correctly iterates by reference, skips empty seed sets with the !seeds.is_empty() check, and dereferences seeds when creating signers. This properly handles the dual-seed scenario in create_associated_token_account.rs where one array element may be empty when custom_rent_payer is true.

programs/compressed-token/program/src/mint_action/actions/create_spl_mint/create_mint_account.rs (1)

36-42: LGTM! Consistent seed refactor.

The conversion to fixed-size arrays follows the same pattern as create_token_account.rs and create_associated_token_account.rs, providing consistency across the codebase while reducing allocations.

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: 3

Caution

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

⚠️ Outside diff range comments (1)
program-libs/compressible/docs/CONFIG_ACCOUNT.md (1)

131-136: Update default rent constants to match code.

RentConfig::default() now pulls base_rent = 500, compression_cost = 6000, compression_incentive = 4000 (combined 10000), and lamports_per_byte_per_epoch = 6 (see program-libs/compressible/src/constants.rs). The table still reports the legacy 1220/11000/10 values, so it will mislead integrators. Please refresh these defaults to reflect the current constants.

♻️ Duplicate comments (2)
program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1)

223-256: Align the documented error code with the expectation.

The inline comment still calls out “Error: 18 (IllegalOwner)”, but the assertion checks for error code 29. Please update the comment (here and around Line 255) or the expectation so they match and avoid confusion.

program-tests/compressed-token-test/tests/ctoken/shared.rs (1)

93-107: Wire compress_to_account_pubkey when compress_to_pubkey is requested

CompressibleData exposes compress_to_pubkey, but both create paths still hardcode compress_to_account_pubkey: None. That means accounts meant to compress back to their own pubkey never set the flag, so the new compress_to_pubkey logic you introduced is never exercised and downstream ownership checks will fail. Please propagate the flag when building the instruction.

-                compress_to_account_pubkey: None,
+                compress_to_account_pubkey: if compressible_data.compress_to_pubkey {
+                    Some(token_account_pubkey)
+                } else {
+                    None
+                },

Also applies to: 145-159

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0c9ae0 and 0eac1b7.

📒 Files selected for processing (41)
  • program-libs/compressible/CLAUDE.md (0 hunks)
  • program-libs/compressible/docs/CONFIG_ACCOUNT.md (1 hunks)
  • program-libs/ctoken-types/src/error.rs (2 hunks)
  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs (4 hunks)
  • program-libs/ctoken-types/src/instructions/transfer2/instruction_data.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/create_ata.rs (1 hunks)
  • program-tests/compressed-token-test/tests/ctoken/shared.rs (1 hunks)
  • program-tests/compressed-token-test/tests/mint/random.rs (1 hunks)
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs (3 hunks)
  • program-tests/compressed-token-test/tests/transfer2/compress_spl_failing.rs (2 hunks)
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs (3 hunks)
  • program-tests/compressed-token-test/tests/transfer2/transfer_failing.rs (2 hunks)
  • programs/compressed-token/program/CLAUDE.md (1 hunks)
  • programs/compressed-token/program/docs/instructions/CLAIM.md (1 hunks)
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md (5 hunks)
  • programs/compressed-token/program/docs/instructions/MINT_ACTION.md (1 hunks)
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md (3 hunks)
  • programs/compressed-token/program/docs/instructions/WITHDRAW_FUNDING_POOL.md (1 hunks)
  • programs/compressed-token/program/src/lib.rs (4 hunks)
  • programs/compressed-token/program/src/shared/owner_validation.rs (1 hunks)
  • programs/compressed-token/program/src/transfer2/token_outputs.rs (1 hunks)
  • programs/compressed-token/program/tests/multi_sum_check.rs (3 hunks)
  • programs/registry/src/compressible/claim.rs (1 hunks)
  • programs/registry/src/compressible/withdraw_funding_pool.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/src/account2.rs (6 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/claim.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/compress_and_close.rs (2 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (3 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/decompress_full.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/mint_action/instruction.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/transfer2/instruction.rs (3 hunks)
  • sdk-libs/compressed-token-sdk/src/instructions/withdraw_funding_pool.rs (1 hunks)
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs (2 hunks)
  • sdk-libs/compressed-token-types/src/constants.rs (1 hunks)
  • sdk-libs/program-test/src/forester/compress_and_close_forester.rs (1 hunks)
  • sdk-libs/token-client/src/instructions/transfer2.rs (7 hunks)
  • sdk-tests/sdk-token-test/src/lib.rs (0 hunks)
  • sdk-tests/sdk-token-test/src/process_compress_full_and_close.rs (2 hunks)
  • sdk-tests/sdk-token-test/src/process_four_transfer2.rs (2 hunks)
  • sdk-tests/sdk-token-test/tests/compress_and_close_cpi.rs (4 hunks)
  • sdk-tests/sdk-token-test/tests/test_compress_full_and_close.rs (1 hunks)
💤 Files with no reviewable changes (2)
  • program-libs/compressible/CLAUDE.md
  • sdk-tests/sdk-token-test/src/lib.rs
✅ Files skipped from review due to trivial changes (2)
  • programs/compressed-token/program/docs/instructions/MINT_ACTION.md
  • programs/compressed-token/program/src/shared/owner_validation.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs
🧰 Additional context used
📓 Path-based instructions (7)
program-libs/compressible/docs/CONFIG_ACCOUNT.md

📄 CodeRabbit inference engine (program-libs/compressible/CLAUDE.md)

Maintain documentation for CompressibleConfig structure and methods in docs/CONFIG_ACCOUNT.md

Files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
programs/compressed-token/program/src/transfer2/**

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Files:

  • programs/compressed-token/program/src/transfer2/token_outputs.rs
programs/compressed-token/program/src/**/*.rs

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Return errors as ProgramError::Custom(error_code as u32) on-chain

Files:

  • programs/compressed-token/program/src/transfer2/token_outputs.rs
  • programs/compressed-token/program/src/lib.rs
sdk-tests/sdk-token-test/**/tests/**/*.rs

📄 CodeRabbit inference engine (sdk-tests/sdk-token-test/CLAUDE.md)

Every test should only contain functional integration tests

Files:

  • sdk-tests/sdk-token-test/tests/compress_and_close_cpi.rs
  • sdk-tests/sdk-token-test/tests/test_compress_full_and_close.rs
programs/compressed-token/program/docs/instructions/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/CLAUDE.md)

Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/docs/instructions/CLAIM.md
  • programs/compressed-token/program/docs/instructions/WITHDRAW_FUNDING_POOL.md
programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
programs/compressed-token/program/docs/**/instructions/**/*.md

📄 CodeRabbit inference engine (programs/compressed-token/program/docs/CLAUDE.md)

Keep detailed instruction documentation files under the instructions/ directory; add additional instruction docs as needed

Files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/docs/instructions/CLAIM.md
  • programs/compressed-token/program/docs/instructions/WITHDRAW_FUNDING_POOL.md
🧠 Learnings (33)
📓 Common learnings
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/ctoken_transfer.rs : CTokenTransfer must perform SPL-compatible transfers between decompressed accounts

Applied to files:

  • sdk-libs/compressed-token-types/src/constants.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • sdk-libs/compressed-token-sdk/src/instructions/decompress_full.rs
  • sdk-libs/compressed-token-sdk/src/account2.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • sdk-tests/sdk-token-test/src/process_four_transfer2.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • program-tests/compressed-token-test/tests/transfer2/transfer_failing.rs
  • sdk-tests/sdk-token-test/src/process_compress_full_and_close.rs
  • sdk-tests/sdk-token-test/tests/test_compress_full_and_close.rs
  • programs/compressed-token/program/src/lib.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_spl_failing.rs
  • sdk-libs/compressed-token-sdk/src/instructions/compress_and_close.rs
  • programs/compressed-token/program/tests/multi_sum_check.rs
  • sdk-libs/compressed-token-sdk/src/instructions/transfer2/instruction.rs
📚 Learning: 2025-10-11T21:59:52.702Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/docs/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:52.702Z
Learning: Applies to program-libs/account-checks/docs/**/DISCRIMINATOR.md : DISCRIMINATOR.md must document 8-byte discriminators, the Discriminator trait, constant arrays for compile-time checks, and integration with account initialization

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • programs/compressed-token/program/src/lib.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/MINT_ACTION.md : Document Mint operations and compressed mint management (9 actions) in instructions/MINT_ACTION.md

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • sdk-libs/compressed-token-sdk/src/instructions/mint_action/instruction.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/{CREATE_TOKEN_ACCOUNT,MINT_ACTION,TRANSFER2,CLAIM,CLOSE_TOKEN_ACCOUNT,DECOMPRESSED_TRANSFER,WITHDRAW_FUNDING_POOL}.md : Every instruction description must include sections: path, description, instruction_data, Accounts, instruction logic and checks, Errors

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLAIM.md : Document rent reclamation from expired compressible accounts in instructions/CLAIM.md

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CLAIM.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CLOSE_TOKEN_ACCOUNT.md : Document closing decompressed token accounts with rent distribution in instructions/CLOSE_TOKEN_ACCOUNT.md

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/DECOMPRESSED_TRANSFER.md : Document SPL-compatible transfers between decompressed accounts in instructions/DECOMPRESSED_TRANSFER.md

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • sdk-libs/compressed-token-sdk/src/account2.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • program-tests/compressed-token-test/tests/transfer2/compress_spl_failing.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/mint_action/** : MintAction must implement the 9 listed actions and handle both compressed and decompressed minting flows

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/instructions/*.md : Each instruction doc must include: path, description, instruction_data (code paths), Accounts (order and checks), instruction logic and checks, and Errors (with causes)

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{claim/**,withdraw_funding_pool.rs} : Enforce Not Inactive config validation for Claim and Withdraw Funding Pool instructions

Applied to files:

  • programs/compressed-token/program/CLAUDE.md
  • sdk-libs/compressed-token-sdk/src/instructions/claim.rs
  • programs/compressed-token/program/docs/instructions/CLAIM.md
  • programs/compressed-token/program/docs/instructions/WITHDRAW_FUNDING_POOL.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/docs/ACCOUNTS.md : Accounts documentation must include: description, discriminator, state layout, serialization example, hashing (only for compressed accounts), derivation (only for PDAs), and associated instructions

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/docs/CONFIG_ACCOUNT.md : Maintain documentation for CompressibleConfig structure and methods in docs/CONFIG_ACCOUNT.md

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/CREATE_TOKEN_ACCOUNT.md : Document Create Token Account & Associated Token Account instructions in instructions/CREATE_TOKEN_ACCOUNT.md

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/{create_token_account.rs,create_associated_token_account.rs} : Enforce ACTIVE-only config validation for Create CToken Account and Create Associated CToken Account instructions

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/ctoken/shared.rs
  • programs/compressed-token/program/src/lib.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/ACCOUNTS.md : Maintain ACCOUNTS.md with complete account layouts and data structures

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/*.rs : Context structs for wrapper instructions must include standard accounts: optional registered_forester_pda (mut), authority Signer, cpi_authority with seeds/bump for CPI_AUTHORITY_PDA_SEED, registered_program_pda, target program handle, log_wrapper, and mutable target_account.

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • sdk-tests/sdk-token-test/tests/compress_and_close_cpi.rs
  • programs/registry/src/compressible/withdraw_funding_pool.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/**/ACCOUNTS.md : Provide complete account layouts and data structures in ACCOUNTS.md

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/close_token_account{.rs,/**} : On closing ctoken accounts: if compressible, return rent exemption to the rent recipient; send remaining lamports to the destination

Applied to files:

  • program-libs/compressible/docs/CONFIG_ACCOUNT.md
  • sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • sdk-tests/sdk-token-test/tests/compress_and_close_cpi.rs
  • sdk-libs/compressed-token-sdk/src/instructions/decompress_full.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • sdk-tests/sdk-token-test/src/process_four_transfer2.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • sdk-tests/sdk-token-test/src/process_compress_full_and_close.rs
  • program-tests/compressed-token-test/tests/ctoken/shared.rs
  • sdk-libs/compressed-token-sdk/src/instructions/compress_and_close.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Refactor rent logic so that 1 lamport is the minimum rent payment

Applied to files:

  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
  • program-libs/ctoken-types/src/instructions/extensions/compressible.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/config.rs : Update config parameters including max write fee and max funded epoch

Applied to files:

  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: CToken account layout matches SPL token accounts with a custom Compressible extension; compressed mint accounts support the TokenMetadata extension

Applied to files:

  • program-tests/compressed-token-test/tests/transfer2/compress_failing.rs
  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
  • sdk-tests/sdk-token-test/src/process_compress_full_and_close.rs
  • program-tests/compressed-token-test/tests/transfer2/compress_spl_failing.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/TRANSFER2.md : Document the batch transfer instruction supporting compressed/decompressed operations in instructions/TRANSFER2.md

Applied to files:

  • sdk-libs/compressed-token-sdk/src/account2.rs
  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/**/*.rs : Pass the data Vec<u8> through unchanged from the wrapper to the target program CPI; the target program performs deserialization.

Applied to files:

  • programs/registry/src/compressible/withdraw_funding_pool.rs
📚 Learning: 2025-10-15T03:46:26.758Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:26.758Z
Learning: Applies to programs/registry/src/account_compression_cpi/**/*.rs : CPI processing functions must derive PDA signer seeds as [CPI_AUTHORITY_PDA_SEED, bump] and use CpiContext::new_with_signer with cpi_authority as the authority account and mapped target accounts.

Applied to files:

  • programs/registry/src/compressible/withdraw_funding_pool.rs
📚 Learning: 2025-10-15T03:45:40.029Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:40.029Z
Learning: Applies to programs/compressed-token/program/docs/**/instructions/CREATE_TOKEN_ACCOUNT.md : Provide CREATE_TOKEN_ACCOUNT.md in the instructions/ directory documenting create token account and associated token account instructions

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Determine compressibility and compute rent using calculate_rent_and_balance

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • sdk-libs/token-client/src/instructions/transfer2.rs
📚 Learning: 2025-10-15T03:44:42.664Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:44:42.664Z
Learning: Applies to program-libs/compressible/src/rent.rs : Update RentConfig values at claim time to reflect current policy

Applied to files:

  • programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
  • programs/registry/src/compressible/claim.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/src/transfer2/** : Transfer2 must support Compress, Decompress, and CompressAndClose modes and perform multi-mint sum checks

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/tests/multi_sum_check.rs
📚 Learning: 2025-10-15T03:45:17.264Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:45:17.264Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Define all program-specific error codes in anchor_compressed_token::ErrorCode and expose them for program-wide use

Applied to files:

  • programs/compressed-token/program/docs/instructions/TRANSFER2.md
  • programs/compressed-token/program/tests/multi_sum_check.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/discriminator.rs : Define and keep discriminator constants and the Discriminator trait in discriminator.rs for compile-time verification

Applied to files:

  • programs/compressed-token/program/src/lib.rs
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/src/**/*.rs : Validate account type with 8-byte discriminators using check_discriminator before deserialization

Applied to files:

  • programs/compressed-token/program/src/lib.rs
📚 Learning: 2025-10-15T03:46:03.545Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-10-15T03:46:03.545Z
Learning: Applies to programs/compressed-token/program/docs/instructions/instructions/WITHDRAW_FUNDING_POOL.md : Document withdrawal from the rent recipient funding pool in instructions/WITHDRAW_FUNDING_POOL.md

Applied to files:

  • programs/compressed-token/program/docs/instructions/WITHDRAW_FUNDING_POOL.md
🧬 Code graph analysis (13)
program-tests/compressed-token-test/tests/transfer2/compress_failing.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new_empty (99-114)
sdk-libs/compressed-token-sdk/src/instructions/decompress_full.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new (32-60)
sdk-libs/token-client/src/instructions/transfer2.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (5)
  • new (32-60)
  • new_delegated (66-96)
  • owner (383-385)
  • mint (371-373)
  • new_empty (99-114)
sdk-tests/sdk-token-test/src/process_four_transfer2.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new (32-60)
program-tests/compressed-token-test/tests/transfer2/decompress_failing.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new (32-60)
program-tests/compressed-token-test/tests/transfer2/transfer_failing.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new (32-60)
sdk-tests/sdk-token-test/src/process_compress_full_and_close.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new_empty (99-114)
program-tests/compressed-token-test/tests/ctoken/create_ata.rs (4)
program-tests/compressed-token-test/tests/ctoken/shared.rs (3)
  • setup_account_test (40-63)
  • create_and_assert_ata (400-461)
  • create_and_assert_ata_fails (464-514)
sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (3)
  • create_compressible_associated_token_account (41-45)
  • create_associated_token_account (98-104)
  • derive_ctoken_ata (226-235)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
program-tests/utils/src/assert_create_token_account.rs (1)
  • assert_create_associated_token_account (258-291)
program-tests/compressed-token-test/tests/ctoken/shared.rs (8)
sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (5)
  • create_associated_token_account (98-104)
  • derive_ctoken_ata (226-235)
  • create_compressible_associated_token_account_idempotent (48-52)
  • create_compressible_associated_token_account (41-45)
  • create_associated_token_account_idempotent (107-113)
sdk-libs/compressed-token-sdk/src/instructions/create_token_account/instruction.rs (2)
  • create_token_account (90-116)
  • create_compressible_token_account (38-88)
sdk-libs/program-test/src/forester/compress_and_close_forester.rs (1)
  • compress_and_close_forester (38-244)
program-tests/utils/src/assert_close_token_account.rs (1)
  • assert_close_token_account (8-106)
program-tests/utils/src/assert_create_token_account.rs (2)
  • assert_create_token_account (236-252)
  • assert_create_associated_token_account (258-291)
sdk-libs/program-test/src/utils/assert.rs (1)
  • assert_rpc_error (7-144)
sdk-libs/token-client/src/instructions/transfer2.rs (1)
  • create_generic_transfer2_instruction (145-638)
js/stateless.js/src/utils/instruction.ts (1)
  • PackedAccounts (5-99)
programs/compressed-token/program/src/lib.rs (1)
programs/compressed-token/program/src/ctoken_transfer.rs (1)
  • process_ctoken_transfer (19-34)
program-tests/compressed-token-test/tests/transfer2/compress_spl_failing.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (2)
  • mint (371-373)
  • new_empty (99-114)
sdk-libs/compressed-token-sdk/src/instructions/compress_and_close.rs (1)
sdk-libs/compressed-token-sdk/src/account2.rs (1)
  • new_empty (99-114)
programs/compressed-token/program/tests/multi_sum_check.rs (1)
programs/compressed-token/program/src/transfer2/sum_check.rs (2)
  • sum_check_multi_mint (92-121)
  • validate_mint_uniqueness (127-161)
🪛 LanguageTool
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

[grammar] ~76-~76: There might be a mistake here.
Context: ...is not exactly 1 epoch - Check: compressible_config.rent_payment != 1 - Error: `ErrorCode::OneEpochPrefundingNot...

(QB_NEW_EN)


[grammar] ~117-~117: There might be a mistake here.
Context: ...* 100 (non-idempotent), 102 (idempotent) enum: `CTokenInstruction::CreateAsso...

(QB_NEW_EN)


[grammar] ~180-~180: There might be a mistake here.
Context: ...epoch (see create ctoken account errors)

(QB_NEW_EN)

programs/compressed-token/program/docs/instructions/CLAIM.md

[grammar] ~3-~3: There might be a mistake here.
Context: ## Claim discriminator: 104 enum: InstructionType::Claim **pat...

(QB_NEW_EN)

programs/compressed-token/program/docs/instructions/WITHDRAW_FUNDING_POOL.md

[grammar] ~3-~3: There might be a mistake here.
Context: ...raw Funding Pool discriminator: 105 enum: `InstructionType::WithdrawFund...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.18.1)
programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md

112-112: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


180-180: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client light-compr...
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: system-programs (sdk-token-test-program, ["cargo-test-sbf -p sdk-token-test"])
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: Forester e2e test
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: stateless-js-v2
  • GitHub Check: stateless-js-v1
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test program-libs-fast
  • GitHub Check: cli-v1
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • GitHub Check: cli-v2
  • GitHub Check: programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test_transf...
  • GitHub Check: programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_address", "c...
  • GitHub Check: programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test --test v1", "cargo-...
  • GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
  • GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
  • GitHub Check: programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_compress...
  • GitHub Check: lint
🔇 Additional comments (24)
sdk-tests/sdk-token-test/src/process_four_transfer2.rs (1)

190-192: LGTM! Clean API migration.

The changes correctly migrate from the old API where output_tree_index was passed to CTokenAccount2::new to the new API where it's specified once via Transfer2Inputs.output_queue. This consolidation simplifies the API and reduces redundancy, as all accounts in a transfer now share a single output queue index.

The migration is consistent across both transfer operations and properly maintains error handling.

Also applies to: 200-202, 244-244

programs/registry/src/compressible/withdraw_funding_pool.rs (1)

47-48: No action required: WithdrawFundingPool discriminator 105 matches compressed-token program

program-libs/ctoken-types/src/error.rs (1)

130-131: LGTM: TooManySeeds variant correctly implemented and used

The TooManySeeds variant, message, and error code (18041) follow existing patterns, and its usage in seed-limit checks has been verified.

programs/registry/src/compressible/claim.rs (1)

37-38: LGTM! Discriminator update consistent with SDK.

The discriminator update from 107 to 104 is correct and consistent with the corresponding change in sdk-libs/compressed-token-sdk/src/instructions/claim.rs. The comment accurately reflects the new discriminator value.

As noted in the SDK file review, this is a breaking change requiring coordinated deployment across all components.

sdk-libs/compressed-token-sdk/src/instructions/claim.rs (1)

36-36: Discriminator update verified; breaking change requires coordinated deployment.

Verification confirms no remaining references to discriminator 107u8 in SDK code—the update to 104u8 is cleanly applied. The breaking change concern remains valid and critical: old SDK clients will reject transactions against the new on-chain program expecting 104, and new SDK clients will fail against old programs still expecting 107. Ensure atomic deployment of SDK and on-chain program.

sdk-libs/compressed-token-sdk/src/instructions/create_associated_token_account.rs (3)

158-158: Type change correctly propagated through function signature.

The u64 → u8 type change for pre_pay_num_epochs is correctly propagated through the compressible_config tuple parameter and unpacking logic. The assignment to rent_payment at line 174 maintains type consistency.

Also applies to: 169-174


32-32: Program-side validation and documentation confirmed; type narrowing approved.

Verification confirms the 1-epoch prefunding constraint is properly enforced:

  • Validation checks rent_payment == 1 in both create_associated_token_account.rs:152 and create_token_account.rs:165
  • Returns OneEpochPrefundingNotAllowed error (code 6116) with clear error messaging
  • Constraint is documented in programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md with explanation of the epoch boundary footgun prevention

The type narrowing from u64 to u8 is appropriate for epoch counts and aligns with the PR's constraint enforcement.


15-16: Discriminators verified as consistent with program specification.

The values (100 for non-idempotent, 102 for idempotent) match the program documentation in CREATE_TOKEN_ACCOUNT.md. No consistency issues detected.

sdk-libs/compressed-token-sdk/src/instructions/withdraw_funding_pool.rs (3)

23-26: LGTM! The instruction data encoding is correct.

The instruction data is correctly formatted with the discriminator, bump, and amount in the expected order and byte layout.


28-37: LGTM! Account setup is correct.

The accounts are properly configured with the correct mutability and signer flags:

  • Pool PDA is writable (source of funds)
  • Authority is readonly and a signer
  • Destination is writable (receives funds)
  • System program is readonly

24-24: WithdrawFundingPool discriminator consistency confirmed
The 105 value is used across the SDK, registry program, on-chain compressed-token program, and no 108 references remain in code or tests.

sdk-libs/compressed-token-sdk/src/account2.rs (2)

32-60: LGTM: Simplified constructor signature.

Removing the output_merkle_tree_index parameter streamlines the API by centralizing output queue configuration at the instruction level rather than per-account.


469-480: Based on verification of the codebase, the hardcoded output_queue: 0 for decompressed account transfers is appropriate and consistent.

Comment clarity could be improved.

The value output_queue: 0 appears correctly across multiple decompressed-only transfer patterns (account2.rs lines 479, 556 and compress_and_close.rs line 258), and the field is used for queue indices calculation even in decompressed contexts. However, the comment "Decompressed accounts only, no output queue needed" is slightly ambiguous compared to the clearer comment in compress_and_close.rs ("Output queue is at index 0 in packed_accounts"), which explicitly documents what the index value represents.

Consider updating the comments to be consistent and explicit about what output_queue: 0 means in this context—either clarify that it refers to index placement or that compressed token outputs are not generated.

sdk-libs/program-test/src/forester/compress_and_close_forester.rs (1)

84-84: LGTM: Removed unused index binding.

The output_tree_index binding is no longer needed since output queue handling is now centralized.

sdk-tests/sdk-token-test/tests/test_compress_full_and_close.rs (1)

260-261: LGTM: Consistent removal of unused index binding.

programs/compressed-token/program/CLAUDE.md (2)

61-76: LGTM: Documentation updated for discriminator changes.

The discriminator updates are consistent with the code changes and clearly documented.


275-275: Good clarification on compress_to_pubkey validation.

The added note clarifies that compress_to_pubkey validation ONLY applies when the rent authority closes, not when the owner closes. This is an important distinction for understanding the permission model.

sdk-libs/compressed-token-sdk/src/instructions/transfer2/instruction.rs (3)

66-66: LGTM: Added output_queue field to Transfer2Inputs.

The field is properly wired through the instruction creation flow.


71-80: LGTM: Proper extraction and usage of output_queue.


102-121: LGTM: Correct propagation of output_queue to instruction data.

programs/compressed-token/program/docs/instructions/TRANSFER2.md (3)

16-16: LGTM: Discriminator documentation updated.


275-282: Excellent clarification on compress_to_pubkey validation scope.

This note clearly distinguishes between owner-initiated and rent-authority-initiated closures, preventing potential confusion about when validation applies.


306-306: LGTM: New DuplicateMint error documented.

The error description clearly explains the validation: "Duplicate mint index detected in inputs, outputs, or compressions (same mint referenced by multiple indices or same index used multiple times)."

program-libs/ctoken-types/src/instructions/transfer2/instruction_data.rs (1)

19-19: The review comment mischaracterizes this change as a breaking change.

The output_queue field has a sensible default value (0 for u8), and Transfer2Inputs derives Default. All 11 callsites identified are correctly updated: 10 explicitly provide output_queue, and 1 (decompress_full.rs:110–115) properly uses ..Default::default(), which sets output_queue to its default. This pattern is idiomatic Rust and requires no corrective action.

Likely an incorrect or invalid review comment.

Comment on lines +39 to 44
- `rent_payment`: Number of epochs to prepay for rent (u64)
- `rent_payment = 1` is explicitly forbidden to prevent epoch boundary timing edge case
- Allowed values: 0 (no prefunding) or 2+ epochs (safe buffer)
- Rationale: Accounts created with exactly 1 epoch near epoch boundaries could become immediately compressible
- `write_top_up`: Additional lamports allocated for future write operations on the compressed account

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

Update rent_payment type to match code

CompressibleExtensionInstructionData::rent_payment was narrowed to u8, but this doc still advertises it as u64. Please update the type (and any related wording) so the instruction documentation matches the current serialization.

🤖 Prompt for AI Agents
In programs/compressed-token/program/docs/instructions/CREATE_TOKEN_ACCOUNT.md
around lines 39 to 44, the documentation lists `rent_payment` as a u64 but the
code now serializes it as u8; update the type and any related wording to reflect
`rent_payment: u8` (e.g., "Number of epochs to prepay for rent (u8)"), ensure
allowed values wording still makes sense for an 8-bit range (0 or 2+ epochs) and
adjust any examples or serialization notes to reference u8 instead of u64 so the
doc matches the implementation.

Comment on lines +47 to 50
// Build instruction data: [discriminator(105), pool_pda_bump, amount]
let mut instruction_data = vec![105u8]; // WithdrawFundingPool instruction discriminator

instruction_data.extend_from_slice(&amount.to_le_bytes());
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 | 🟠 Major

Fix the stale comment describing instruction data format.

The comment on line 47 claims the instruction data includes pool_pda_bump, but the code only appends the discriminator (line 48) and amount (line 50). The bump is never added to instruction_data.

Apply this diff to correct the comment:

-    // Build instruction data: [discriminator(105), pool_pda_bump, amount]
+    // Build instruction data: [discriminator(105), amount]
     let mut instruction_data = vec![105u8]; // WithdrawFundingPool instruction discriminator
 
     instruction_data.extend_from_slice(&amount.to_le_bytes());
📝 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
// Build instruction data: [discriminator(105), pool_pda_bump, amount]
let mut instruction_data = vec![105u8]; // WithdrawFundingPool instruction discriminator
instruction_data.extend_from_slice(&amount.to_le_bytes());
// Build instruction data: [discriminator(105), amount]
let mut instruction_data = vec![105u8]; // WithdrawFundingPool instruction discriminator
instruction_data.extend_from_slice(&amount.to_le_bytes());
🤖 Prompt for AI Agents
In programs/registry/src/compressible/withdraw_funding_pool.rs around lines 47
to 50, the comment incorrectly states the instruction data contains
`pool_pda_bump` though the code only pushes the discriminator and the amount;
update the comment to accurately describe the data layout (e.g.,
"[discriminator(105), amount]") so it matches the actual instruction_data being
constructed, or alternatively, if the bump is actually required, append the bump
byte to instruction_data—ensure comment and code are consistent.

pub const CREATE_TOKEN_POOL: [u8; 8] = [23, 169, 27, 122, 147, 169, 209, 152];
pub const CREATE_ADDITIONAL_TOKEN_POOL: [u8; 8] = [114, 143, 210, 73, 96, 115, 1, 228];
pub const TRANSFER2: u8 = 104;
pub const TRANSFER2: u8 = 101;
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 | 🔴 Critical

🧩 Analysis chain

Breaking change: Discriminator updated.

The TRANSFER2 discriminator changed from 104 to 101. This is a breaking change that affects all clients and must be coordinated with documentation updates.

Verify all usages of the TRANSFER2 discriminator have been updated:


🏁 Script executed:

#!/bin/bash
# Search for any remaining references to the old discriminator value 104
rg -n '\b104\b' --type rust | rg -i 'transfer2|discriminator'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for any occurrences of the old discriminator value 104 in Rust code
rg -nP '\b104\b' --type rust -C2 || true

# Search for any occurrences of the old discriminator in markdown documentation
rg -n '104' -g '*.md' -C2 || true

# Search for any usage of the constant TRANSFER2
rg -n 'TRANSFER2' --type rust -C2 || true

Length of output: 14842


Update program docs: correct TRANSFER2 discriminator
Change the Transfer2 discriminator in programs/compressed-token/program/docs/ACCOUNTS.md (line 25) from 104 to 101.

🤖 Prompt for AI Agents
In sdk-libs/compressed-token-types/src/constants.rs around line 52, TRANSFER2 is
defined as 101 but the program docs still list the Transfer2 discriminator as
104; update programs/compressed-token/program/docs/ACCOUNTS.md (around line 25)
to change the Transfer2 discriminator value from 104 to 101 so the documentation
matches the constant, and save the file.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants