Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions program-tests/compressed-token-test/tests/light_token/burn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ async fn test_burn_success_cases() {
amount: burn_amount,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -79,6 +80,7 @@ async fn test_burn_success_cases() {
amount: burn_amount,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -129,6 +131,7 @@ async fn test_burn_fails() {
amount: 50,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -159,6 +162,7 @@ async fn test_burn_fails() {
amount: 50,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -205,6 +209,7 @@ async fn test_burn_fails() {
amount: 50,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -235,6 +240,7 @@ async fn test_burn_fails() {
amount: 200, // More than 100 balance
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -270,6 +276,7 @@ async fn test_burn_fails() {
amount: 50,
authority: wrong_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -371,6 +378,7 @@ async fn setup_burn_test() -> BurnTestContext {
amount: 100,
authority: mint_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -416,6 +424,7 @@ async fn test_burn_checked_success() {
decimals: 8, // Correct decimals
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -448,6 +457,7 @@ async fn test_burn_checked_wrong_decimals() {
decimals: 7, // Wrong decimals
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ async fn test_ctoken_transfer_fails_when_mint_paused() {
decimals: 9,
authority: owner.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -243,6 +244,7 @@ async fn test_ctoken_transfer_fails_with_non_zero_transfer_fee() {
decimals: 9,
authority: owner.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -291,6 +293,7 @@ async fn test_ctoken_transfer_fails_with_non_nil_transfer_hook() {
decimals: 9,
authority: owner.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ async fn transfer_checked_and_assert(
decimals,
authority: authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -769,6 +770,7 @@ async fn transfer_checked_and_assert_fails(
decimals,
authority: authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -941,6 +943,7 @@ async fn test_ctoken_transfer_checked_max_top_up_exceeded() {
decimals: 9,
authority: owner_keypair.pubkey(),
max_top_up: Some(1),
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ async fn test_transfer_requires_checked_for_restricted_extensions() {
amount: transfer_amount,
authority: owner.pubkey(),
max_top_up: Some(0), // 0 = no limit, but includes system program for compressible
fee_payer: None,
}
.instruction()
.unwrap();
Expand All @@ -188,6 +189,7 @@ async fn test_transfer_requires_checked_for_restricted_extensions() {
decimals: 9,
authority: owner.pubkey(),
max_top_up: Some(0), // 0 = no limit, but includes system program for compressible
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down
2 changes: 2 additions & 0 deletions program-tests/compressed-token-test/tests/mint/burn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ async fn test_ctoken_burn() {
amount: 500,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand All @@ -122,6 +123,7 @@ async fn test_ctoken_burn() {
amount: 500,
authority: ctx.owner_keypair.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down
4 changes: 4 additions & 0 deletions program-tests/compressed-token-test/tests/mint/mint_to.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ async fn test_ctoken_mint_to() {
amount: 500,
authority: ctx.mint_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand All @@ -117,6 +118,7 @@ async fn test_ctoken_mint_to() {
amount: 500,
authority: ctx.mint_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -168,6 +170,7 @@ async fn test_ctoken_mint_to_checked_success() {
decimals: 8, // Correct decimals
authority: ctx.mint_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down Expand Up @@ -210,6 +213,7 @@ async fn test_ctoken_mint_to_checked_wrong_decimals() {
decimals: 7, // Wrong decimals
authority: ctx.mint_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.unwrap();
Expand Down
1 change: 1 addition & 0 deletions program-tests/registry-test/tests/compressible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,7 @@ async fn mint_to_token<R: Rpc>(
amount,
authority: mint_authority.pubkey(),
max_top_up: None,
fee_payer: None,
}
.instruction()
.map_err(|e| RpcError::CustomError(format!("Failed to create MintTo instruction: {:?}", e)))?;
Expand Down
9 changes: 8 additions & 1 deletion programs/compressed-token/program/docs/ctoken/BURN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ Format 2 (10 bytes):
- (signer)
- Owner of the source CToken account
- Must sign the transaction
- Also serves as payer for rent top-ups if needed
- If no fee_payer provided: also serves as payer for top-ups (must be writable)
- If fee_payer provided: readonly (only needs to sign)

4. fee_payer (optional)
- (signer, writable)
- Optional separate account to pay for rent top-ups
- If not provided, authority account pays for top-ups
- Must have sufficient lamports to cover the top-up amount

**Instruction Logic and Checks:**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ Format 2 (11 bytes):
- (signer)
- Owner of the source CToken account
- Must sign the transaction
- Also serves as payer for rent top-ups if needed
- If no fee_payer provided: also serves as payer for top-ups (must be writable)
- If fee_payer provided: readonly (only needs to sign)

4. fee_payer (optional)
- (signer, writable)
- Optional separate account to pay for rent top-ups
- If not provided, authority account pays for top-ups
- Must have sufficient lamports to cover the top-up amount

**Instruction Logic and Checks:**

Expand Down
11 changes: 9 additions & 2 deletions programs/compressed-token/program/docs/ctoken/MINT_TO.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,17 @@ Format variants:
- May receive rent top-up if compressible

3. authority
- (signer, writable when top-ups needed)
- (signer)
- Mint authority of the CMint account
- Validated: must sign the transaction
- Also serves as payer for rent top-ups if needed
- If no fee_payer provided: also serves as payer for top-ups (must be writable)
- If fee_payer provided: readonly (only needs to sign)

4. fee_payer (optional)
- (signer, writable)
- Optional separate account to pay for rent top-ups
- If not provided, authority account pays for top-ups
- Must have sufficient lamports to cover the top-up amount

**Instruction Logic and Checks:**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,17 @@ Format variants:
- May receive rent top-up if compressible

3. authority
- (signer, writable when top-ups needed)
- (signer)
- Mint authority of the CMint account
- Validated: must sign the transaction
- Also serves as payer for rent top-ups if needed
- If no fee_payer provided: also serves as payer for top-ups (must be writable)
- If fee_payer provided: readonly (only needs to sign)

4. fee_payer (optional)
- (signer, writable)
- Optional separate account to pay for rent top-ups
- If not provided, authority account pays for top-ups
- Must have sufficient lamports to cover the top-up amount
Comment on lines 44 to +55
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

Document the system_program account and payer fallback clearly.

The SDK/program path now expects a system_program placeholder plus optional fee_payer. The docs still list only 3 required accounts and say authority pays top-ups unconditionally. Please update the account list, minimum accounts, and top-up payer language to match the new flow. As per coding guidelines, docs must match the implementation.

📝 Suggested doc update
-3. authority
+3. authority
    - (signer)
    - Mint authority of the CMint account
    - Validated: must sign the transaction
    - If no fee_payer provided: also serves as payer for top-ups (must be writable)
    - If fee_payer provided: readonly (only needs to sign)

-4. fee_payer (optional)
+4. system_program
+   - (readonly)
+   - System program used for rent/top-up transfers
+
+5. fee_payer (optional)
    - (signer, writable)
    - Optional separate account to pay for rent top-ups
    - If not provided, authority account pays for top-ups
    - Must have sufficient lamports to cover the top-up amount
-1. **Validate minimum accounts:**
-   - Require at least 3 accounts (cmint, destination, authority)
+1. **Validate minimum accounts:**
+   - Require at least 4 accounts (cmint, destination, authority, system_program)
-   - Transfer lamports from authority to both accounts if needed
+   - Transfer lamports from fee_payer if provided, otherwise authority

Also applies to: 59-61, 79-84

🤖 Prompt for AI Agents
In `@programs/compressed-token/program/docs/ctoken/MINT_TO_CHECKED.md` around
lines 44 - 55, Update the MINT_TO_CHECKED.md account list and descriptions to
include the required system_program account and to clarify the fee payer
fallback: add a new "system_program" account entry (readonly, not signer)
required by the SDK/program, update "authority" to be signer and writable when
it will act as the top-up payer (i.e., when no fee_payer provided) and readonly
if a separate fee_payer is supplied, and update "fee_payer (optional)" to state
it is signer and writable when present and that if omitted the authority must be
writable and have sufficient lamports to cover rent top-ups; also update the
"minimum accounts" and any top-up payer language elsewhere in the doc (including
the other occurrences noted) to match this flow so docs reflect the actual
implementation.


**Instruction Logic and Checks:**

Expand Down
10 changes: 8 additions & 2 deletions programs/compressed-token/program/docs/ctoken/TRANSFER.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,14 @@ After discriminator byte, the following formats are supported:
- (signer)
- Owner of the source account or delegate with sufficient allowance
- Must sign the transaction

Note: The authority account (index 2) also serves as the payer for top-ups when accounts have compressible extension.
- If no fee_payer provided: also serves as payer for top-ups (must be writable)
- If fee_payer provided: readonly (only needs to sign)

4. fee_payer (optional)
- (signer, writable)
- Optional separate account to pay for rent top-ups
- If not provided, authority account pays for top-ups
- Must have sufficient lamports to cover the top-up amount

**Instruction Logic and Checks:**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,14 @@ Transfers tokens between decompressed ctoken solana accounts with mint decimals
- Owner of the source account or delegate with sufficient allowance
- Must sign the transaction
- If is permanent delegate, validated as signer and pinocchio validation is skipped
- Also serves as payer for top-ups when accounts have compressible extension
- If no fee_payer provided: also serves as payer for top-ups (must be writable)
- If fee_payer provided: readonly (only needs to sign)

5. fee_payer (optional)
- (signer, writable)
- Optional separate account to pay for rent top-ups
- If not provided, authority account pays for top-ups
- Must have sufficient lamports to cover the top-up amount

**Instruction Logic and Checks:**

Expand Down
21 changes: 16 additions & 5 deletions programs/compressed-token/program/src/ctoken/burn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ pub(crate) type ProcessorFn = fn(&[AccountInfo], &[u8]) -> Result<(), PinocchioP
pub(crate) const BASE_LEN_UNCHECKED: usize = 8;
pub(crate) const BASE_LEN_CHECKED: usize = 9;

/// Burn account indices: [ctoken=0, cmint=1, authority=2]
/// Burn account indices: [ctoken=0, cmint=1, authority=2, system_program=3, fee_payer=4 (optional)]
const BURN_CMINT_IDX: usize = 1;
const BURN_CTOKEN_IDX: usize = 0;
const PAYER_IDX: usize = 2;
#[allow(dead_code)]
const SYSTEM_PROGRAM_IDX: usize = 3;
const FEE_PAYER_IDX: usize = 4;

/// Process ctoken burn instruction
///
Expand All @@ -26,7 +30,9 @@ const BURN_CTOKEN_IDX: usize = 0;
/// Account layout:
/// 0: source CToken account (writable)
/// 1: CMint account (writable)
/// 2: authority (signer, also payer for top-ups)
/// 2: authority (signer, readonly if fee_payer provided, writable otherwise)
/// 3: system_program (readonly) - required for rent top-up CPIs
/// 4: fee_payer (optional, signer, writable) - pays for top-ups instead of authority
#[profile]
#[inline(always)]
pub fn process_ctoken_burn(
Expand All @@ -49,7 +55,9 @@ pub fn process_ctoken_burn(
/// Account layout (same as burn):
/// 0: source CToken account (writable)
/// 1: CMint account (writable)
/// 2: authority (signer, also payer for top-ups)
/// 2: authority (signer, readonly if fee_payer provided, writable otherwise)
/// 3: system_program (readonly) - required for rent top-up CPIs
/// 4: fee_payer (optional, signer, writable) - pays for top-ups instead of authority
#[profile]
#[inline(always)]
pub fn process_ctoken_burn_checked(
Expand Down Expand Up @@ -112,7 +120,10 @@ pub(crate) fn process_ctoken_supply_change_inner<
// SAFETY: accounts.len() >= 3 validated at function entry
let cmint = &accounts[CMINT_IDX];
let ctoken = &accounts[CTOKEN_IDX];
let payer = accounts.get(2);
// Use fee_payer if provided, otherwise fall back to authority
let authority_payer = accounts.get(PAYER_IDX);
let fee_payer = accounts.get(FEE_PAYER_IDX);
let effective_payer = fee_payer.or(authority_payer);

calculate_and_execute_compressible_top_ups(cmint, ctoken, payer, max_top_up)
calculate_and_execute_compressible_top_ups(cmint, ctoken, effective_payer, max_top_up)
}
8 changes: 6 additions & 2 deletions programs/compressed-token/program/src/ctoken/mint_to.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ pub(crate) const MINT_CTOKEN_IDX: usize = 1;
/// Account layout:
/// 0: CMint account (writable)
/// 1: destination CToken account (writable)
/// 2: authority (signer, also payer for top-ups)
/// 2: authority (signer, readonly if fee_payer provided, writable otherwise)
/// 3: system_program (readonly) - required for rent top-up CPIs
/// 4: fee_payer (optional, signer, writable) - pays for top-ups instead of authority
#[profile]
#[inline(always)]
pub fn process_ctoken_mint_to(
Expand All @@ -43,7 +45,9 @@ pub fn process_ctoken_mint_to(
/// Account layout (same as mint_to):
/// 0: CMint account (writable)
/// 1: destination CToken account (writable)
/// 2: authority (signer, also payer for top-ups)
/// 2: authority (signer, readonly if fee_payer provided, writable otherwise)
/// 3: system_program (readonly) - required for rent top-up CPIs
/// 4: fee_payer (optional, signer, writable) - pays for top-ups instead of authority
#[profile]
#[inline(always)]
pub fn process_ctoken_mint_to_checked(
Expand Down
Loading