realloc.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use {
  2. solana_account_info::{next_account_info, AccountInfo},
  3. solana_cpi::invoke,
  4. solana_instruction::{AccountMeta, Instruction},
  5. solana_keypair::Keypair,
  6. solana_program_error::ProgramResult,
  7. solana_program_test::{processor, ProgramTest},
  8. solana_pubkey::Pubkey,
  9. solana_signer::Signer,
  10. solana_system_interface::instruction as system_instruction,
  11. solana_sysvar::rent,
  12. solana_transaction::Transaction,
  13. };
  14. fn process_instruction(
  15. _program_id: &Pubkey,
  16. accounts: &[AccountInfo],
  17. _input: &[u8],
  18. ) -> ProgramResult {
  19. let account_info_iter = &mut accounts.iter();
  20. let account_info = next_account_info(account_info_iter)?;
  21. let destination_info = next_account_info(account_info_iter)?;
  22. let owner_info = next_account_info(account_info_iter)?;
  23. let token_program_info = next_account_info(account_info_iter)?;
  24. invoke(
  25. &Instruction::new_with_bytes(
  26. *token_program_info.key,
  27. &[9], // close account
  28. vec![
  29. AccountMeta::new(*account_info.key, false),
  30. AccountMeta::new(*destination_info.key, false),
  31. AccountMeta::new_readonly(*owner_info.key, true),
  32. ],
  33. ),
  34. &[
  35. account_info.clone(),
  36. destination_info.clone(),
  37. owner_info.clone(),
  38. ],
  39. )?;
  40. Ok(())
  41. }
  42. #[tokio::test]
  43. async fn realloc_smaller_in_cpi() {
  44. let program_id = Pubkey::new_unique();
  45. let program_test = ProgramTest::new(
  46. "program-test-realloc",
  47. program_id,
  48. processor!(process_instruction),
  49. );
  50. let context = program_test.start_with_context().await;
  51. let token_2022_id = spl_generic_token::token_2022::id();
  52. let mint = Keypair::new();
  53. let account = Keypair::new();
  54. let rent = context.banks_client.get_rent().await.unwrap();
  55. let mint_space = 82;
  56. let account_space = 165;
  57. let transaction = Transaction::new_signed_with_payer(
  58. &[
  59. system_instruction::create_account(
  60. &context.payer.pubkey(),
  61. &mint.pubkey(),
  62. rent.minimum_balance(mint_space),
  63. mint_space as u64,
  64. &token_2022_id,
  65. ),
  66. Instruction::new_with_bytes(
  67. token_2022_id,
  68. &[0; 35], // initialize mint
  69. vec![
  70. AccountMeta::new(mint.pubkey(), false),
  71. AccountMeta::new_readonly(rent::id(), false),
  72. ],
  73. ),
  74. system_instruction::create_account(
  75. &context.payer.pubkey(),
  76. &account.pubkey(),
  77. rent.minimum_balance(account_space),
  78. account_space as u64,
  79. &token_2022_id,
  80. ),
  81. Instruction::new_with_bytes(
  82. token_2022_id,
  83. &[1], // initialize account
  84. vec![
  85. AccountMeta::new(account.pubkey(), false),
  86. AccountMeta::new_readonly(mint.pubkey(), false),
  87. AccountMeta::new_readonly(account.pubkey(), false),
  88. AccountMeta::new_readonly(rent::id(), false),
  89. ],
  90. ),
  91. Instruction::new_with_bytes(
  92. program_id,
  93. &[], // close account
  94. vec![
  95. AccountMeta::new(account.pubkey(), false),
  96. AccountMeta::new(mint.pubkey(), false),
  97. AccountMeta::new_readonly(account.pubkey(), true),
  98. AccountMeta::new_readonly(token_2022_id, false),
  99. ],
  100. ),
  101. ],
  102. Some(&context.payer.pubkey()),
  103. &[&context.payer, &mint, &account],
  104. context.last_blockhash,
  105. );
  106. context
  107. .banks_client
  108. .process_transaction(transaction)
  109. .await
  110. .unwrap();
  111. }