solana-program-library/token/program/tests/close_account.rs

203 lines
5.7 KiB
Rust

#![cfg(feature = "test-bpf")]
use {
solana_program_test::{processor, tokio, ProgramTest, ProgramTestContext},
solana_sdk::{
instruction::InstructionError,
program_pack::Pack,
pubkey::Pubkey,
signature::Signer,
signer::keypair::Keypair,
system_instruction,
transaction::{Transaction, TransactionError},
},
spl_token::{
instruction,
processor::Processor,
state::{Account, Mint},
},
};
async fn setup_mint_and_account(
context: &mut ProgramTestContext,
mint: &Keypair,
token_account: &Keypair,
owner: &Pubkey,
token_program_id: &Pubkey,
) {
let rent = context.banks_client.get_rent().await.unwrap();
let mint_authority_pubkey = Pubkey::new_unique();
let space = Mint::LEN;
let tx = Transaction::new_signed_with_payer(
&[
system_instruction::create_account(
&context.payer.pubkey(),
&mint.pubkey(),
rent.minimum_balance(space),
space as u64,
&token_program_id,
),
instruction::initialize_mint(
&token_program_id,
&mint.pubkey(),
&mint_authority_pubkey,
None,
9,
)
.unwrap(),
],
Some(&context.payer.pubkey()),
&[&context.payer, mint],
context.last_blockhash,
);
context.banks_client.process_transaction(tx).await.unwrap();
let space = Account::LEN;
let tx = Transaction::new_signed_with_payer(
&[
system_instruction::create_account(
&context.payer.pubkey(),
&token_account.pubkey(),
rent.minimum_balance(space),
space as u64,
&token_program_id,
),
instruction::initialize_account(
&token_program_id,
&token_account.pubkey(),
&mint.pubkey(),
&owner,
)
.unwrap(),
],
Some(&context.payer.pubkey()),
&[&context.payer, &token_account],
context.last_blockhash,
);
context.banks_client.process_transaction(tx).await.unwrap();
}
#[tokio::test]
async fn success_init_after_close_account() {
let program_test =
ProgramTest::new("spl_token", spl_token::id(), processor!(Processor::process));
let mut context = program_test.start_with_context().await;
let mint = Keypair::new();
let token_account = Keypair::new();
let owner = Keypair::new();
let token_program_id = spl_token::id();
setup_mint_and_account(
&mut context,
&mint,
&token_account,
&owner.pubkey(),
&token_program_id,
)
.await;
let destination = Pubkey::new_unique();
let tx = Transaction::new_signed_with_payer(
&[
instruction::close_account(
&token_program_id,
&token_account.pubkey(),
&destination,
&owner.pubkey(),
&[],
)
.unwrap(),
system_instruction::create_account(
&context.payer.pubkey(),
&token_account.pubkey(),
1_000_000_000,
Account::LEN as u64,
&token_program_id,
),
instruction::initialize_account(
&token_program_id,
&token_account.pubkey(),
&mint.pubkey(),
&owner.pubkey(),
)
.unwrap(),
],
Some(&context.payer.pubkey()),
&[&context.payer, &owner, &token_account],
context.last_blockhash,
);
context.banks_client.process_transaction(tx).await.unwrap();
let destination = context
.banks_client
.get_account(destination)
.await
.unwrap()
.unwrap();
assert!(destination.lamports > 0);
}
#[tokio::test]
async fn fail_init_after_close_account() {
let program_test =
ProgramTest::new("spl_token", spl_token::id(), processor!(Processor::process));
let mut context = program_test.start_with_context().await;
let mint = Keypair::new();
let token_account = Keypair::new();
let owner = Keypair::new();
let token_program_id = spl_token::id();
setup_mint_and_account(
&mut context,
&mint,
&token_account,
&owner.pubkey(),
&token_program_id,
)
.await;
let destination = Pubkey::new_unique();
let tx = Transaction::new_signed_with_payer(
&[
instruction::close_account(
&token_program_id,
&token_account.pubkey(),
&destination,
&owner.pubkey(),
&[],
)
.unwrap(),
system_instruction::transfer(
&context.payer.pubkey(),
&token_account.pubkey(),
1_000_000_000,
),
instruction::initialize_account(
&token_program_id,
&token_account.pubkey(),
&mint.pubkey(),
&owner.pubkey(),
)
.unwrap(),
],
Some(&context.payer.pubkey()),
&[&context.payer, &owner],
context.last_blockhash,
);
#[allow(clippy::useless_conversion)]
let error: TransactionError = context
.banks_client
.process_transaction(tx)
.await
.unwrap_err()
.unwrap()
.into();
assert_eq!(
error,
TransactionError::InstructionError(2, InstructionError::InvalidAccountData)
);
assert!(context
.banks_client
.get_account(destination)
.await
.unwrap()
.is_none());
}