From a1bb6f144e24b1e75c388ab69c89cb96aed1efab Mon Sep 17 00:00:00 2001 From: ananas-block Date: Mon, 2 Dec 2024 17:02:26 +0000 Subject: [PATCH] feat: use anchor InterfaceAccounts instead of manual checks --- programs/compressed-token/src/burn.rs | 57 ++------- programs/compressed-token/src/freeze.rs | 23 ---- .../compressed-token/src/instructions/burn.rs | 12 +- .../src/instructions/create_token_pool.rs | 41 +------ .../src/instructions/freeze.rs | 9 +- .../src/instructions/transfer.rs | 8 +- programs/compressed-token/src/lib.rs | 13 +- .../src/process_compress_spl_token_account.rs | 14 +-- programs/compressed-token/src/process_mint.rs | 114 ++++++------------ .../compressed-token/src/spl_compression.rs | 75 +++--------- .../compressed-token-test/tests/test.rs | 84 ++++++++----- test-utils/src/spl.rs | 8 +- 12 files changed, 142 insertions(+), 316 deletions(-) diff --git a/programs/compressed-token/src/burn.rs b/programs/compressed-token/src/burn.rs index a7e2f76a26..368adddf7b 100644 --- a/programs/compressed-token/src/burn.rs +++ b/programs/compressed-token/src/burn.rs @@ -15,7 +15,6 @@ use crate::{ get_input_compressed_accounts_with_merkle_context_and_check_signer, DelegatedTransfer, InputTokenDataWithContext, }, - spl_compression::spl_token_pool_derivation, BurnInstruction, ErrorCode, }; @@ -64,52 +63,20 @@ pub fn burn_spl_from_pool_pda<'info>( ctx: &Context<'_, '_, '_, 'info, BurnInstruction<'info>>, inputs: &CompressedTokenInstructionDataBurn, ) -> Result<()> { - if *ctx.accounts.mint.owner != *ctx.accounts.token_program.key { - return err!(crate::ErrorCode::InvalidTokenMintOwner); - } - spl_token_pool_derivation( - ctx.accounts.mint.key, - &crate::ID, - &ctx.accounts.token_pool_pda.key(), - )?; - - let pre_token_balance = TokenAccount::try_deserialize( - &mut &ctx.accounts.token_pool_pda.to_account_info().data.borrow()[..], - )? - .amount; - + let pre_token_balance = ctx.accounts.token_pool_pda.amount; + let cpi_accounts = anchor_spl::token_interface::Burn { + mint: ctx.accounts.mint.to_account_info(), + from: ctx.accounts.token_pool_pda.to_account_info(), + authority: ctx.accounts.cpi_authority_pda.to_account_info(), + }; let signer_seeds = get_cpi_signer_seeds(); let signer_seeds_ref = &[&signer_seeds[..]]; - - match *ctx.accounts.token_program.key { - spl_token::ID => { - let cpi_accounts = anchor_spl::token::Burn { - mint: ctx.accounts.mint.to_account_info(), - from: ctx.accounts.token_pool_pda.to_account_info(), - authority: ctx.accounts.cpi_authority_pda.to_account_info(), - }; - let cpi_ctx = CpiContext::new_with_signer( - ctx.accounts.token_program.to_account_info(), - cpi_accounts, - signer_seeds_ref, - ); - anchor_spl::token::burn(cpi_ctx, inputs.burn_amount) - } - anchor_spl::token_2022::ID => { - let cpi_accounts = anchor_spl::token_2022::Burn { - mint: ctx.accounts.mint.to_account_info(), - from: ctx.accounts.token_pool_pda.to_account_info(), - authority: ctx.accounts.cpi_authority_pda.to_account_info(), - }; - let cpi_ctx = CpiContext::new_with_signer( - ctx.accounts.token_program.to_account_info(), - cpi_accounts, - signer_seeds_ref, - ); - anchor_spl::token_2022::burn(cpi_ctx, inputs.burn_amount) - } - _ => err!(crate::ErrorCode::InvalidTokenProgram), - }?; + let cpi_ctx = CpiContext::new_with_signer( + ctx.accounts.token_program.to_account_info(), + cpi_accounts, + signer_seeds_ref, + ); + anchor_spl::token_interface::burn(cpi_ctx, inputs.burn_amount)?; let post_token_balance = TokenAccount::try_deserialize( &mut &ctx.accounts.token_pool_pda.to_account_info().data.borrow()[..], diff --git a/programs/compressed-token/src/freeze.rs b/programs/compressed-token/src/freeze.rs index ac0ea84354..22bbb3b315 100644 --- a/programs/compressed-token/src/freeze.rs +++ b/programs/compressed-token/src/freeze.rs @@ -1,5 +1,4 @@ use anchor_lang::prelude::*; -use anchor_spl::token::Mint; use light_hasher::DataHasher; use light_hasher::Poseidon; use light_system_program::{ @@ -47,7 +46,6 @@ pub fn process_freeze_or_thaw< ) -> Result<()> { let inputs: CompressedTokenInstructionDataFreeze = CompressedTokenInstructionDataFreeze::deserialize(&mut inputs.as_slice())?; - check_mint_and_freeze_authority(&ctx.accounts.mint, ctx.accounts.authority.key)?; let (compressed_input_accounts, output_compressed_accounts) = create_input_and_output_accounts_freeze_or_thaw::( &inputs, @@ -67,27 +65,6 @@ pub fn process_freeze_or_thaw< ) } -/// Checks: -/// 1. Mint account is owner token22 or spl token program. -/// 2. Mint account is correct account. -/// 3. Freeze authority is authority. -pub fn check_mint_and_freeze_authority(mint: &AccountInfo<'_>, authority: &Pubkey) -> Result<()> { - let freeze_authority = match *mint.owner { - anchor_spl::token_2022::ID | spl_token::ID => { - let mint = Mint::try_deserialize(&mut &mint.try_borrow_data()?[..])?; - Ok(mint - .freeze_authority - .ok_or(crate::ErrorCode::MintHasNoFreezeAuthority)?) - } - _ => err!(crate::ErrorCode::InvalidTokenProgram), - }?; - if freeze_authority != *authority { - err!(crate::ErrorCode::InvalidFreezeAuthority) - } else { - Ok(()) - } -} - pub fn create_input_and_output_accounts_freeze_or_thaw< const FROZEN_INPUTS: bool, const FROZEN_OUTPUTS: bool, diff --git a/programs/compressed-token/src/instructions/burn.rs b/programs/compressed-token/src/instructions/burn.rs index 61ae755587..c670567b99 100644 --- a/programs/compressed-token/src/instructions/burn.rs +++ b/programs/compressed-token/src/instructions/burn.rs @@ -1,11 +1,12 @@ use account_compression::{program::AccountCompression, utils::constants::CPI_AUTHORITY_PDA_SEED}; use anchor_lang::prelude::*; +use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface}; use light_system_program::{ program::LightSystemProgram, sdk::accounts::{InvokeAccounts, SignerAccounts}, }; -use crate::program::LightCompressedToken; +use crate::{program::LightCompressedToken, POOL_SEED}; #[derive(Accounts)] pub struct BurnInstruction<'info> { @@ -22,12 +23,11 @@ pub struct BurnInstruction<'info> { pub cpi_authority_pda: UncheckedAccount<'info>, /// CHECK: is used to burn tokens. #[account(mut)] - pub mint: AccountInfo<'info>, + pub mint: InterfaceAccount<'info, Mint>, /// CHECK: (seed constraint) is derived from mint account. - #[account(mut)] - pub token_pool_pda: AccountInfo<'info>, - /// CHECK: in burn_spl_from_pool_pda. - pub token_program: AccountInfo<'info>, + #[account(mut, seeds = [POOL_SEED, mint.key().as_ref()], bump)] + pub token_pool_pda: InterfaceAccount<'info, TokenAccount>, + pub token_program: Interface<'info, TokenInterface>, pub light_system_program: Program<'info, LightSystemProgram>, /// CHECK: (account compression program). pub registered_program_pda: AccountInfo<'info>, diff --git a/programs/compressed-token/src/instructions/create_token_pool.rs b/programs/compressed-token/src/instructions/create_token_pool.rs index 5cc428da3a..ef4b3a1e27 100644 --- a/programs/compressed-token/src/instructions/create_token_pool.rs +++ b/programs/compressed-token/src/instructions/create_token_pool.rs @@ -1,10 +1,6 @@ use account_compression::utils::constants::CPI_AUTHORITY_PDA_SEED; use anchor_lang::prelude::*; -use anchor_spl::{ - token::{Mint, Token, TokenAccount}, - token_2022::Token2022, - token_interface::{Mint as Mint22, TokenAccount as Token22Account}, -}; +use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface}; use spl_token_2022::{ extension::{BaseStateWithExtensions, ExtensionType, PodStateWithExtensions}, pod::PodMint, @@ -12,7 +8,7 @@ use spl_token_2022::{ pub const POOL_SEED: &[u8] = b"pool"; -/// Creates a spl token pool account which is owned by the token authority pda. +/// Creates a spl or token 2022 token pool account which is owned by the token authority pda. #[derive(Accounts)] pub struct CreateTokenPoolInstruction<'info> { /// UNCHECKED: only pays fees. @@ -28,39 +24,12 @@ pub struct CreateTokenPoolInstruction<'info> { token::mint = mint, token::authority = cpi_authority_pda, )] - pub token_pool_pda: Account<'info, TokenAccount>, - pub system_program: Program<'info, System>, - /// CHECK: is mint account. - #[account(mut)] - pub mint: Account<'info, Mint>, - pub token_program: Program<'info, Token>, - /// CHECK: (seeds anchor constraint). - #[account(seeds = [CPI_AUTHORITY_PDA_SEED], bump)] - pub cpi_authority_pda: AccountInfo<'info>, -} - -/// Creates a token22 token pool account which is owned by the token authority pda. -#[derive(Accounts)] -pub struct CreateTokenPoolInstruction2022<'info> { - /// UNCHECKED: only pays fees. - #[account(mut)] - pub fee_payer: Signer<'info>, - #[account( - init, - seeds = [ - POOL_SEED, &mint.key().to_bytes(), - ], - bump, - payer = fee_payer, - token::mint = mint, - token::authority = cpi_authority_pda, - )] - pub token_pool_pda: InterfaceAccount<'info, Token22Account>, + pub token_pool_pda: InterfaceAccount<'info, TokenAccount>, pub system_program: Program<'info, System>, /// CHECK: is mint account. #[account(mut)] - pub mint: InterfaceAccount<'info, Mint22>, - pub token_program: Program<'info, Token2022>, + pub mint: InterfaceAccount<'info, Mint>, + pub token_program: Interface<'info, TokenInterface>, /// CHECK: (seeds anchor constraint). #[account(seeds = [CPI_AUTHORITY_PDA_SEED], bump)] pub cpi_authority_pda: AccountInfo<'info>, diff --git a/programs/compressed-token/src/instructions/freeze.rs b/programs/compressed-token/src/instructions/freeze.rs index 002ec32951..9353eae13c 100644 --- a/programs/compressed-token/src/instructions/freeze.rs +++ b/programs/compressed-token/src/instructions/freeze.rs @@ -1,5 +1,6 @@ use account_compression::{program::AccountCompression, utils::constants::CPI_AUTHORITY_PDA_SEED}; use anchor_lang::prelude::*; +use anchor_spl::token_interface::Mint; use light_system_program::{ program::LightSystemProgram, sdk::accounts::{InvokeAccounts, SignerAccounts}, @@ -12,8 +13,8 @@ pub struct FreezeInstruction<'info> { /// UNCHECKED: only pays fees. #[account(mut)] pub fee_payer: Signer<'info>, - /// CHECK: is freeze authority, in instruction with - /// check_mint_and_freeze_authority(). + #[account(constraint= authority.key() == mint.freeze_authority.ok_or(crate::ErrorCode::MintHasNoFreezeAuthority)? + @ crate::ErrorCode::InvalidFreezeAuthority)] pub authority: Signer<'info>, /// CHECK: (seed constraint). #[account(seeds = [CPI_AUTHORITY_PDA_SEED], bump,)] @@ -31,9 +32,7 @@ pub struct FreezeInstruction<'info> { /// that this program is the signer of the cpi. pub self_program: Program<'info, LightCompressedToken>, pub system_program: Program<'info, System>, - /// CHECK: owner and account type in instruction with - /// check_mint_and_freeze_authority(). - pub mint: AccountInfo<'info>, + pub mint: InterfaceAccount<'info, Mint>, } impl<'info> InvokeAccounts<'info> for FreezeInstruction<'info> { diff --git a/programs/compressed-token/src/instructions/transfer.rs b/programs/compressed-token/src/instructions/transfer.rs index 3f46eed03a..6e4552b7b4 100644 --- a/programs/compressed-token/src/instructions/transfer.rs +++ b/programs/compressed-token/src/instructions/transfer.rs @@ -1,5 +1,6 @@ use account_compression::{program::AccountCompression, utils::constants::CPI_AUTHORITY_PDA_SEED}; use anchor_lang::prelude::*; +use anchor_spl::token_interface::{TokenAccount, TokenInterface}; use light_system_program::{ self, program::LightSystemProgram, @@ -32,12 +33,11 @@ pub struct TransferInstruction<'info> { /// CHECK:(system program) used to derive cpi_authority_pda and check that /// this program is the signer of the cpi. pub self_program: Program<'info, LightCompressedToken>, - /// CHECK: derivation checked in compress or decompress function. #[account(mut)] - pub token_pool_pda: Option>, + pub token_pool_pda: Option>, #[account(mut, constraint= if token_pool_pda.is_some() {Ok(token_pool_pda.as_ref().unwrap().key() != compress_or_decompress_token_account.key())}else {err!(crate::ErrorCode::TokenPoolPdaUndefined)}? @crate::ErrorCode::IsTokenPoolPda)] - pub compress_or_decompress_token_account: Option>, - pub token_program: Option>, + pub compress_or_decompress_token_account: Option>, + pub token_program: Option>, pub system_program: Program<'info, System>, } diff --git a/programs/compressed-token/src/lib.rs b/programs/compressed-token/src/lib.rs index 6b1dddbe26..8be83fdbf3 100644 --- a/programs/compressed-token/src/lib.rs +++ b/programs/compressed-token/src/lib.rs @@ -39,18 +39,11 @@ pub mod light_compressed_token { /// transferrred to the token pool, and their compressed equivalent is /// minted into a Merkle tree. pub fn create_token_pool<'info>( - _ctx: Context<'_, '_, '_, 'info, CreateTokenPoolInstruction<'info>>, - ) -> Result<()> { - Ok(()) - } - - pub fn create_token_pool_2022<'info>( - ctx: Context<'_, '_, '_, 'info, CreateTokenPoolInstruction2022<'info>>, + ctx: Context<'_, '_, '_, 'info, CreateTokenPoolInstruction<'info>>, ) -> Result<()> { create_token_pool::assert_mint_extensions( &ctx.accounts.mint.to_account_info().try_borrow_data()?, - )?; - Ok(()) + ) } /// Mints tokens from an spl token mint to a list of compressed accounts. @@ -211,7 +204,5 @@ pub enum ErrorCode { NoInputsProvided, InvalidMintAccount, MintHasNoFreezeAuthority, - InvalidTokenProgram, - InvalidTokenMintOwner, MintWithInvalidExtension, } diff --git a/programs/compressed-token/src/process_compress_spl_token_account.rs b/programs/compressed-token/src/process_compress_spl_token_account.rs index d6cfcc7ff0..891c70ae04 100644 --- a/programs/compressed-token/src/process_compress_spl_token_account.rs +++ b/programs/compressed-token/src/process_compress_spl_token_account.rs @@ -6,7 +6,6 @@ use crate::{ ErrorCode, }; use anchor_lang::prelude::*; -use anchor_lang::solana_program::program_pack::Pack; use light_system_program::sdk::CompressedCpiContext; pub fn process_compress_spl_token_account<'info>( @@ -17,18 +16,7 @@ pub fn process_compress_spl_token_account<'info>( ) -> Result<()> { let compression_token_account = if let Some(token_account) = ctx.accounts.compress_or_decompress_token_account.as_ref() { - if *token_account.owner - != ctx - .accounts - .token_program - .as_ref() - .ok_or(ErrorCode::InvalidTokenProgram)? - .key() - { - msg!("Token account is not owned by the token program."); - return err!(ErrorCode::InvalidTokenProgram); - } - spl_token::state::Account::unpack(&token_account.data.borrow())? + token_account } else { return err!(ErrorCode::CompressedPdaUndefinedForCompress); }; diff --git a/programs/compressed-token/src/process_mint.rs b/programs/compressed-token/src/process_mint.rs index f0c71c6085..a3b32c6098 100644 --- a/programs/compressed-token/src/process_mint.rs +++ b/programs/compressed-token/src/process_mint.rs @@ -1,12 +1,9 @@ use account_compression::{program::AccountCompression, utils::constants::CPI_AUTHORITY_PDA_SEED}; -use anchor_lang::{prelude::*, solana_program::program_option::COption}; -use anchor_spl::{ - token::{Mint, TokenAccount}, - token_2022, -}; +use anchor_lang::prelude::*; +use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface}; use light_system_program::{program::LightSystemProgram, OutputCompressedAccountWithPackedContext}; -use crate::{program::LightCompressedToken, spl_compression::spl_token_pool_derivation}; +use crate::{program::LightCompressedToken, POOL_SEED}; #[cfg(target_os = "solana")] use { @@ -278,11 +275,6 @@ pub fn serialize_mint_to_cpi_instruction_data( #[inline(never)] pub fn mint_spl_to_pool_pda(ctx: &Context, amounts: &[u64]) -> Result<()> { - spl_token_pool_derivation( - &ctx.accounts.mint.key(), - &crate::ID, - &ctx.accounts.token_pool_pda.key(), - )?; let mut mint_amount: u64 = 0; for amount in amounts.iter() { mint_amount = mint_amount @@ -290,46 +282,20 @@ pub fn mint_spl_to_pool_pda(ctx: &Context, amounts: &[u64]) - .ok_or(crate::ErrorCode::MintTooLarge)?; } - if let COption::Some(mint_authority) = - Mint::try_deserialize(&mut &ctx.accounts.mint.data.borrow()[..])?.mint_authority - { - if mint_authority != ctx.accounts.authority.key() { - return err!(crate::ErrorCode::InvalidAuthorityMint); - } - } else { - return err!(crate::ErrorCode::InvalidAuthorityMint); - } + let pre_token_balance = ctx.accounts.token_pool_pda.amount; + let cpi_accounts = anchor_spl::token_interface::MintTo { + mint: ctx.accounts.mint.to_account_info(), + to: ctx.accounts.token_pool_pda.to_account_info(), + authority: ctx.accounts.authority.to_account_info(), + }; - let pre_token_balance = - TokenAccount::try_deserialize(&mut &ctx.accounts.token_pool_pda.data.borrow()[..])?.amount; - match ctx.accounts.token_program.key() { - spl_token::ID => { - let cpi_ctx = CpiContext::new( - ctx.accounts.token_program.to_account_info(), - anchor_spl::token::MintTo { - mint: ctx.accounts.mint.to_account_info(), - to: ctx.accounts.token_pool_pda.to_account_info(), - authority: ctx.accounts.authority.to_account_info(), - }, - ); - anchor_spl::token::mint_to(cpi_ctx, mint_amount) - } - token_2022::ID => { - let cpi_ctx = CpiContext::new( - ctx.accounts.token_program.to_account_info(), - anchor_spl::token_2022::MintTo { - mint: ctx.accounts.mint.to_account_info(), - to: ctx.accounts.token_pool_pda.to_account_info(), - authority: ctx.accounts.authority.to_account_info(), - }, - ); - anchor_spl::token_2022::mint_to(cpi_ctx, mint_amount) - } - _ => err!(crate::ErrorCode::InvalidTokenProgram), - }?; + let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts); + anchor_spl::token_interface::mint_to(cpi_ctx, mint_amount)?; - let post_token_balance = - TokenAccount::try_deserialize(&mut &ctx.accounts.token_pool_pda.data.borrow()[..])?.amount; + let post_token_balance = TokenAccount::try_deserialize( + &mut &ctx.accounts.token_pool_pda.to_account_info().data.borrow()[..], + )? + .amount; // Guard against unexpected behavior of the SPL token program. if post_token_balance != pre_token_balance + mint_amount { msg!( @@ -353,13 +319,15 @@ pub struct MintToInstruction<'info> { /// CHECK: #[account(seeds = [CPI_AUTHORITY_PDA_SEED], bump)] pub cpi_authority_pda: UncheckedAccount<'info>, - /// CHECK: in mint_spl_to_pool_pda(). - #[account(mut)] - pub mint: AccountInfo<'info>, - /// CHECK: with spl_token_pool_derivation(). - #[account(mut)] - pub token_pool_pda: AccountInfo<'info>, - pub token_program: AccountInfo<'info>, + #[account( + mut, + constraint = mint.mint_authority.unwrap() == authority.key() + @ crate::ErrorCode::InvalidAuthorityMint + )] + pub mint: InterfaceAccount<'info, Mint>, + #[account(mut, seeds = [POOL_SEED, mint.key().as_ref()], bump)] + pub token_pool_pda: InterfaceAccount<'info, TokenAccount>, + pub token_program: Interface<'info, TokenInterface>, pub light_system_program: Program<'info, LightSystemProgram>, /// CHECK: (different program) checked in account compression program pub registered_program_pda: UncheckedAccount<'info>, @@ -389,39 +357,25 @@ pub mod mint_sdk { use light_system_program::sdk::invoke::get_sol_pool_pda; use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; - pub fn create_create_token_pool_instruction(fee_payer: &Pubkey, mint: &Pubkey) -> Instruction { - let token_pool_pda = get_token_pool_pda(mint); - let instruction_data = crate::instruction::CreateTokenPool {}; - - let accounts = crate::accounts::CreateTokenPoolInstruction { - fee_payer: *fee_payer, - token_pool_pda, - system_program: system_program::ID, - mint: *mint, - token_program: anchor_spl::token::ID, - cpi_authority_pda: get_cpi_authority_pda().0, - }; - - Instruction { - program_id: crate::ID, - accounts: accounts.to_account_metas(Some(true)), - data: instruction_data.data(), - } - } - - pub fn create_create_token_pool_2022_instruction( + pub fn create_create_token_pool_instruction( fee_payer: &Pubkey, mint: &Pubkey, + is_token_22: bool, ) -> Instruction { let token_pool_pda = get_token_pool_pda(mint); - let instruction_data = crate::instruction::CreateTokenPool2022 {}; + let instruction_data = crate::instruction::CreateTokenPool {}; - let accounts = crate::accounts::CreateTokenPoolInstruction2022 { + let token_program: Pubkey = if is_token_22 { + anchor_spl::token_2022::ID + } else { + anchor_spl::token::ID + }; + let accounts = crate::accounts::CreateTokenPoolInstruction { fee_payer: *fee_payer, token_pool_pda, system_program: system_program::ID, mint: *mint, - token_program: anchor_spl::token_2022::ID, + token_program, cpi_authority_pda: get_cpi_authority_pda().0, }; diff --git a/programs/compressed-token/src/spl_compression.rs b/programs/compressed-token/src/spl_compression.rs index 669b322eeb..85d4525c83 100644 --- a/programs/compressed-token/src/spl_compression.rs +++ b/programs/compressed-token/src/spl_compression.rs @@ -1,6 +1,6 @@ #![allow(deprecated)] use anchor_lang::{prelude::*, solana_program::account_info::AccountInfo}; -use anchor_spl::token::Transfer; +use anchor_spl::token_interface; use crate::{ process_transfer::get_cpi_signer_seeds, CompressedTokenInstructionDataTransfer, @@ -9,7 +9,7 @@ use crate::{ pub fn process_compression_or_decompression( inputs: &CompressedTokenInstructionDataTransfer, - ctx: &Context<'_, '_, '_, '_, TransferInstruction>, + ctx: &Context, ) -> Result<()> { if inputs.is_compress { compress_spl_tokens(inputs, ctx) @@ -34,7 +34,7 @@ pub fn spl_token_pool_derivation( pub fn decompress_spl_tokens( inputs: &CompressedTokenInstructionDataTransfer, - ctx: &Context<'_, '_, '_, '_, TransferInstruction>, + ctx: &Context, ) -> Result<()> { let recipient = match ctx.accounts.compress_or_decompress_token_account.as_ref() { Some(compression_recipient) => compression_recipient.to_account_info(), @@ -50,11 +50,7 @@ pub fn decompress_spl_tokens( Some(amount) => amount, None => return err!(crate::ErrorCode::DeCompressAmountUndefinedForDecompress), }; - let is_token_22 = match ctx.accounts.token_program.as_ref().unwrap().key() { - spl_token::ID => Ok(false), - anchor_spl::token_2022::ID => Ok(true), - _ => err!(crate::ErrorCode::InvalidTokenProgram), - }?; + transfer( token_pool_pda, recipient, @@ -65,13 +61,12 @@ pub fn decompress_spl_tokens( .unwrap() .to_account_info(), amount, - is_token_22, ) } pub fn compress_spl_tokens( inputs: &CompressedTokenInstructionDataTransfer, - ctx: &Context<'_, '_, '_, '_, TransferInstruction>, + ctx: &Context, ) -> Result<()> { let recipient_token_pool = match ctx.accounts.token_pool_pda.as_ref() { Some(token_pool_pda) => token_pool_pda, @@ -83,11 +78,6 @@ pub fn compress_spl_tokens( None => return err!(crate::ErrorCode::DeCompressAmountUndefinedForCompress), }; - let is_token_22 = match ctx.accounts.token_program.as_ref().unwrap().key() { - spl_token::ID => Ok(false), - anchor_spl::token_2022::ID => Ok(true), - _ => err!(crate::ErrorCode::InvalidTokenProgram), - }?; transfer_compress( ctx.accounts .compress_or_decompress_token_account @@ -102,7 +92,6 @@ pub fn compress_spl_tokens( .unwrap() .to_account_info(), amount, - is_token_22, ) } @@ -112,32 +101,17 @@ pub fn transfer<'info>( authority: AccountInfo<'info>, token_program: AccountInfo<'info>, amount: u64, - token_22: bool, ) -> Result<()> { let signer_seeds = get_cpi_signer_seeds(); let signer_seeds_ref = &[&signer_seeds[..]]; - if token_22 { - let accounts = anchor_spl::token_2022::Transfer { - from, - to, - authority, - }; - let cpi_ctx = CpiContext::new_with_signer( - token_program.to_account_info(), - accounts, - signer_seeds_ref, - ); - anchor_spl::token_2022::transfer(cpi_ctx, amount) - } else { - let accounts = Transfer { - from, - to, - authority, - }; - let cpi_ctx = CpiContext::new_with_signer(token_program, accounts, signer_seeds_ref); - anchor_spl::token::transfer(cpi_ctx, amount) - } + let accounts = token_interface::Transfer { + from, + to, + authority, + }; + let cpi_ctx = CpiContext::new_with_signer(token_program, accounts, signer_seeds_ref); + anchor_spl::token_interface::transfer(cpi_ctx, amount) } pub fn transfer_compress<'info>( @@ -146,23 +120,12 @@ pub fn transfer_compress<'info>( authority: AccountInfo<'info>, token_program: AccountInfo<'info>, amount: u64, - token_22: bool, ) -> Result<()> { - if token_22 { - let accounts = anchor_spl::token_2022::Transfer { - from, - to, - authority, - }; - let cpi_ctx = CpiContext::new(token_program, accounts); - anchor_spl::token_2022::transfer(cpi_ctx, amount) - } else { - let accounts = Transfer { - from, - to, - authority, - }; - let cpi_ctx = CpiContext::new(token_program, accounts); - anchor_spl::token::transfer(cpi_ctx, amount) - } + let accounts = token_interface::Transfer { + from, + to, + authority, + }; + let cpi_ctx = CpiContext::new(token_program, accounts); + anchor_spl::token_interface::transfer(cpi_ctx, amount) } diff --git a/test-programs/compressed-token-test/tests/test.rs b/test-programs/compressed-token-test/tests/test.rs index d492e2ca50..5d6fca1e3e 100644 --- a/test-programs/compressed-token-test/tests/test.rs +++ b/test-programs/compressed-token-test/tests/test.rs @@ -12,10 +12,8 @@ use light_compressed_token::delegation::sdk::{ }; use light_compressed_token::freeze::sdk::{create_instruction, CreateInstructionInputs}; use light_compressed_token::get_token_pool_pda; +use light_compressed_token::mint_sdk::create_create_token_pool_instruction; use light_compressed_token::mint_sdk::create_mint_to_instruction; -use light_compressed_token::mint_sdk::{ - create_create_token_pool_2022_instruction, create_create_token_pool_instruction, -}; use light_compressed_token::process_transfer::transfer_sdk::create_transfer_instruction; use light_compressed_token::process_transfer::{get_cpi_authority_pda, TokenTransferOutputData}; use light_compressed_token::spl_compression::spl_token_pool_derivation; @@ -155,6 +153,32 @@ async fn test_failing_create_token_pool() { ) .unwrap(); } + // Invalid program id. + { + let instruction_data = light_compressed_token::instruction::CreateTokenPool {}; + let accounts = light_compressed_token::accounts::CreateTokenPoolInstruction { + fee_payer: payer.pubkey(), + token_pool_pda: mint_1_pool_pda, + system_program: system_program::ID, + mint: mint_1_keypair.pubkey(), + token_program: light_system_program::ID, // invalid program id should be spl token program or token 2022 program + cpi_authority_pda: get_cpi_authority_pda().0, + }; + let instruction = Instruction { + program_id: light_compressed_token::ID, + accounts: accounts.to_account_metas(Some(true)), + data: instruction_data.data(), + }; + let result = rpc + .create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer]) + .await; + assert_rpc_error( + result, + 0, + anchor_lang::error::ErrorCode::InvalidProgramId.into(), + ) + .unwrap(); + } // Try to create pool for `mint_2` while using seeds of `mint_1` for PDAs. { let instruction_data = light_compressed_token::instruction::CreateTokenPool {}; @@ -219,9 +243,10 @@ async fn test_failing_create_token_pool() { ) .unwrap(), ); - instructions.push(create_create_token_pool_2022_instruction( + instructions.push(create_create_token_pool_instruction( &payer_pubkey, &mint.pubkey(), + true, )); let result = rpc @@ -275,9 +300,10 @@ async fn test_failing_create_token_pool() { ) .unwrap(), ); - instructions.push(create_create_token_pool_2022_instruction( + instructions.push(create_create_token_pool_instruction( &payer_pubkey, &mint.pubkey(), + true, )); rpc.create_and_send_transaction(&instructions, &payer_pubkey, &[&payer, &mint]) .await @@ -348,11 +374,8 @@ async fn test_wrapped_sol() { assert_eq!(unpacked_token_account.owner, payer.pubkey()); assert_eq!(unpacked_token_account.mint, native_mint); assert!(unpacked_token_account.is_native.is_some()); - let instruction = if is_token_22 { - create_create_token_pool_2022_instruction(&payer.pubkey(), &native_mint) - } else { - create_create_token_pool_instruction(&payer.pubkey(), &native_mint) - }; + let instruction = + create_create_token_pool_instruction(&payer.pubkey(), &native_mint, is_token_22); rpc.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer]) .await .unwrap(); @@ -657,12 +680,7 @@ async fn test_mint_to_failing() { .create_and_send_transaction(&[instruction], &payer_2.pubkey(), &[&payer_2]) .await; // Owner doesn't match the mint authority. - assert_rpc_error( - result, - 0, - light_compressed_token::ErrorCode::InvalidAuthorityMint.into(), - ) - .unwrap(); + assert_rpc_error(result, 0, ErrorCode::InvalidAuthorityMint.into()).unwrap(); } // 2. Try to mint token from `mint_2` and sign the transaction with `mint_1` // authority. @@ -681,12 +699,7 @@ async fn test_mint_to_failing() { .create_and_send_transaction(&[instruction], &payer_1.pubkey(), &[&payer_1]) .await; // Owner doesn't match the mint authority. - assert_rpc_error( - result, - 0, - light_compressed_token::ErrorCode::InvalidAuthorityMint.into(), - ) - .unwrap(); + assert_rpc_error(result, 0, ErrorCode::InvalidAuthorityMint.into()).unwrap(); } // 3. Try to mint token to random token account. { @@ -731,7 +744,12 @@ async fn test_mint_to_failing() { let result = rpc .create_and_send_transaction(&[instruction], &payer_1.pubkey(), &[&payer_1]) .await; - assert_rpc_error(result, 0, ErrorCode::InvalidTokenPoolPda.into()).unwrap(); + assert_rpc_error( + result, + 0, + anchor_lang::error::ErrorCode::ConstraintSeeds.into(), + ) + .unwrap(); } // 4. Try to mint token from `mint_2` while using `mint_1` pool. { @@ -766,7 +784,12 @@ async fn test_mint_to_failing() { let result = rpc .create_and_send_transaction(&[instruction], &payer_2.pubkey(), &[&payer_2]) .await; - assert_rpc_error(result, 0, ErrorCode::InvalidTokenPoolPda.into()).unwrap(); + assert_rpc_error( + result, + 0, + anchor_lang::error::ErrorCode::ConstraintSeeds.into(), + ) + .unwrap(); } // 5. Invalid CPI authority. { @@ -2528,13 +2551,12 @@ async fn failing_tests_burn() { let res = rpc .create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer, &sender]) .await; - assert_rpc_error(res, 0, ErrorCode::InvalidTokenMintOwner.into()).unwrap(); - // assert!(matches!( - // res, - // Err(RpcError::TransactionError( - // TransactionError::InstructionError(0, InstructionError::InvalidAccountData) - // )) - // )); + assert_rpc_error( + res, + 0, + anchor_lang::error::ErrorCode::AccountNotInitialized.into(), + ) + .unwrap(); } // 6. invalid change merkle tree { diff --git a/test-utils/src/spl.rs b/test-utils/src/spl.rs index 557deb4326..bd01f088a4 100644 --- a/test-utils/src/spl.rs +++ b/test-utils/src/spl.rs @@ -1,7 +1,6 @@ use anchor_spl::token::{Mint, TokenAccount}; use forester_utils::create_account_instruction; use forester_utils::indexer::{Indexer, TokenDataWithContext}; -use light_compressed_token::mint_sdk::create_create_token_pool_2022_instruction; use light_compressed_token::process_compress_spl_token_account::sdk::create_compress_spl_token_account_instruction; use light_compressed_token::{ burn::sdk::{create_burn_instruction, CreateBurnInstructionInputs}, @@ -324,11 +323,8 @@ pub fn create_initialize_mint_22_instructions( let transfer_ix = anchor_lang::solana_program::system_instruction::transfer(payer, &mint_pubkey, rent); - let instruction = if token_22 { - create_create_token_pool_2022_instruction(payer, &mint_pubkey) - } else { - create_create_token_pool_instruction(payer, &mint_pubkey) - }; + let instruction = create_create_token_pool_instruction(payer, &mint_pubkey, token_22); + let pool_pubkey = get_token_pool_pda(&mint_pubkey); ( [