spl_token_2022/extension/memo_transfer/
processor.rs

1use {
2    crate::{
3        check_program_account,
4        extension::{
5            memo_transfer::{instruction::RequiredMemoTransfersInstruction, MemoTransfer},
6            BaseStateWithExtensionsMut, PodStateWithExtensionsMut,
7        },
8        instruction::decode_instruction_type,
9        pod::PodAccount,
10        processor::Processor,
11    },
12    solana_program::{
13        account_info::{next_account_info, AccountInfo},
14        entrypoint::ProgramResult,
15        msg,
16        pubkey::Pubkey,
17    },
18};
19
20/// Toggle the `RequiredMemoTransfers` extension, initializing the extension if
21/// not already present.
22fn process_toggle_required_memo_transfers(
23    program_id: &Pubkey,
24    accounts: &[AccountInfo],
25    enable: bool,
26) -> ProgramResult {
27    let account_info_iter = &mut accounts.iter();
28    let token_account_info = next_account_info(account_info_iter)?;
29    let owner_info = next_account_info(account_info_iter)?;
30    let owner_info_data_len = owner_info.data_len();
31
32    let mut account_data = token_account_info.data.borrow_mut();
33    let mut account = PodStateWithExtensionsMut::<PodAccount>::unpack(&mut account_data)?;
34
35    Processor::validate_owner(
36        program_id,
37        &account.base.owner,
38        owner_info,
39        owner_info_data_len,
40        account_info_iter.as_slice(),
41    )?;
42
43    let extension = if let Ok(extension) = account.get_extension_mut::<MemoTransfer>() {
44        extension
45    } else {
46        account.init_extension::<MemoTransfer>(true)?
47    };
48    extension.require_incoming_transfer_memos = enable.into();
49    Ok(())
50}
51
52pub(crate) fn process_instruction(
53    program_id: &Pubkey,
54    accounts: &[AccountInfo],
55    input: &[u8],
56) -> ProgramResult {
57    check_program_account(program_id)?;
58
59    match decode_instruction_type(input)? {
60        RequiredMemoTransfersInstruction::Enable => {
61            msg!("RequiredMemoTransfersInstruction::Enable");
62            process_toggle_required_memo_transfers(program_id, accounts, true /* enable */)
63        }
64        RequiredMemoTransfersInstruction::Disable => {
65            msg!("RequiredMemoTransfersInstruction::Disable");
66            process_toggle_required_memo_transfers(program_id, accounts, false /* disable */)
67        }
68    }
69}