manifest/program/processor/
global_create.rs1use std::{cell::Ref, mem::size_of};
2
3use crate::{
4 logs::{emit_stack, GlobalCreateLog},
5 program::invoke,
6 state::GlobalFixed,
7 utils::create_account,
8 validation::{get_global_address, get_global_vault_address, loaders::GlobalCreateContext},
9};
10use hypertree::{get_mut_helper, trace};
11use solana_program::{
12 account_info::AccountInfo, entrypoint::ProgramResult, program_pack::Pack, pubkey::Pubkey,
13 rent::Rent, sysvar::Sysvar,
14};
15use spl_token_2022::{
16 extension::{BaseStateWithExtensions, ExtensionType, PodStateWithExtensions},
17 pod::PodMint,
18 state::Account,
19};
20
21pub(crate) fn process_global_create(
22 _program_id: &Pubkey,
23 accounts: &[AccountInfo],
24 _data: &[u8],
25) -> ProgramResult {
26 {
27 trace!("process_global_create accs={accounts:?}");
28 let global_create_context: GlobalCreateContext = GlobalCreateContext::load(accounts)?;
29
30 let GlobalCreateContext {
31 payer,
32 global,
33 system_program,
34 global_mint,
35 global_vault,
36 token_program,
37 } = global_create_context;
38
39 {
41 let (_global_key, global_bump) = get_global_address(global_mint.info.key);
42 let global_seeds: Vec<Vec<u8>> = vec![
43 b"global".to_vec(),
44 global_mint.info.key.as_ref().to_vec(),
45 vec![global_bump],
46 ];
47 create_account(
48 payer.as_ref(),
49 global.as_ref(),
50 system_program.as_ref(),
51 &crate::id(),
52 &Rent::get()?,
53 size_of::<GlobalFixed>() as u64,
54 global_seeds,
55 )?;
56
57 let empty_global_fixed: GlobalFixed = GlobalFixed::new_empty(&global_mint.as_ref().key);
59 assert_eq!(global.info.data_len(), size_of::<GlobalFixed>());
60
61 let global_bytes: &mut [u8] = &mut global.info.try_borrow_mut_data()?[..];
62 *get_mut_helper::<GlobalFixed>(global_bytes, 0_u32) = empty_global_fixed;
63
64 }
66
67 {
69 let is_mint_22: bool = *global_mint.info.owner == spl_token_2022::id();
71 let token_program_for_mint: Pubkey = if is_mint_22 {
72 spl_token_2022::id()
73 } else {
74 spl_token::id()
75 };
76
77 let (_global_vault_key, global_vault_bump) =
78 get_global_vault_address(global_mint.info.key);
79 let global_vault_seeds: Vec<Vec<u8>> = vec![
80 b"global-vault".to_vec(),
81 global_mint.info.key.as_ref().to_vec(),
82 vec![global_vault_bump],
83 ];
84 let rent: Rent = Rent::get()?;
85
86 if is_mint_22 {
87 let mint_data: Ref<'_, &mut [u8]> = global_mint.info.data.borrow();
88 let mint_with_extension: PodStateWithExtensions<'_, PodMint> =
89 PodStateWithExtensions::<PodMint>::unpack(&mint_data).unwrap();
90 let mint_extensions: Vec<ExtensionType> =
91 mint_with_extension.get_extension_types()?;
92 let required_extensions: Vec<ExtensionType> =
93 ExtensionType::get_required_init_account_extensions(&mint_extensions);
94 let space: usize =
95 ExtensionType::try_calculate_account_len::<Account>(&required_extensions)?;
96 create_account(
97 payer.as_ref(),
98 global_vault.info,
99 system_program.as_ref(),
100 &token_program_for_mint,
101 &rent,
102 space as u64,
103 global_vault_seeds,
104 )?;
105 invoke(
106 &spl_token_2022::instruction::initialize_account3(
107 &spl_token_2022::id(),
108 global_vault.as_ref().key,
109 global_mint.info.key,
110 global_vault.as_ref().key,
111 )?,
112 &[
113 payer.as_ref().clone(),
114 global_vault.as_ref().clone(),
115 global_mint.as_ref().clone(),
116 token_program.as_ref().clone(),
117 ],
118 )?;
119 } else {
120 let space: usize = spl_token::state::Account::LEN;
121 create_account(
122 payer.as_ref(),
123 global_vault.info,
124 system_program.as_ref(),
125 &token_program_for_mint,
126 &rent,
127 space as u64,
128 global_vault_seeds,
129 )?;
130 invoke(
131 &spl_token::instruction::initialize_account3(
132 &spl_token::id(),
133 global_vault.as_ref().key,
134 global_mint.info.key,
135 global_vault.as_ref().key,
136 )?,
137 &[
138 payer.as_ref().clone(),
139 global_vault.as_ref().clone(),
140 global_mint.as_ref().clone(),
141 token_program.as_ref().clone(),
142 ],
143 )?;
144 }
145 }
146
147 emit_stack(GlobalCreateLog {
148 global: *global.info.key,
149 creator: *payer.key,
150 })?;
151 }
152
153 Ok(())
154}