coal_api/
instruction.rs

1use bytemuck::{Pod, Zeroable};
2use drillx::Solution;
3use num_enum::TryFromPrimitive;
4use solana_program::{
5    instruction::{AccountMeta, Instruction},
6    pubkey::Pubkey,
7    system_program, sysvar,
8};
9
10use crate::{
11    consts::*,
12    utils::{impl_instruction_from_bytes, impl_to_bytes},
13};
14
15#[repr(u8)]
16#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
17#[rustfmt::skip]
18pub enum CoalInstruction {
19    // User
20    Claim = 0,
21    Close = 1,
22    Mine = 2,
23    OpenCoal = 3,
24    Reset = 4,
25    Stake = 5,
26    Update = 6,
27    OpenWood = 7,
28    Equip = 8,
29    Unequip = 9,
30    InitReprocess = 10,
31    FinalizeReprocess = 11,
32    // Admin
33    // InitCoal = 100,
34    // InitWood = 101,
35    InitChromium = 102,
36}
37
38impl CoalInstruction {
39    pub fn to_vec(&self) -> Vec<u8> {
40        vec![*self as u8]
41    }
42}
43
44#[repr(C)]
45#[derive(Clone, Copy, Debug, Pod, Zeroable)]
46pub struct InitializeArgs {
47    pub bus_0_bump: u8,
48    pub bus_1_bump: u8,
49    pub bus_2_bump: u8,
50    pub bus_3_bump: u8,
51    pub bus_4_bump: u8,
52    pub bus_5_bump: u8,
53    pub bus_6_bump: u8,
54    pub bus_7_bump: u8,
55    pub config_bump: u8,
56    pub metadata_bump: u8,
57    pub mint_bump: u8,
58    pub treasury_bump: u8,
59}
60
61#[repr(C)]
62#[derive(Clone, Copy, Debug, Pod, Zeroable)]
63pub struct InitChromiumArgs {
64    pub metadata_bump: u8,
65    pub mint_bump: u8,
66    pub treasury_bump: u8,
67}
68
69#[repr(C)]
70#[derive(Clone, Copy, Debug, Pod, Zeroable)]
71pub struct OpenArgs {
72    pub bump: u8,
73}
74
75#[repr(C)]
76#[derive(Clone, Copy, Debug, Pod, Zeroable)]
77pub struct EquipArgs {
78    pub bump: u8,
79}
80
81#[repr(C)]
82#[derive(Clone, Copy, Debug, Pod, Zeroable)]
83pub struct UnequipArgs {
84    pub bump: u8,
85    pub plugin_authority_bump: u8,
86}
87
88#[repr(C)]
89#[derive(Clone, Copy, Debug, Pod, Zeroable)]
90pub struct MineArgs {
91    pub digest: [u8; 16],
92    pub nonce: [u8; 8],
93}
94
95#[repr(C)]
96#[derive(Clone, Copy, Debug, Pod, Zeroable)]
97pub struct MineArgsV2 {
98    pub digest: [u8; 16],
99    pub nonce: [u8; 8],
100}
101
102#[repr(C)]
103#[derive(Clone, Copy, Debug, Pod, Zeroable)]
104pub struct ClaimArgs {
105    pub amount: [u8; 8],
106}
107
108#[repr(C)]
109#[derive(Clone, Copy, Debug, Pod, Zeroable)]
110pub struct ReprocessArgs {
111    pub reprocessor_bump: u8,
112}
113
114#[repr(C)]
115#[derive(Clone, Copy, Debug, Pod, Zeroable)]
116pub struct StakeArgs {
117    pub amount: [u8; 8],
118}
119
120#[repr(C)]
121#[derive(Clone, Copy, Debug, Pod, Zeroable)]
122pub struct UpgradeArgs {
123    pub amount: [u8; 8],
124}
125
126impl_to_bytes!(InitializeArgs);
127impl_to_bytes!(InitChromiumArgs);
128impl_to_bytes!(OpenArgs);
129impl_to_bytes!(MineArgs);
130impl_to_bytes!(ClaimArgs);
131impl_to_bytes!(StakeArgs);
132impl_to_bytes!(UpgradeArgs);
133impl_to_bytes!(EquipArgs);
134impl_to_bytes!(UnequipArgs);
135impl_to_bytes!(ReprocessArgs);
136
137impl_instruction_from_bytes!(InitializeArgs);
138impl_instruction_from_bytes!(InitChromiumArgs);
139impl_instruction_from_bytes!(OpenArgs);
140impl_instruction_from_bytes!(MineArgs);
141impl_instruction_from_bytes!(ClaimArgs);
142impl_instruction_from_bytes!(StakeArgs);
143impl_instruction_from_bytes!(UpgradeArgs);
144impl_instruction_from_bytes!(EquipArgs);
145impl_instruction_from_bytes!(UnequipArgs);
146impl_instruction_from_bytes!(ReprocessArgs);
147
148/// Builds an auth instruction.
149pub fn auth(proof: Pubkey) -> Instruction {
150    Instruction {
151        program_id: NOOP_PROGRAM_ID,
152        accounts: vec![],
153        data: proof.to_bytes().to_vec(),
154    }
155}
156
157/// Builds a claim instruction.
158pub fn claim_coal(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
159    let proof = Pubkey::find_program_address(&[COAL_PROOF, signer.as_ref()], &crate::id()).0;
160    let treasury_tokens = spl_associated_token_account::get_associated_token_address(
161        &TREASURY_ADDRESS,
162        &COAL_MINT_ADDRESS,
163    );
164    Instruction {
165        program_id: crate::id(),
166        accounts: vec![
167            AccountMeta::new(signer, true),
168            AccountMeta::new(beneficiary, false),
169            AccountMeta::new(proof, false),
170            AccountMeta::new_readonly(TREASURY_ADDRESS, false),
171            AccountMeta::new(treasury_tokens, false),
172            AccountMeta::new_readonly(spl_token::id(), false),
173        ],
174        data: [
175            CoalInstruction::Claim.to_vec(),
176            ClaimArgs {
177                amount: amount.to_le_bytes(),
178            }
179            .to_bytes()
180            .to_vec(),
181        ]
182        .concat(),
183    }
184}
185
186pub fn claim_wood(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
187    let proof = Pubkey::find_program_address(&[WOOD_PROOF, signer.as_ref()], &crate::id()).0;
188    let treasury_tokens = spl_associated_token_account::get_associated_token_address(
189        &TREASURY_ADDRESS,
190        &WOOD_MINT_ADDRESS,
191    );
192    Instruction {
193        program_id: crate::id(),
194        accounts: vec![
195            AccountMeta::new(signer, true),
196            AccountMeta::new(beneficiary, false),
197            AccountMeta::new(proof, false),
198            AccountMeta::new_readonly(TREASURY_ADDRESS, false),
199            AccountMeta::new(treasury_tokens, false),
200            AccountMeta::new_readonly(spl_token::id(), false),
201        ],
202        data: [
203            CoalInstruction::Claim.to_vec(),
204            ClaimArgs {
205                amount: amount.to_le_bytes(),
206            }
207            .to_bytes()
208            .to_vec(),
209        ]
210        .concat(),
211    }
212}
213
214/// Builds a close instruction.
215pub fn close_coal(signer: Pubkey) -> Instruction {
216    let proof_pda = Pubkey::find_program_address(&[COAL_PROOF, signer.as_ref()], &crate::id());
217    Instruction {
218        program_id: crate::id(),
219        accounts: vec![
220            AccountMeta::new(signer, true),
221            AccountMeta::new(proof_pda.0, false),
222            AccountMeta::new_readonly(solana_program::system_program::id(), false),
223        ],
224        data: CoalInstruction::Close.to_vec(),
225    }
226}
227
228pub fn close_wood(signer: Pubkey) -> Instruction {
229    let proof_pda = Pubkey::find_program_address(&[WOOD_PROOF, signer.as_ref()], &crate::id());
230    Instruction {
231        program_id: crate::id(),
232        accounts: vec![
233            AccountMeta::new(signer, true),
234            AccountMeta::new(proof_pda.0, false),
235            AccountMeta::new_readonly(solana_program::system_program::id(), false),
236        ],
237        data: CoalInstruction::Close.to_vec(),
238    }
239}
240
241/// Builds a mine instruction.
242pub fn mine_coal(
243    signer: Pubkey,
244    proof_authority: Pubkey,
245    bus: Pubkey,
246    tool: Option<Pubkey>,
247    member: Option<Pubkey>,
248    guild: Option<Pubkey>,
249    solution: Solution,
250) -> Instruction {
251    let proof = Pubkey::find_program_address(&[COAL_PROOF, proof_authority.as_ref()], &crate::id()).0;
252
253    let mut accounts = vec![
254        AccountMeta::new(signer, true),
255        AccountMeta::new(bus, false),
256        AccountMeta::new_readonly(COAL_CONFIG_ADDRESS, false),
257        AccountMeta::new(proof, false),
258        AccountMeta::new_readonly(sysvar::instructions::id(), false),
259        AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
260    ];
261
262    if let Some(tool) = tool {
263        accounts.push(AccountMeta::new(tool, false));
264    }
265
266    if let Some(member) = member {
267        let guild_config = coal_guilds_api::state::config_pda().0;
268        accounts.push(AccountMeta::new_readonly(guild_config, false));
269        accounts.push(AccountMeta::new_readonly(member, false));
270    }
271
272    if let Some(guild) = guild {
273        accounts.push(AccountMeta::new_readonly(guild, false));
274    }
275
276    Instruction {
277        program_id: crate::id(),
278        accounts,
279        data: [
280            CoalInstruction::Mine.to_vec(),
281            MineArgs {
282                digest: solution.d,
283                nonce: solution.n,
284            }
285            .to_bytes()
286            .to_vec(),
287        ]
288        .concat(),
289    }
290}
291
292pub fn chop_wood(
293    signer: Pubkey,
294    proof_authority: Pubkey,
295    bus: Pubkey,
296    solution: Solution,
297) -> Instruction {
298    let proof = Pubkey::find_program_address(&[WOOD_PROOF, proof_authority.as_ref()], &crate::id()).0;
299    let tool = Pubkey::find_program_address(&[WOOD_MAIN_HAND_TOOL, proof_authority.as_ref()], &crate::id()).0;
300
301    Instruction {
302        program_id: crate::id(),
303        accounts: vec![
304            AccountMeta::new(signer, true),
305            AccountMeta::new(bus, false),
306            AccountMeta::new_readonly(WOOD_CONFIG_ADDRESS, false),
307            AccountMeta::new(proof, false),
308            AccountMeta::new_readonly(sysvar::instructions::id(), false),
309            AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
310            AccountMeta::new(tool, false),
311        ],
312        data: [
313            CoalInstruction::Mine.to_vec(),
314            MineArgs {
315                digest: solution.d,
316                nonce: solution.n,
317            }
318            .to_bytes()
319            .to_vec(),
320        ]
321        .concat(),
322    }
323}
324
325/// Builds an open instruction.
326pub fn open_coal(signer: Pubkey, miner: Pubkey, payer: Pubkey) -> Instruction {
327    let proof_pda = Pubkey::find_program_address(&[COAL_PROOF, signer.as_ref()], &crate::id());
328    Instruction {
329        program_id: crate::id(),
330        accounts: vec![
331            AccountMeta::new(signer, true),
332            AccountMeta::new_readonly(miner, false),
333            AccountMeta::new(payer, true),
334            AccountMeta::new(proof_pda.0, false),
335            AccountMeta::new_readonly(solana_program::system_program::id(), false),
336            AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
337        ],
338        data: [
339            CoalInstruction::OpenCoal.to_vec(),
340            OpenArgs { bump: proof_pda.1 }.to_bytes().to_vec(),
341        ]
342        .concat(),
343    }
344}
345
346pub fn open_wood(signer: Pubkey, miner: Pubkey, payer: Pubkey) -> Instruction {
347    let proof_pda = Pubkey::find_program_address(&[WOOD_PROOF, signer.as_ref()], &crate::id());
348    Instruction {
349        program_id: crate::id(),
350        accounts: vec![
351            AccountMeta::new(signer, true),
352            AccountMeta::new_readonly(miner, false),
353            AccountMeta::new(payer, true),
354            AccountMeta::new(proof_pda.0, false),
355            AccountMeta::new_readonly(solana_program::system_program::id(), false),
356            AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
357        ],
358        data: [
359            CoalInstruction::OpenWood.to_vec(),
360            OpenArgs { bump: proof_pda.1 }.to_bytes().to_vec(),
361        ]
362        .concat(),
363    }
364}
365
366
367/// Builds an equip instruction
368pub fn equip(
369    signer: Pubkey,
370    miner: Pubkey,
371    payer: Pubkey,
372    asset: Pubkey,
373    collection: Pubkey,
374    seed: &[u8],
375) -> Instruction {
376    let tool_pda = Pubkey::find_program_address(&[seed, signer.as_ref()], &crate::id());
377
378    Instruction {
379        program_id: crate::id(),
380        accounts: vec![
381            AccountMeta::new(signer, true),
382            AccountMeta::new_readonly(miner, false),
383            AccountMeta::new(payer, true),
384            AccountMeta::new(asset, false),
385            AccountMeta::new_readonly(collection, false),
386            AccountMeta::new(tool_pda.0, false),
387            AccountMeta::new_readonly(mpl_core::ID, false),
388            AccountMeta::new_readonly(system_program::ID, false),
389        ],
390        data: [
391            CoalInstruction::Equip.to_vec(),
392            EquipArgs {
393                bump: tool_pda.1,
394            }
395            .to_bytes()
396            .to_vec(),
397        ]
398        .concat(),
399    }
400}
401
402/// Builds an unequip instruction
403pub fn unequip(
404    signer: Pubkey,
405    miner: Pubkey,
406    payer: Pubkey,
407    asset: Pubkey,
408    collection: Pubkey,
409    seed: &[u8],
410) -> Instruction {
411    let tool_pda = Pubkey::find_program_address(&[seed, signer.as_ref()], &crate::id());
412    let plugin_authority = Pubkey::find_program_address(&[PLUGIN_UPDATE_AUTHORITY], &crate::id());
413
414    Instruction {
415        program_id: crate::id(),
416        accounts: vec![
417            AccountMeta::new(signer, true),
418            AccountMeta::new_readonly(miner, false),
419            AccountMeta::new(payer, true),
420            AccountMeta::new(asset, false),
421            AccountMeta::new(collection, false),
422            AccountMeta::new(tool_pda.0, false),
423            AccountMeta::new(plugin_authority.0, false),
424            AccountMeta::new_readonly(mpl_core::ID, false),
425            AccountMeta::new_readonly(system_program::ID, false),
426        ],
427        data: [
428            CoalInstruction::Unequip.to_vec(),
429            UnequipArgs {
430                bump: tool_pda.1,
431                plugin_authority_bump: plugin_authority.1,
432            }
433            .to_bytes()
434            .to_vec(),
435        ]
436        .concat(),
437    }
438}
439
440/// Builds a reset instruction.
441pub fn reset_coal(signer: Pubkey) -> Instruction {
442    let treasury_tokens = spl_associated_token_account::get_associated_token_address(
443        &TREASURY_ADDRESS,
444        &COAL_MINT_ADDRESS,
445    );
446    Instruction {
447        program_id: crate::id(),
448        accounts: vec![
449            AccountMeta::new(signer, true),
450            AccountMeta::new(COAL_BUS_ADDRESSES[0], false),
451            AccountMeta::new(COAL_BUS_ADDRESSES[1], false),
452            AccountMeta::new(COAL_BUS_ADDRESSES[2], false),
453            AccountMeta::new(COAL_BUS_ADDRESSES[3], false),
454            AccountMeta::new(COAL_BUS_ADDRESSES[4], false),
455            AccountMeta::new(COAL_BUS_ADDRESSES[5], false),
456            AccountMeta::new(COAL_BUS_ADDRESSES[6], false),
457            AccountMeta::new(COAL_BUS_ADDRESSES[7], false),
458            AccountMeta::new(COAL_CONFIG_ADDRESS, false),
459            AccountMeta::new(COAL_MINT_ADDRESS, false),
460            AccountMeta::new(TREASURY_ADDRESS, false),
461            AccountMeta::new(treasury_tokens, false),
462            AccountMeta::new_readonly(spl_token::id(), false),
463        ],
464        data: CoalInstruction::Reset.to_vec(),
465    }
466}
467
468pub fn reset_wood(signer: Pubkey) -> Instruction {
469    let treasury_tokens = spl_associated_token_account::get_associated_token_address(
470        &TREASURY_ADDRESS,
471        &WOOD_MINT_ADDRESS,
472    );
473    Instruction {
474        program_id: crate::id(),
475        accounts: vec![
476            AccountMeta::new(signer, true),
477            AccountMeta::new(WOOD_BUS_ADDRESSES[0], false),
478            AccountMeta::new(WOOD_BUS_ADDRESSES[1], false),
479            AccountMeta::new(WOOD_BUS_ADDRESSES[2], false),
480            AccountMeta::new(WOOD_BUS_ADDRESSES[3], false),
481            AccountMeta::new(WOOD_BUS_ADDRESSES[4], false),
482            AccountMeta::new(WOOD_BUS_ADDRESSES[5], false),
483            AccountMeta::new(WOOD_BUS_ADDRESSES[6], false),
484            AccountMeta::new(WOOD_BUS_ADDRESSES[7], false),
485            AccountMeta::new(WOOD_CONFIG_ADDRESS, false),
486            AccountMeta::new(WOOD_MINT_ADDRESS, false),
487            AccountMeta::new(TREASURY_ADDRESS, false),
488            AccountMeta::new(treasury_tokens, false),
489            AccountMeta::new_readonly(spl_token::id(), false),
490        ],
491        data: CoalInstruction::Reset.to_vec(),
492    }
493}
494
495/// Build a stake instruction.
496pub fn stake_coal(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
497    let proof = Pubkey::find_program_address(&[COAL_PROOF, signer.as_ref()], &crate::id()).0;
498    let treasury_tokens = spl_associated_token_account::get_associated_token_address(
499        &TREASURY_ADDRESS,
500        &COAL_MINT_ADDRESS,
501    );
502    Instruction {
503        program_id: crate::id(),
504        accounts: vec![
505            AccountMeta::new(signer, true),
506            AccountMeta::new(proof, false),
507            AccountMeta::new(sender, false),
508            AccountMeta::new(treasury_tokens, false),
509            AccountMeta::new_readonly(spl_token::id(), false),
510        ],
511        data: [
512            CoalInstruction::Stake.to_vec(),
513            StakeArgs {
514                amount: amount.to_le_bytes(),
515            }
516            .to_bytes()
517            .to_vec(),
518        ]
519        .concat(),
520    }
521}
522
523pub fn stake_wood(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
524    let proof = Pubkey::find_program_address(&[WOOD_PROOF, signer.as_ref()], &crate::id()).0;
525    let treasury_tokens = spl_associated_token_account::get_associated_token_address(
526        &TREASURY_ADDRESS,
527        &WOOD_MINT_ADDRESS,
528    );
529    Instruction {
530        program_id: crate::id(),
531        accounts: vec![
532            AccountMeta::new(signer, true),
533            AccountMeta::new(proof, false),
534            AccountMeta::new(sender, false),
535            AccountMeta::new(treasury_tokens, false),
536            AccountMeta::new_readonly(spl_token::id(), false),
537        ],
538        data: [
539            CoalInstruction::Stake.to_vec(),
540            StakeArgs {
541                amount: amount.to_le_bytes(),
542            }
543            .to_bytes()
544            .to_vec(),
545        ]
546        .concat(),
547    }
548}
549
550// Build an update instruction.
551pub fn update_coal(signer: Pubkey, miner: Pubkey) -> Instruction {
552    let proof = Pubkey::find_program_address(&[COAL_PROOF, signer.as_ref()], &crate::id()).0;
553    Instruction {
554        program_id: crate::id(),
555        accounts: vec![
556            AccountMeta::new(signer, true),
557            AccountMeta::new_readonly(miner, false),
558            AccountMeta::new(proof, false),
559        ],
560        data: CoalInstruction::Update.to_vec(),
561    }
562}
563
564pub fn update_wood(signer: Pubkey, miner: Pubkey) -> Instruction {
565    let proof = Pubkey::find_program_address(&[WOOD_PROOF, signer.as_ref()], &crate::id()).0;
566    Instruction {
567        program_id: crate::id(),
568        accounts: vec![
569            AccountMeta::new(signer, true),
570            AccountMeta::new_readonly(miner, false),
571            AccountMeta::new(proof, false),
572        ],
573        data: CoalInstruction::Update.to_vec(),
574    }
575}
576
577pub fn init_chromium(signer: Pubkey) -> Instruction {
578    let mint_pda = Pubkey::find_program_address(&[CHROMIUM_MINT, MINT_NOISE.as_slice()], &crate::id());
579    let metadata_pda = Pubkey::find_program_address(
580        &[
581            METADATA,
582            mpl_token_metadata::ID.as_ref(),
583            mint_pda.0.as_ref(),
584            ],
585            &mpl_token_metadata::ID,
586        );
587    let treasury_pda = Pubkey::find_program_address(&[TREASURY], &crate::id());
588    let treasury_tokens =
589        spl_associated_token_account::get_associated_token_address(&treasury_pda.0, &mint_pda.0);
590
591    Instruction {
592        program_id: crate::id(),
593        accounts: vec![
594            AccountMeta::new(signer, true),
595            AccountMeta::new(mint_pda.0, false),
596            AccountMeta::new(metadata_pda.0, false),
597            AccountMeta::new_readonly(treasury_pda.0, false),
598            AccountMeta::new(treasury_tokens, false),
599            AccountMeta::new_readonly(system_program::id(), false),
600            AccountMeta::new_readonly(spl_token::id(), false),
601            AccountMeta::new_readonly(spl_associated_token_account::id(), false),
602            AccountMeta::new_readonly(mpl_token_metadata::ID, false),
603            AccountMeta::new_readonly(sysvar::rent::id(), false),
604        ],
605        data: [
606            CoalInstruction::InitChromium.to_vec(),
607            InitChromiumArgs {
608                metadata_bump: metadata_pda.1,
609                mint_bump: mint_pda.1,
610                treasury_bump: treasury_pda.1,
611            }
612            .to_bytes()
613            .to_vec(),
614        ]
615        .concat(),
616    }
617}
618
619pub fn init_reprocess(signer: Pubkey) -> Instruction {
620    let (reprocessor, reprocessor_bump) = Pubkey::find_program_address(&[REPROCESSOR, signer.as_ref()], &crate::id());
621
622    Instruction {
623        program_id: crate::id(),
624        accounts: vec![
625            AccountMeta::new(signer, true),
626            AccountMeta::new(TREASURY_ADDRESS, false),
627            AccountMeta::new(reprocessor, false),
628            AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
629            AccountMeta::new_readonly(system_program::id(), false),
630        ],
631        data: [
632            CoalInstruction::InitReprocess.to_vec(),
633            ReprocessArgs {
634                reprocessor_bump,
635            }
636            .to_bytes()
637            .to_vec(),
638        ]
639        .concat(),
640    }
641}
642
643pub fn reprocess(signer: Pubkey) -> Instruction {
644    let (proof, _proof_bump) = Pubkey::find_program_address(&[COAL_PROOF, signer.as_ref()], &crate::id());
645    let (reprocessor, reprocessor_bump) = Pubkey::find_program_address(&[REPROCESSOR, signer.as_ref()], &crate::id());
646    let (bus, _bus_bump) = Pubkey::find_program_address(&[COAL_BUS, &[0]], &crate::id());
647    let tokens = spl_associated_token_account::get_associated_token_address(&signer, &CHROMIUM_MINT_ADDRESS);
648    
649    Instruction {
650        program_id: crate::id(),
651        accounts: vec![
652            AccountMeta::new(signer, true),
653            AccountMeta::new(reprocessor, false),
654            AccountMeta::new(proof, false),
655            AccountMeta::new(bus, false),
656            AccountMeta::new(CHROMIUM_MINT_ADDRESS, false),
657            AccountMeta::new(tokens, false),
658            AccountMeta::new_readonly(TREASURY_ADDRESS, false),
659            AccountMeta::new_readonly(spl_token::id(), false),
660            AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
661        ],
662        data: [
663            CoalInstruction::FinalizeReprocess.to_vec(),
664            ReprocessArgs {
665                reprocessor_bump,
666            }
667            .to_bytes()
668            .to_vec(),
669        ]
670        .concat(),
671    }
672}