Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transfer Hook: Provide extra metas as instruction data #4999

Merged
merged 1 commit into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libraries/type-length-value/src/pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub fn pod_slice_from_bytes<T: Pod>(bytes: &[u8]) -> Result<&[T], ProgramError>
pub fn pod_slice_from_bytes_mut<T: Pod>(bytes: &mut [u8]) -> Result<&mut [T], ProgramError> {
bytemuck::try_cast_slice_mut(bytes).map_err(|_| ProgramError::InvalidArgument)
}
/// Convert a pod slice into its raw bytes
pub fn pod_slice_to_bytes<T: Pod>(slice: &[T]) -> &[u8] {
bytemuck::cast_slice(slice)
}

/// Simple macro for implementing conversion functions between Pod* ints and
/// standard ints.
Expand Down
20 changes: 8 additions & 12 deletions token/transfer-hook-example/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ pub fn process_execute(
}

/// Processes a [InitializeExtraAccountMetaList](enum.TransferHookInstruction.html) instruction.
pub fn process_initialize_extra_account_metas(
pub fn process_initialize_extra_account_meta_list(
program_id: &Pubkey,
accounts: &[AccountInfo],
extra_account_metas: &[ExtraAccountMeta],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();

Expand Down Expand Up @@ -127,8 +128,7 @@ pub fn process_initialize_extra_account_metas(
// Create the account
let bump_seed = [bump_seed];
let signer_seeds = collect_extra_account_metas_signer_seeds(mint_info.key, &bump_seed);
let extra_account_infos = account_info_iter.as_slice();
let length = extra_account_infos.len();
let length = extra_account_metas.len();
let account_size = ExtraAccountMetaList::size_of(length)?;
invoke_signed(
&system_instruction::allocate(extra_account_metas_info.key, account_size as u64),
Expand All @@ -143,13 +143,7 @@ pub fn process_initialize_extra_account_metas(

// Write the data
let mut data = extra_account_metas_info.try_borrow_mut_data()?;
ExtraAccountMetaList::init::<ExecuteInstruction>(
&mut data,
&extra_account_infos
.iter()
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>(),
)?;
ExtraAccountMetaList::init::<ExecuteInstruction>(&mut data, extra_account_metas)?;

Ok(())
}
Expand All @@ -163,9 +157,11 @@ pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> P
msg!("Instruction: Execute");
process_execute(program_id, accounts, amount)
}
TransferHookInstruction::InitializeExtraAccountMetaList => {
TransferHookInstruction::InitializeExtraAccountMetaList {
extra_account_metas,
} => {
msg!("Instruction: InitializeExtraAccountMetaList");
process_initialize_extra_account_metas(program_id, accounts)
process_initialize_extra_account_meta_list(program_id, accounts, &extra_account_metas)
}
}
}
88 changes: 50 additions & 38 deletions token/transfer-hook-example/tests/functional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ use {
system_instruction, sysvar,
transaction::{Transaction, TransactionError},
},
spl_tlv_account_resolution::state::ExtraAccountMetaList,
spl_tlv_account_resolution::{account::ExtraAccountMeta, state::ExtraAccountMetaList},
spl_token_2022::{
extension::{transfer_hook::TransferHookAccount, ExtensionType, StateWithExtensionsMut},
state::{Account, AccountState, Mint},
},
spl_transfer_hook_interface::{
error::TransferHookError,
get_extra_account_metas_address,
instruction::{execute_with_extra_account_metas, initialize_extra_account_metas},
instruction::{execute_with_extra_account_metas, initialize_extra_account_meta_list},
onchain,
},
};
Expand Down Expand Up @@ -151,30 +151,35 @@ async fn success_execute() {
true,
);

let extra_account_metas = get_extra_account_metas_address(&mint_address, &program_id);
let extra_account_metas_address = get_extra_account_metas_address(&mint_address, &program_id);

let extra_account_pubkeys = [
let extra_account_metas = [
AccountMeta::new_readonly(sysvar::instructions::id(), false),
AccountMeta::new_readonly(mint_authority_pubkey, true),
AccountMeta::new(extra_account_metas, false),
AccountMeta::new(extra_account_metas_address, false),
];
let init_extra_account_metas = extra_account_metas
.iter()
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>();

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(extra_account_pubkeys.len()).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,
&extra_account_metas_address,
rent_lamports,
),
initialize_extra_account_metas(
initialize_extra_account_meta_list(
&program_id,
&extra_account_metas,
&extra_account_metas_address,
&mint_address,
&mint_authority_pubkey,
&extra_account_pubkeys,
&init_extra_account_metas,
),
],
Some(&context.payer.pubkey()),
Expand All @@ -197,8 +202,8 @@ async fn success_execute() {
&mint_address,
&destination,
&wallet.pubkey(),
&extra_account_metas,
&extra_account_pubkeys[..2],
&extra_account_metas_address,
&extra_account_metas[..2],
0,
)],
Some(&context.payer.pubkey()),
Expand All @@ -222,7 +227,7 @@ async fn success_execute() {

// fail with wrong account
{
let extra_account_pubkeys = [
let extra_account_metas = [
AccountMeta::new_readonly(sysvar::instructions::id(), false),
AccountMeta::new_readonly(mint_authority_pubkey, true),
AccountMeta::new(wallet.pubkey(), false),
Expand All @@ -234,8 +239,8 @@ async fn success_execute() {
&mint_address,
&destination,
&wallet.pubkey(),
&extra_account_metas_address,
&extra_account_metas,
&extra_account_pubkeys,
0,
)],
Some(&context.payer.pubkey()),
Expand All @@ -259,10 +264,10 @@ async fn success_execute() {

// fail with not signer
{
let extra_account_pubkeys = [
let extra_account_metas = [
AccountMeta::new_readonly(sysvar::instructions::id(), false),
AccountMeta::new_readonly(mint_authority_pubkey, false),
AccountMeta::new(extra_account_metas, false),
AccountMeta::new(extra_account_metas_address, false),
];
let transaction = Transaction::new_signed_with_payer(
&[execute_with_extra_account_metas(
Expand All @@ -271,8 +276,8 @@ async fn success_execute() {
&mint_address,
&destination,
&wallet.pubkey(),
&extra_account_metas_address,
&extra_account_metas,
&extra_account_pubkeys,
0,
)],
Some(&context.payer.pubkey()),
Expand Down Expand Up @@ -303,8 +308,8 @@ async fn success_execute() {
&mint_address,
&destination,
&wallet.pubkey(),
&extra_account_metas_address,
&extra_account_metas,
&extra_account_pubkeys,
0,
)],
Some(&context.payer.pubkey()),
Expand Down Expand Up @@ -358,7 +363,7 @@ async fn fail_incorrect_derivation() {
&extra_account_metas,
rent_lamports,
),
initialize_extra_account_metas(
initialize_extra_account_meta_list(
&program_id,
&extra_account_metas,
&mint_address,
Expand Down Expand Up @@ -431,31 +436,37 @@ async fn success_on_chain_invoke() {
true,
);

let extra_account_metas = get_extra_account_metas_address(&mint_address, &hook_program_id);
let extra_account_metas_address =
get_extra_account_metas_address(&mint_address, &hook_program_id);

let writable_pubkey = Pubkey::new_unique();
let extra_account_pubkeys = [
let extra_account_metas = [
AccountMeta::new_readonly(sysvar::instructions::id(), false),
AccountMeta::new_readonly(mint_authority_pubkey, true),
AccountMeta::new(writable_pubkey, false),
];
let init_extra_account_metas = extra_account_metas
.iter()
.map(ExtraAccountMeta::from)
.collect::<Vec<_>>();

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(extra_account_pubkeys.len()).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,
&extra_account_metas_address,
rent_lamports,
),
initialize_extra_account_metas(
initialize_extra_account_meta_list(
&hook_program_id,
&extra_account_metas,
&extra_account_metas_address,
&mint_address,
&mint_authority_pubkey,
&extra_account_pubkeys,
&init_extra_account_metas,
),
],
Some(&context.payer.pubkey()),
Expand All @@ -476,8 +487,8 @@ async fn success_on_chain_invoke() {
&mint_address,
&destination,
&wallet.pubkey(),
&extra_account_metas_address,
&extra_account_metas,
&extra_account_pubkeys,
0,
);
test_instruction
Expand Down Expand Up @@ -522,25 +533,26 @@ async fn fail_without_transferring_flag() {
false,
);

let extra_account_metas = get_extra_account_metas_address(&mint_address, &program_id);
let extra_account_pubkeys = [];
let extra_account_metas_address = get_extra_account_metas_address(&mint_address, &program_id);
let extra_account_metas = [];
let init_extra_account_metas = [];
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(extra_account_pubkeys.len()).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,
&extra_account_metas_address,
rent_lamports,
),
initialize_extra_account_metas(
initialize_extra_account_meta_list(
&program_id,
&extra_account_metas,
&extra_account_metas_address,
&mint_address,
&mint_authority_pubkey,
&extra_account_pubkeys,
&init_extra_account_metas,
),
],
Some(&context.payer.pubkey()),
Expand All @@ -560,8 +572,8 @@ async fn fail_without_transferring_flag() {
&mint_address,
&destination,
&wallet.pubkey(),
&extra_account_metas_address,
&extra_account_metas,
&extra_account_pubkeys,
0,
)],
Some(&context.payer.pubkey()),
Expand Down
Loading
Loading