Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds on-chain rent_sponsor plumbing and a 50,000-lamport MINT_CREATION_FEE for compressed-mint creation; threads Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Instruction Builder
participant Program as Mint Action Processor
participant FeePayer as Fee Payer (payer)
participant RentSponsor as Rent Sponsor PDA
participant CPI as System/CPI
Client->>Program: submit create_compressed_mint(with compressible_config, rent_sponsor, create_mint)
Program->>Program: parse accounts (needs_rent_sponsor -> true)
alt write-mode CPI invocation
Program->>Program: require write_mode rent_sponsor present
Program->>CPI: transfer_lamports_via_cpi(FeePayer -> RentSponsor, MINT_CREATION_FEE)
CPI-->>RentSponsor: lamports credited
Program->>Program: proceed with write-mode mint creation
else execute-mode (non-CPI)
Program->>Program: validate rent_sponsor PDA == config or RENT_SPONSOR_V1
Program->>CPI: transfer_lamports_via_cpi(FeePayer -> RentSponsor, MINT_CREATION_FEE)
CPI-->>RentSponsor: lamports credited
Program->>Program: create/init compressed mint accounts
end
Program-->>Client: return success / error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
sdk-libs/compressed-token-sdk/src/compressed_token/v2/create_compressed_mint/instruction.rs (1)
75-91:⚠️ Potential issue | 🟠 Major
create_compressed_mint_cpi_writein this file is permanently broken by the program guard.The companion function
create_compressed_mint_cpi_write(lines 123-174) enforces thatfirst_set_context || set_contextistruebefore building the instruction. Because the program now rejects anycreate_mintinstruction wherewrite_to_cpi_context = true, every instruction produced bycreate_compressed_mint_cpi_writewill be rejected at runtime withCpiContextSetNotUsable.This function should be deprecated (with a
#[deprecated]attribute and a clear explanation) or removed in this PR to avoid shipping dead, misleading API surface.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk-libs/compressed-token-sdk/src/compressed_token/v2/create_compressed_mint/instruction.rs` around lines 75 - 91, The create_compressed_mint_cpi_write function is permanently broken by the program guard that rejects instructions with write_to_cpi_context=true; remove or deprecate this dead API: add a #[deprecated] attribute to create_compressed_mint_cpi_write with a clear message explaining it always triggers CpiContextSetNotUsable and suggest the proper alternative (e.g., create_compressed_mint or the non-CPI helper), update the public API/export list to avoid re-exporting it if necessary, and remove or mark any related tests/docs referencing create_compressed_mint_cpi_write to prevent confusion.sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/cpi_accounts.rs (1)
202-246: 🧹 Nitpick | 🔵 Trivial
to_account_infos()andto_account_metas()ordering is consistent and correct.Both methods place
rent_sponsorafterauthorityand beforefee_payer, which aligns with the program's account iterator order forcreate_mint. The capacity hint (20 + ctoken_accounts.len()) should be bumped to21to account for the new optionalrent_sponsorslot, avoiding a reallocation in the commoncreate_mintpath.✏️ Suggested fix
- let mut accounts = Vec::with_capacity(20 + self.ctoken_accounts.len()); + let mut accounts = Vec::with_capacity(21 + self.ctoken_accounts.len());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/cpi_accounts.rs` around lines 202 - 246, The capacity hint for the accounts Vec is off by one because the optional rent_sponsor adds an extra slot; update the allocation in to_account_infos (and the sibling to_account_metas) from Vec::with_capacity(20 + self.ctoken_accounts.len()) to Vec::with_capacity(21 + self.ctoken_accounts.len()) so the common create_mint path avoids a reallocation while preserving the existing account order (mint_signer, authority, optional rent_sponsor, then fee_payer, ...).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 113-114: The parsed optional account rent_sponsor (obtained via
iter.next_option_mut("rent_sponsor", config.needs_rent_sponsor())) is not being
validated and can be an arbitrary writable account; add an on-chain check that
the account.key() equals the expected protocol PDA constant
(LIGHT_TOKEN_RENT_SPONSOR) before proceeding with any fee transfer or
rent-sponsor logic, and return an appropriate error if it does not; apply the
same check in the other occurrence handling CMint create/close (the block that
mirrors this logic around the other use site).
- Around line 460-467: The function create_compressed_mint_cpi_write produces
instructions that will always hit the guard in accounts.rs (write_to_cpi_context
&& parsed_instruction_data.create_mint.is_some()) and thus always return
ErrorCode::CpiContextSetNotUsable; remove create_compressed_mint_cpi_write (and
the helper new_mint_write_to_cpi_context if unused) or mark
create_compressed_mint_cpi_write #[deprecated] and change its implementation to
return a clear compile/runtime error (or None) so SDK consumers cannot produce
broken instructions—ensure you update/remove any references and add a short doc
comment explaining the deprecation decision.
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 53-56: The code currently uses
ErrorCode::MintActionMissingExecutingAccounts for both executing being None and
rent_sponsor being None; add a new distinct error variant (e.g.,
MintCreationFeeRentSponsorMissing) to the ErrorCode enum and replace the second
.ok_or(...) on rent_sponsor with
.ok_or(ErrorCode::MintCreationFeeRentSponsorMissing) so the rent fee-recipient
missing case is reported separately (keep the existing
.ok_or(ErrorCode::MintActionMissingExecutingAccounts) for executing).
In `@programs/compressed-token/program/src/lib.rs`:
- Line 39: Add a doc comment above the MINT_CREATION_FEE constant explaining why
it is set to 50_000 lamports (e.g., what costs or policy it covers and how it
relates to related constants like COMPRESSION_COST and COMPRESSION_INCENTIVE);
update the declaration for MINT_CREATION_FEE with a concise justification that
references those related constants (COMPRESSION_COST = 10_000,
COMPRESSION_INCENTIVE = 1_000) so maintainers/auditors can understand the fee
basis and any assumptions used to derive the 50_000 value.
In
`@sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/cpi_accounts.rs`:
- Line 92: The rent_sponsor account is only checked for writability via
next_option_mut, so update the parsing in try_from_account_infos_full (the block
that assigns let rent_sponsor = iter.next_option_mut("rent_sponsor",
config.create_mint)?) to validate the account's public key against the constant
LIGHT_TOKEN_RENT_SPONSOR when present; if the optional account exists and its
key does not equal LIGHT_TOKEN_RENT_SPONSOR return a descriptive error (e.g.,
InvalidAccountKey or a custom error) instead of accepting any writable account.
Ensure you use the same iterator/variable names (rent_sponsor, iter, config) and
keep the optional semantics (only validate when Some) so callers get an early,
descriptive failure.
In `@sdk-libs/token-sdk/tests/mint_action_cpi_accounts_tests.rs`:
- Around line 289-297: Add a negative test that ensures AccountsConfig::new()
rejects create_mint when the CPI context set flag is used: construct a
ZMintActionCompressedInstructionData (use the SDK helper
new_mint_write_to_cpi_context) with create_mint populated and
cpi_context.first_set_context/set_context = true and then call
AccountsConfig::new(...); assert it returns Err(CpiContextSetNotUsable). Place
this alongside the existing mint tests (referencing LIGHT_TOKEN_RENT_SPONSOR in
the test setup) to cover the new guard and prevent regressions.
---
Outside diff comments:
In
`@sdk-libs/compressed-token-sdk/src/compressed_token/v2/create_compressed_mint/instruction.rs`:
- Around line 75-91: The create_compressed_mint_cpi_write function is
permanently broken by the program guard that rejects instructions with
write_to_cpi_context=true; remove or deprecate this dead API: add a
#[deprecated] attribute to create_compressed_mint_cpi_write with a clear message
explaining it always triggers CpiContextSetNotUsable and suggest the proper
alternative (e.g., create_compressed_mint or the non-CPI helper), update the
public API/export list to avoid re-exporting it if necessary, and remove or mark
any related tests/docs referencing create_compressed_mint_cpi_write to prevent
confusion.
In
`@sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/cpi_accounts.rs`:
- Around line 202-246: The capacity hint for the accounts Vec is off by one
because the optional rent_sponsor adds an extra slot; update the allocation in
to_account_infos (and the sibling to_account_metas) from Vec::with_capacity(20 +
self.ctoken_accounts.len()) to Vec::with_capacity(21 +
self.ctoken_accounts.len()) so the common create_mint path avoids a reallocation
while preserving the existing account order (mint_signer, authority, optional
rent_sponsor, then fee_payer, ...).
---
Duplicate comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 49-59: The transfer currently sends MINT_CREATION_FEE to whichever
writable account is passed as executing.rent_sponsor without validating its
identity; before calling transfer_lamports_via_cpi in the block guarded by
accounts_config.create_mint, verify the rent_sponsor is the expected account
(e.g., compare executing.rent_sponsor pubkey against the validated/expected rent
sponsor from parsed accounts or require it is a signer/authority similar to the
check in accounts.rs) and return ErrorCode::MintActionMissingExecutingAccounts
(or a new appropriate error) if the identity check fails; perform this
validation immediately after fetching executing and rent_sponsor and only then
call transfer_lamports_via_cpi(MINT_CREATION_FEE, executing.system.fee_payer,
rent_sponsor).
programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs
Show resolved
Hide resolved
programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs
Outdated
Show resolved
Hide resolved
programs/compressed-token/program/src/compressed_token/mint_action/processor.rs
Outdated
Show resolved
Hide resolved
sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/cpi_accounts.rs
Show resolved
Hide resolved
| // Rent sponsor (required for create_mint, known PDA) | ||
| create_test_account( | ||
| LIGHT_TOKEN_RENT_SPONSOR, | ||
| [0u8; 32], | ||
| false, | ||
| true, | ||
| false, | ||
| vec![], | ||
| ), |
There was a problem hiding this comment.
Happy-path test for rent_sponsor is correct; missing negative test for the new CPI-context guard.
The new LIGHT_TOKEN_RENT_SPONSOR account and the assert!(parsed.rent_sponsor.is_some()) assertion are correct. However, AccountsConfig::new() in the program now rejects create_mint when write_to_cpi_context = true — that invariant has no test coverage. A failing test case like the one below would prevent regressions:
✅ Suggested negative test
#[test]
fn test_create_mint_rejected_when_write_to_cpi_context() {
// Build a ZMintActionCompressedInstructionData with create_mint set
// AND cpi_context.first_set_context = true / set_context = true.
// AccountsConfig::new() must return Err(CpiContextSetNotUsable).
//
// (Use the SDK's new_mint_write_to_cpi_context builder to construct the data.)
}Also applies to: 354-354
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@sdk-libs/token-sdk/tests/mint_action_cpi_accounts_tests.rs` around lines 289
- 297, Add a negative test that ensures AccountsConfig::new() rejects
create_mint when the CPI context set flag is used: construct a
ZMintActionCompressedInstructionData (use the SDK helper
new_mint_write_to_cpi_context) with create_mint populated and
cpi_context.first_set_context/set_context = true and then call
AccountsConfig::new(...); assert it returns Err(CpiContextSetNotUsable). Place
this alongside the existing mint tests (referencing LIGHT_TOKEN_RENT_SPONSOR in
the test setup) to cover the new guard and prevent regressions.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
sdk-libs/token-sdk/src/instruction/create_mints.rs (1)
282-307:⚠️ Potential issue | 🔴 CriticalFix
invoke_multiple_mints: The multi-mint CPI write path is broken by the new guard.
invoke_cpi_writeconstructs each write instruction viaMintActionCompressedInstructionData::new_mint_write_to_cpi_context, which sets bothcreate_mint: Some(CreateMint::default())andcpi_context: Some(cpi_context). This means thewrite_to_cpi_contextflag (derived fromcpi_context.first_set_context() || cpi_context.set_context()) will always be true. The guard inAccountsConfig::newat lines 468–474 ofaccounts.rsexplicitly rejects any instruction where both conditions hold, returningCpiContextSetNotUsable. Every call toinvoke_cpi_writein the N>1 loop (lines 293–295) will therefore fail immediately at accounts validation, makinginvoke_multiple_mints— and thusCreateMintsCpiwith N≥2 or nonzerocpi_context_offset— unreachable. The module docstring still advertises the N>1 path, so callers will silently hit this hard error.
invoke_single_mintandinvoke_executeare unaffected because they useinvoke_execute, which does not setwrite_to_cpi_context(flags are both false). The guard must either be removed for write operations orinvoke_cpi_writemust be redesigned to avoid the incompatibility.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk-libs/token-sdk/src/instruction/create_mints.rs` around lines 282 - 307, invoke_multiple_mints fails because invoke_cpi_write builds instructions that set both create_mint (Some) and cpi_context (Some), which the new AccountsConfig guard rejects; fix by changing invoke_cpi_write so the CPI write instructions do not set create_mint at all (i.e., build the MintActionCompressedInstructionData for a pure "write to CPI context" path with create_mint = None and only the cpi_context set), or use/introduce an alternative constructor that produces a write-only instruction; update invoke_cpi_write (and any helper constructor calls it uses) to avoid the simultaneous create_mint + cpi_context combination so the accounts validation no longer returns CpiContextSetNotUsable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 454-458: Replace the reused
ErrorCode::CompressAndCloseCMintMustBeOnlyAction with a new, distinct error
variant to represent the separate invariant that create_mint (top-level) cannot
be combined with CompressAndCloseCMint: add a new enum variant e.g.,
CannotCombineCreateMintWithCompressAndClose to the ErrorCode definition, give it
a clear error message, and update the check in accounts.rs that currently
references ErrorCode::CompressAndCloseCMintMustBeOnlyAction (the block using
has_compress_and_close_cmint_action &&
parsed_instruction_data.create_mint.is_some()) to return the new variant
instead; keep the original CompressAndCloseCMintMustBeOnlyAction for the
existing actions-only case.
In `@programs/compressed-token/program/tests/mint_action.rs`:
- Around line 348-362: The variable is_creating_mint is misnamed:
instruction_data.mint.is_none() actually represents the
compressed-mint-decompressed flag (cmint_decompressed) in production; rename
is_creating_mint to cmint_decompressed to match accounts.rs semantics and avoid
confusion, and if you intended to detect a true "creating new mint" case
instead, replace that expression with the correct condition
(create_mint.is_some() && mint.is_none() or create_mint.is_some() &&
mint.is_some() per your creation logic) and update the combined error check that
references is_creating_mint accordingly.
---
Outside diff comments:
In `@sdk-libs/token-sdk/src/instruction/create_mints.rs`:
- Around line 282-307: invoke_multiple_mints fails because invoke_cpi_write
builds instructions that set both create_mint (Some) and cpi_context (Some),
which the new AccountsConfig guard rejects; fix by changing invoke_cpi_write so
the CPI write instructions do not set create_mint at all (i.e., build the
MintActionCompressedInstructionData for a pure "write to CPI context" path with
create_mint = None and only the cpi_context set), or use/introduce an
alternative constructor that produces a write-only instruction; update
invoke_cpi_write (and any helper constructor calls it uses) to avoid the
simultaneous create_mint + cpi_context combination so the accounts validation no
longer returns CpiContextSetNotUsable.
---
Duplicate comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 114-115: The rent_sponsor account returned by
iter.next_option_mut("rent_sponsor", config.needs_rent_sponsor()) is not being
validated and can be replaced by an attacker to receive MINT_CREATION_FEE;
derive the expected protocol PDA for LIGHT_TOKEN_RENT_SPONSOR (using the same
seeds/constants used elsewhere in this crate and the program id, e.g., via
Pubkey::find_program_address) and compare it to the provided rent_sponsor.key
(and error if missing or mismatched), so that the processor only transfers
MINT_CREATION_FEE to the canonical LIGHT_TOKEN_RENT_SPONSOR PDA; update the
validation near where rent_sponsor is parsed (the code around
iter.next_option_mut, config.needs_rent_sponsor(), and the MINT_CREATION_FEE
transfer) to perform this check and return an appropriate error if the PDA does
not match.
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 49-58: The code is using a single error variant
MintActionMissingExecutingAccounts for three different failure modes; update the
error enum to add distinct variants (e.g., MintActionMissingExecutingAccounts,
MintActionMissingRentSponsor, MintActionIdempotentExit) and replace the
.ok_or(...) calls accordingly: leave
validated_accounts.executing.ok_or(MintActionMissingExecutingAccounts) for the
missing executing accounts case, use
rent_sponsor.ok_or(MintActionMissingRentSponsor) for the missing rent_sponsor
case, and change the idempotent-exit usage (the other spot that currently
returns MintActionMissingExecutingAccounts) to return MintActionIdempotentExit;
update any matching error handling or docs to reflect the new variants so
callers can differentiate the three failure reasons.
In
`@sdk-libs/compressed-token-sdk/src/compressed_token/v2/create_compressed_mint/instruction.rs`:
- Around line 123-174: The create_compressed_mint_cpi_write function builds an
instruction using new_mint_write_to_cpi_context which always sets create_mint =
Some(...), causing write_to_cpi_context=true + create_mint populated (and thus
CpiContextSetNotUsable) — fix by using an instruction constructor that does not
set create_mint (or explicitly set create_mint = None) when building
MintActionCompressedInstructionData for CPI write, or switch to the correct
factory (e.g., a non-creating "write only" constructor) so create_mint is not
populated; update create_compressed_mint_cpi_write to call that alternative
constructor (or clear the create_mint field) and ensure cpi_context flags remain
consistent with the chosen constructor.
programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/account_metas.rs`:
- Around line 132-137: The with_rent_sponsor setter allows setting rent_sponsor
without compressible_config which can reorder account metas and break
create_mint/compressible parsing; update the implementation to guard against
this by either (A) making with_rent_sponsor also require/attach a
compressible_config (or call into with_compressible_mint) or (B) add a
validation step in the build/validate method that checks if rent_sponsor is
Some(...) while compressible_config is None and then return/error/panic with a
clear message; also update the doc comment on with_rent_sponsor to state it must
be paired with compressible_config (or use with_compressible_mint) and reference
the compressible_config field and with_compressible_mint method for callers.
---
Duplicate comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 456-460: The current branch that checks
has_compress_and_close_cmint_action &&
parsed_instruction_data.create_mint.is_some() reuses
CompressAndCloseCMintMustBeOnlyAction which is misleading; add a new error
variant (e.g. CreateMintWithCompressAndCloseCMintNotAllowed) to the ErrorCode
enum and replace the Err(...) return in this if-block with the new variant, and
update the msg! invocation to a clear, specific message referencing create_mint
+ CompressAndCloseCMint; also update any error docs/tests that assert the old
variant.
- Around line 469-476: The current guard blocks any instruction with
parsed_instruction_data.create_mint when write_to_cpi_context is true, which
makes the helper create_compressed_mint_cpi_write produce unusable instructions;
remove or deprecate the create_compressed_mint_cpi_write helper (and any SDK
bindings that call it) so callers cannot generate instructions that will always
fail due to this guard (referencing write_to_cpi_context,
parsed_instruction_data.create_mint and the ErrorCode::CpiContextSetNotUsable
check), or alternatively change the helper to never set create_mint when
targeting CPI-write contexts so the guard no longer triggers.
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 48-68: Change the generic error mapping for a missing rent_sponsor
to a distinct error variant: instead of mapping rent_sponsor absence to
ErrorCode::MintActionMissingExecutingAccounts, add a new ErrorCode variant
(e.g., ErrorCode::MintActionMissingRentSponsor) and return that when
executing.rent_sponsor is None; update the check in the mint creation block (the
code using accounts_config.create_mint, validated_accounts.executing, let
rent_sponsor = executing.rent_sponsor.ok_or(...)? and the subsequent
rent_sponsor.key() comparison) to use the new ErrorCode and adjust any tests or
match arms that expect the old error.
In
`@sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/cpi_accounts.rs`:
- Around line 94-96: After reading rent_sponsor via
iter.next_option_mut("rent_sponsor", config.create_mint) validate that
rent_sponsor.key() equals the expected PDA before proceeding: derive the
expected PDA using the same seeds/program-id logic used when the rent sponsor
PDA is originally created (use config.create_mint and the program id/seeds used
by your program), compare it to rent_sponsor.key(), and return a clear error if
it does not match; place this check immediately after the rent_sponsor binding
in the same function so callers fail fast with a readable message.
sdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/account_metas.rs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 91-102: The rent_sponsor account must be parsed as mutable when
config.create_mint is true because fee transfer writes lamports; replace the
call to iter.next_account("rent_sponsor")? with the mut-validated iterator call
(e.g., iter.next_mut("rent_sponsor")?) so write_mode_rent_sponsor is obtained as
a mutable account; keep the surrounding conditional (config.create_mint) and
leave the rest (CpiContextLightSystemAccounts::new(...) and the system_program
handling) unchanged.
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 184-190: The current idempotent early-exit branch uses
ErrorCode::MintActionMissingExecutingAccounts which is misleading for
create_mint; add a new error variant (e.g., CreateMintIdempotentNotAllowed) to
the ErrorCode enum and return that when is_idempotent_early_exit(err) is true
and accounts_config.create_mint is set; update any error display/serialization
as needed and replace the existing return
Err(ErrorCode::MintActionMissingExecutingAccounts.into()) in the create_mint
branch with Err(ErrorCode::CreateMintIdempotentNotAllowed.into()) so the failure
reason is explicit (refer to is_idempotent_early_exit,
accounts_config.create_mint, and the create_mint code path).
---
Duplicate comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 476-480: The check that blocks combining create_mint with
CompressAndCloseCMint uses the generic
ErrorCode::CompressAndCloseCMintMustBeOnlyAction which is ambiguous; add a new
dedicated error variant (e.g.,
ErrorCode::CreateMintCannotCombineWithCompressAndCloseCMint) to your ErrorCode
enum and return that here instead of CompressAndCloseCMintMustBeOnlyAction,
updating the msg! string accordingly and ensuring the new error is
documented/converted to ProgramError where needed; change the conditional in the
block that references has_compress_and_close_cmint_action and
parsed_instruction_data.create_mint to return the new error.
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 50-58: The code uses the same ErrorCode variant
(MintActionMissingExecutingAccounts) for multiple missing-option failures; add
distinct error variants (e.g., MintActionMissingRentSponsor and
MintActionMissingCompressibleConfig) to the ErrorCode enum and update the
processor code around validated_accounts.executing: keep the existing check that
returns MintActionMissingExecutingAccounts when executing is None, but change
the rent_sponsor unwrap to return MintActionMissingRentSponsor when
executing.rent_sponsor is None and the compressible_config unwrap to return
MintActionMissingCompressibleConfig when executing.compressible_config is None;
also update any tests or match arms that rely on the old variant.
programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs
Show resolved
Hide resolved
programs/compressed-token/program/src/compressed_token/mint_action/processor.rs
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs (1)
91-95:⚠️ Potential issue | 🟡 Minor
rent_sponsormust be parsed as mutable in write mode.The fee transfer at
processor.rs:78credits lamports to this account, so it must be writable. Usingnext_accountdoesn't enforce mutability.🔧 Suggested fix
let write_mode_rent_sponsor = if config.create_mint { - Some(iter.next_account("rent_sponsor")?) + Some(iter.next_mut("rent_sponsor")?) } else { None };Based on learnings: "Use specialized AccountIterator methods (
next_signer,next_mut,next_signer_mut, etc.) instead of manually callingnext_account()followed by separate validation functions".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs` around lines 91 - 95, The rent_sponsor account is written to (lamports credited in processor.rs:78) so when config.create_mint is true you must parse it as mutable; replace the current Some(iter.next_account("rent_sponsor")?) with Some(iter.next_mut("rent_sponsor")?) (or next_signer_mut if it must also be a signer) so the AccountIterator enforces writability for write_mode_rent_sponsor.programs/compressed-token/program/src/compressed_token/mint_action/processor.rs (1)
52-57:⚠️ Potential issue | 🟡 MinorError codes conflate distinct failure modes.
Lines 54 and 57 both return
MintActionMissingExecutingAccountsfor different missing accounts:
- Line 54:
rent_sponsorisNone- Line 57:
compressible_configisNoneWhen SDK consumers receive this error, they can't distinguish which account was missing. Consider using
MissingRentSponsorfor Line 54 (or a similar dedicated variant) to make failures immediately actionable.🛠️ Suggested differentiation
let rent_sponsor = executing .rent_sponsor - .ok_or(ErrorCode::MintActionMissingExecutingAccounts)?; + .ok_or(ErrorCode::MissingRentSponsor)?; let config = executing .compressible_config .ok_or(ErrorCode::MintActionMissingExecutingAccounts)?;You'd need to add
MissingRentSponsorto theErrorCodeenum inanchor/src/lib.rs.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs` around lines 52 - 57, The two Option unwraps in processor.rs currently map different missing accounts to the same ErrorCode::MintActionMissingExecutingAccounts; add a distinct enum variant (e.g., ErrorCode::MissingRentSponsor) to the ErrorCode enum (anchor/src/lib.rs) and change the rent_sponsor None branch in the mint action (the let rent_sponsor = executing.rent_sponsor.ok_or(...)) to return ErrorCode::MissingRentSponsor while leaving compressible_config to return the existing ErrorCode::MintActionMissingExecutingAccounts (or add another specific variant if desired) so callers can distinguish which executing account is missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 66-77: The code reuses
ErrorCode::MintActionMissingExecutingAccounts for two different missing fields
in write mode; introduce a new error variant (e.g.,
ErrorCode::MintActionMissingWriteModeFeePayer) and replace the ok_or on the
fee_payer extraction so the absence of write_to_cpi_context_system.fee_payer
returns that new variant; keep the existing check and InvalidRentSponsor error
for rent_sponsor (referencing write_mode_rent_sponsor,
write_to_cpi_context_system, fee_payer,
ErrorCode::MintActionMissingExecutingAccounts, and
ErrorCode::InvalidRentSponsor) so each distinct failure has its own error.
---
Duplicate comments:
In
`@programs/compressed-token/program/src/compressed_token/mint_action/accounts.rs`:
- Around line 91-95: The rent_sponsor account is written to (lamports credited
in processor.rs:78) so when config.create_mint is true you must parse it as
mutable; replace the current Some(iter.next_account("rent_sponsor")?) with
Some(iter.next_mut("rent_sponsor")?) (or next_signer_mut if it must also be a
signer) so the AccountIterator enforces writability for write_mode_rent_sponsor.
In
`@programs/compressed-token/program/src/compressed_token/mint_action/processor.rs`:
- Around line 52-57: The two Option unwraps in processor.rs currently map
different missing accounts to the same
ErrorCode::MintActionMissingExecutingAccounts; add a distinct enum variant
(e.g., ErrorCode::MissingRentSponsor) to the ErrorCode enum (anchor/src/lib.rs)
and change the rent_sponsor None branch in the mint action (the let rent_sponsor
= executing.rent_sponsor.ok_or(...)) to return ErrorCode::MissingRentSponsor
while leaving compressible_config to return the existing
ErrorCode::MintActionMissingExecutingAccounts (or add another specific variant
if desired) so callers can distinguish which executing account is missing.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (5)
program-tests/compressed-token-test/tests/mint/cpi_context.rsis excluded by none and included by nonesdk-tests/sdk-token-test/src/ctoken_pda/mint.rsis excluded by none and included by nonesdk-tests/sdk-token-test/src/ctoken_pda/mod.rsis excluded by none and included by nonesdk-tests/sdk-token-test/src/mint_compressed_tokens_cpi_write.rsis excluded by none and included by nonesdk-tests/sdk-token-test/tests/ctoken_pda.rsis excluded by none and included by none
📒 Files selected for processing (7)
programs/compressed-token/anchor/src/lib.rsprograms/compressed-token/program/src/compressed_token/mint_action/accounts.rsprograms/compressed-token/program/src/compressed_token/mint_action/processor.rsprograms/compressed-token/program/tests/constants.rssdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/account_metas.rssdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/instruction.rssdk-libs/compressed-token-sdk/src/compressed_token/v2/mint_action/mod.rs
programs/compressed-token/program/src/compressed_token/mint_action/processor.rs
Show resolved
Hide resolved
Entire-Checkpoint: 3b001a578b94
Removes the restriction that blocked create_mint when write_to_cpi_context is true. This enables multi-mint creation (N-1 write-mode CPI calls + 1 execute-mode call). In write mode, the mint creation fee is charged by validating rent_sponsor against the hardcoded RENT_SPONSOR_V1 constant (no compressible_config account needed). The system program is included as a trailing account to enable the fee transfer CPI. Entire-Checkpoint: 3c0618ad006f
The wrapper program doesn't include rent_sponsor in its CPI, so the error changes from 6035 (CpiContextSetNotUsable) to 20009 (account iterator parse failure).
3df502c to
ad85389
Compare
Summary by CodeRabbit
New Features
Bug Fixes / Validation