diff --git a/programs/cp-swap/src/instructions/initialize.rs b/programs/cp-swap/src/instructions/initialize.rs index 4546f79..88ed79e 100644 --- a/programs/cp-swap/src/instructions/initialize.rs +++ b/programs/cp-swap/src/instructions/initialize.rs @@ -101,7 +101,7 @@ pub struct Initialize<'info> { )] pub creator_lp_token: Box>, - /// CHECK: Token_0 vault for the pool, create by contract + /// CHECK: Token_0 vault for the pool, created by contract #[account( mut, seeds = [ @@ -113,7 +113,7 @@ pub struct Initialize<'info> { )] pub token_0_vault: UncheckedAccount<'info>, - /// CHECK: Token_1 vault for the pool, create by contract + /// CHECK: Token_1 vault for the pool, created by contract #[account( mut, seeds = [ @@ -186,12 +186,12 @@ pub fn initialize( &ctx.accounts.token_0_mint.to_account_info(), &ctx.accounts.system_program.to_account_info(), &ctx.accounts.token_0_program.to_account_info(), - &[&[ + &[ POOL_VAULT_SEED.as_bytes(), ctx.accounts.pool_state.key().as_ref(), ctx.accounts.token_0_mint.key().as_ref(), &[ctx.bumps.token_0_vault][..], - ][..]], + ], )?; create_token_account( @@ -201,12 +201,12 @@ pub fn initialize( &ctx.accounts.token_1_mint.to_account_info(), &ctx.accounts.system_program.to_account_info(), &ctx.accounts.token_1_program.to_account_info(), - &[&[ + &[ POOL_VAULT_SEED.as_bytes(), ctx.accounts.pool_state.key().as_ref(), ctx.accounts.token_1_mint.key().as_ref(), &[ctx.bumps.token_1_vault][..], - ][..]], + ], )?; let pool_state_loader = create_pool( @@ -338,7 +338,7 @@ pub fn create_pool<'info>( token_1_mint: &AccountInfo<'info>, system_program: &AccountInfo<'info>, ) -> Result> { - if pool_account_info.owner != &system_program::ID || pool_account_info.lamports() != 0 { + if pool_account_info.owner != &system_program::ID { return err!(ErrorCode::NotApproved); } @@ -356,22 +356,19 @@ pub fn create_pool<'info>( require_eq!(pool_account_info.is_signer, true); } - let cpi_accounts = anchor_lang::system_program::CreateAccount { - from: payer.clone(), - to: pool_account_info.clone(), - }; - let cpi_context = CpiContext::new(system_program.to_account_info(), cpi_accounts); - anchor_lang::system_program::create_account( - cpi_context.with_signer(&[&[ + token::create_or_allocate_account( + &crate::id(), + payer.to_account_info(), + system_program.to_account_info(), + pool_account_info.clone(), + &[ POOL_SEED.as_bytes(), amm_config.key().as_ref(), token_0_mint.key().as_ref(), token_1_mint.key().as_ref(), &[bump], - ][..]]), - Rent::get()?.minimum_balance(PoolState::LEN), - PoolState::LEN as u64, - &crate::id(), + ], + PoolState::LEN, )?; Ok(AccountLoad::::try_from_unchecked( diff --git a/programs/cp-swap/src/utils/token.rs b/programs/cp-swap/src/utils/token.rs index 63fb59c..9a57964 100644 --- a/programs/cp-swap/src/utils/token.rs +++ b/programs/cp-swap/src/utils/token.rs @@ -1,5 +1,5 @@ use crate::error::ErrorCode; -use anchor_lang::prelude::*; +use anchor_lang::{prelude::*, system_program}; use anchor_spl::{ token::{Token, TokenAccount}, token_2022::{ @@ -203,7 +203,7 @@ pub fn create_token_account<'a>( mint_account: &AccountInfo<'a>, system_program: &AccountInfo<'a>, token_program: &AccountInfo<'a>, - signer_seeds: &[&[&[u8]]], + signer_seeds: &[&[u8]], ) -> Result<()> { let space = { let mint_info = mint_account.to_account_info(); @@ -221,17 +221,13 @@ pub fn create_token_account<'a>( TokenAccount::LEN } }; - let lamports = Rent::get()?.minimum_balance(space); - let cpi_accounts = anchor_lang::system_program::CreateAccount { - from: payer.to_account_info(), - to: token_account.to_account_info(), - }; - let cpi_context = CpiContext::new(system_program.to_account_info(), cpi_accounts); - anchor_lang::system_program::create_account( - cpi_context.with_signer(signer_seeds), - lamports, - space as u64, + create_or_allocate_account( token_program.key, + payer.to_account_info(), + system_program.to_account_info(), + token_account.to_account_info(), + signer_seeds, + space, )?; initialize_account3(CpiContext::new( token_program.to_account_info(), @@ -242,3 +238,58 @@ pub fn create_token_account<'a>( }, )) } + +pub fn create_or_allocate_account<'a>( + program_id: &Pubkey, + payer: AccountInfo<'a>, + system_program: AccountInfo<'a>, + target_account: AccountInfo<'a>, + siger_seed: &[&[u8]], + space: usize, +) -> Result<()> { + let rent = Rent::get()?; + let current_lamports = target_account.lamports(); + + if current_lamports == 0 { + let lamports = rent.minimum_balance(space); + let cpi_accounts = system_program::CreateAccount { + from: payer, + to: target_account.clone(), + }; + let cpi_context = CpiContext::new(system_program.clone(), cpi_accounts); + system_program::create_account( + cpi_context.with_signer(&[siger_seed]), + lamports, + u64::try_from(space).unwrap(), + program_id, + )?; + } else { + let required_lamports = rent + .minimum_balance(space) + .max(1) + .saturating_sub(current_lamports); + if required_lamports > 0 { + let cpi_accounts = system_program::Transfer { + from: payer.to_account_info(), + to: target_account.clone(), + }; + let cpi_context = CpiContext::new(system_program.clone(), cpi_accounts); + system_program::transfer(cpi_context, required_lamports)?; + } + let cpi_accounts = system_program::Allocate { + account_to_allocate: target_account.clone(), + }; + let cpi_context = CpiContext::new(system_program.clone(), cpi_accounts); + system_program::allocate( + cpi_context.with_signer(&[siger_seed]), + u64::try_from(space).unwrap(), + )?; + + let cpi_accounts = system_program::Assign { + account_to_assign: target_account.clone(), + }; + let cpi_context = CpiContext::new(system_program.clone(), cpi_accounts); + system_program::assign(cpi_context.with_signer(&[siger_seed]), program_id)?; + } + Ok(()) +}