pinocchio_token/instructions/
initialize_multisig_2.rs

1use core::{mem::MaybeUninit, slice};
2
3use solana_account_view::AccountView;
4use solana_instruction_view::{cpi::invoke_with_bounds, InstructionAccount, InstructionView};
5use solana_program_error::{ProgramError, ProgramResult};
6
7use crate::instructions::MAX_MULTISIG_SIGNERS;
8
9/// Initialize a new Multisig.
10///
11/// ### Accounts:
12///   0. `[writable]` The multisig account to initialize.
13///   1. ..`1+N`. `[]` The N signer accounts, where N is between 1 and 11.
14pub struct InitializeMultisig2<'a, 'b>
15where
16    'a: 'b,
17{
18    /// Multisig Account.
19    pub multisig: &'a AccountView,
20    /// Signer Accounts
21    pub signers: &'b [&'a AccountView],
22    /// The number of signers (M) required to validate this multisignature
23    /// account.
24    pub m: u8,
25}
26
27impl InitializeMultisig2<'_, '_> {
28    #[inline(always)]
29    pub fn invoke(&self) -> ProgramResult {
30        let &Self {
31            multisig,
32            signers,
33            m,
34        } = self;
35
36        if signers.len() > MAX_MULTISIG_SIGNERS {
37            return Err(ProgramError::InvalidArgument);
38        }
39
40        let num_accounts = 1 + signers.len();
41
42        // Instruction accounts
43        const UNINIT_INSTRUCTION_ACCOUNT: MaybeUninit<InstructionAccount> =
44            MaybeUninit::<InstructionAccount>::uninit();
45        let mut instruction_accounts = [UNINIT_INSTRUCTION_ACCOUNT; 1 + MAX_MULTISIG_SIGNERS];
46
47        unsafe {
48            // SAFETY:
49            // - `instruction_accounts` is sized to 1 + MAX_MULTISIG_SIGNERS
50            // - Index 0 is always present
51            instruction_accounts
52                .get_unchecked_mut(0)
53                .write(InstructionAccount::writable(multisig.address()));
54        }
55
56        for (instruction_account, signer) in
57            instruction_accounts[1..].iter_mut().zip(signers.iter())
58        {
59            instruction_account.write(InstructionAccount::readonly(signer.address()));
60        }
61
62        // Instruction data layout:
63        // -  [0]: instruction discriminator (1 byte, u8)
64        // -  [1]: m (1 byte, u8)
65        let data = &[19, m];
66
67        let instruction = InstructionView {
68            program_id: &crate::ID,
69            accounts: unsafe {
70                slice::from_raw_parts(instruction_accounts.as_ptr() as _, num_accounts)
71            },
72            data,
73        };
74
75        // Account view array
76        const UNINIT_VIEW: MaybeUninit<&AccountView> = MaybeUninit::uninit();
77        let mut acc_views = [UNINIT_VIEW; 1 + MAX_MULTISIG_SIGNERS];
78
79        unsafe {
80            // SAFETY:
81            // - `account_views` is sized to 1 + MAX_MULTISIG_SIGNERS
82            // - Index 0 is always present
83            acc_views.get_unchecked_mut(0).write(multisig);
84        }
85
86        // Fill signer accounts
87        for (account_view, signer) in acc_views[1..].iter_mut().zip(signers.iter()) {
88            account_view.write(signer);
89        }
90
91        invoke_with_bounds::<{ 1 + MAX_MULTISIG_SIGNERS }>(&instruction, unsafe {
92            slice::from_raw_parts(acc_views.as_ptr() as _, num_accounts)
93        })
94    }
95}