Skip to content

Commit

Permalink
Transfer Hook: Provide extra metas as instruction data (#4999)
Browse files Browse the repository at this point in the history
init metas as instruction data
  • Loading branch information
buffalojoec authored Aug 11, 2023
1 parent b7fe9a9 commit 7d3e824
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 61 deletions.
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

0 comments on commit 7d3e824

Please sign in to comment.