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 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 = "owner", signer, writable))]
212 #[codama(account(name = "vault", writable))]
213 #[codama(account(name = "user_share_account", writable))]
214 #[codama(account(name = "share_mint", writable))]
215 #[codama(account(name = "recipient_token_account", writable))]
216 #[codama(account(name = "custody", writable))]
217 #[codama(account(name = "base_token_program"))]
218 #[codama(account(name = "sub_account"))]
219 #[codama(account(name = "action"))]
220 #[codama(account(name = "token_program", default_value = program("token")))]
221 AtomicRedeem(#[codama(name = "args")] AtomicRedeemArgs) = 25,
222
223 #[codama(account(name = "strategist", signer))]
224 #[codama(account(name = "vault"))]
225 #[codama(account(name = "sub_account"))]
226 #[codama(account(name = "input_custody", writable))]
227 #[codama(account(name = "output_custody", writable))]
228 #[codama(account(name = "action"))]
229 Swap(#[codama(name = "args")] SwapArgs) = 26,
230
231 #[codama(account(name = "admin", signer))]
232 #[codama(account(name = "vault", writable))]
233 WriteDownFees(#[codama(name = "args")] WriteDownFeesArgs) = 27,
234
235 #[codama(account(name = "admin", signer, writable))]
236 #[codama(account(name = "vault"))]
237 #[codama(account(name = "destination_token_account"))]
238 #[codama(account(name = "external_destination", writable))]
239 #[codama(account(name = "system_program", default_value = program("system")))]
240 RegisterExternalDestination = 28,
241
242 #[codama(account(name = "admin", signer, writable))]
243 #[codama(account(name = "vault"))]
244 #[codama(account(name = "external_destination", writable))]
245 RevokeExternalDestination = 29,
246
247 #[codama(account(name = "admin", signer, writable))]
248 #[codama(account(name = "vault"))]
249 #[codama(account(name = "share_mint"))]
250 #[codama(account(name = "metadata", writable))]
251 #[codama(account(name = "token_metadata_program"))]
252 #[codama(account(name = "system_program", default_value = program("system")))]
253 SetShareMetadata(#[codama(name = "args")] SetShareMetadataArgs) = 30,
254
255 #[codama(account(name = "token_account"))]
256 AssertDelegateCleared = 31,
257
258 #[codama(account(name = "admin", signer))]
259 #[codama(account(name = "vault"))]
260 #[codama(account(name = "action", writable))]
261 AdminSetFlashFeeRate(#[codama(name = "args")] AdminSetFlashFeeRateArgs) = 32,
262
263 #[codama(account(name = "strategist", signer))]
264 #[codama(account(name = "vault"))]
265 #[codama(account(name = "action", writable))]
266 StrategistLowerFlashFeeRate(#[codama(name = "args")] StrategistLowerFlashFeeRateArgs) = 33,
267}
268
269impl RoshiInstruction {
270 pub const fn tag(&self) -> u8 {
271 match self {
272 Self::InitializeProgram(_) => tags::INITIALIZE_PROGRAM,
273 Self::InitializeVault(_) => tags::INITIALIZE_VAULT,
274 Self::AuthorizeAction(_) => tags::AUTHORIZE_ACTION,
275 Self::RevokeAction(_) => tags::REVOKE_ACTION,
276 Self::Manage(_) => tags::MANAGE,
277 Self::ManageBatch(_) => tags::MANAGE_BATCH,
278 Self::ReportNav(_) => tags::REPORT_NAV,
279 Self::Deposit(_) => tags::DEPOSIT,
280 Self::Redeem(_) => tags::REDEEM,
281 Self::CancelRedeem(_) => tags::CANCEL_REDEEM,
282 Self::ProcessWithdrawals => tags::PROCESS_WITHDRAWALS,
283 Self::UpdateVaultConfig(_) => tags::UPDATE_VAULT_CONFIG,
284 Self::InitializeAsset(_) => tags::INITIALIZE_ASSET,
285 Self::UpdateAsset(_) => tags::UPDATE_ASSET,
286 Self::InvestExternal(_) => tags::INVEST_EXTERNAL,
287 Self::ReturnExternal(_) => tags::RETURN_EXTERNAL,
288 Self::SetPauseFlags(_) => tags::SET_PAUSE_FLAGS,
289 Self::SetVaultAccess(_) => tags::SET_VAULT_ACCESS,
290 Self::TransferProgramAuthority(_) => tags::TRANSFER_PROGRAM_AUTHORITY,
291 Self::TransferVaultAuthority(_) => tags::TRANSFER_VAULT_AUTHORITY,
292 Self::SetStrategist(_) => tags::SET_STRATEGIST,
293 Self::SetNavAuthority(_) => tags::SET_NAV_AUTHORITY,
294 Self::SetWithdrawalAuthority(_) => tags::SET_WITHDRAWAL_AUTHORITY,
295 Self::CollectFees(_) => tags::COLLECT_FEES,
296 Self::AtomicRedeem(_) => tags::ATOMIC_REDEEM,
297 Self::Swap(_) => tags::SWAP,
298 Self::WriteDownFees(_) => tags::WRITE_DOWN_FEES,
299 Self::RegisterExternalDestination => tags::REGISTER_EXTERNAL_DESTINATION,
300 Self::RevokeExternalDestination => tags::REVOKE_EXTERNAL_DESTINATION,
301 Self::SetShareMetadata(_) => tags::SET_SHARE_METADATA,
302 Self::AssertDelegateCleared => tags::ASSERT_DELEGATE_CLEARED,
303 Self::AdminSetFlashFeeRate(_) => tags::ADMIN_SET_FLASH_FEE_RATE,
304 Self::StrategistLowerFlashFeeRate(_) => tags::STRATEGIST_LOWER_FLASH_FEE_RATE,
305 }
306 }
307
308 #[allow(clippy::result_unit_err)]
309 pub fn decode(data: &[u8]) -> Result<Self, ()> {
310 let (tag, payload) = data.split_first().ok_or(())?;
311
312 match *tag {
313 tags::INITIALIZE_PROGRAM => Ok(Self::InitializeProgram(decode_payload(payload)?)),
314 tags::INITIALIZE_VAULT => Ok(Self::InitializeVault(decode_payload(payload)?)),
315 tags::AUTHORIZE_ACTION => Ok(Self::AuthorizeAction(decode_payload(payload)?)),
316 tags::REVOKE_ACTION => Ok(Self::RevokeAction(decode_payload(payload)?)),
317 tags::MANAGE => Ok(Self::Manage(decode_payload(payload)?)),
318 tags::MANAGE_BATCH => Ok(Self::ManageBatch(decode_payload(payload)?)),
319 tags::REPORT_NAV => Ok(Self::ReportNav(decode_payload(payload)?)),
320 tags::DEPOSIT => Ok(Self::Deposit(decode_payload(payload)?)),
321 tags::REDEEM => Ok(Self::Redeem(decode_payload(payload)?)),
322 tags::CANCEL_REDEEM => Ok(Self::CancelRedeem(decode_payload(payload)?)),
323 tags::PROCESS_WITHDRAWALS => {
324 let ProcessWithdrawalsArgs = decode_payload(payload)?;
325 Ok(Self::ProcessWithdrawals)
326 }
327 tags::UPDATE_VAULT_CONFIG => Ok(Self::UpdateVaultConfig(decode_payload(payload)?)),
328 tags::INITIALIZE_ASSET => Ok(Self::InitializeAsset(decode_payload(payload)?)),
329 tags::UPDATE_ASSET => Ok(Self::UpdateAsset(decode_payload(payload)?)),
330 tags::INVEST_EXTERNAL => Ok(Self::InvestExternal(decode_payload(payload)?)),
331 tags::RETURN_EXTERNAL => Ok(Self::ReturnExternal(decode_payload(payload)?)),
332 tags::SET_PAUSE_FLAGS => Ok(Self::SetPauseFlags(decode_payload(payload)?)),
333 tags::SET_VAULT_ACCESS => Ok(Self::SetVaultAccess(decode_payload(payload)?)),
334 tags::TRANSFER_PROGRAM_AUTHORITY => {
335 Ok(Self::TransferProgramAuthority(decode_payload(payload)?))
336 }
337 tags::TRANSFER_VAULT_AUTHORITY => {
338 Ok(Self::TransferVaultAuthority(decode_payload(payload)?))
339 }
340 tags::SET_STRATEGIST => Ok(Self::SetStrategist(decode_payload(payload)?)),
341 tags::SET_NAV_AUTHORITY => Ok(Self::SetNavAuthority(decode_payload(payload)?)),
342 tags::SET_WITHDRAWAL_AUTHORITY => {
343 Ok(Self::SetWithdrawalAuthority(decode_payload(payload)?))
344 }
345 tags::COLLECT_FEES => Ok(Self::CollectFees(decode_payload(payload)?)),
346 tags::ATOMIC_REDEEM => Ok(Self::AtomicRedeem(decode_payload(payload)?)),
347 tags::SWAP => Ok(Self::Swap(decode_payload(payload)?)),
348 tags::WRITE_DOWN_FEES => Ok(Self::WriteDownFees(decode_payload(payload)?)),
349 tags::REGISTER_EXTERNAL_DESTINATION => {
350 let RegisterExternalDestinationArgs = decode_payload(payload)?;
351 Ok(Self::RegisterExternalDestination)
352 }
353 tags::REVOKE_EXTERNAL_DESTINATION => {
354 let RevokeExternalDestinationArgs = decode_payload(payload)?;
355 Ok(Self::RevokeExternalDestination)
356 }
357 tags::SET_SHARE_METADATA => Ok(Self::SetShareMetadata(decode_payload(payload)?)),
358 tags::ASSERT_DELEGATE_CLEARED => {
359 let AssertDelegateClearedArgs = decode_payload(payload)?;
360 Ok(Self::AssertDelegateCleared)
361 }
362 tags::ADMIN_SET_FLASH_FEE_RATE => {
363 Ok(Self::AdminSetFlashFeeRate(decode_payload(payload)?))
364 }
365 tags::STRATEGIST_LOWER_FLASH_FEE_RATE => {
366 Ok(Self::StrategistLowerFlashFeeRate(decode_payload(payload)?))
367 }
368 _ => Err(()),
369 }
370 }
371
372 pub fn serialize(&self) -> Result<Vec<u8>, wincode::WriteError> {
373 let mut data = vec![self.tag()];
374
375 match self {
376 Self::InitializeProgram(args) => wincode::serialize_into(&mut data, args)?,
377 Self::InitializeVault(args) => wincode::serialize_into(&mut data, args)?,
378 Self::AuthorizeAction(args) => wincode::serialize_into(&mut data, args)?,
379 Self::RevokeAction(args) => wincode::serialize_into(&mut data, args)?,
380 Self::Manage(args) => wincode::serialize_into(&mut data, args)?,
381 Self::ManageBatch(args) => wincode::serialize_into(&mut data, args)?,
382 Self::ReportNav(args) => wincode::serialize_into(&mut data, args)?,
383 Self::Deposit(args) => wincode::serialize_into(&mut data, args)?,
384 Self::Redeem(args) => wincode::serialize_into(&mut data, args)?,
385 Self::CancelRedeem(args) => wincode::serialize_into(&mut data, args)?,
386 Self::ProcessWithdrawals => {
387 wincode::serialize_into(&mut data, &ProcessWithdrawalsArgs)?
388 }
389 Self::UpdateVaultConfig(args) => wincode::serialize_into(&mut data, args)?,
390 Self::InitializeAsset(args) => wincode::serialize_into(&mut data, args)?,
391 Self::UpdateAsset(args) => wincode::serialize_into(&mut data, args)?,
392 Self::InvestExternal(args) => wincode::serialize_into(&mut data, args)?,
393 Self::ReturnExternal(args) => wincode::serialize_into(&mut data, args)?,
394 Self::SetPauseFlags(args) => wincode::serialize_into(&mut data, args)?,
395 Self::SetVaultAccess(args) => wincode::serialize_into(&mut data, args)?,
396 Self::TransferProgramAuthority(args) => wincode::serialize_into(&mut data, args)?,
397 Self::TransferVaultAuthority(args) => wincode::serialize_into(&mut data, args)?,
398 Self::SetStrategist(args) => wincode::serialize_into(&mut data, args)?,
399 Self::SetNavAuthority(args) => wincode::serialize_into(&mut data, args)?,
400 Self::SetWithdrawalAuthority(args) => wincode::serialize_into(&mut data, args)?,
401 Self::CollectFees(args) => wincode::serialize_into(&mut data, args)?,
402 Self::AtomicRedeem(args) => wincode::serialize_into(&mut data, args)?,
403 Self::Swap(args) => wincode::serialize_into(&mut data, args)?,
404 Self::WriteDownFees(args) => wincode::serialize_into(&mut data, args)?,
405 Self::RegisterExternalDestination => {
406 wincode::serialize_into(&mut data, &RegisterExternalDestinationArgs)?
407 }
408 Self::RevokeExternalDestination => {
409 wincode::serialize_into(&mut data, &RevokeExternalDestinationArgs)?
410 }
411 Self::SetShareMetadata(args) => wincode::serialize_into(&mut data, args)?,
412 Self::AssertDelegateCleared => {
413 wincode::serialize_into(&mut data, &AssertDelegateClearedArgs)?
414 }
415 Self::AdminSetFlashFeeRate(args) => wincode::serialize_into(&mut data, args)?,
416 Self::StrategistLowerFlashFeeRate(args) => wincode::serialize_into(&mut data, args)?,
417 }
418
419 Ok(data)
420 }
421}
422
423fn decode_payload<'a, T>(payload: &'a [u8]) -> Result<T, ()>
424where
425 T: SchemaRead<'a, DefaultConfig, Dst = T>,
426{
427 wincode::deserialize_exact(payload).map_err(|_| ())
428}
429
430macro_rules! impl_instruction_args {
431 ($( $args:ty = $tag:expr ),+ $(,)?) => {
432 $(
433 impl InstructionArgs for $args {
434 const TAG: u8 = $tag;
435 }
436 )+
437
438 #[cfg(test)]
439 const TAG_CASES: &[u8] = &[
440 $(
441 $tag,
442 )+
443 ];
444 };
445}
446
447impl_instruction_args! {
448 InitializeProgramArgs = tags::INITIALIZE_PROGRAM,
449 InitializeVaultArgs = tags::INITIALIZE_VAULT,
450 AuthorizeActionArgs = tags::AUTHORIZE_ACTION,
451 RevokeActionArgs = tags::REVOKE_ACTION,
452 ManageArgs = tags::MANAGE,
453 ManageBatchArgs = tags::MANAGE_BATCH,
454 ReportNavArgs = tags::REPORT_NAV,
455 DepositArgs = tags::DEPOSIT,
456 RedeemArgs = tags::REDEEM,
457 CancelRedeemArgs = tags::CANCEL_REDEEM,
458 ProcessWithdrawalsArgs = tags::PROCESS_WITHDRAWALS,
459 UpdateVaultConfigArgs = tags::UPDATE_VAULT_CONFIG,
460 InitializeAssetArgs = tags::INITIALIZE_ASSET,
461 UpdateAssetArgs = tags::UPDATE_ASSET,
462 SetPauseFlagsArgs = tags::SET_PAUSE_FLAGS,
463 SetVaultAccessArgs = tags::SET_VAULT_ACCESS,
464 TransferProgramAuthorityArgs = tags::TRANSFER_PROGRAM_AUTHORITY,
465 TransferVaultAuthorityArgs = tags::TRANSFER_VAULT_AUTHORITY,
466 SetStrategistArgs = tags::SET_STRATEGIST,
467 SetNavAuthorityArgs = tags::SET_NAV_AUTHORITY,
468 SetWithdrawalAuthorityArgs = tags::SET_WITHDRAWAL_AUTHORITY,
469 CollectFeesArgs = tags::COLLECT_FEES,
470 InvestExternalArgs = tags::INVEST_EXTERNAL,
471 ReturnExternalArgs = tags::RETURN_EXTERNAL,
472 AtomicRedeemArgs = tags::ATOMIC_REDEEM,
473 SwapArgs = tags::SWAP,
474 WriteDownFeesArgs = tags::WRITE_DOWN_FEES,
475 RegisterExternalDestinationArgs = tags::REGISTER_EXTERNAL_DESTINATION,
476 RevokeExternalDestinationArgs = tags::REVOKE_EXTERNAL_DESTINATION,
477 SetShareMetadataArgs = tags::SET_SHARE_METADATA,
478 AssertDelegateClearedArgs = tags::ASSERT_DELEGATE_CLEARED,
479 AdminSetFlashFeeRateArgs = tags::ADMIN_SET_FLASH_FEE_RATE,
480 StrategistLowerFlashFeeRateArgs = tags::STRATEGIST_LOWER_FLASH_FEE_RATE,
481}
482
483pub fn serialize_instruction<T>(args: &T) -> Result<Vec<u8>, wincode::WriteError>
484where
485 T: InstructionArgs,
486{
487 let mut data = vec![T::TAG];
488 wincode::serialize_into(&mut data, args)?;
489 Ok(data)
490}
491
492#[cfg(test)]
493mod tests {
494 use super::*;
495 use codama::{Codama, NodeTrait};
496 use serde_json::Value;
497 use std::path::Path;
498 use wincode::deserialize_exact;
499
500 #[test]
501 fn instruction_args_tags_match_canonical_tags() {
502 assert_eq!(
504 TAG_CASES,
505 &[
506 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
507 23, 25, 26, 27, 28, 29, 30, 31, 32, 33
508 ]
509 );
510 assert_eq!(
511 RoshiInstruction::ProcessWithdrawals.tag(),
512 <ProcessWithdrawalsArgs as InstructionArgs>::TAG
513 );
514 }
515
516 #[test]
517 fn codama_idl_uses_canonical_instruction_discriminators() {
518 let mut idl = Codama::load(Path::new(env!("CARGO_MANIFEST_DIR")))
519 .unwrap()
520 .get_idl()
521 .unwrap();
522 idl.program.name = "roshi".into();
523 let idl: Value = serde_json::from_str(&idl.to_json().unwrap()).unwrap();
524 let instructions = idl["program"]["instructions"].as_array().unwrap();
525
526 assert_eq!(idl["program"]["name"], "roshi");
527 assert_eq!(
528 idl["program"]["publicKey"],
529 "Roshi11111111111111111111111111111111111111"
530 );
531 assert_eq!(instructions.len(), TAG_CASES.len());
532
533 for (name, tag) in IDL_TAG_CASES {
534 assert_instruction_discriminator(instructions, name, *tag);
535 }
536
537 let deposit = instruction(instructions, "deposit");
538 assert_eq!(deposit["arguments"][1]["name"], "args");
539 assert_eq!(deposit["arguments"][1]["type"]["name"], "depositArgs");
540
541 let process_withdrawals = instruction(instructions, "processWithdrawals");
542 assert_eq!(
543 process_withdrawals["arguments"].as_array().unwrap().len(),
544 1
545 );
546 }
547
548 #[test]
549 fn instruction_decode_rejects_unknown_values() {
550 assert!(RoshiInstruction::decode(&[255]).is_err());
551 }
552
553 #[test]
554 fn serialize_instruction_writes_tag_then_args_payload() {
555 let args = DepositArgs {
556 asset_mint: [4; 32],
557 amount: 123,
558 min_shares_out: 456,
559 access_proof: vec![[1; 32], [2; 32], [3; 32]],
560 };
561
562 let encoded = serialize_instruction(&args).unwrap();
563 let decoded: DepositArgs = deserialize_exact(&encoded[1..]).unwrap();
564
565 assert_eq!(encoded[0], <DepositArgs as InstructionArgs>::TAG);
566 assert_eq!(decoded.asset_mint, [4; 32]);
567 assert_eq!(decoded.amount, 123);
568 assert_eq!(decoded.min_shares_out, 456);
569 assert_eq!(decoded.access_proof, vec![[1; 32], [2; 32], [3; 32]]);
570 }
571
572 #[test]
573 fn canonical_instruction_serializes_like_args_helper() {
574 let args = DepositArgs {
575 asset_mint: [4; 32],
576 amount: 123,
577 min_shares_out: 456,
578 access_proof: vec![[1; 32]],
579 };
580
581 assert_eq!(
582 RoshiInstruction::Deposit(args).serialize().unwrap(),
583 serialize_instruction(&DepositArgs {
584 asset_mint: [4; 32],
585 amount: 123,
586 min_shares_out: 456,
587 access_proof: vec![[1; 32]],
588 })
589 .unwrap()
590 );
591 }
592
593 #[test]
594 fn serialize_zero_sized_args_writes_only_tag() {
595 assert_eq!(
596 serialize_instruction(&ProcessWithdrawalsArgs).unwrap(),
597 vec![<ProcessWithdrawalsArgs as InstructionArgs>::TAG]
598 );
599 assert_eq!(
600 RoshiInstruction::ProcessWithdrawals.serialize().unwrap(),
601 vec![<ProcessWithdrawalsArgs as InstructionArgs>::TAG]
602 );
603 }
604
605 fn instruction<'a>(instructions: &'a [Value], name: &str) -> &'a Value {
606 instructions
607 .iter()
608 .find(|instruction| instruction["name"] == name)
609 .unwrap()
610 }
611
612 fn assert_instruction_discriminator(instructions: &[Value], name: &str, tag: u8) {
613 assert_eq!(
614 instruction(instructions, name)["arguments"][0]["defaultValue"]["number"],
615 u64::from(tag)
616 );
617 }
618
619 const IDL_TAG_CASES: &[(&str, u8)] = &[
620 ("initializeProgram", tags::INITIALIZE_PROGRAM),
621 ("initializeVault", tags::INITIALIZE_VAULT),
622 ("authorizeAction", tags::AUTHORIZE_ACTION),
623 ("revokeAction", tags::REVOKE_ACTION),
624 ("manage", tags::MANAGE),
625 ("manageBatch", tags::MANAGE_BATCH),
626 ("reportNav", tags::REPORT_NAV),
627 ("deposit", tags::DEPOSIT),
628 ("redeem", tags::REDEEM),
629 ("cancelRedeem", tags::CANCEL_REDEEM),
630 ("processWithdrawals", tags::PROCESS_WITHDRAWALS),
631 ("updateVaultConfig", tags::UPDATE_VAULT_CONFIG),
632 ("initializeAsset", tags::INITIALIZE_ASSET),
633 ("updateAsset", tags::UPDATE_ASSET),
634 ("setPauseFlags", tags::SET_PAUSE_FLAGS),
635 ("setVaultAccess", tags::SET_VAULT_ACCESS),
636 ("transferProgramAuthority", tags::TRANSFER_PROGRAM_AUTHORITY),
637 ("transferVaultAuthority", tags::TRANSFER_VAULT_AUTHORITY),
638 ("setStrategist", tags::SET_STRATEGIST),
639 ("setNavAuthority", tags::SET_NAV_AUTHORITY),
640 ("setWithdrawalAuthority", tags::SET_WITHDRAWAL_AUTHORITY),
641 ("collectFees", tags::COLLECT_FEES),
642 ("investExternal", tags::INVEST_EXTERNAL),
643 ("returnExternal", tags::RETURN_EXTERNAL),
644 ("atomicRedeem", tags::ATOMIC_REDEEM),
645 ("swap", tags::SWAP),
646 ("writeDownFees", tags::WRITE_DOWN_FEES),
647 (
648 "registerExternalDestination",
649 tags::REGISTER_EXTERNAL_DESTINATION,
650 ),
651 (
652 "revokeExternalDestination",
653 tags::REVOKE_EXTERNAL_DESTINATION,
654 ),
655 ("setShareMetadata", tags::SET_SHARE_METADATA),
656 ("assertDelegateCleared", tags::ASSERT_DELEGATE_CLEARED),
657 ("adminSetFlashFeeRate", tags::ADMIN_SET_FLASH_FEE_RATE),
658 (
659 "strategistLowerFlashFeeRate",
660 tags::STRATEGIST_LOWER_FLASH_FEE_RATE,
661 ),
662 ];
663}