Skip to content

Commit 9f9f470

Browse files
committed
Add LiteSVM integration test for cutils program
Exercises the cutils program end to end under LiteSVM: - Builds a real Token-Metadata sized-collection NFT (mint + metadata + master edition) so Bubblegum MintToCollectionV1's collection check passes. - Creates a ConcurrentMerkleTree<3,8> via account-compression alloc + Bubblegum create_tree_config. - Calls the cutils `mint` instruction to mint one cNFT into the tree/collection. - Recomputes data_hash/creator_hash exactly as Bubblegum stores the leaf (collection verified=true after MintToCollectionV1), builds the empty-node proof for leaf 0, reads the live root, and calls the cutils `verify` instruction, asserting success and that a tampered data_hash fails. Adds the mpl_token_metadata mainnet fixture (required by MintToCollectionV1) and two clippy allows in the program source (diverging_sub_expression false positive from Anchor's #[program] macro, and vec_init_then_push on the intentional MintToCollectionV1 account-meta builder). https://claude.ai/code/session_013dpnF6uSGWXjkJJZseqzcP
1 parent 8638f00 commit 9f9f470

6 files changed

Lines changed: 773 additions & 22 deletions

File tree

compression/cutils/anchor/programs/cutils/src/bubblegum_types.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,13 @@ pub fn leaf_schema_v1_hash(
105105
pub fn get_asset_id(tree: &Pubkey, nonce: u64) -> Pubkey {
106106
// mpl-bubblegum program ID
107107
let bubblegum_id = Pubkey::new_from_array([
108-
0x98, 0x8b, 0x80, 0xeb, 0x79, 0x35, 0x28, 0x69, 0xb2, 0x24, 0x74, 0x5f, 0x59, 0xdd,
109-
0xbf, 0x8a, 0x26, 0x58, 0xca, 0x13, 0xdc, 0x68, 0x81, 0x21, 0x26, 0x35, 0x1c, 0xae,
110-
0x07, 0xc1, 0xa5, 0xa5,
108+
0x98, 0x8b, 0x80, 0xeb, 0x79, 0x35, 0x28, 0x69, 0xb2, 0x24, 0x74, 0x5f, 0x59, 0xdd, 0xbf,
109+
0x8a, 0x26, 0x58, 0xca, 0x13, 0xdc, 0x68, 0x81, 0x21, 0x26, 0x35, 0x1c, 0xae, 0x07, 0xc1,
110+
0xa5, 0xa5,
111111
]);
112-
Pubkey::find_program_address(&[b"asset", tree.as_ref(), &nonce.to_le_bytes()], &bubblegum_id).0
112+
Pubkey::find_program_address(
113+
&[b"asset", tree.as_ref(), &nonce.to_le_bytes()],
114+
&bubblegum_id,
115+
)
116+
.0
113117
}

compression/cutils/anchor/programs/cutils/src/instructions/mint.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::bubblegum_types::{
2-
Collection, Creator, MetadataArgs, MintToCollectionV1InstructionArgs,
3-
TokenProgramVersion, TokenStandard, MINT_TO_COLLECTION_V1_DISCRIMINATOR,
2+
Collection, Creator, MetadataArgs, MintToCollectionV1InstructionArgs, TokenProgramVersion,
3+
TokenStandard, MINT_TO_COLLECTION_V1_DISCRIMINATOR,
44
};
55
use crate::*;
66
use anchor_lang::solana_program::{
@@ -75,10 +75,10 @@ impl Mint<'_> {
7575
Ok(())
7676
}
7777

78-
pub fn actuate<'info>(
79-
context: Context<'info, Mint<'info>>,
80-
params: MintParams,
81-
) -> Result<()> {
78+
// `with_capacity` + push is intentional here: it documents the exact 16-account
79+
// MintToCollectionV1 layout in CPI order, so allow clippy's vec_init_then_push.
80+
#[allow(clippy::vec_init_then_push)]
81+
pub fn actuate<'info>(context: Context<'info, Mint<'info>>, params: MintParams) -> Result<()> {
8282
// Build MintToCollectionV1 instruction data
8383
let args = MintToCollectionV1InstructionArgs {
8484
metadata: MetadataArgs {
@@ -188,7 +188,10 @@ impl Mint<'_> {
188188
context.accounts.payer.to_account_info(),
189189
context.accounts.tree_delegate.to_account_info(),
190190
context.accounts.collection_authority.to_account_info(),
191-
context.accounts.collection_authority_record_pda.to_account_info(),
191+
context
192+
.accounts
193+
.collection_authority_record_pda
194+
.to_account_info(),
192195
context.accounts.collection_mint.to_account_info(),
193196
context.accounts.collection_metadata.to_account_info(),
194197
context.accounts.edition_account.to_account_info(),

compression/cutils/anchor/programs/cutils/src/lib.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// False positive emitted by Anchor's `#[program]` macro expansion; accepted in
2+
// this repo (the sibling cnft-burn example does the same).
3+
#![allow(clippy::diverging_sub_expression)]
4+
15
pub mod instructions;
26
pub use instructions::*;
37

@@ -10,16 +14,14 @@ use anchor_lang::prelude::*;
1014

1115
/// SPL Account Compression program ID (cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK)
1216
const SPL_ACCOUNT_COMPRESSION_ID: Pubkey = Pubkey::new_from_array([
13-
0x09, 0x2a, 0x13, 0xee, 0x95, 0xc4, 0x1c, 0xba, 0x08, 0xa6, 0x7f, 0x5a, 0xc6, 0x7e, 0x8d,
14-
0xf7, 0xe1, 0xda, 0x11, 0x62, 0x5e, 0x1d, 0x64, 0x13, 0x7f, 0x8f, 0x4f, 0x23, 0x83, 0x03,
15-
0x7f, 0x14,
17+
0x09, 0x2a, 0x13, 0xee, 0x95, 0xc4, 0x1c, 0xba, 0x08, 0xa6, 0x7f, 0x5a, 0xc6, 0x7e, 0x8d, 0xf7,
18+
0xe1, 0xda, 0x11, 0x62, 0x5e, 0x1d, 0x64, 0x13, 0x7f, 0x8f, 0x4f, 0x23, 0x83, 0x03, 0x7f, 0x14,
1619
]);
1720

1821
/// mpl-bubblegum program ID (BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY)
1922
const MPL_BUBBLEGUM_ID: Pubkey = Pubkey::new_from_array([
20-
0x98, 0x8b, 0x80, 0xeb, 0x79, 0x35, 0x28, 0x69, 0xb2, 0x24, 0x74, 0x5f, 0x59, 0xdd, 0xbf,
21-
0x8a, 0x26, 0x58, 0xca, 0x13, 0xdc, 0x68, 0x81, 0x21, 0x26, 0x35, 0x1c, 0xae, 0x07, 0xc1,
22-
0xa5, 0xa5,
23+
0x98, 0x8b, 0x80, 0xeb, 0x79, 0x35, 0x28, 0x69, 0xb2, 0x24, 0x74, 0x5f, 0x59, 0xdd, 0xbf, 0x8a,
24+
0x26, 0x58, 0xca, 0x13, 0xdc, 0x68, 0x81, 0x21, 0x26, 0x35, 0x1c, 0xae, 0x07, 0xc1, 0xa5, 0xa5,
2325
]);
2426

2527
#[derive(Clone)]
@@ -38,10 +40,7 @@ pub mod cutils {
3840
use super::*;
3941

4042
#[access_control(context.accounts.validate(&context, &params))]
41-
pub fn mint<'info>(
42-
context: Context<'info, Mint<'info>>,
43-
params: MintParams,
44-
) -> Result<()> {
43+
pub fn mint<'info>(context: Context<'info, Mint<'info>>, params: MintParams) -> Result<()> {
4544
Mint::actuate(context, params)
4645
}
4746

0 commit comments

Comments
 (0)