Skip to content

fix: add additional self transfer checks, add rent exemption create token account check, add additiona create ata idempotent check#2292

Merged
ananas-block merged 4 commits intomainfrom
jorrit/refactor-add-additional-ctoken-transfer-checks
Feb 17, 2026
Merged

fix: add additional self transfer checks, add rent exemption create token account check, add additiona create ata idempotent check#2292
ananas-block merged 4 commits intomainfrom
jorrit/refactor-add-additional-ctoken-transfer-checks

Conversation

@ananas-block
Copy link
Contributor

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

Summary

  1. Add data length validation for non-compressible token accounts in create.rs

    • Verify account is exactly BASE_TOKEN_ACCOUNT_SIZE (165 bytes)
  2. Add rent-exemption check for non-compressible token accounts in create.rs

    • Check account has minimum lamports required by rent sysvar
  3. Add mint and owner field validation in idempotent ATA creation (create_ata.rs)

    • Deserialize token account and verify mint matches expected mint
    • Verify owner field matches expected owner
  4. Add frozen state check for self-transfers (shared.rs)

    • from_account_info_checked rejects frozen accounts (state != 1)
  5. Add balance sufficiency check for self-transfers (shared.rs)

    • Return InsufficientFunds error if account balance is less than transfer amount
  6. Thread instruction_data through self-transfer validation (default.rs, checked.rs)

    • Pass instruction_data to validate_self_transfer for amount extraction in the cold path

Tests

Added failing tests for all new checks:

Self-transfer (transfer.rs):

  • test_ctoken_self_transfer_frozen - frozen account self-transfer returns InvalidAccountData
  • test_ctoken_self_transfer_insufficient_funds - amount > balance returns InsufficientFunds (6154)
  • test_ctoken_self_transfer_success - valid self-transfer succeeds, balance unchanged
  • test_ctoken_transfer_checked_self_transfer_frozen - frozen account via transfer_checked
  • test_ctoken_transfer_checked_self_transfer_insufficient_funds - insufficient funds via transfer_checked

Non-compressible account creation (create.rs):

  • Non-compressible account with wrong data length (200 != 165) returns InvalidAccountData

Idempotent ATA creation (create_ata.rs):

  • test_create_ata_idempotent_owner_mismatch - tampered owner field returns InvalidAccountData
  • test_create_ata_idempotent_mint_mismatch - tampered mint field returns InvalidAccountData

Summary by CodeRabbit

Bug Fixes

  • Added validation to ensure token accounts meet required size and rent-exemption standards during creation
  • Enhanced verification of associated token accounts to confirm proper ownership and mint references
  • Improved self-transfer operations with comprehensive validation of transaction instruction payloads and fund availability checks

- create.rs: verify non-compressible token account is rent-exempt before
  initializing (audit issue #8)
- create_ata.rs: in idempotent mode, deserialize existing account and
  verify mint and owner fields match expected values (audit issue #4)

Entire-Checkpoint: caaa14ac3051
Entire-Checkpoint: caaa14ac3051
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Adds stricter validations: enforce exact account size and rent-exemption for non-compressible token accounts on creation; verify existing ATA's mint and owner match expected values; and extend self-transfer validation to accept instruction payload and check transfer amount against token balance.

Changes

Cohort / File(s) Summary
Account creation & ATA
programs/compressed-token/program/src/ctoken/create.rs, programs/compressed-token/program/src/ctoken/create_ata.rs
Enforce BASE_TOKEN_ACCOUNT_SIZE and rent-exemption for non-compressible token accounts on create (Solana target gated). In idempotent ATA path, validate existing ATA's mint and owner match expected values before returning early.
Self-transfer validation
programs/compressed-token/program/src/ctoken/transfer/shared.rs
validate_self_transfer and internal authority check now accept instruction_data: &[u8]; parse amount from instruction payload and require source balance ≥ amount (also rely on existing frozen/account checks).
Transfer callers
programs/compressed-token/program/src/ctoken/transfer/checked.rs, programs/compressed-token/program/src/ctoken/transfer/default.rs
Updated calls to validate_self_transfer(...) to pass instruction_data (call site arity change only).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Program
    participant TokenAccount
    participant RentSysvar
    participant MintAccount

    Client->>Program: Create token account / Create ATA / Transfer (with instruction_data)
    alt Create non-compressible account
        Program->>TokenAccount: check data.len() == BASE_TOKEN_ACCOUNT_SIZE
        Program->>RentSysvar: verify rent-exempt
        RentSysvar-->>Program: rent-exempt? (ok / error)
    end
    alt Idempotent ATA path (account exists && owned by signer)
        Program->>TokenAccount: from_account_info_checked()
        Program->>MintAccount: compare token.base.mint == expected_mint
        Program->>TokenAccount: compare token.base.owner == expected_owner
    end
    alt Self-transfer path
        Program->>TokenAccount: validate_self_transfer(source,dest,auth,instruction_data)
        Note right of Program: parse amount from instruction_data (u64 LE)
        Program->>TokenAccount: check source.balance >= amount
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

ai-review

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

✨ New guards stand at creation's gate,
Size and rent confirm the state,
Owner, mint—aligned and true,
Transfers read the bytes anew,
Small checks keep the ledger great. 🎉

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title covers the main changes but contains a typo ('additiona' instead of 'additional') and is somewhat verbose for a PR title.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 70.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ 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/refactor-add-additional-ctoken-transfer-checks

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

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@programs/compressed-token/program/src/ctoken/transfer/shared.rs`:
- Around line 51-55: The code assumes instruction_data has at least 8 bytes when
parsing amount with u64::from_le_bytes(instruction_data[..8]), which can panic
if a future caller omits the length check; update the function
validate_self_transfer (in shared.rs) to defensively check
instruction_data.len() >= 8 and return ProgramError::InvalidInstructionData (or
appropriate error) before slicing, or alternatively add a clear doc comment on
validate_self_transfer stating the minimum byte length requirement and
referencing the 8-byte amount layout so all callers must validate length first.

Entire-Checkpoint: 2b4028368dbf
Entire-Checkpoint: c298aaf24a18
@ananas-block ananas-block merged commit 21d7863 into main Feb 17, 2026
30 checks passed
@ananas-block ananas-block deleted the jorrit/refactor-add-additional-ctoken-transfer-checks branch February 17, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants