From 822f861717b6209826fcbf73477bfc2457d6237b Mon Sep 17 00:00:00 2001 From: ananas-block Date: Fri, 5 Dec 2025 18:24:19 +0000 Subject: [PATCH] refactor: remove create ata2 --- .../create_associated_token_account.rs | 5 - .../create_associated_token_account2.rs | 14 - .../ctoken-types/src/instructions/mod.rs | 1 - .../tests/ctoken/create_ata.rs | 17 +- .../src/create_associated_token_account.rs | 32 ++- .../src/create_associated_token_account2.rs | 62 ----- programs/compressed-token/program/src/lib.rs | 18 -- .../src/ctoken/create_ata.rs | 247 +----------------- .../tests/create_associated_token_account.rs | 3 +- sdk-tests/sdk-ctoken-test/src/create_ata.rs | 84 +++--- sdk-tests/sdk-ctoken-test/src/create_ata2.rs | 6 +- .../sdk-ctoken-test/tests/test_create_ata.rs | 14 +- 12 files changed, 104 insertions(+), 399 deletions(-) delete mode 100644 program-libs/ctoken-types/src/instructions/create_associated_token_account2.rs delete mode 100644 programs/compressed-token/program/src/create_associated_token_account2.rs diff --git a/program-libs/ctoken-types/src/instructions/create_associated_token_account.rs b/program-libs/ctoken-types/src/instructions/create_associated_token_account.rs index 987f844390..167e573edc 100644 --- a/program-libs/ctoken-types/src/instructions/create_associated_token_account.rs +++ b/program-libs/ctoken-types/src/instructions/create_associated_token_account.rs @@ -1,4 +1,3 @@ -use light_compressed_account::Pubkey; use light_zero_copy::ZeroCopy; use crate::{ @@ -9,10 +8,6 @@ use crate::{ #[repr(C)] #[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy)] pub struct CreateAssociatedTokenAccountInstructionData { - /// The owner of the associated token account - pub owner: Pubkey, - /// The mint for the associated token account - pub mint: Pubkey, pub bump: u8, /// Optional compressible configuration for the token account pub compressible_config: Option, diff --git a/program-libs/ctoken-types/src/instructions/create_associated_token_account2.rs b/program-libs/ctoken-types/src/instructions/create_associated_token_account2.rs deleted file mode 100644 index 26abc36583..0000000000 --- a/program-libs/ctoken-types/src/instructions/create_associated_token_account2.rs +++ /dev/null @@ -1,14 +0,0 @@ -use light_zero_copy::ZeroCopy; - -use crate::{ - instructions::extensions::compressible::CompressibleExtensionInstructionData, - AnchorDeserialize, AnchorSerialize, -}; - -#[repr(C)] -#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy)] -pub struct CreateAssociatedTokenAccount2InstructionData { - pub bump: u8, - /// Optional compressible configuration for the token account - pub compressible_config: Option, -} diff --git a/program-libs/ctoken-types/src/instructions/mod.rs b/program-libs/ctoken-types/src/instructions/mod.rs index 0b1f7ffc1a..ef33ca4384 100644 --- a/program-libs/ctoken-types/src/instructions/mod.rs +++ b/program-libs/ctoken-types/src/instructions/mod.rs @@ -1,5 +1,4 @@ pub mod create_associated_token_account; -pub mod create_associated_token_account2; pub mod transfer2; pub mod create_ctoken_account; diff --git a/program-tests/compressed-token-test/tests/ctoken/create_ata.rs b/program-tests/compressed-token-test/tests/ctoken/create_ata.rs index 2c7fc0d628..7d5d4bf44f 100644 --- a/program-tests/compressed-token-test/tests/ctoken/create_ata.rs +++ b/program-tests/compressed-token-test/tests/ctoken/create_ata.rs @@ -326,8 +326,6 @@ async fn test_create_ata_failing() { }; let instruction_data = CreateAssociatedTokenAccountInstructionData { - owner: context.owner_keypair.pubkey().into(), - mint: context.mint_pubkey.into(), bump, compressible_config: Some(CompressibleExtensionInstructionData { compression_only: 0, @@ -342,9 +340,15 @@ async fn test_create_ata_failing() { let mut data = vec![100]; // CreateAssociatedTokenAccount discriminator instruction_data.serialize(&mut data).unwrap(); + // Account order: mint, payer, ata, system_program, config, rent_sponsor let ix = Instruction { program_id: light_compressed_token::ID, accounts: vec![ + solana_sdk::instruction::AccountMeta::new_readonly( + context.owner_keypair.pubkey(), + false, + ), + solana_sdk::instruction::AccountMeta::new_readonly(context.mint_pubkey, false), solana_sdk::instruction::AccountMeta::new(payer_pubkey, true), solana_sdk::instruction::AccountMeta::new(ata_pubkey, false), solana_sdk::instruction::AccountMeta::new_readonly( @@ -392,9 +396,8 @@ async fn test_create_ata_failing() { correct_bump + 1 }; + // Owner and mint are now passed as accounts, not in instruction data let instruction_data = CreateAssociatedTokenAccountInstructionData { - owner: context.owner_keypair.pubkey().into(), - mint: context.mint_pubkey.into(), bump: wrong_bump, // Wrong bump! compressible_config: Some(CompressibleExtensionInstructionData { compression_only: 0, @@ -409,9 +412,15 @@ async fn test_create_ata_failing() { let mut data = vec![100]; // CreateAssociatedTokenAccount discriminator instruction_data.serialize(&mut data).unwrap(); + // Account order: owner, mint, payer, ata, system_program, config, rent_sponsor let ix = Instruction { program_id: light_compressed_token::ID, accounts: vec![ + solana_sdk::instruction::AccountMeta::new_readonly( + context.owner_keypair.pubkey(), + false, + ), + solana_sdk::instruction::AccountMeta::new_readonly(context.mint_pubkey, false), solana_sdk::instruction::AccountMeta::new(payer_pubkey, true), solana_sdk::instruction::AccountMeta::new(ata_pubkey, false), solana_sdk::instruction::AccountMeta::new_readonly( diff --git a/programs/compressed-token/program/src/create_associated_token_account.rs b/programs/compressed-token/program/src/create_associated_token_account.rs index dc19e6c5cd..24f06aeb7e 100644 --- a/programs/compressed-token/program/src/create_associated_token_account.rs +++ b/programs/compressed-token/program/src/create_associated_token_account.rs @@ -20,6 +20,7 @@ use crate::{ }; /// Process the create associated token account instruction (non-idempotent) +/// Owner and mint are passed as accounts instead of instruction data #[inline(always)] pub fn process_create_associated_token_account( account_infos: &[AccountInfo], @@ -28,7 +29,8 @@ pub fn process_create_associated_token_account( process_create_associated_token_account_with_mode::(account_infos, instruction_data) } -/// Process the create associated token account instruction (non-idempotent) +/// Process the create associated token account instruction (idempotent) +/// Owner and mint are passed as accounts instead of instruction data #[inline(always)] pub fn process_create_associated_token_account_idempotent( account_infos: &[AccountInfo], @@ -37,26 +39,42 @@ pub fn process_create_associated_token_account_idempotent( process_create_associated_token_account_with_mode::(account_infos, instruction_data) } -/// Process create associated token account with compile-time idempotent mode +/// Convert create_associated_token_account instruction format to create_ata format by extracting +/// owner and mint from accounts and calling the inner function directly /// /// Note: /// - we don't validate the mint because it would be very expensive with compressed mints /// - it is possible to create an associated token account for non existing mints /// - accounts with non existing mints can never have a balance +/// +/// Account order: +/// 0. owner (non-mut, non-signer) +/// 1. mint (non-mut, non-signer) +/// 2. fee_payer (signer, mut) +/// 3. associated_token_account (mut) +/// 4. system_program +/// 5. optional accounts (config, rent_payer, etc.) #[inline(always)] -#[profile] -pub(crate) fn process_create_associated_token_account_with_mode( +fn process_create_associated_token_account_with_mode( account_infos: &[AccountInfo], mut instruction_data: &[u8], ) -> Result<(), ProgramError> { + if account_infos.len() < 2 { + return Err(ProgramError::NotEnoughAccountKeys); + } + let instruction_inputs = CreateAssociatedTokenAccountInstructionData::deserialize(&mut instruction_data) .map_err(ProgramError::from)?; + let (owner_and_mint, remaining_accounts) = account_infos.split_at(2); + let owner = &owner_and_mint[0]; + let mint = &owner_and_mint[1]; + process_create_associated_token_account_inner::( - account_infos, - &instruction_inputs.owner.to_bytes(), - &instruction_inputs.mint.to_bytes(), + remaining_accounts, + owner.key(), + mint.key(), instruction_inputs.bump, instruction_inputs.compressible_config, ) diff --git a/programs/compressed-token/program/src/create_associated_token_account2.rs b/programs/compressed-token/program/src/create_associated_token_account2.rs deleted file mode 100644 index 3dd686443c..0000000000 --- a/programs/compressed-token/program/src/create_associated_token_account2.rs +++ /dev/null @@ -1,62 +0,0 @@ -use anchor_lang::prelude::ProgramError; -use borsh::BorshDeserialize; -use light_ctoken_types::instructions::create_associated_token_account2::CreateAssociatedTokenAccount2InstructionData; -use pinocchio::account_info::AccountInfo; - -use crate::create_associated_token_account::process_create_associated_token_account_inner; - -/// Process the create associated token account 2 instruction (non-idempotent) -/// Owner and mint are passed as accounts instead of instruction data -#[inline(always)] -pub fn process_create_associated_token_account2( - account_infos: &[AccountInfo], - instruction_data: &[u8], -) -> Result<(), ProgramError> { - process_create_associated_token_account2_inner::(account_infos, instruction_data) -} - -/// Process the create associated token account 2 instruction (idempotent) -/// Owner and mint are passed as accounts instead of instruction data -#[inline(always)] -pub fn process_create_associated_token_account2_idempotent( - account_infos: &[AccountInfo], - instruction_data: &[u8], -) -> Result<(), ProgramError> { - process_create_associated_token_account2_inner::(account_infos, instruction_data) -} - -/// Convert create_ata2 instruction format to create_ata format by extracting -/// owner and mint from accounts and calling the inner function directly -/// -/// Account order: -/// 0. owner (non-mut, non-signer) -/// 1. mint (non-mut, non-signer) -/// 2. fee_payer (signer, mut) -/// 3. associated_token_account (mut) -/// 4. system_program -/// 5. optional accounts (config, rent_payer, etc.) -#[inline(always)] -fn process_create_associated_token_account2_inner( - account_infos: &[AccountInfo], - mut instruction_data: &[u8], -) -> Result<(), ProgramError> { - if account_infos.len() < 2 { - return Err(ProgramError::NotEnoughAccountKeys); - } - - let instruction_inputs = - CreateAssociatedTokenAccount2InstructionData::deserialize(&mut instruction_data) - .map_err(ProgramError::from)?; - - let (owner_and_mint, remaining_accounts) = account_infos.split_at(2); - let owner = &owner_and_mint[0]; - let mint = &owner_and_mint[1]; - - process_create_associated_token_account_inner::( - remaining_accounts, - owner.key(), - mint.key(), - instruction_inputs.bump, - instruction_inputs.compressible_config, - ) -} diff --git a/programs/compressed-token/program/src/lib.rs b/programs/compressed-token/program/src/lib.rs index c845890ca9..30d2637feb 100644 --- a/programs/compressed-token/program/src/lib.rs +++ b/programs/compressed-token/program/src/lib.rs @@ -9,7 +9,6 @@ pub mod claim; pub mod close_token_account; pub mod convert_account_infos; pub mod create_associated_token_account; -pub mod create_associated_token_account2; pub mod create_token_account; pub mod ctoken_transfer; pub mod extensions; @@ -25,9 +24,6 @@ use close_token_account::processor::process_close_token_account; use create_associated_token_account::{ process_create_associated_token_account, process_create_associated_token_account_idempotent, }; -use create_associated_token_account2::{ - process_create_associated_token_account2, process_create_associated_token_account2_idempotent, -}; use create_token_account::process_create_token_account; use ctoken_transfer::process_ctoken_transfer; use withdraw_funding_pool::process_withdraw_funding_pool; @@ -75,10 +71,6 @@ pub enum InstructionType { Claim = 104, /// Withdraw funds from pool PDA WithdrawFundingPool = 105, - /// Create associated token account with owner and mint as accounts (non-idempotent) - CreateAssociatedTokenAccount2 = 106, - /// Create associated token account with owner and mint as accounts (idempotent) - CreateAssociatedTokenAccount2Idempotent = 107, Other, } @@ -95,8 +87,6 @@ impl From for InstructionType { 103 => InstructionType::MintAction, 104 => InstructionType::Claim, 105 => InstructionType::WithdrawFundingPool, - 106 => InstructionType::CreateAssociatedTokenAccount2, - 107 => InstructionType::CreateAssociatedTokenAccount2Idempotent, _ => InstructionType::Other, // anchor instructions } } @@ -156,14 +146,6 @@ pub fn process_instruction( msg!("WithdrawFundingPool"); process_withdraw_funding_pool(accounts, &instruction_data[1..])?; } - InstructionType::CreateAssociatedTokenAccount2 => { - msg!("CreateAssociatedTokenAccount2"); - process_create_associated_token_account2(accounts, &instruction_data[1..])?; - } - InstructionType::CreateAssociatedTokenAccount2Idempotent => { - msg!("CreateAssociatedTokenAccount2Idempotent"); - process_create_associated_token_account2_idempotent(accounts, &instruction_data[1..])?; - } // anchor instructions have no discriminator conflicts with InstructionType // TODO: add test for discriminator conflict _ => { diff --git a/sdk-libs/compressed-token-sdk/src/ctoken/create_ata.rs b/sdk-libs/compressed-token-sdk/src/ctoken/create_ata.rs index 71068391e6..c867ff0b1e 100644 --- a/sdk-libs/compressed-token-sdk/src/ctoken/create_ata.rs +++ b/sdk-libs/compressed-token-sdk/src/ctoken/create_ata.rs @@ -1,7 +1,6 @@ use borsh::BorshSerialize; use light_ctoken_types::instructions::{ create_associated_token_account::CreateAssociatedTokenAccountInstructionData, - create_associated_token_account2::CreateAssociatedTokenAccount2InstructionData, extensions::compressible::CompressibleExtensionInstructionData, }; use solana_account_info::AccountInfo; @@ -14,8 +13,6 @@ use crate::ctoken::{compressible::CompressibleParamsInfos, CompressibleParams}; const CREATE_ATA_DISCRIMINATOR: u8 = 100; const CREATE_ATA_IDEMPOTENT_DISCRIMINATOR: u8 = 102; -const CREATE_ATA2_DISCRIMINATOR: u8 = 106; -const CREATE_ATA2_IDEMPOTENT_DISCRIMINATOR: u8 = 107; pub fn derive_ctoken_ata(owner: &Pubkey, mint: &Pubkey) -> (Pubkey, u8) { Pubkey::find_program_address( @@ -28,19 +25,15 @@ pub fn derive_ctoken_ata(owner: &Pubkey, mint: &Pubkey) -> (Pubkey, u8) { ) } -// ============================================================================ -// V1: Associated Token Account (owner/mint in instruction data) -// ============================================================================ - #[derive(Debug, Clone)] pub struct CreateAssociatedTokenAccount { - pub idempotent: bool, - pub bump: u8, pub payer: Pubkey, pub owner: Pubkey, pub mint: Pubkey, pub associated_token_account: Pubkey, + pub bump: u8, pub compressible: Option, + pub idempotent: bool, } impl CreateAssociatedTokenAccount { @@ -75,8 +68,8 @@ impl CreateAssociatedTokenAccount { } } - pub fn with_compressible(mut self, compressible: CompressibleParams) -> Self { - self.compressible = Some(compressible); + pub fn with_compressible(mut self, compressible_params: CompressibleParams) -> Self { + self.compressible = Some(compressible_params); self } @@ -103,8 +96,6 @@ impl CreateAssociatedTokenAccount { }); let instruction_data = CreateAssociatedTokenAccountInstructionData { - owner: light_compressed_account::Pubkey::from(self.owner.to_bytes()), - mint: light_compressed_account::Pubkey::from(self.mint.to_bytes()), bump: self.bump, compressible_config: compressible_extension, }; @@ -115,226 +106,6 @@ impl CreateAssociatedTokenAccount { CREATE_ATA_DISCRIMINATOR }; - let mut data = Vec::new(); - data.push(discriminator); - instruction_data - .serialize(&mut data) - .map_err(|e| ProgramError::BorshIoError(e.to_string()))?; - - let mut accounts = vec![ - AccountMeta::new(self.payer, true), - AccountMeta::new(self.associated_token_account, false), - AccountMeta::new_readonly(Pubkey::default(), false), // system_program - ]; - - if let Some(config) = &self.compressible { - accounts.push(AccountMeta::new_readonly(config.compressible_config, false)); - accounts.push(AccountMeta::new(config.rent_sponsor, false)); - } - - Ok(Instruction { - program_id: Pubkey::from(light_ctoken_types::COMPRESSED_TOKEN_PROGRAM_ID), - accounts, - data, - }) - } -} - -pub struct CreateAssociatedTokenAccountInfos<'info> { - pub bump: u8, - pub idempotent: bool, - pub owner: Pubkey, - pub mint: Pubkey, - pub payer: AccountInfo<'info>, - pub associated_token_account: AccountInfo<'info>, - pub system_program: AccountInfo<'info>, - pub compressible: Option>, -} - -impl<'info> CreateAssociatedTokenAccountInfos<'info> { - pub fn new( - bump: u8, - owner: Pubkey, - mint: Pubkey, - payer: AccountInfo<'info>, - associated_token_account: AccountInfo<'info>, - system_program: AccountInfo<'info>, - compressible: CompressibleParamsInfos<'info>, - ) -> Self { - Self { - bump, - idempotent: false, - owner, - mint, - payer, - associated_token_account, - system_program, - compressible: Some(compressible), - } - } - - pub fn with_idempotent(mut self) -> Self { - self.idempotent = true; - self - } - - pub fn instruction(&self) -> Result { - CreateAssociatedTokenAccount::from(self).instruction() - } - - pub fn invoke(self) -> Result<(), ProgramError> { - let instruction = self.instruction()?; - if let Some(compressible) = self.compressible { - let account_infos = [ - self.payer, - self.associated_token_account, - self.system_program, - compressible.compressible_config, - compressible.rent_sponsor, - ]; - invoke(&instruction, &account_infos) - } else { - let account_infos = [ - self.payer, - self.associated_token_account, - self.system_program, - ]; - invoke(&instruction, &account_infos) - } - } - - pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> { - let instruction = self.instruction()?; - if let Some(compressible) = self.compressible { - let account_infos = [ - self.payer, - self.associated_token_account, - self.system_program, - compressible.compressible_config, - compressible.rent_sponsor, - ]; - invoke_signed(&instruction, &account_infos, signer_seeds) - } else { - let account_infos = [ - self.payer, - self.associated_token_account, - self.system_program, - ]; - invoke_signed(&instruction, &account_infos, signer_seeds) - } - } -} - -impl<'info> From<&CreateAssociatedTokenAccountInfos<'info>> for CreateAssociatedTokenAccount { - fn from(account_infos: &CreateAssociatedTokenAccountInfos<'info>) -> Self { - Self { - payer: *account_infos.payer.key, - owner: account_infos.owner, - mint: account_infos.mint, - associated_token_account: *account_infos.associated_token_account.key, - bump: account_infos.bump, - compressible: account_infos - .compressible - .as_ref() - .map(|config| CompressibleParams { - compressible_config: *config.compressible_config.key, - rent_sponsor: *config.rent_sponsor.key, - pre_pay_num_epochs: config.pre_pay_num_epochs, - lamports_per_write: config.lamports_per_write, - compress_to_account_pubkey: None, - token_account_version: config.token_account_version, - }), - idempotent: account_infos.idempotent, - } - } -} - -// ============================================================================ -// V2: Associated Token Account (owner/mint as accounts) -// ============================================================================ - -#[derive(Debug, Clone)] -pub struct CreateAssociatedTokenAccount2 { - pub payer: Pubkey, - pub owner: Pubkey, - pub mint: Pubkey, - pub associated_token_account: Pubkey, - pub bump: u8, - pub compressible: Option, - pub idempotent: bool, -} - -impl CreateAssociatedTokenAccount2 { - pub fn new( - payer: Pubkey, - owner: Pubkey, - mint: Pubkey, - compressible_params: CompressibleParams, - ) -> Self { - let (ata, bump) = derive_ctoken_ata(&owner, &mint); - Self { - payer, - owner, - mint, - associated_token_account: ata, - bump, - compressible: Some(compressible_params), - idempotent: false, - } - } - - pub fn new_with_bump( - payer: Pubkey, - owner: Pubkey, - mint: Pubkey, - compressible_params: CompressibleParams, - associated_token_account: Pubkey, - bump: u8, - ) -> Self { - Self { - payer, - owner, - mint, - associated_token_account, - bump, - compressible: Some(compressible_params), - idempotent: false, - } - } - - pub fn idempotent(mut self) -> Self { - self.idempotent = true; - self - } - - pub fn instruction(self) -> Result { - let compressible_extension = - self.compressible - .as_ref() - .map(|config| CompressibleExtensionInstructionData { - token_account_version: config.token_account_version as u8, - rent_payment: config.pre_pay_num_epochs, - has_top_up: if config.lamports_per_write.is_some() { - 1 - } else { - 0 - }, - compression_only: 0, - write_top_up: config.lamports_per_write.unwrap_or(0), - compress_to_account_pubkey: None, - }); - - let instruction_data = CreateAssociatedTokenAccount2InstructionData { - bump: self.bump, - compressible_config: compressible_extension, - }; - - let discriminator = if self.idempotent { - CREATE_ATA2_IDEMPOTENT_DISCRIMINATOR - } else { - CREATE_ATA2_DISCRIMINATOR - }; - let mut data = Vec::new(); data.push(discriminator); instruction_data @@ -362,7 +133,7 @@ impl CreateAssociatedTokenAccount2 { } } -pub struct CreateAssociatedTokenAccount2Infos<'info> { +pub struct CreateAssociatedTokenAccountInfos<'info> { pub owner: AccountInfo<'info>, pub mint: AccountInfo<'info>, pub payer: AccountInfo<'info>, @@ -373,9 +144,9 @@ pub struct CreateAssociatedTokenAccount2Infos<'info> { pub idempotent: bool, } -impl<'info> CreateAssociatedTokenAccount2Infos<'info> { +impl<'info> CreateAssociatedTokenAccountInfos<'info> { pub fn instruction(&self) -> Result { - CreateAssociatedTokenAccount2::from(self).instruction() + CreateAssociatedTokenAccount::from(self).instruction() } pub fn invoke(self) -> Result<(), ProgramError> { @@ -429,8 +200,8 @@ impl<'info> CreateAssociatedTokenAccount2Infos<'info> { } } -impl<'info> From<&CreateAssociatedTokenAccount2Infos<'info>> for CreateAssociatedTokenAccount2 { - fn from(account_infos: &CreateAssociatedTokenAccount2Infos<'info>) -> Self { +impl<'info> From<&CreateAssociatedTokenAccountInfos<'info>> for CreateAssociatedTokenAccount { + fn from(account_infos: &CreateAssociatedTokenAccountInfos<'info>) -> Self { Self { payer: *account_infos.payer.key, owner: *account_infos.owner.key, diff --git a/sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs b/sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs index 43485a0d81..276f4f45ec 100644 --- a/sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs +++ b/sdk-libs/compressed-token-sdk/tests/create_associated_token_account.rs @@ -77,5 +77,6 @@ fn test_account_count() { .instruction() .unwrap(); - assert_eq!(ix_compressible.accounts.len(), 5); + // Account order: owner, mint, payer, ata, system_program, config, rent_sponsor (7 accounts) + assert_eq!(ix_compressible.accounts.len(), 7); } diff --git a/sdk-tests/sdk-ctoken-test/src/create_ata.rs b/sdk-tests/sdk-ctoken-test/src/create_ata.rs index fc65f36529..8e75efe6b6 100644 --- a/sdk-tests/sdk-ctoken-test/src/create_ata.rs +++ b/sdk-tests/sdk-ctoken-test/src/create_ata.rs @@ -6,11 +6,9 @@ use solana_program::{account_info::AccountInfo, program_error::ProgramError, pub use crate::{ATA_SEED, ID}; -/// Instruction data for create ATA +/// Instruction data for create ATA (owner and mint passed as accounts) #[derive(BorshSerialize, BorshDeserialize, Debug)] pub struct CreateAtaData { - pub owner: Pubkey, - pub mint: Pubkey, pub bump: u8, pub pre_pay_num_epochs: u8, pub lamports_per_write: u32, @@ -19,36 +17,39 @@ pub struct CreateAtaData { /// Handler for creating a compressible associated token account (invoke) /// /// Account order: -/// - accounts[0]: payer (signer) -/// - accounts[1]: associated token account (derived) -/// - accounts[2]: system_program -/// - accounts[3]: compressible_config -/// - accounts[4]: rent_sponsor +/// - accounts[0]: owner +/// - accounts[1]: mint +/// - accounts[2]: payer (signer) +/// - accounts[3]: associated token account (derived) +/// - accounts[4]: system_program +/// - accounts[5]: compressible_config +/// - accounts[6]: rent_sponsor pub fn process_create_ata_invoke( accounts: &[AccountInfo], data: CreateAtaData, ) -> Result<(), ProgramError> { - if accounts.len() < 5 { + if accounts.len() < 7 { return Err(ProgramError::NotEnoughAccountKeys); } // Build the compressible params using constructor let compressible_params = CompressibleParamsInfos::new( - accounts[3].clone(), + accounts[5].clone(), + accounts[6].clone(), accounts[4].clone(), - accounts[2].clone(), ); - // Use the CreateAssociatedTokenAccountInfos constructor - CreateAssociatedTokenAccountInfos::new( - data.bump, - data.owner, - data.mint, - accounts[0].clone(), - accounts[1].clone(), - accounts[2].clone(), - compressible_params, - ) + // Use the CreateAssociatedTokenAccountInfos - owner and mint are AccountInfos + CreateAssociatedTokenAccountInfos { + owner: accounts[0].clone(), + mint: accounts[1].clone(), + payer: accounts[2].clone(), + associated_token_account: accounts[3].clone(), + system_program: accounts[4].clone(), + bump: data.bump, + compressible: Some(compressible_params), + idempotent: false, + } .invoke()?; Ok(()) @@ -57,16 +58,18 @@ pub fn process_create_ata_invoke( /// Handler for creating a compressible ATA with PDA ownership (invoke_signed) /// /// Account order: -/// - accounts[0]: payer (PDA, signer via invoke_signed) -/// - accounts[1]: associated token account (derived) -/// - accounts[2]: system_program -/// - accounts[3]: compressible_config -/// - accounts[4]: rent_sponsor +/// - accounts[0]: owner +/// - accounts[1]: mint +/// - accounts[2]: payer (PDA, signer via invoke_signed) +/// - accounts[3]: associated token account (derived) +/// - accounts[4]: system_program +/// - accounts[5]: compressible_config +/// - accounts[6]: rent_sponsor pub fn process_create_ata_invoke_signed( accounts: &[AccountInfo], data: CreateAtaData, ) -> Result<(), ProgramError> { - if accounts.len() < 5 { + if accounts.len() < 7 { return Err(ProgramError::NotEnoughAccountKeys); } @@ -74,27 +77,28 @@ pub fn process_create_ata_invoke_signed( let (pda, bump) = Pubkey::find_program_address(&[ATA_SEED], &ID); // Verify the payer is the PDA - if &pda != accounts[0].key { + if &pda != accounts[2].key { return Err(ProgramError::InvalidSeeds); } // Build the compressible params using constructor let compressible_params = CompressibleParamsInfos::new( - accounts[3].clone(), + accounts[5].clone(), + accounts[6].clone(), accounts[4].clone(), - accounts[2].clone(), ); - // Use the CreateAssociatedTokenAccountInfos constructor - let account_infos = CreateAssociatedTokenAccountInfos::new( - data.bump, - data.owner, - data.mint, - accounts[0].clone(), - accounts[1].clone(), - accounts[2].clone(), - compressible_params, - ); + // Use the CreateAssociatedTokenAccountInfos - owner and mint are AccountInfos + let account_infos = CreateAssociatedTokenAccountInfos { + owner: accounts[0].clone(), + mint: accounts[1].clone(), + payer: accounts[2].clone(), + associated_token_account: accounts[3].clone(), + system_program: accounts[4].clone(), + bump: data.bump, + compressible: Some(compressible_params), + idempotent: false, + }; // Invoke with PDA signing let signer_seeds: &[&[u8]] = &[ATA_SEED, &[bump]]; diff --git a/sdk-tests/sdk-ctoken-test/src/create_ata2.rs b/sdk-tests/sdk-ctoken-test/src/create_ata2.rs index 0cfdac38d5..dce22a6962 100644 --- a/sdk-tests/sdk-ctoken-test/src/create_ata2.rs +++ b/sdk-tests/sdk-ctoken-test/src/create_ata2.rs @@ -1,6 +1,6 @@ use borsh::{BorshDeserialize, BorshSerialize}; use light_compressed_token_sdk::ctoken::{ - CompressibleParamsInfos, CreateAssociatedTokenAccount2Infos, + CompressibleParamsInfos, CreateAssociatedTokenAccountInfos, }; use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; @@ -38,7 +38,7 @@ pub fn process_create_ata2_invoke( accounts[4].clone(), ); - CreateAssociatedTokenAccount2Infos { + CreateAssociatedTokenAccountInfos { owner: accounts[0].clone(), mint: accounts[1].clone(), payer: accounts[2].clone(), @@ -86,7 +86,7 @@ pub fn process_create_ata2_invoke_signed( ); let signer_seeds: &[&[u8]] = &[ATA_SEED, &[bump]]; - CreateAssociatedTokenAccount2Infos { + CreateAssociatedTokenAccountInfos { owner: accounts[0].clone(), mint: accounts[1].clone(), payer: accounts[2].clone(), // PDA diff --git a/sdk-tests/sdk-ctoken-test/tests/test_create_ata.rs b/sdk-tests/sdk-ctoken-test/tests/test_create_ata.rs index efe10b5853..31b43afce4 100644 --- a/sdk-tests/sdk-ctoken-test/tests/test_create_ata.rs +++ b/sdk-tests/sdk-ctoken-test/tests/test_create_ata.rs @@ -36,10 +36,8 @@ async fn test_create_ata_invoke() { use light_compressed_token_sdk::ctoken::derive_ctoken_ata; let (ata_address, bump) = derive_ctoken_ata(&owner, &mint_pda); - // Build CreateAtaData + // Build CreateAtaData (owner and mint are passed as accounts) let create_ata_data = CreateAtaData { - owner, - mint: mint_pda, bump, pre_pay_num_epochs: 2, lamports_per_write: 1, @@ -51,9 +49,12 @@ async fn test_create_ata_invoke() { let config = config_pda(); let rent_sponsor = rent_sponsor_pda(); + // Account order: owner, mint, payer, ata, system_program, config, rent_sponsor, ctoken_program let instruction = Instruction { program_id: ID, accounts: vec![ + AccountMeta::new_readonly(owner, false), + AccountMeta::new_readonly(mint_pda, false), AccountMeta::new(payer.pubkey(), true), AccountMeta::new(ata_address, false), AccountMeta::new_readonly(Pubkey::default(), false), // system_program @@ -121,10 +122,8 @@ async fn test_create_ata_invoke_signed() { use light_compressed_token_sdk::ctoken::derive_ctoken_ata; let (ata_address, bump) = derive_ctoken_ata(&pda_owner, &mint_pda); - // Build CreateAtaData with PDA as owner + // Build CreateAtaData with PDA as owner (owner and mint are passed as accounts) let create_ata_data = CreateAtaData { - owner: pda_owner, - mint: mint_pda, bump, pre_pay_num_epochs: 2, lamports_per_write: 1, @@ -136,9 +135,12 @@ async fn test_create_ata_invoke_signed() { let config = config_pda(); let rent_sponsor = rent_sponsor_pda(); + // Account order: owner, mint, payer, ata, system_program, config, rent_sponsor, ctoken_program let instruction = Instruction { program_id: ID, accounts: vec![ + AccountMeta::new_readonly(pda_owner, false), // owner + AccountMeta::new_readonly(mint_pda, false), AccountMeta::new(pda_owner, false), // PDA payer - not a signer (program signs via invoke_signed) AccountMeta::new(ata_address, false), AccountMeta::new_readonly(Pubkey::default(), false), // system_program