Skip to content

fix: add missing field comparisons in ZCToken PartialEq#2085

Merged
SwenSchaeferjohann merged 1 commit intomainfrom
jorrit/fix-ctoken-eq
Dec 2, 2025
Merged

fix: add missing field comparisons in ZCToken PartialEq#2085
SwenSchaeferjohann merged 1 commit intomainfrom
jorrit/fix-ctoken-eq

Conversation

@ananas-block
Copy link
Contributor

@ananas-block ananas-block commented Dec 2, 2025

The eq() implementation for the Compressible extension was missing comparisons for compress_to_pubkey and account_version fields. This could cause two CToken instances to be considered equal even when these fields differed.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Enhanced token comparison accuracy by validating additional configuration fields during equality checks.
  • Tests

    • Added test coverage for token equality comparisons with compressed extensions.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 2, 2025

Walkthrough

Enhanced equality comparison logic for ZCToken's Compressible extension configuration by adding three new field comparisons (config_account_version, compress_to_pubkey, account_version) alongside existing validation. Introduces corresponding test to verify bidirectional equality behavior with configuration mismatches.

Changes

Cohort / File(s) Summary
Production Logic Enhancement
program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
Extends PartialEq<CToken> implementation to enforce stricter equality checks for Compressible extensions by comparing config_account_version, compress_to_pubkey, and account_version fields in addition to existing last_claimed_slot
Test Coverage
program-libs/ctoken-types/tests/ctoken/spl_compat.rs
Adds test test_compressible_extension_partial_eq validating bidirectional equality between ZCToken and CToken with Compressible extension, including mismatch scenarios for compress_to_pubkey and account_version

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Areas requiring attention:

  • Test duplication: The test block appears duplicated at the end of spl_compat.rs—verify if this is intentional or requires consolidation
  • Field semantics: Ensure the three new field comparisons (config_account_version, compress_to_pubkey, account_version) logically belong in the Compressible extension equality contract
  • Zero-copy vs. in-memory alignment: Confirm the test's construction properly mirrors zero-copy buffer population to in-memory CToken conversion for accurate parity validation

Suggested labels

ai-review

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

🔐 Equality now runs deeper still,
Three fields compared with stricter will,
CToken and ZCToken aligned so true,
Compressible configs verified through and through! 🎯

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 accurately and concisely describes the main change: adding missing field comparisons in the ZCToken PartialEq implementation for the Compressible extension.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 70.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-ctoken-eq

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c90d54 and c00af72.

📒 Files selected for processing (2)
  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs (1 hunks)
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
program-libs/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in program-libs must not depend on light-test-utils; any test requiring light-test-utils must be in program-tests

Files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Use `calculate_close_lamports` function to determine lamport distribution when closing CToken accounts
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/*instruction*.rs : Validate CompressibleConfig state using `validate_active()` method to ensure state == Active before allowing new compressed token account creation
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Use CompressibleConfig discriminator `[180, 4, 231, 26, 220, 144, 55, 168]` for account validation in Solana programs and clients
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) for CompressibleConfig account state verification
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: When working with ctoken accounts having the compressible extension, you must read program-libs/compressible/docs/ documentation including RENT.md, CONFIG_ACCOUNT.md, and SOLANA_RENT.md for rent system understanding
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Compressed token accounts (ctoken solana accounts) must use the same account layout as SPL tokens with a custom Compressible extension
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/README.md:0-0
Timestamp: 2025-11-24T17:54:38.537Z
Learning: Implement compressed token program interfaces for third-party token creation and usage on Solana using ZK Compression
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/create_*_account*.rs : Token account creation instructions (Create CToken Account and Create Associated CToken Account) require ACTIVE config validation only
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/README.md:0-0
Timestamp: 2025-11-24T17:54:38.537Z
Learning: Ensure compressed token program documentation is maintained at the official documentation site (https://zkcompression.com)
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Use `calculate_rent_and_balance` function to determine if a CToken account is compressible
📚 Learning: 2025-11-24T17:54:20.982Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/zero-copy-derive/README.md:0-0
Timestamp: 2025-11-24T17:54:20.982Z
Learning: Applies to program-libs/zero-copy-derive/**/*.rs : Apply #[derive(ZeroCopyEq)] macro to structs to derive PartialEq comparing ZeroCopy representation with original struct

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Use `calculate_close_lamports` function to determine lamport distribution when closing CToken accounts

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:42.343Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Compressed token accounts (ctoken solana accounts) must use the same account layout as SPL tokens with a custom Compressible extension

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/program-libs/compressible/src/config.rs : CompressibleConfig struct must use `#[repr(C)]` for proper memory layout with fixed field ordering: version (u16, 2 bytes), state (u8, 1 byte), bump (u8, 1 byte), update_authority (Pubkey, 32 bytes), withdrawal_authority (Pubkey, 32 bytes), rent_sponsor (Pubkey, 32 bytes), compression_authority (Pubkey, 32 bytes), rent_sponsor_bump (u8, 1 byte), compression_authority_bump (u8, 1 byte), rent_config (RentConfig, 8 bytes), address_space ([Pubkey; 4], 128 bytes), and _place_holder ([u8; 32], 32 bytes) for total of 256 bytes

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) for CompressibleConfig account state verification

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Derive PDA addresses using `derive_pda` and `derive_v1_config_pda` functions for CToken account configuration

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Use `calculate_rent_and_balance` function to determine if a CToken account is compressible

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:42.343Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/{claim,transfer2}/**/*.rs : Rent authority can only compress accounts when is_compressible() returns true; lamport distribution on close is: rent → rent_sponsor, unutilized → destination

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/config.rs : Set CompressibleConfig default values for CToken V1: base_rent = 1220, compression_cost = 11000, lamports_per_byte_per_epoch = 10, and address_space[0] = `amt2kaJA14v3urZbZvnc5v2np8jqvc4Z8zDep5wbtzx`

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:14.087Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:14.087Z
Learning: Applies to program-libs/compressible/**/*.rs : Use Anchor serialization for CompressibleConfig account structures in Rust programs

Applied to files:

  • program-libs/ctoken-types/src/state/ctoken/zero_copy.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run compressed token core tests using `cargo test-sbf -p compressed-token-test --test ctoken`, `--test v1`, `--test mint`, and `--test transfer2`

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T17:55:32.059Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-11-24T17:55:32.059Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use the builder pattern from `light-compressed-token-sdk::ctoken` module for CPI operations instead of manual instruction building

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:42.343Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/**/*.rs : Compressed mint accounts (cmints) support only one extension: TokenMetadata

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:42.343Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: Applies to programs/compressed-token/program/src/transfer2/**/*.rs : Transfer2 instruction must support Compress, Decompress, and CompressAndClose operations with multi-mint support and sum checks

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/instructions.rs : Compress/decompress instruction handlers and context struct generation should be implemented in `instructions.rs`, with compress using PDA-only and decompress supporting full PDA + ctoken

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/decompress_context.rs : Decompression trait implementation (`DecompressContext`) with account accessors, PDA/token separation logic, and token processing delegation should be in `decompress_context.rs`

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:42.343Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:42.343Z
Learning: When working with ctoken accounts having the compressible extension, you must read program-libs/compressible/docs/ documentation including RENT.md, CONFIG_ACCOUNT.md, and SOLANA_RENT.md for rent system understanding

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program compression tests using `cargo test-sbf -p system-test -- test_with_compression` and `cargo test-sbf -p system-test --test test_re_init_cpi_account` to test compressed account operations

Applied to files:

  • program-libs/ctoken-types/tests/ctoken/spl_compat.rs
🧬 Code graph analysis (1)
program-libs/ctoken-types/tests/ctoken/spl_compat.rs (3)
sdk-libs/sdk/src/compressible/compression_info.rs (1)
  • compression_info (37-37)
program-libs/ctoken-types/src/state/ctoken/zero_copy.rs (4)
  • byte_len (638-656)
  • new_zero_copy (658-712)
  • zero_copy_at (77-141)
  • zero_copy_at (425-443)
sdk-libs/compressed-token-sdk/src/ctoken/compressible.rs (1)
  • compress_to_pubkey (41-44)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • 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-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 (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: Test program-libs-fast
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: lint
🔇 Additional comments (2)
program-libs/ctoken-types/src/state/ctoken/zero_copy.rs (1)

297-305: LGTM! This correctly addresses the missing field comparisons.

The addition of compress_to_pubkey and account_version comparisons completes the equality check for the Compressible extension. Without these, two CToken instances could be incorrectly considered equal even when these fields differed — a subtle but significant correctness bug in equality semantics.

The implementation follows the same straightforward comparison pattern used for the other fields in this block.

program-libs/ctoken-types/tests/ctoken/spl_compat.rs (1)

490-587: Well-structured test that validates the fix comprehensively.

This test correctly:

  1. Exercises the newly added field comparisons (compress_to_pubkey, account_version)
  2. Validates equality in both directions via PartialEq symmetry checks
  3. Confirms that mismatched values properly cause inequality

The mismatch tests at lines 566-586 are particularly important — they ensure the fix actually detects differences rather than just passing through.

One minor observation: you could also add a mismatch test for config_account_version for completeness, but since that comparison existed before this PR, it's not strictly necessary here.


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.

The eq() implementation for the Compressible extension was missing
comparisons for compress_to_pubkey and account_version fields. This
could cause two CToken instances to be considered equal even when
these fields differed.
@SwenSchaeferjohann SwenSchaeferjohann merged commit 90da898 into main Dec 2, 2025
31 of 32 checks passed
@SwenSchaeferjohann SwenSchaeferjohann deleted the jorrit/fix-ctoken-eq branch December 2, 2025 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants