close_account.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #![cfg(feature = "test-sbf")]
  2. use {
  3. solana_program_test::{processor, tokio, ProgramTest, ProgramTestContext},
  4. solana_sdk::{
  5. instruction::InstructionError,
  6. program_pack::Pack,
  7. pubkey::Pubkey,
  8. signature::Signer,
  9. signer::keypair::Keypair,
  10. system_instruction,
  11. transaction::{Transaction, TransactionError},
  12. },
  13. spl_token::{
  14. instruction,
  15. processor::Processor,
  16. state::{Account, Mint},
  17. },
  18. };
  19. async fn setup_mint_and_account(
  20. context: &mut ProgramTestContext,
  21. mint: &Keypair,
  22. token_account: &Keypair,
  23. owner: &Pubkey,
  24. token_program_id: &Pubkey,
  25. ) {
  26. let rent = context.banks_client.get_rent().await.unwrap();
  27. let mint_authority_pubkey = Pubkey::new_unique();
  28. let space = Mint::LEN;
  29. let tx = Transaction::new_signed_with_payer(
  30. &[
  31. system_instruction::create_account(
  32. &context.payer.pubkey(),
  33. &mint.pubkey(),
  34. rent.minimum_balance(space),
  35. space as u64,
  36. token_program_id,
  37. ),
  38. instruction::initialize_mint(
  39. token_program_id,
  40. &mint.pubkey(),
  41. &mint_authority_pubkey,
  42. None,
  43. 9,
  44. )
  45. .unwrap(),
  46. ],
  47. Some(&context.payer.pubkey()),
  48. &[&context.payer, mint],
  49. context.last_blockhash,
  50. );
  51. context.banks_client.process_transaction(tx).await.unwrap();
  52. let space = Account::LEN;
  53. let tx = Transaction::new_signed_with_payer(
  54. &[
  55. system_instruction::create_account(
  56. &context.payer.pubkey(),
  57. &token_account.pubkey(),
  58. rent.minimum_balance(space),
  59. space as u64,
  60. token_program_id,
  61. ),
  62. instruction::initialize_account(
  63. token_program_id,
  64. &token_account.pubkey(),
  65. &mint.pubkey(),
  66. owner,
  67. )
  68. .unwrap(),
  69. ],
  70. Some(&context.payer.pubkey()),
  71. &[&context.payer, token_account],
  72. context.last_blockhash,
  73. );
  74. context.banks_client.process_transaction(tx).await.unwrap();
  75. }
  76. #[tokio::test]
  77. async fn success_init_after_close_account() {
  78. let program_test =
  79. ProgramTest::new("spl_token", spl_token::id(), processor!(Processor::process));
  80. let mut context = program_test.start_with_context().await;
  81. let mint = Keypair::new();
  82. let token_account = Keypair::new();
  83. let owner = Keypair::new();
  84. let token_program_id = spl_token::id();
  85. setup_mint_and_account(
  86. &mut context,
  87. &mint,
  88. &token_account,
  89. &owner.pubkey(),
  90. &token_program_id,
  91. )
  92. .await;
  93. let destination = Pubkey::new_unique();
  94. let tx = Transaction::new_signed_with_payer(
  95. &[
  96. instruction::close_account(
  97. &token_program_id,
  98. &token_account.pubkey(),
  99. &destination,
  100. &owner.pubkey(),
  101. &[],
  102. )
  103. .unwrap(),
  104. system_instruction::create_account(
  105. &context.payer.pubkey(),
  106. &token_account.pubkey(),
  107. 1_000_000_000,
  108. Account::LEN as u64,
  109. &token_program_id,
  110. ),
  111. instruction::initialize_account(
  112. &token_program_id,
  113. &token_account.pubkey(),
  114. &mint.pubkey(),
  115. &owner.pubkey(),
  116. )
  117. .unwrap(),
  118. ],
  119. Some(&context.payer.pubkey()),
  120. &[&context.payer, &owner, &token_account],
  121. context.last_blockhash,
  122. );
  123. context.banks_client.process_transaction(tx).await.unwrap();
  124. let destination = context
  125. .banks_client
  126. .get_account(destination)
  127. .await
  128. .unwrap()
  129. .unwrap();
  130. assert!(destination.lamports > 0);
  131. }
  132. #[tokio::test]
  133. async fn fail_init_after_close_account() {
  134. let program_test =
  135. ProgramTest::new("spl_token", spl_token::id(), processor!(Processor::process));
  136. let mut context = program_test.start_with_context().await;
  137. let mint = Keypair::new();
  138. let token_account = Keypair::new();
  139. let owner = Keypair::new();
  140. let token_program_id = spl_token::id();
  141. setup_mint_and_account(
  142. &mut context,
  143. &mint,
  144. &token_account,
  145. &owner.pubkey(),
  146. &token_program_id,
  147. )
  148. .await;
  149. let destination = Pubkey::new_unique();
  150. let tx = Transaction::new_signed_with_payer(
  151. &[
  152. instruction::close_account(
  153. &token_program_id,
  154. &token_account.pubkey(),
  155. &destination,
  156. &owner.pubkey(),
  157. &[],
  158. )
  159. .unwrap(),
  160. system_instruction::transfer(
  161. &context.payer.pubkey(),
  162. &token_account.pubkey(),
  163. 1_000_000_000,
  164. ),
  165. instruction::initialize_account(
  166. &token_program_id,
  167. &token_account.pubkey(),
  168. &mint.pubkey(),
  169. &owner.pubkey(),
  170. )
  171. .unwrap(),
  172. ],
  173. Some(&context.payer.pubkey()),
  174. &[&context.payer, &owner],
  175. context.last_blockhash,
  176. );
  177. #[allow(clippy::useless_conversion)]
  178. let error: TransactionError = context
  179. .banks_client
  180. .process_transaction(tx)
  181. .await
  182. .unwrap_err()
  183. .unwrap()
  184. .into();
  185. assert_eq!(
  186. error,
  187. TransactionError::InstructionError(2, InstructionError::InvalidAccountData)
  188. );
  189. assert!(context
  190. .banks_client
  191. .get_account(destination)
  192. .await
  193. .unwrap()
  194. .is_none());
  195. }