1pub mod args;
2
3pub use args::*;
4
5use wincode::{config::DefaultConfig, SchemaRead, SchemaWrite};
6
7pub trait InstructionArgs: SchemaWrite<DefaultConfig, Src = Self> {
8 const TAG: u8;
9}
10
11pub mod tags {
12 pub const INITIALIZE_PROGRAM: u8 = 0;
13 pub const INITIALIZE_VAULT: u8 = 1;
14 pub const AUTHORIZE_ACTION: u8 = 2;
15 pub const REVOKE_ACTION: u8 = 3;
16 pub const MANAGE: u8 = 4;
17 pub const MANAGE_BATCH: u8 = 5;
18 pub const REPORT_NAV: u8 = 6;
19 pub const DEPOSIT: u8 = 7;
20 pub const REDEEM: u8 = 8;
21 pub const CANCEL_REDEEM: u8 = 9;
22 pub const PROCESS_WITHDRAWALS: u8 = 10;
23 pub const UPDATE_VAULT_CONFIG: u8 = 11;
24 pub const INITIALIZE_ASSET: u8 = 12;
25 pub const UPDATE_ASSET: u8 = 13;
26 pub const SET_PAUSE_FLAGS: u8 = 14;
27 pub const SET_VAULT_ACCESS: u8 = 15;
28 pub const TRANSFER_PROGRAM_AUTHORITY: u8 = 16;
29 pub const TRANSFER_VAULT_AUTHORITY: u8 = 17;
30 pub const SET_STRATEGIST: u8 = 18;
31 pub const SET_NAV_AUTHORITY: u8 = 19;
32 pub const SET_WITHDRAWAL_AUTHORITY: u8 = 20;
33 pub const COLLECT_FEES: u8 = 21;
34 pub const INVEST_EXTERNAL: u8 = 22;
35 pub const RETURN_EXTERNAL: u8 = 23;
36 pub const SET_SWAP_AUTHORITY: u8 = 24;
37 pub const ATOMIC_REDEEM: u8 = 25;
38 pub const SWAP: u8 = 26;
39 pub const WRITE_DOWN_FEES: u8 = 27;
40 pub const REGISTER_EXTERNAL_DESTINATION: u8 = 28;
41 pub const REVOKE_EXTERNAL_DESTINATION: u8 = 29;
42 pub const SET_SHARE_METADATA: u8 = 30;
43 pub const ASSERT_DELEGATE_CLEARED: u8 = 31;
44 pub const ADMIN_SET_FLASH_FEE_RATE: u8 = 32;
45 pub const STRATEGIST_LOWER_FLASH_FEE_RATE: u8 = 33;
46}
47
48#[repr(u8)]
51#[derive(codama_macros::CodamaInstructions)]
52#[allow(clippy::large_enum_variant)]
53#[codama(program(
54 name = "roshi",
55 address = "Roshi11111111111111111111111111111111111111"
56))]
57pub enum RoshiInstruction {
58 #[codama(account(name = "payer", signer, writable))]
59 #[codama(account(name = "program_config", writable))]
60 #[codama(account(name = "system_program", default_value = program("system")))]
61 InitializeProgram(#[codama(name = "args")] InitializeProgramArgs) = 0,
62
63 #[codama(account(name = "program_authority", signer))]
64 #[codama(account(name = "program_config"))]
65 #[codama(account(name = "payer", signer, writable))]
66 #[codama(account(name = "vault", writable))]
67 #[codama(account(name = "base_mint"))]
68 #[codama(account(name = "share_mint", writable))]
69 #[codama(account(name = "treasury"))]
70 #[codama(account(name = "system_program", default_value = program("system")))]
71 #[codama(account(name = "token_program", default_value = program("token")))]
72 InitializeVault(#[codama(name = "args")] InitializeVaultArgs) = 1,
73
74 #[codama(account(name = "admin", signer, writable))]
75 #[codama(account(name = "vault"))]
76 #[codama(account(name = "action", writable))]
77 #[codama(account(name = "system_program", default_value = program("system")))]
78 AuthorizeAction(#[codama(name = "args")] AuthorizeActionArgs) = 2,
79
80 #[codama(account(name = "admin", signer))]
81 #[codama(account(name = "vault"))]
82 #[codama(account(name = "action", writable))]
83 RevokeAction(#[codama(name = "args")] RevokeActionArgs) = 3,
84
85 #[codama(account(name = "executor", signer))]
86 #[codama(account(name = "vault"))]
87 #[codama(account(name = "sub_account", writable))]
88 #[codama(account(name = "action"))]
89 Manage(#[codama(name = "args")] ManageArgs) = 4,
90
91 #[codama(account(name = "executor", signer))]
92 #[codama(account(name = "vault"))]
93 ManageBatch(#[codama(name = "args")] ManageBatchArgs) = 5,
94
95 #[codama(account(name = "nav_authority", signer))]
96 #[codama(account(name = "vault", writable))]
97 #[codama(account(name = "share_mint"))]
98 #[codama(account(name = "base_mint"))]
99 #[codama(account(name = "deposit_base_custody"))]
100 #[codama(account(name = "withdraw_base_custody"))]
101 ReportNav(#[codama(name = "args")] ReportNavArgs) = 6,
102
103 #[codama(account(name = "depositor", signer))]
104 #[codama(account(name = "vault", writable))]
105 #[codama(account(name = "user_source_token_account", writable))]
106 #[codama(account(name = "vault_custody_token_account", writable))]
107 #[codama(account(name = "user_share_account", writable))]
108 #[codama(account(name = "share_mint", writable))]
109 #[codama(account(name = "share_token_program", default_value = program("token")))]
110 #[codama(account(name = "asset_token_program"))]
111 Deposit(#[codama(name = "args")] DepositArgs) = 7,
112
113 #[codama(account(name = "owner", signer, writable))]
114 #[codama(account(name = "vault", writable))]
115 #[codama(account(name = "user_share_account", writable))]
116 #[codama(account(name = "share_mint", writable))]
117 #[codama(account(name = "recipient_token_account"))]
118 #[codama(account(name = "withdrawal_ticket", writable))]
119 #[codama(account(name = "system_program", default_value = program("system")))]
120 #[codama(account(name = "token_program", default_value = program("token")))]
121 Redeem(#[codama(name = "args")] RedeemArgs) = 8,
122
123 #[codama(account(name = "owner", signer, writable))]
124 #[codama(account(name = "vault", writable))]
125 #[codama(account(name = "withdrawal_ticket", writable))]
126 #[codama(account(name = "share_mint", writable))]
127 #[codama(account(name = "owner_share_account", writable))]
128 #[codama(account(name = "token_program", default_value = program("token")))]
129 CancelRedeem(#[codama(name = "args")] CancelRedeemArgs) = 9,
130
131 #[codama(account(name = "withdrawal_authority", signer))]
132 #[codama(account(name = "vault", writable))]
133 #[codama(account(name = "withdraw_sub_account"))]
134 #[codama(account(name = "custody", writable))]
135 #[codama(account(name = "share_mint"))]
136 #[codama(account(name = "token_program", default_value = program("token")))]
137 ProcessWithdrawals = 10,
138
139 #[codama(account(name = "admin", signer))]
140 #[codama(account(name = "vault", writable))]
141 #[codama(account(name = "treasury"))]
142 UpdateVaultConfig(#[codama(name = "args")] UpdateVaultConfigArgs) = 11,
143
144 #[codama(account(name = "admin", signer, writable))]
145 #[codama(account(name = "vault"))]
146 #[codama(account(name = "asset_mint"))]
147 #[codama(account(name = "asset", writable))]
148 #[codama(account(name = "system_program", default_value = program("system")))]
149 InitializeAsset(#[codama(name = "args")] InitializeAssetArgs) = 12,
150
151 #[codama(account(name = "admin", signer))]
152 #[codama(account(name = "vault"))]
153 #[codama(account(name = "asset", writable))]
154 UpdateAsset(#[codama(name = "args")] UpdateAssetArgs) = 13,
155
156 #[codama(account(name = "admin", signer))]
157 #[codama(account(name = "vault", writable))]
158 SetPauseFlags(#[codama(name = "args")] SetPauseFlagsArgs) = 14,
159
160 #[codama(account(name = "admin", signer))]
161 #[codama(account(name = "vault", writable))]
162 SetVaultAccess(#[codama(name = "args")] SetVaultAccessArgs) = 15,
163
164 #[codama(account(name = "authority", signer))]
165 #[codama(account(name = "program_config", writable))]
166 TransferProgramAuthority(#[codama(name = "args")] TransferProgramAuthorityArgs) = 16,
167
168 #[codama(account(name = "admin", signer))]
169 #[codama(account(name = "vault", writable))]
170 TransferVaultAuthority(#[codama(name = "args")] TransferVaultAuthorityArgs) = 17,
171
172 #[codama(account(name = "admin", signer))]
173 #[codama(account(name = "vault", writable))]
174 SetStrategist(#[codama(name = "args")] SetStrategistArgs) = 18,
175
176 #[codama(account(name = "admin", signer))]
177 #[codama(account(name = "vault", writable))]
178 SetNavAuthority(#[codama(name = "args")] SetNavAuthorityArgs) = 19,
179
180 #[codama(account(name = "admin", signer))]
181 #[codama(account(name = "vault", writable))]
182 SetWithdrawalAuthority(#[codama(name = "args")] SetWithdrawalAuthorityArgs) = 20,
183
184 #[codama(account(name = "admin", signer))]
185 #[codama(account(name = "vault", writable))]
186 #[codama(account(name = "fee_sub_account"))]
187 #[codama(account(name = "custody", writable))]
188 #[codama(account(name = "treasury", writable))]
189 #[codama(account(name = "token_program", default_value = program("token")))]
190 CollectFees(#[codama(name = "args")] CollectFeesArgs) = 21,
191
192 #[codama(account(name = "strategist", signer))]
193 #[codama(account(name = "vault", writable))]
194 #[codama(account(name = "sub_account"))]
195 #[codama(account(name = "custody", writable))]
196 #[codama(account(name = "external_account", writable))]
197 #[codama(account(name = "external_destination"))]
198 #[codama(account(name = "token_program", default_value = program("token")))]
199 InvestExternal(#[codama(name = "args")] InvestExternalArgs) = 22,
200
201 #[codama(account(name = "strategist", signer))]
202 #[codama(account(name = "external_authority", signer))]
203 #[codama(account(name = "vault", writable))]
204 #[codama(account(name = "sub_account"))]
205 #[codama(account(name = "external_account", writable))]
206 #[codama(account(name = "custody", writable))]
207 #[codama(account(name = "token_program", default_value = program("token")))]
208 ReturnExternal(#[codama(name = "args")] ReturnExternalArgs) = 23,
209
210 #[codama(account(name = "admin", signer))]
211 #[codama(account(name = "vault", writable))]
212 SetSwapAuthority(#[codama(name = "args")] SetSwapAuthorityArgs) = 24,
213
214 #[codama(account(name = "owner", signer, writable))]
215 #[codama(account(name = "vault", writable))]
216 #[codama(account(name = "user_share_account", writable))]
217 #[codama(account(name = "share_mint", writable))]
218 #[codama(account(name = "recipient_token_account", writable))]
219 #[codama(account(name = "custody", writable))]
220 #[codama(account(name = "base_token_program"))]
221 #[codama(account(name = "sub_account"))]
222 #[codama(account(name = "action"))]
223 #[codama(account(name = "token_program", default_value = program("token")))]
224 AtomicRedeem(#[codama(name = "args")] AtomicRedeemArgs) = 25,
225
226 #[codama(account(name = "swap_authority", signer))]
227 #[codama(account(name = "vault"))]
228 #[codama(account(name = "sub_account"))]
229 #[codama(account(name = "input_custody", writable))]
230 #[codama(account(name = "output_custody", writable))]
231 #[codama(account(name = "action"))]
232 Swap(#[codama(name = "args")] SwapArgs) = 26,
233
234 #[codama(account(name = "admin", signer))]
235 #[codama(account(name = "vault", writable))]
236 WriteDownFees(#[codama(name = "args")] WriteDownFeesArgs) = 27,
237
238 #[codama(account(name = "admin", signer, writable))]
239 #[codama(account(name = "vault"))]
240 #[codama(account(name = "destination_token_account"))]
241 #[codama(account(name = "external_destination", writable))]
242 #[codama(account(name = "system_program", default_value = program("system")))]
243 RegisterExternalDestination = 28,
244
245 #[codama(account(name = "admin", signer, writable))]
246 #[codama(account(name = "vault"))]
247 #[codama(account(name = "external_destination", writable))]
248 RevokeExternalDestination = 29,
249
250 #[codama(account(name = "admin", signer, writable))]
251 #[codama(account(name = "vault"))]
252 #[codama(account(name = "share_mint"))]
253 #[codama(account(name = "metadata", writable))]
254 #[codama(account(name = "token_metadata_program"))]
255 #[codama(account(name = "system_program", default_value = program("system")))]
256 SetShareMetadata(#[codama(name = "args")] SetShareMetadataArgs) = 30,
257
258 #[codama(account(name = "token_account"))]
259 AssertDelegateCleared = 31,
260
261 #[codama(account(name = "admin", signer))]
262 #[codama(account(name = "vault"))]
263 #[codama(account(name = "action", writable))]
264 AdminSetFlashFeeRate(#[codama(name = "args")] AdminSetFlashFeeRateArgs) = 32,
265
266 #[codama(account(name = "strategist", signer))]
267 #[codama(account(name = "vault"))]
268 #[codama(account(name = "action", writable))]
269 StrategistLowerFlashFeeRate(#[codama(name = "args")] StrategistLowerFlashFeeRateArgs) = 33,
270}
271
272impl RoshiInstruction {
273 pub const fn tag(&self) -> u8 {
274 match self {
275 Self::InitializeProgram(_) => tags::INITIALIZE_PROGRAM,
276 Self::InitializeVault(_) => tags::INITIALIZE_VAULT,
277 Self::AuthorizeAction(_) => tags::AUTHORIZE_ACTION,
278 Self::RevokeAction(_) => tags::REVOKE_ACTION,
279 Self::Manage(_) => tags::MANAGE,
280 Self::ManageBatch(_) => tags::MANAGE_BATCH,
281 Self::ReportNav(_) => tags::REPORT_NAV,
282 Self::Deposit(_) => tags::DEPOSIT,
283 Self::Redeem(_) => tags::REDEEM,
284 Self::CancelRedeem(_) => tags::CANCEL_REDEEM,
285 Self::ProcessWithdrawals => tags::PROCESS_WITHDRAWALS,
286 Self::UpdateVaultConfig(_) => tags::UPDATE_VAULT_CONFIG,
287 Self::InitializeAsset(_) => tags::INITIALIZE_ASSET,
288 Self::UpdateAsset(_) => tags::UPDATE_ASSET,
289 Self::InvestExternal(_) => tags::INVEST_EXTERNAL,
290 Self::ReturnExternal(_) => tags::RETURN_EXTERNAL,
291 Self::SetPauseFlags(_) => tags::SET_PAUSE_FLAGS,
292 Self::SetVaultAccess(_) => tags::SET_VAULT_ACCESS,
293 Self::TransferProgramAuthority(_) => tags::TRANSFER_PROGRAM_AUTHORITY,
294 Self::TransferVaultAuthority(_) => tags::TRANSFER_VAULT_AUTHORITY,
295 Self::SetStrategist(_) => tags::SET_STRATEGIST,
296 Self::SetSwapAuthority(_) => tags::SET_SWAP_AUTHORITY,
297 Self::SetNavAuthority(_) => tags::SET_NAV_AUTHORITY,
298 Self::SetWithdrawalAuthority(_) => tags::SET_WITHDRAWAL_AUTHORITY,
299 Self::CollectFees(_) => tags::COLLECT_FEES,
300 Self::AtomicRedeem(_) => tags::ATOMIC_REDEEM,
301 Self::Swap(_) => tags::SWAP,
302 Self::WriteDownFees(_) => tags::WRITE_DOWN_FEES,
303 Self::RegisterExternalDestination => tags::REGISTER_EXTERNAL_DESTINATION,
304 Self::RevokeExternalDestination => tags::REVOKE_EXTERNAL_DESTINATION,
305 Self::SetShareMetadata(_) => tags::SET_SHARE_METADATA,
306 Self::AssertDelegateCleared => tags::ASSERT_DELEGATE_CLEARED,
307 Self::AdminSetFlashFeeRate(_) => tags::ADMIN_SET_FLASH_FEE_RATE,
308 Self::StrategistLowerFlashFeeRate(_) => tags::STRATEGIST_LOWER_FLASH_FEE_RATE,
309 }
310 }
311
312 #[allow(clippy::result_unit_err)]
313 pub fn decode(data: &[u8]) -> Result<Self, ()> {
314 let (tag, payload) = data.split_first().ok_or(())?;
315
316 match *tag {
317 tags::INITIALIZE_PROGRAM => Ok(Self::InitializeProgram(decode_payload(payload)?)),
318 tags::INITIALIZE_VAULT => Ok(Self::InitializeVault(decode_payload(payload)?)),
319 tags::AUTHORIZE_ACTION => Ok(Self::AuthorizeAction(decode_payload(payload)?)),
320 tags::REVOKE_ACTION => Ok(Self::RevokeAction(decode_payload(payload)?)),
321 tags::MANAGE => Ok(Self::Manage(decode_payload(payload)?)),
322 tags::MANAGE_BATCH => Ok(Self::ManageBatch(decode_payload(payload)?)),
323 tags::REPORT_NAV => Ok(Self::ReportNav(decode_payload(payload)?)),
324 tags::DEPOSIT => Ok(Self::Deposit(decode_payload(payload)?)),
325 tags::REDEEM => Ok(Self::Redeem(decode_payload(payload)?)),
326 tags::CANCEL_REDEEM => Ok(Self::CancelRedeem(decode_payload(payload)?)),
327 tags::PROCESS_WITHDRAWALS => {
328 let ProcessWithdrawalsArgs = decode_payload(payload)?;
329 Ok(Self::ProcessWithdrawals)
330 }
331 tags::UPDATE_VAULT_CONFIG => Ok(Self::UpdateVaultConfig(decode_payload(payload)?)),
332 tags::INITIALIZE_ASSET => Ok(Self::InitializeAsset(decode_payload(payload)?)),
333 tags::UPDATE_ASSET => Ok(Self::UpdateAsset(decode_payload(payload)?)),
334 tags::INVEST_EXTERNAL => Ok(Self::InvestExternal(decode_payload(payload)?)),
335 tags::RETURN_EXTERNAL => Ok(Self::ReturnExternal(decode_payload(payload)?)),
336 tags::SET_PAUSE_FLAGS => Ok(Self::SetPauseFlags(decode_payload(payload)?)),
337 tags::SET_VAULT_ACCESS => Ok(Self::SetVaultAccess(decode_payload(payload)?)),
338 tags::TRANSFER_PROGRAM_AUTHORITY => {
339 Ok(Self::TransferProgramAuthority(decode_payload(payload)?))
340 }
341 tags::TRANSFER_VAULT_AUTHORITY => {
342 Ok(Self::TransferVaultAuthority(decode_payload(payload)?))
343 }
344 tags::SET_STRATEGIST => Ok(Self::SetStrategist(decode_payload(payload)?)),
345 tags::SET_SWAP_AUTHORITY => Ok(Self::SetSwapAuthority(decode_payload(payload)?)),
346 tags::SET_NAV_AUTHORITY => Ok(Self::SetNavAuthority(decode_payload(payload)?)),
347 tags::SET_WITHDRAWAL_AUTHORITY => {
348 Ok(Self::SetWithdrawalAuthority(decode_payload(payload)?))
349 }
350 tags::COLLECT_FEES => Ok(Self::CollectFees(decode_payload(payload)?)),
351 tags::ATOMIC_REDEEM => Ok(Self::AtomicRedeem(decode_payload(payload)?)),
352 tags::SWAP => Ok(Self::Swap(decode_payload(payload)?)),
353 tags::WRITE_DOWN_FEES => Ok(Self::WriteDownFees(decode_payload(payload)?)),
354 tags::REGISTER_EXTERNAL_DESTINATION => {
355 let RegisterExternalDestinationArgs = decode_payload(payload)?;
356 Ok(Self::RegisterExternalDestination)
357 }
358 tags::REVOKE_EXTERNAL_DESTINATION => {
359 let RevokeExternalDestinationArgs = decode_payload(payload)?;
360 Ok(Self::RevokeExternalDestination)
361 }
362 tags::SET_SHARE_METADATA => Ok(Self::SetShareMetadata(decode_payload(payload)?)),
363 tags::ASSERT_DELEGATE_CLEARED => {
364 let AssertDelegateClearedArgs = decode_payload(payload)?;
365 Ok(Self::AssertDelegateCleared)
366 }
367 tags::ADMIN_SET_FLASH_FEE_RATE => {
368 Ok(Self::AdminSetFlashFeeRate(decode_payload(payload)?))
369 }
370 tags::STRATEGIST_LOWER_FLASH_FEE_RATE => {
371 Ok(Self::StrategistLowerFlashFeeRate(decode_payload(payload)?))
372 }
373 _ => Err(()),
374 }
375 }
376
377 pub fn serialize(&self) -> Result<Vec<u8>, wincode::WriteError> {
378 let mut data = vec![self.tag()];
379
380 match self {
381 Self::InitializeProgram(args) => wincode::serialize_into(&mut data, args)?,
382 Self::InitializeVault(args) => wincode::serialize_into(&mut data, args)?,
383 Self::AuthorizeAction(args) => wincode::serialize_into(&mut data, args)?,
384 Self::RevokeAction(args) => wincode::serialize_into(&mut data, args)?,
385 Self::Manage(args) => wincode::serialize_into(&mut data, args)?,
386 Self::ManageBatch(args) => wincode::serialize_into(&mut data, args)?,
387 Self::ReportNav(args) => wincode::serialize_into(&mut data, args)?,
388 Self::Deposit(args) => wincode::serialize_into(&mut data, args)?,
389 Self::Redeem(args) => wincode::serialize_into(&mut data, args)?,
390 Self::CancelRedeem(args) => wincode::serialize_into(&mut data, args)?,
391 Self::ProcessWithdrawals => {
392 wincode::serialize_into(&mut data, &ProcessWithdrawalsArgs)?
393 }
394 Self::UpdateVaultConfig(args) => wincode::serialize_into(&mut data, args)?,
395 Self::InitializeAsset(args) => wincode::serialize_into(&mut data, args)?,
396 Self::UpdateAsset(args) => wincode::serialize_into(&mut data, args)?,
397 Self::InvestExternal(args) => wincode::serialize_into(&mut data, args)?,
398 Self::ReturnExternal(args) => wincode::serialize_into(&mut data, args)?,
399 Self::SetPauseFlags(args) => wincode::serialize_into(&mut data, args)?,
400 Self::SetVaultAccess(args) => wincode::serialize_into(&mut data, args)?,
401 Self::TransferProgramAuthority(args) => wincode::serialize_into(&mut data, args)?,
402 Self::TransferVaultAuthority(args) => wincode::serialize_into(&mut data, args)?,
403 Self::SetStrategist(args) => wincode::serialize_into(&mut data, args)?,
404 Self::SetSwapAuthority(args) => wincode::serialize_into(&mut data, args)?,
405 Self::SetNavAuthority(args) => wincode::serialize_into(&mut data, args)?,
406 Self::SetWithdrawalAuthority(args) => wincode::serialize_into(&mut data, args)?,
407 Self::CollectFees(args) => wincode::serialize_into(&mut data, args)?,
408 Self::AtomicRedeem(args) => wincode::serialize_into(&mut data, args)?,
409 Self::Swap(args) => wincode::serialize_into(&mut data, args)?,
410 Self::WriteDownFees(args) => wincode::serialize_into(&mut data, args)?,
411 Self::RegisterExternalDestination => {
412 wincode::serialize_into(&mut data, &RegisterExternalDestinationArgs)?
413 }
414 Self::RevokeExternalDestination => {
415 wincode::serialize_into(&mut data, &RevokeExternalDestinationArgs)?
416 }
417 Self::SetShareMetadata(args) => wincode::serialize_into(&mut data, args)?,
418 Self::AssertDelegateCleared => {
419 wincode::serialize_into(&mut data, &AssertDelegateClearedArgs)?
420 }
421 Self::AdminSetFlashFeeRate(args) => wincode::serialize_into(&mut data, args)?,
422 Self::StrategistLowerFlashFeeRate(args) => wincode::serialize_into(&mut data, args)?,
423 }
424
425 Ok(data)
426 }
427}
428
429fn decode_payload<'a, T>(payload: &'a [u8]) -> Result<T, ()>
430where
431 T: SchemaRead<'a, DefaultConfig, Dst = T>,
432{
433 wincode::deserialize_exact(payload).map_err(|_| ())
434}
435
436macro_rules! impl_instruction_args {
437 ($( $args:ty = $tag:expr ),+ $(,)?) => {
438 $(
439 impl InstructionArgs for $args {
440 const TAG: u8 = $tag;
441 }
442 )+
443
444 #[cfg(test)]
445 const TAG_CASES: &[u8] = &[
446 $(
447 $tag,
448 )+
449 ];
450 };
451}
452
453impl_instruction_args! {
454 InitializeProgramArgs = tags::INITIALIZE_PROGRAM,
455 InitializeVaultArgs = tags::INITIALIZE_VAULT,
456 AuthorizeActionArgs = tags::AUTHORIZE_ACTION,
457 RevokeActionArgs = tags::REVOKE_ACTION,
458 ManageArgs = tags::MANAGE,
459 ManageBatchArgs = tags::MANAGE_BATCH,
460 ReportNavArgs = tags::REPORT_NAV,
461 DepositArgs = tags::DEPOSIT,
462 RedeemArgs = tags::REDEEM,
463 CancelRedeemArgs = tags::CANCEL_REDEEM,
464 ProcessWithdrawalsArgs = tags::PROCESS_WITHDRAWALS,
465 UpdateVaultConfigArgs = tags::UPDATE_VAULT_CONFIG,
466 InitializeAssetArgs = tags::INITIALIZE_ASSET,
467 UpdateAssetArgs = tags::UPDATE_ASSET,
468 SetPauseFlagsArgs = tags::SET_PAUSE_FLAGS,
469 SetVaultAccessArgs = tags::SET_VAULT_ACCESS,
470 TransferProgramAuthorityArgs = tags::TRANSFER_PROGRAM_AUTHORITY,
471 TransferVaultAuthorityArgs = tags::TRANSFER_VAULT_AUTHORITY,
472 SetStrategistArgs = tags::SET_STRATEGIST,
473 SetNavAuthorityArgs = tags::SET_NAV_AUTHORITY,
474 SetWithdrawalAuthorityArgs = tags::SET_WITHDRAWAL_AUTHORITY,
475 CollectFeesArgs = tags::COLLECT_FEES,
476 InvestExternalArgs = tags::INVEST_EXTERNAL,
477 ReturnExternalArgs = tags::RETURN_EXTERNAL,
478 SetSwapAuthorityArgs = tags::SET_SWAP_AUTHORITY,
479 AtomicRedeemArgs = tags::ATOMIC_REDEEM,
480 SwapArgs = tags::SWAP,
481 WriteDownFeesArgs = tags::WRITE_DOWN_FEES,
482 RegisterExternalDestinationArgs = tags::REGISTER_EXTERNAL_DESTINATION,
483 RevokeExternalDestinationArgs = tags::REVOKE_EXTERNAL_DESTINATION,
484 SetShareMetadataArgs = tags::SET_SHARE_METADATA,
485 AssertDelegateClearedArgs = tags::ASSERT_DELEGATE_CLEARED,
486 AdminSetFlashFeeRateArgs = tags::ADMIN_SET_FLASH_FEE_RATE,
487 StrategistLowerFlashFeeRateArgs = tags::STRATEGIST_LOWER_FLASH_FEE_RATE,
488}
489
490pub fn serialize_instruction<T>(args: &T) -> Result<Vec<u8>, wincode::WriteError>
491where
492 T: InstructionArgs,
493{
494 let mut data = vec![T::TAG];
495 wincode::serialize_into(&mut data, args)?;
496 Ok(data)
497}
498
499#[cfg(test)]
500mod tests {
501 use super::*;
502 use codama::{Codama, NodeTrait};
503 use serde_json::Value;
504 use std::path::Path;
505 use wincode::deserialize_exact;
506
507 #[test]
508 fn instruction_args_tags_match_canonical_tags() {
509 assert_eq!(
510 TAG_CASES,
511 &[
512 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
513 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33
514 ]
515 );
516 assert_eq!(
517 RoshiInstruction::ProcessWithdrawals.tag(),
518 <ProcessWithdrawalsArgs as InstructionArgs>::TAG
519 );
520 }
521
522 #[test]
523 fn codama_idl_uses_canonical_instruction_discriminators() {
524 let mut idl = Codama::load(Path::new(env!("CARGO_MANIFEST_DIR")))
525 .unwrap()
526 .get_idl()
527 .unwrap();
528 idl.program.name = "roshi".into();
529 let idl: Value = serde_json::from_str(&idl.to_json().unwrap()).unwrap();
530 let instructions = idl["program"]["instructions"].as_array().unwrap();
531
532 assert_eq!(idl["program"]["name"], "roshi");
533 assert_eq!(
534 idl["program"]["publicKey"],
535 "Roshi11111111111111111111111111111111111111"
536 );
537 assert_eq!(instructions.len(), TAG_CASES.len());
538
539 for (name, tag) in IDL_TAG_CASES {
540 assert_instruction_discriminator(instructions, name, *tag);
541 }
542
543 let deposit = instruction(instructions, "deposit");
544 assert_eq!(deposit["arguments"][1]["name"], "args");
545 assert_eq!(deposit["arguments"][1]["type"]["name"], "depositArgs");
546
547 let process_withdrawals = instruction(instructions, "processWithdrawals");
548 assert_eq!(
549 process_withdrawals["arguments"].as_array().unwrap().len(),
550 1
551 );
552 }
553
554 #[test]
555 fn instruction_decode_rejects_unknown_values() {
556 assert!(RoshiInstruction::decode(&[255]).is_err());
557 }
558
559 #[test]
560 fn serialize_instruction_writes_tag_then_args_payload() {
561 let args = DepositArgs {
562 asset_mint: [4; 32],
563 amount: 123,
564 min_shares_out: 456,
565 access_proof: vec![[1; 32], [2; 32], [3; 32]],
566 };
567
568 let encoded = serialize_instruction(&args).unwrap();
569 let decoded: DepositArgs = deserialize_exact(&encoded[1..]).unwrap();
570
571 assert_eq!(encoded[0], <DepositArgs as InstructionArgs>::TAG);
572 assert_eq!(decoded.asset_mint, [4; 32]);
573 assert_eq!(decoded.amount, 123);
574 assert_eq!(decoded.min_shares_out, 456);
575 assert_eq!(decoded.access_proof, vec![[1; 32], [2; 32], [3; 32]]);
576 }
577
578 #[test]
579 fn canonical_instruction_serializes_like_args_helper() {
580 let args = DepositArgs {
581 asset_mint: [4; 32],
582 amount: 123,
583 min_shares_out: 456,
584 access_proof: vec![[1; 32]],
585 };
586
587 assert_eq!(
588 RoshiInstruction::Deposit(args).serialize().unwrap(),
589 serialize_instruction(&DepositArgs {
590 asset_mint: [4; 32],
591 amount: 123,
592 min_shares_out: 456,
593 access_proof: vec![[1; 32]],
594 })
595 .unwrap()
596 );
597 }
598
599 #[test]
600 fn serialize_zero_sized_args_writes_only_tag() {
601 assert_eq!(
602 serialize_instruction(&ProcessWithdrawalsArgs).unwrap(),
603 vec![<ProcessWithdrawalsArgs as InstructionArgs>::TAG]
604 );
605 assert_eq!(
606 RoshiInstruction::ProcessWithdrawals.serialize().unwrap(),
607 vec![<ProcessWithdrawalsArgs as InstructionArgs>::TAG]
608 );
609 }
610
611 fn instruction<'a>(instructions: &'a [Value], name: &str) -> &'a Value {
612 instructions
613 .iter()
614 .find(|instruction| instruction["name"] == name)
615 .unwrap()
616 }
617
618 fn assert_instruction_discriminator(instructions: &[Value], name: &str, tag: u8) {
619 assert_eq!(
620 instruction(instructions, name)["arguments"][0]["defaultValue"]["number"],
621 u64::from(tag)
622 );
623 }
624
625 const IDL_TAG_CASES: &[(&str, u8)] = &[
626 ("initializeProgram", tags::INITIALIZE_PROGRAM),
627 ("initializeVault", tags::INITIALIZE_VAULT),
628 ("authorizeAction", tags::AUTHORIZE_ACTION),
629 ("revokeAction", tags::REVOKE_ACTION),
630 ("manage", tags::MANAGE),
631 ("manageBatch", tags::MANAGE_BATCH),
632 ("reportNav", tags::REPORT_NAV),
633 ("deposit", tags::DEPOSIT),
634 ("redeem", tags::REDEEM),
635 ("cancelRedeem", tags::CANCEL_REDEEM),
636 ("processWithdrawals", tags::PROCESS_WITHDRAWALS),
637 ("updateVaultConfig", tags::UPDATE_VAULT_CONFIG),
638 ("initializeAsset", tags::INITIALIZE_ASSET),
639 ("updateAsset", tags::UPDATE_ASSET),
640 ("setPauseFlags", tags::SET_PAUSE_FLAGS),
641 ("setVaultAccess", tags::SET_VAULT_ACCESS),
642 ("transferProgramAuthority", tags::TRANSFER_PROGRAM_AUTHORITY),
643 ("transferVaultAuthority", tags::TRANSFER_VAULT_AUTHORITY),
644 ("setStrategist", tags::SET_STRATEGIST),
645 ("setNavAuthority", tags::SET_NAV_AUTHORITY),
646 ("setWithdrawalAuthority", tags::SET_WITHDRAWAL_AUTHORITY),
647 ("collectFees", tags::COLLECT_FEES),
648 ("investExternal", tags::INVEST_EXTERNAL),
649 ("returnExternal", tags::RETURN_EXTERNAL),
650 ("setSwapAuthority", tags::SET_SWAP_AUTHORITY),
651 ("atomicRedeem", tags::ATOMIC_REDEEM),
652 ("swap", tags::SWAP),
653 ("writeDownFees", tags::WRITE_DOWN_FEES),
654 (
655 "registerExternalDestination",
656 tags::REGISTER_EXTERNAL_DESTINATION,
657 ),
658 (
659 "revokeExternalDestination",
660 tags::REVOKE_EXTERNAL_DESTINATION,
661 ),
662 ("setShareMetadata", tags::SET_SHARE_METADATA),
663 ("assertDelegateCleared", tags::ASSERT_DELEGATE_CLEARED),
664 ("adminSetFlashFeeRate", tags::ADMIN_SET_FLASH_FEE_RATE),
665 (
666 "strategistLowerFlashFeeRate",
667 tags::STRATEGIST_LOWER_FLASH_FEE_RATE,
668 ),
669 ];
670}