pinocchio_token/instructions/
initialize_multisig_2.rs1use {
2 crate::{
3 instructions::{
4 account_borrow_failed_error, invalid_argument_error, CpiWriter, MAX_MULTISIG_SIGNERS,
5 },
6 UNINIT_BYTE, UNINIT_CPI_ACCOUNT, UNINIT_INSTRUCTION_ACCOUNT,
7 },
8 core::{mem::MaybeUninit, slice::from_raw_parts},
9 solana_account_view::AccountView,
10 solana_instruction_view::{
11 cpi::{invoke_unchecked, CpiAccount},
12 InstructionAccount, InstructionView,
13 },
14 solana_program_error::{ProgramError, ProgramResult},
15};
16
17pub struct InitializeMultisig2<'account, 'multisig, MultisigSigner: AsRef<AccountView>>
26where
27 'account: 'multisig,
28{
29 pub multisig: &'account AccountView,
31
32 pub multisig_signers: &'multisig [MultisigSigner],
34
35 pub m: u8,
38}
39
40impl<'account, 'multisig, MultisigSigner: AsRef<AccountView>>
41 InitializeMultisig2<'account, 'multisig, MultisigSigner>
42where
43 'account: 'multisig,
44{
45 pub const DISCRIMINATOR: u8 = 19;
46
47 pub const MAX_ACCOUNTS_LEN: usize = 1 + MAX_MULTISIG_SIGNERS;
53
54 pub const DATA_LEN: usize = 2;
58
59 #[inline(always)]
60 pub fn new(
61 multisig: &'account AccountView,
62 multisig_signers: &'multisig [MultisigSigner],
63 m: u8,
64 ) -> Self {
65 Self {
66 multisig,
67 multisig_signers,
68 m,
69 }
70 }
71
72 #[inline(always)]
73 pub fn invoke(&self) -> ProgramResult {
74 if self.multisig_signers.len() > MAX_MULTISIG_SIGNERS {
75 return Err(ProgramError::InvalidArgument);
76 }
77
78 let mut instruction_accounts =
79 [UNINIT_INSTRUCTION_ACCOUNT; InitializeMultisig2::<&AccountView>::MAX_ACCOUNTS_LEN];
80 let written_instruction_accounts =
81 self.write_instruction_accounts(&mut instruction_accounts)?;
82
83 let mut accounts =
84 [UNINIT_CPI_ACCOUNT; InitializeMultisig2::<&AccountView>::MAX_ACCOUNTS_LEN];
85 let written_accounts = self.write_accounts(&mut accounts)?;
86
87 let mut instruction_data = [UNINIT_BYTE; InitializeMultisig2::<&AccountView>::DATA_LEN];
88 let written_instruction_data = self.write_instruction_data(&mut instruction_data)?;
89
90 unsafe {
91 invoke_unchecked(
92 &InstructionView {
93 program_id: &crate::ID,
94 accounts: from_raw_parts(
95 instruction_accounts.as_ptr() as _,
96 written_instruction_accounts,
97 ),
98 data: from_raw_parts(instruction_data.as_ptr() as _, written_instruction_data),
99 },
100 from_raw_parts(accounts.as_ptr() as _, written_accounts),
101 );
102 }
103
104 Ok(())
105 }
106}
107
108impl<MultisigSigner: AsRef<AccountView>> CpiWriter for InitializeMultisig2<'_, '_, MultisigSigner> {
109 #[inline(always)]
110 fn write_accounts<'cpi>(
111 &self,
112 accounts: &mut [MaybeUninit<CpiAccount<'cpi>>],
113 ) -> Result<usize, ProgramError>
114 where
115 Self: 'cpi,
116 {
117 write_accounts(self.multisig, self.multisig_signers, accounts)
118 }
119
120 #[inline(always)]
121 fn write_instruction_accounts<'cpi>(
122 &self,
123 accounts: &mut [MaybeUninit<InstructionAccount<'cpi>>],
124 ) -> Result<usize, ProgramError>
125 where
126 Self: 'cpi,
127 {
128 write_instruction_accounts(self.multisig, self.multisig_signers, accounts)
129 }
130
131 #[inline(always)]
132 fn write_instruction_data(&self, data: &mut [MaybeUninit<u8>]) -> Result<usize, ProgramError> {
133 write_instruction_data(self.m, data)
134 }
135}
136
137impl<MultisigSigner: AsRef<AccountView>> super::IntoBatch
138 for InitializeMultisig2<'_, '_, MultisigSigner>
139{
140 #[inline(always)]
141 fn into_batch<'account, 'state>(
142 self,
143 batch: &mut super::Batch<'account, 'state>,
144 ) -> ProgramResult
145 where
146 Self: 'account + 'state,
147 {
148 batch.push(
149 |accounts| write_accounts(self.multisig, self.multisig_signers, accounts),
150 |accounts| write_instruction_accounts(self.multisig, self.multisig_signers, accounts),
151 |data| write_instruction_data(self.m, data),
152 )
153 }
154}
155
156#[inline(always)]
157fn write_accounts<'account, 'multisig, 'out, MultisigSigner: AsRef<AccountView>>(
158 multisig: &'account AccountView,
159 multisig_signers: &'multisig [MultisigSigner],
160 accounts: &mut [MaybeUninit<CpiAccount<'out>>],
161) -> Result<usize, ProgramError>
162where
163 'account: 'out,
164 'multisig: 'out,
165{
166 let expected_accounts = 1 + multisig_signers.len();
167
168 if expected_accounts > accounts.len() {
169 return Err(invalid_argument_error());
170 }
171
172 if multisig.is_borrowed() {
173 return Err(account_borrow_failed_error());
174 }
175
176 CpiAccount::init_from_account_view(multisig, &mut accounts[0]);
177
178 for (account, signer) in accounts[1..expected_accounts]
179 .iter_mut()
180 .zip(multisig_signers.iter())
181 {
182 CpiAccount::init_from_account_view(signer.as_ref(), account);
183 }
184
185 Ok(expected_accounts)
186}
187
188#[inline(always)]
189fn write_instruction_accounts<'account, 'multisig, 'out, MultisigSigner: AsRef<AccountView>>(
190 multisig: &'account AccountView,
191 multisig_signers: &'multisig [MultisigSigner],
192 accounts: &mut [MaybeUninit<InstructionAccount<'out>>],
193) -> Result<usize, ProgramError>
194where
195 'account: 'out,
196 'multisig: 'out,
197{
198 let expected_accounts = 1 + multisig_signers.len();
199
200 if expected_accounts > accounts.len() {
201 return Err(invalid_argument_error());
202 }
203
204 accounts[0].write(InstructionAccount::writable(multisig.address()));
205
206 for (account, signer) in accounts[1..expected_accounts]
207 .iter_mut()
208 .zip(multisig_signers.iter())
209 {
210 account.write(InstructionAccount::readonly(signer.as_ref().address()));
211 }
212
213 Ok(expected_accounts)
214}
215
216#[inline(always)]
217fn write_instruction_data(m: u8, data: &mut [MaybeUninit<u8>]) -> Result<usize, ProgramError> {
218 if data.len() < InitializeMultisig2::<&AccountView>::DATA_LEN {
219 return Err(invalid_argument_error());
220 }
221
222 data[0].write(InitializeMultisig2::<&AccountView>::DISCRIMINATOR);
223
224 data[1].write(m);
225
226 Ok(InitializeMultisig2::<&AccountView>::DATA_LEN)
227}