Skip to content

fix: correct epochs_funded_ahead calculation for lagging claims#2087

Merged
ananas-block merged 2 commits intomainfrom
jorrit/fix-epochs-funded-ahead-calculation
Dec 4, 2025
Merged

fix: correct epochs_funded_ahead calculation for lagging claims#2087
ananas-block merged 2 commits intomainfrom
jorrit/fix-epochs-funded-ahead-calculation

Conversation

@ananas-block
Copy link
Contributor

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

When last_claimed_slot lagged behind current_slot, the epochs_funded_ahead calculation incorrectly counted arrears as "ahead" epochs. This caused top-ups to be skipped when they should have triggered.

Example of the bug:

  • last_claimed_epoch=0, current_epoch=3, available_balance=5*rent_per_epoch
  • Old: epochs_funded_ahead = (4+1) - 3 = 2 >= max=2 → skip top-up
  • Fixed: epochs_funded_ahead = 4 - 3 = 1 < max=2 → trigger top-up

Changes:

  • program-libs/compressible: Remove +1 from epochs_funded_ahead calculation
  • sdk-libs/sdk: Subtract required_epochs from total_epochs_fundable
  • Add test cases for lagging claim scenarios

Summary by CodeRabbit

  • Bug Fixes

    • More accurate calculation of funded epochs; maintenance top-ups now trigger correctly in borderline and arrears scenarios, so some accounts may receive smaller periodic top-ups that were previously skipped.
  • Tests

    • Expanded and renamed test cases covering boundary conditions, lagging claims, and exact-funded behavior to validate the revised top-up logic.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 2, 2025

Walkthrough

Replaces inline funded-epochs arithmetic with a new AccountRentState::epochs_funded_ahead(...) method and updates callers/tests to use it. Tests were renamed/adjusted to reflect revised top-up expectations and added coverage for arrears (lagging claims).

Changes

Cohort / File(s) Summary
Program-libs: top-up callsite
program-libs/compressible/src/compression_info.rs
Replaced manual epochs_funded_ahead arithmetic with a call to state.epochs_funded_ahead(&self.rent_config, rent_exemption_lamports); keep max_funded_epochs check and lamports_per_write fallback.
SDK-libs: top-up callsite
sdk-libs/sdk/src/compressible/compression_info.rs
Same replacement as program-libs: use state.epochs_funded_ahead(...) instead of inlined balance/epoch math; preserves existing control flow for max_funded_epochs and top-up.
Program-libs: rent logic
program-libs/compressible/src/rent/account_rent.rs
Added pub fn epochs_funded_ahead(&self, config: &impl RentConfigTrait, rent_exemption_lamports: u64) -> u64 which computes available rent balance, rent per epoch, total fundable epochs, required epochs (including ongoing epoch), and returns funded-ahead (or 0).
Program-libs: tests
program-libs/compressible/tests/compression_info.rs
Renamed/rewrote test cases and expectations to match revised top-up logic; added "LAGGING CLAIMS" tests to assert arrears do not increase funded-ahead and adjusted edge-case expectations (including zero lamports_per_write scenarios).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify correctness of the new epochs_funded_ahead math (available balance, rent-per-epoch, required epochs including ongoing epoch).
  • Confirm callers' behavior unchanged except for relying on the new method (off-by-one and boundary checks).
  • Review updated tests for coverage of arrears/lagging claims and ensure expectations match the new calculation.

Possibly related PRs

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

A rent-line now wrapped in a single call,
Epochs counted cleaner — no hidden fall,
Tests march forward, arrears held at bay,
Top-ups align with the math today,
Tiny change, steadier rails for pay. 🎉

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 describes the main fix: correcting the epochs_funded_ahead calculation for lagging claims, which is the core purpose of this bug fix PR.
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-epochs-funded-ahead-calculation

📜 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 15acd45 and 1cfedfb.

⛔ Files ignored due to path filters (2)
  • program-tests/compressed-token-test/tests/ctoken/functional.rs is excluded by none and included by none
  • program-tests/compressed-token-test/tests/ctoken/transfer.rs is excluded by none and included by none
📒 Files selected for processing (4)
  • program-libs/compressible/src/compression_info.rs (1 hunks)
  • program-libs/compressible/src/rent/account_rent.rs (1 hunks)
  • program-libs/compressible/tests/compression_info.rs (3 hunks)
  • sdk-libs/sdk/src/compressible/compression_info.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
program-libs/compressible/**/*.rs

📄 CodeRabbit inference engine (program-libs/compressible/CLAUDE.md)

program-libs/compressible/**/*.rs: Use Anchor serialization for CompressibleConfig account structures in Rust programs
Implement state validation methods (validate_active, validate_not_inactive) for CompressibleConfig account state verification
Derive PDA addresses using derive_pda and derive_v1_config_pda functions for CToken account configuration
Use rent curve algorithms (rent_curve_per_epoch) from RentConfig for calculating compressibility thresholds
Calculate claimable rent using claimable_lamports function before closing CToken accounts
Error types must use numeric codes in the 19xxx range for rent/config module errors
Support multiple serialization formats (Anchor, Pinocchio, Borsh) for cross-program compatibility
Use calculate_rent_and_balance function to determine if a CToken account is compressible
Use calculate_close_lamports function to determine lamport distribution when closing CToken accounts

Files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
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/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
sdk-libs/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
🧠 Learnings (36)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_last_funded_epoch` function to determine the last epoch number covered by rent payments.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Use epoch-based accounting (432,000 slots ≈ 2.5 days) instead of continuous time for Light Protocol rent collection
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_close_lamports` function to return (u64, u64) tuple splitting lamports between rent recipient and user, with rent recipient receiving completed epochs and user receiving partial epoch remainder.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node
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 : Calculate claimable rent using `claimable_lamports` function before closing CToken accounts
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Rent is calculated per epoch (432,000 slots). Accounts must maintain sufficient balance for all epochs since last claim.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_rent` function to calculate total rent across multiple epochs using: rent_curve_per_epoch * epochs.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_inner` as a generic helper function with INCLUDE_CURRENT const parameter to calculate rent components, returning (required_epochs, rent_per_epoch, epochs_paid, unutilized_lamports).
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: When closing accounts, partial epoch rent is returned to the user while completed epochs go to the rent recipient.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_and_balance` function to determine compressibility by checking if account balance covers required rent for epochs since last claim, returning (bool, u64) tuple.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `rent_curve_per_epoch` function with formula: base_rent + (num_bytes * lamports_per_byte_per_epoch).
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:03.786Z
Learning: Applies to program-libs/account-checks/**/checks.rs : Use rent exemption checks (`check_account_balance_is_rent_exempt`) in account validation functions
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_last_funded_epoch` function to determine the last epoch number covered by rent payments.

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_and_balance` function to determine compressibility by checking if account balance covers required rent for epochs since last claim, returning (bool, u64) tuple.

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_rent` function to calculate total rent across multiple epochs using: rent_curve_per_epoch * epochs.

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_inner` as a generic helper function with INCLUDE_CURRENT const parameter to calculate rent components, returning (required_epochs, rent_per_epoch, epochs_paid, unutilized_lamports).

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `rent_curve_per_epoch` function with formula: base_rent + (num_bytes * lamports_per_byte_per_epoch).

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_close_lamports` function to return (u64, u64) tuple splitting lamports between rent recipient and user, with rent recipient receiving completed epochs and user receiving partial epoch remainder.

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `claimable_lamports` function to return None if account is compressible, otherwise return Some(amount) for completed epochs only (excluding current ongoing epoch).

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.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 rent curve algorithms (`rent_curve_per_epoch`) from RentConfig for calculating compressibility thresholds

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_rent_exemption_lamports` function to return Solana's rent-exempt balance for a given account size, with error handling for unavailable rent sysvar.

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Light Protocol rent is calculated per epoch as: 1220 minimum + (data_bytes * 10) lamports per epoch

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.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/close_token_account.rs : Close Token Account instruction must return rent exemption to rent recipient if compressible, and return remaining lamports to destination account

Applied to files:

  • program-libs/compressible/src/rent/account_rent.rs
  • program-libs/compressible/src/compression_info.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/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.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/compressible/tests/compression_info.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 : Calculate claimable rent using `claimable_lamports` function before closing CToken accounts

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.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/compressible/tests/compression_info.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/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement compression cost and incentive values as constants: COMPRESSION_COST = 10,000 lamports, COMPRESSION_INCENTIVE = 1,000 lamports.

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement rent constants with values: BASE_RENT = 1,220 lamports, RENT_PER_BYTE = 10 lamports, SLOTS_PER_EPOCH = 432,000.

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : In test environments, mock Solana rent exemption instead of calling the actual Rent sysvar, using a hardcoded value like 2_282_880 lamports

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Light Protocol accounts must satisfy both Solana rent exemption and Light Protocol rent requirements, plus an 11,000 lamport compression incentive during creation

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Rent is calculated per epoch (432,000 slots). Accounts must maintain sufficient balance for all epochs since last claim.

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
  • sdk-libs/sdk/src/compressible/compression_info.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,withdraw_funding_pool}*.rs : Claim and Withdraw Funding Pool instructions require config validation that allows Not Inactive state (active or deprecated OK)

Applied to files:

  • program-libs/compressible/tests/compression_info.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:

  • sdk-libs/sdk/src/compressible/compression_info.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 : RentConfig struct must use fixed-size fields: base_rent (u16, 2 bytes), compression_cost (u16, 2 bytes), lamports_per_byte_per_epoch (u8, 1 byte), and _place_holder_bytes ([u8; 3], 3 bytes padding) for proper 8-byte alignment

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : RentConfig struct must be exactly 8 bytes and contain: base_rent (u16), compression_cost (u16), lamports_per_byte_per_epoch (u8), and 3 bytes of padding.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.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:

  • sdk-libs/sdk/src/compressible/compression_info.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:

  • sdk-libs/sdk/src/compressible/compression_info.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:

  • sdk-libs/sdk/src/compressible/compression_info.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: CompressibleConfig module provides account configuration and rent management for the Light Registry program

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
📚 Learning: 2025-11-24T18:00:21.501Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/ERRORS.md:0-0
Timestamp: 2025-11-24T18:00:21.501Z
Learning: Applies to program-libs/compressible/docs/program-libs/compressible/src/error.rs : FailedBorrowRentSysvar (Error Code 19001): Ensure the rent sysvar is properly initialized in test environments and verify the sysvar is accessible for on-chain programs. Use `solana_program::rent::Rent::get()` with proper error handling for borrowing rent sysvar.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.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 : Define CompressibleConfig constant `LEN = 256` to represent the account size in bytes for rent calculation and account creation

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Use `rent_curve_per_epoch(base_rent, lamports_per_byte_per_epoch, num_bytes)` function for base rent calculations in all rent operations.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Accounts become compressible when they lack rent for the current epoch plus the next epoch (compressibility window).

Applied to files:

  • program-libs/compressible/src/compression_info.rs
🧬 Code graph analysis (2)
sdk-libs/sdk/src/compressible/compression_info.rs (1)
program-libs/compressible/src/rent/account_rent.rs (1)
  • epochs_funded_ahead (171-182)
program-libs/compressible/src/compression_info.rs (1)
program-libs/compressible/src/rent/account_rent.rs (1)
  • epochs_funded_ahead (171-182)
⏰ 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). (8)
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • 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 (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
  • GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
  • 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 --test v1", "cargo-...
🔇 Additional comments (2)
program-libs/compressible/src/rent/account_rent.rs (1)

162-182: Epochs-funding helper correctly centralizes arrears‑aware math

epochs_funded_ahead cleanly reuses get_available_rent_balance, rent_curve_per_epoch, and get_required_epochs::<true>() so that “funded ahead” is measured strictly beyond the current epoch and naturally discounts arrears. The saturating_sub on total_epochs_fundable - required_epochs also gives a safe 0 floor in pathological cases. This aligns with the epoch‑based rent accounting described around calculate_rent_inner/required_epochs in RENT.md.
Based on learnings, this matches the documented rent model.

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

92-121: On‑chain top‑up logic correctly reuses AccountRentState::epochs_funded_ahead

The calculate_top_up_lamports implementation now uses state.epochs_funded_ahead(&self.rent_config, rent_exemption_lamports) for the “already at target” check, so the program’s notion of “funded ahead” matches the shared rent helper and the SDK. This should eliminate drift between CTokens and SDK for both normal and lagging‑claim scenarios.
Based on learnings, this keeps on‑chain behavior consistent with the documented compressibility thresholds.


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

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/tests/compression_info.rs (1)

412-419: Stale epochs_funded_ahead value in test description (semantic nit)

In TestCase { name: "exact boundary - lagging claim requires top-up", ... } the description says epochs_funded_ahead=1 < max=2, but with the updated program logic and its comment (“if last_funded_epoch_number == current_epoch ... has 0 epochs funded ahead”), this scenario (last_claimed_slot = 0, 2 epochs of rent, current_slot = SLOTS_PER_EPOCH) actually has epochs_funded_ahead = 0. The expected behavior (expected_top_up = lamports_per_write) is still correct; only the explanatory text is out of date. I’d update the description to reflect epochs_funded_ahead = 0 (or drop the explicit value) so it stays consistent with the new definition used in code and the LAGGING CLAIMS tests.

📜 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 15acd45.

📒 Files selected for processing (3)
  • program-libs/compressible/src/compression_info.rs (1 hunks)
  • program-libs/compressible/tests/compression_info.rs (3 hunks)
  • sdk-libs/sdk/src/compressible/compression_info.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
sdk-libs/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
program-libs/compressible/**/*.rs

📄 CodeRabbit inference engine (program-libs/compressible/CLAUDE.md)

program-libs/compressible/**/*.rs: Use Anchor serialization for CompressibleConfig account structures in Rust programs
Implement state validation methods (validate_active, validate_not_inactive) for CompressibleConfig account state verification
Derive PDA addresses using derive_pda and derive_v1_config_pda functions for CToken account configuration
Use rent curve algorithms (rent_curve_per_epoch) from RentConfig for calculating compressibility thresholds
Calculate claimable rent using claimable_lamports function before closing CToken accounts
Error types must use numeric codes in the 19xxx range for rent/config module errors
Support multiple serialization formats (Anchor, Pinocchio, Borsh) for cross-program compatibility
Use calculate_rent_and_balance function to determine if a CToken account is compressible
Use calculate_close_lamports function to determine lamport distribution when closing CToken accounts

Files:

  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
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/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_last_funded_epoch` function to determine the last epoch number covered by rent payments.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Use epoch-based accounting (432,000 slots ≈ 2.5 days) instead of continuous time for Light Protocol rent collection
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_close_lamports` function to return (u64, u64) tuple splitting lamports between rent recipient and user, with rent recipient receiving completed epochs and user receiving partial epoch remainder.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)
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 : Calculate claimable rent using `claimable_lamports` function before closing CToken accounts
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Light Protocol rent is calculated per epoch as: 1220 minimum + (data_bytes * 10) lamports per epoch
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_and_balance` function to determine compressibility by checking if account balance covers required rent for epochs since last claim, returning (bool, u64) tuple.
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Rent is calculated per epoch (432,000 slots). Accounts must maintain sufficient balance for all epochs since last claim.
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_last_funded_epoch` function to determine the last epoch number covered by rent payments.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_close_lamports` function to return (u64, u64) tuple splitting lamports between rent recipient and user, with rent recipient receiving completed epochs and user receiving partial epoch remainder.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_and_balance` function to determine compressibility by checking if account balance covers required rent for epochs since last claim, returning (bool, u64) tuple.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `calculate_rent_inner` as a generic helper function with INCLUDE_CURRENT const parameter to calculate rent components, returning (required_epochs, rent_per_epoch, epochs_paid, unutilized_lamports).

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.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 : Calculate claimable rent using `claimable_lamports` function before closing CToken accounts

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.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:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Light Protocol rent is calculated per epoch as: 1220 minimum + (data_bytes * 10) lamports per epoch

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `claimable_lamports` function to return None if account is compressible, otherwise return Some(amount) for completed epochs only (excluding current ongoing epoch).

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Account closure must distribute lamports according to: Solana rent exemption → returned to user, completed epoch rent → rent recipient, partial epoch rent → user, compression incentive → forester node

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Rent is calculated per epoch (432,000 slots). Accounts must maintain sufficient balance for all epochs since last claim.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `get_rent` function to calculate total rent across multiple epochs using: rent_curve_per_epoch * epochs.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement `rent_curve_per_epoch` function with formula: base_rent + (num_bytes * lamports_per_byte_per_epoch).

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.rs
  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Use `rent_curve_per_epoch(base_rent, lamports_per_byte_per_epoch, num_bytes)` function for base rent calculations in all rent operations.

Applied to files:

  • sdk-libs/sdk/src/compressible/compression_info.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/compressible/tests/compression_info.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/compressible/tests/compression_info.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/compressible/tests/compression_info.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/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement compression cost and incentive values as constants: COMPRESSION_COST = 10,000 lamports, COMPRESSION_INCENTIVE = 1,000 lamports.

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:36.663Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/RENT.md:0-0
Timestamp: 2025-11-24T18:00:36.663Z
Learning: Applies to program-libs/compressible/docs/**/*rent*.rs : Implement rent constants with values: BASE_RENT = 1,220 lamports, RENT_PER_BYTE = 10 lamports, SLOTS_PER_EPOCH = 432,000.

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : In test environments, mock Solana rent exemption instead of calling the actual Rent sysvar, using a hardcoded value like 2_282_880 lamports

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Light Protocol accounts must satisfy both Solana rent exemption and Light Protocol rent requirements, plus an 11,000 lamport compression incentive during creation

Applied to files:

  • program-libs/compressible/tests/compression_info.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,withdraw_funding_pool}*.rs : Claim and Withdraw Funding Pool instructions require config validation that allows Not Inactive state (active or deprecated OK)

Applied to files:

  • program-libs/compressible/tests/compression_info.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Return error `AccountError::AccountNotRentExempt` (error code 12011) when account balance is insufficient for rent exemption at calculated size

Applied to files:

  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T17:58:50.237Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_CHECKS.md:0-0
Timestamp: 2025-11-24T17:58:50.237Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/checks.rs : Implement `check_account_balance_is_rent_exempt` function to verify account size matches expected_size and account balance meets rent exemption requirement, returning rent exemption amount or errors `InvalidAccountSize` (20004), `InvalidAccountBalance` (20007), or `FailedBorrowRentSysvar` (20008)

Applied to files:

  • program-libs/compressible/src/compression_info.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Use epoch-based accounting (432,000 slots ≈ 2.5 days) instead of continuous time for Light Protocol rent collection

Applied to files:

  • program-libs/compressible/src/compression_info.rs
🧬 Code graph analysis (1)
program-libs/compressible/src/compression_info.rs (1)
program-libs/compressible/src/rent/account_rent.rs (1)
  • slot_to_epoch (174-176)
⏰ 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). (4)
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: stateless-js-v2
🔇 Additional comments (2)
program-libs/compressible/src/compression_info.rs (1)

118-123: Epochs-funded-ahead off‑by‑one fix matches rent docs and bug scenario

Switching to last_funded_epoch_number.saturating_sub(current_epoch) correctly counts only epochs after the current one, so with last_funded_epoch_number = 4 and current_epoch = 3 you now get epochs_funded_ahead = 1 instead of 2, which aligns with the PR description and prevents arrears from being treated as “ahead” funding. The added comment (“funded through the current epoch but has 0 epochs funded ahead”) is consistent with get_last_funded_epoch’s documented meaning of “epoch through which rent has been prepaid”. Using saturating_sub is a good defensive guard if state ever drifts such that current_epoch > last_funded_epoch_number. Based on learnings from RENT.md about get_last_funded_epoch.

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

535-563: Lagging-claims tests accurately cover the fixed bug scenario

The new LAGGING CLAIMS cases (5/6/4 epochs funded with last_claimed_slot = 0 and current_slot = 3 * SLOTS_PER_EPOCH) exactly exercise the scenario where arrears used to be miscounted as “ahead” funding. They assert that:

  • 5 epochs prepaid yields epochs_funded_ahead = 1 and still triggers a top‑up.
  • 6 epochs prepaid yields epochs_funded_ahead = 2 and skips the top‑up.
  • 4 epochs prepaid only just cover arrears + current, giving epochs_funded_ahead = 0 and requiring a top‑up.

This matches the new “AFTER the current epoch” semantics in the program’s calculate_top_up_lamports implementation and locks in the intended behavior for lagging last_claimed_slot. Based on learnings from SOLANA_RENT.md about epoch-based rent accounting.

When last_claimed_slot lagged behind current_slot, the epochs_funded_ahead
calculation incorrectly counted arrears as "ahead" epochs. This caused
top-ups to be skipped when they should have triggered.

Example of the bug:
- last_claimed_epoch=0, current_epoch=3, available_balance=5*rent_per_epoch
- Old: epochs_funded_ahead = (4+1) - 3 = 2 >= max=2 → skip top-up
- Fixed: epochs_funded_ahead = 4 - 3 = 1 < max=2 → trigger top-up

Changes:
- program-libs/compressible: Remove +1 from epochs_funded_ahead calculation
- sdk-libs/sdk: Subtract required_epochs from total_epochs_fundable
- Add test cases for lagging claim scenarios
@ananas-block ananas-block force-pushed the jorrit/fix-epochs-funded-ahead-calculation branch from 15acd45 to fa37fc8 Compare December 4, 2025 22:14
@ananas-block ananas-block force-pushed the jorrit/fix-epochs-funded-ahead-calculation branch from fa37fc8 to 1cfedfb Compare December 4, 2025 22:28
@ananas-block ananas-block merged commit 23731b0 into main Dec 4, 2025
31 checks passed
@ananas-block ananas-block deleted the jorrit/fix-epochs-funded-ahead-calculation branch December 4, 2025 23:57
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