|
@@ -28,7 +28,10 @@ use {
|
|
|
spl_transfer_hook_interface::{
|
|
spl_transfer_hook_interface::{
|
|
|
error::TransferHookError,
|
|
error::TransferHookError,
|
|
|
get_extra_account_metas_address,
|
|
get_extra_account_metas_address,
|
|
|
- instruction::{execute_with_extra_account_metas, initialize_extra_account_meta_list},
|
|
|
|
|
|
|
+ instruction::{
|
|
|
|
|
+ execute_with_extra_account_metas, initialize_extra_account_meta_list,
|
|
|
|
|
+ update_extra_account_meta_list,
|
|
|
|
|
+ },
|
|
|
onchain,
|
|
onchain,
|
|
|
},
|
|
},
|
|
|
};
|
|
};
|
|
@@ -747,3 +750,649 @@ async fn fail_without_transferring_flag() {
|
|
|
)
|
|
)
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#[tokio::test]
|
|
|
|
|
+async fn success_on_chain_invoke_with_updated_extra_account_metas() {
|
|
|
|
|
+ let hook_program_id = Pubkey::new_unique();
|
|
|
|
|
+ let mut program_test = setup(&hook_program_id);
|
|
|
|
|
+ let program_id = Pubkey::new_unique();
|
|
|
|
|
+ program_test.add_program(
|
|
|
|
|
+ "test_cpi_program",
|
|
|
|
|
+ program_id,
|
|
|
|
|
+ processor!(process_instruction),
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ let token_program_id = spl_token_2022::id();
|
|
|
|
|
+ let wallet = Keypair::new();
|
|
|
|
|
+ let mint_address = Pubkey::new_unique();
|
|
|
|
|
+ let mint_authority = Keypair::new();
|
|
|
|
|
+ let mint_authority_pubkey = mint_authority.pubkey();
|
|
|
|
|
+ let source = Pubkey::new_unique();
|
|
|
|
|
+ let destination = Pubkey::new_unique();
|
|
|
|
|
+ let decimals = 2;
|
|
|
|
|
+ let amount = 0u64;
|
|
|
|
|
+
|
|
|
|
|
+ setup_token_accounts(
|
|
|
|
|
+ &mut program_test,
|
|
|
|
|
+ &token_program_id,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &mint_authority_pubkey,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ decimals,
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ let extra_account_metas_address =
|
|
|
|
|
+ get_extra_account_metas_address(&mint_address, &hook_program_id);
|
|
|
|
|
+ let writable_pubkey = Pubkey::new_unique();
|
|
|
|
|
+
|
|
|
|
|
+ // Create an initial account metas list
|
|
|
|
|
+ let init_extra_account_metas = [
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&sysvar::instructions::id(), false, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&mint_authority_pubkey, true, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::Literal {
|
|
|
|
|
+ bytes: b"init-seed-prefix".to_vec(),
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 0 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::InstructionData {
|
|
|
|
|
+ index: 8, // After instruction discriminator
|
|
|
|
|
+ length: 8, // `u64` (amount)
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 2 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&writable_pubkey, false, true).unwrap(),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let mut context = program_test.start_with_context().await;
|
|
|
|
|
+ let rent = context.banks_client.get_rent().await.unwrap();
|
|
|
|
|
+ let rent_lamports = rent
|
|
|
|
|
+ .minimum_balance(ExtraAccountMetaList::size_of(init_extra_account_metas.len()).unwrap());
|
|
|
|
|
+ let init_transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[
|
|
|
|
|
+ system_instruction::transfer(
|
|
|
|
|
+ &context.payer.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ rent_lamports,
|
|
|
|
|
+ ),
|
|
|
|
|
+ initialize_extra_account_meta_list(
|
|
|
|
|
+ &hook_program_id,
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &mint_authority_pubkey,
|
|
|
|
|
+ &init_extra_account_metas,
|
|
|
|
|
+ ),
|
|
|
|
|
+ ],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(init_transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ // Create an updated account metas list
|
|
|
|
|
+ let updated_extra_account_metas = [
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&sysvar::instructions::id(), false, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&mint_authority_pubkey, true, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::Literal {
|
|
|
|
|
+ bytes: b"updated-seed-prefix".to_vec(),
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 0 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::InstructionData {
|
|
|
|
|
+ index: 8, // After instruction discriminator
|
|
|
|
|
+ length: 8, // `u64` (amount)
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 2 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&writable_pubkey, false, true).unwrap(),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let rent = context.banks_client.get_rent().await.unwrap();
|
|
|
|
|
+ let rent_lamports = rent
|
|
|
|
|
+ .minimum_balance(ExtraAccountMetaList::size_of(updated_extra_account_metas.len()).unwrap());
|
|
|
|
|
+ let update_transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[
|
|
|
|
|
+ system_instruction::transfer(
|
|
|
|
|
+ &context.payer.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ rent_lamports,
|
|
|
|
|
+ ),
|
|
|
|
|
+ update_extra_account_meta_list(
|
|
|
|
|
+ &hook_program_id,
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &mint_authority_pubkey,
|
|
|
|
|
+ &updated_extra_account_metas,
|
|
|
|
|
+ ),
|
|
|
|
|
+ ],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(update_transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let updated_extra_pda_1 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ b"updated-seed-prefix", // Literal prefix
|
|
|
|
|
+ source.as_ref(), // Account at index 0
|
|
|
|
|
+ ],
|
|
|
|
|
+ &hook_program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+ let extra_pda_2 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ &amount.to_le_bytes(), // Instruction data bytes 8 to 16
|
|
|
|
|
+ destination.as_ref(), // Account at index 2
|
|
|
|
|
+ ],
|
|
|
|
|
+ &hook_program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+
|
|
|
|
|
+ let test_updated_extra_account_metas = [
|
|
|
|
|
+ AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
|
|
|
|
+ AccountMeta::new_readonly(mint_authority_pubkey, true),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_1, false),
|
|
|
|
|
+ AccountMeta::new(extra_pda_2, false),
|
|
|
|
|
+ AccountMeta::new(writable_pubkey, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ // Use updated account metas list
|
|
|
|
|
+ let mut test_instruction = execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &test_updated_extra_account_metas,
|
|
|
|
|
+ amount,
|
|
|
|
|
+ );
|
|
|
|
|
+ test_instruction
|
|
|
|
|
+ .accounts
|
|
|
|
|
+ .insert(0, AccountMeta::new_readonly(hook_program_id, false));
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[test_instruction],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[tokio::test]
|
|
|
|
|
+async fn success_execute_with_updated_extra_account_metas() {
|
|
|
|
|
+ let program_id = Pubkey::new_unique();
|
|
|
|
|
+ let mut program_test = setup(&program_id);
|
|
|
|
|
+
|
|
|
|
|
+ let token_program_id = spl_token_2022::id();
|
|
|
|
|
+ let wallet = Keypair::new();
|
|
|
|
|
+ let mint_address = Pubkey::new_unique();
|
|
|
|
|
+ let mint_authority = Keypair::new();
|
|
|
|
|
+ let mint_authority_pubkey = mint_authority.pubkey();
|
|
|
|
|
+ let source = Pubkey::new_unique();
|
|
|
|
|
+ let destination = Pubkey::new_unique();
|
|
|
|
|
+ let decimals = 2;
|
|
|
|
|
+ let amount = 0u64;
|
|
|
|
|
+
|
|
|
|
|
+ setup_token_accounts(
|
|
|
|
|
+ &mut program_test,
|
|
|
|
|
+ &token_program_id,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &mint_authority_pubkey,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ decimals,
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ let extra_account_metas_address = get_extra_account_metas_address(&mint_address, &program_id);
|
|
|
|
|
+
|
|
|
|
|
+ let writable_pubkey = Pubkey::new_unique();
|
|
|
|
|
+
|
|
|
|
|
+ let init_extra_account_metas = [
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&sysvar::instructions::id(), false, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&mint_authority_pubkey, true, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::Literal {
|
|
|
|
|
+ bytes: b"seed-prefix".to_vec(),
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 0 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::InstructionData {
|
|
|
|
|
+ index: 8, // After instruction discriminator
|
|
|
|
|
+ length: 8, // `u64` (amount)
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 2 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&writable_pubkey, false, true).unwrap(),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let extra_pda_1 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ b"seed-prefix", // Literal prefix
|
|
|
|
|
+ source.as_ref(), // Account at index 0
|
|
|
|
|
+ ],
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+
|
|
|
|
|
+ let extra_pda_2 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ &amount.to_le_bytes(), // Instruction data bytes 8 to 16
|
|
|
|
|
+ destination.as_ref(), // Account at index 2
|
|
|
|
|
+ ],
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+
|
|
|
|
|
+ let init_account_metas = [
|
|
|
|
|
+ AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
|
|
|
|
+ AccountMeta::new_readonly(mint_authority_pubkey, true),
|
|
|
|
|
+ AccountMeta::new(extra_pda_1, false),
|
|
|
|
|
+ AccountMeta::new(extra_pda_2, false),
|
|
|
|
|
+ AccountMeta::new(writable_pubkey, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let mut context = program_test.start_with_context().await;
|
|
|
|
|
+ let rent = context.banks_client.get_rent().await.unwrap();
|
|
|
|
|
+ let rent_lamports = rent
|
|
|
|
|
+ .minimum_balance(ExtraAccountMetaList::size_of(init_extra_account_metas.len()).unwrap());
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[
|
|
|
|
|
+ system_instruction::transfer(
|
|
|
|
|
+ &context.payer.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ rent_lamports,
|
|
|
|
|
+ ),
|
|
|
|
|
+ initialize_extra_account_meta_list(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &mint_authority_pubkey,
|
|
|
|
|
+ &init_extra_account_metas,
|
|
|
|
|
+ ),
|
|
|
|
|
+ ],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let updated_amount = 1u64;
|
|
|
|
|
+ let updated_writable_pubkey = Pubkey::new_unique();
|
|
|
|
|
+
|
|
|
|
|
+ // Create updated extra account metas
|
|
|
|
|
+ let updated_extra_account_metas = [
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&sysvar::instructions::id(), false, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&mint_authority_pubkey, true, false).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::Literal {
|
|
|
|
|
+ bytes: b"updated-seed-prefix".to_vec(),
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 0 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::InstructionData {
|
|
|
|
|
+ index: 8, // After instruction discriminator
|
|
|
|
|
+ length: 8, // `u64` (amount)
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 2 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_pubkey(&updated_writable_pubkey, false, true).unwrap(),
|
|
|
|
|
+ ExtraAccountMeta::new_with_seeds(
|
|
|
|
|
+ &[
|
|
|
|
|
+ Seed::Literal {
|
|
|
|
|
+ bytes: b"new-seed-prefix".to_vec(),
|
|
|
|
|
+ },
|
|
|
|
|
+ Seed::AccountKey { index: 0 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ false,
|
|
|
|
|
+ true,
|
|
|
|
|
+ )
|
|
|
|
|
+ .unwrap(),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let updated_extra_pda_1 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ b"updated-seed-prefix", // Literal prefix
|
|
|
|
|
+ source.as_ref(), // Account at index 0
|
|
|
|
|
+ ],
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+
|
|
|
|
|
+ let updated_extra_pda_2 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ &updated_amount.to_le_bytes(), // Instruction data bytes 8 to 16
|
|
|
|
|
+ destination.as_ref(), // Account at index 2
|
|
|
|
|
+ ],
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+
|
|
|
|
|
+ // add another PDA
|
|
|
|
|
+ let new_extra_pda = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ b"new-seed-prefix", // Literal prefix
|
|
|
|
|
+ source.as_ref(), // Account at index 0
|
|
|
|
|
+ ],
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+
|
|
|
|
|
+ let updated_account_metas = [
|
|
|
|
|
+ AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
|
|
|
|
+ AccountMeta::new_readonly(mint_authority_pubkey, true),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_1, false),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_2, false),
|
|
|
|
|
+ AccountMeta::new(updated_writable_pubkey, false),
|
|
|
|
|
+ AccountMeta::new(new_extra_pda, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ let update_transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[
|
|
|
|
|
+ system_instruction::transfer(
|
|
|
|
|
+ &context.payer.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ rent_lamports,
|
|
|
|
|
+ ),
|
|
|
|
|
+ update_extra_account_meta_list(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &mint_authority_pubkey,
|
|
|
|
|
+ &updated_extra_account_metas,
|
|
|
|
|
+ ),
|
|
|
|
|
+ ],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(update_transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ // fail with initial account metas list
|
|
|
|
|
+ {
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &init_account_metas,
|
|
|
|
|
+ updated_amount,
|
|
|
|
|
+ )],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+ let error = context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap_err()
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ error,
|
|
|
|
|
+ TransactionError::InstructionError(
|
|
|
|
|
+ 0,
|
|
|
|
|
+ InstructionError::Custom(AccountResolutionError::IncorrectAccount as u32),
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // fail with missing account
|
|
|
|
|
+ {
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &updated_account_metas[..2],
|
|
|
|
|
+ updated_amount,
|
|
|
|
|
+ )],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+ let error = context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap_err()
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ error,
|
|
|
|
|
+ TransactionError::InstructionError(
|
|
|
|
|
+ 0,
|
|
|
|
|
+ InstructionError::Custom(AccountResolutionError::IncorrectAccount as u32),
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // fail with wrong account
|
|
|
|
|
+ {
|
|
|
|
|
+ let extra_account_metas = [
|
|
|
|
|
+ AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
|
|
|
|
+ AccountMeta::new_readonly(mint_authority_pubkey, true),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_1, false),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_2, false),
|
|
|
|
|
+ AccountMeta::new(Pubkey::new_unique(), false),
|
|
|
|
|
+ ];
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &extra_account_metas,
|
|
|
|
|
+ updated_amount,
|
|
|
|
|
+ )],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+ let error = context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap_err()
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ error,
|
|
|
|
|
+ TransactionError::InstructionError(
|
|
|
|
|
+ 0,
|
|
|
|
|
+ InstructionError::Custom(AccountResolutionError::IncorrectAccount as u32),
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // fail with wrong PDA
|
|
|
|
|
+ let wrong_pda_2 = Pubkey::find_program_address(
|
|
|
|
|
+ &[
|
|
|
|
|
+ &99u64.to_le_bytes(), // Wrong data
|
|
|
|
|
+ destination.as_ref(),
|
|
|
|
|
+ ],
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ .0;
|
|
|
|
|
+ {
|
|
|
|
|
+ let extra_account_metas = [
|
|
|
|
|
+ AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
|
|
|
|
+ AccountMeta::new_readonly(mint_authority_pubkey, true),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_1, false),
|
|
|
|
|
+ AccountMeta::new(wrong_pda_2, false),
|
|
|
|
|
+ AccountMeta::new(writable_pubkey, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &extra_account_metas,
|
|
|
|
|
+ updated_amount,
|
|
|
|
|
+ )],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+ let error = context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap_err()
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ error,
|
|
|
|
|
+ TransactionError::InstructionError(
|
|
|
|
|
+ 0,
|
|
|
|
|
+ InstructionError::Custom(AccountResolutionError::IncorrectAccount as u32),
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // fail with not signer
|
|
|
|
|
+ {
|
|
|
|
|
+ let extra_account_metas = [
|
|
|
|
|
+ AccountMeta::new_readonly(sysvar::instructions::id(), false),
|
|
|
|
|
+ AccountMeta::new_readonly(mint_authority_pubkey, false),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_1, false),
|
|
|
|
|
+ AccountMeta::new(updated_extra_pda_2, false),
|
|
|
|
|
+ AccountMeta::new(writable_pubkey, false),
|
|
|
|
|
+ ];
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &extra_account_metas,
|
|
|
|
|
+ updated_amount,
|
|
|
|
|
+ )],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+ let error = context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap_err()
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ error,
|
|
|
|
|
+ TransactionError::InstructionError(
|
|
|
|
|
+ 0,
|
|
|
|
|
+ InstructionError::Custom(AccountResolutionError::IncorrectAccount as u32),
|
|
|
|
|
+ )
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // success with correct params
|
|
|
|
|
+ {
|
|
|
|
|
+ let transaction = Transaction::new_signed_with_payer(
|
|
|
|
|
+ &[execute_with_extra_account_metas(
|
|
|
|
|
+ &program_id,
|
|
|
|
|
+ &source,
|
|
|
|
|
+ &mint_address,
|
|
|
|
|
+ &destination,
|
|
|
|
|
+ &wallet.pubkey(),
|
|
|
|
|
+ &extra_account_metas_address,
|
|
|
|
|
+ &updated_account_metas,
|
|
|
|
|
+ updated_amount,
|
|
|
|
|
+ )],
|
|
|
|
|
+ Some(&context.payer.pubkey()),
|
|
|
|
|
+ &[&context.payer, &mint_authority],
|
|
|
|
|
+ context.last_blockhash,
|
|
|
|
|
+ );
|
|
|
|
|
+ context
|
|
|
|
|
+ .banks_client
|
|
|
|
|
+ .process_transaction(transaction)
|
|
|
|
|
+ .await
|
|
|
|
|
+ .unwrap();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|