1#[cfg(feature = "spl")]
2use solana_program::program_pack::Pack;
3use solana_program::{
4 account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, system_program, sysvar,
5};
6#[cfg(feature = "spl")]
7use spl_token::state::Mint;
8
9pub fn load_signer<'a, 'info>(info: &'a AccountInfo<'info>) -> Result<(), ProgramError> {
12 if !info.is_signer {
13 return Err(ProgramError::MissingRequiredSignature);
14 }
15
16 Ok(())
17}
18
19#[cfg(feature = "spl")]
26pub fn load_mint<'a, 'info>(
27 info: &'a AccountInfo<'info>,
28 address: Pubkey,
29 is_writable: bool,
30) -> Result<(), ProgramError> {
31 if info.owner.ne(&spl_token::id()) {
32 return Err(ProgramError::InvalidAccountOwner);
33 }
34
35 if info.key.ne(&address) {
36 return Err(ProgramError::InvalidSeeds);
37 }
38
39 if info.data_is_empty() {
40 return Err(ProgramError::UninitializedAccount);
41 }
42
43 Mint::unpack(&info.data.borrow())?;
44
45 if is_writable && !info.is_writable {
46 return Err(ProgramError::InvalidAccountData);
47 }
48
49 Ok(())
50}
51
52#[cfg(feature = "spl")]
60pub fn load_token_account<'a, 'info>(
61 info: &'a AccountInfo<'info>,
62 owner: Option<&Pubkey>,
63 mint: &Pubkey,
64 is_writable: bool,
65) -> Result<(), ProgramError> {
66 if info.owner.ne(&spl_token::id()) {
67 return Err(ProgramError::InvalidAccountOwner);
68 }
69
70 if info.data_is_empty() {
71 return Err(ProgramError::UninitializedAccount);
72 }
73
74 let account_data = info.data.borrow();
75 let account = spl_token::state::Account::unpack(&account_data)?;
76
77 if account.mint.ne(&mint) {
78 return Err(ProgramError::InvalidAccountData);
79 }
80
81 if let Some(owner) = owner {
82 if account.owner.ne(owner) {
83 return Err(ProgramError::InvalidAccountData);
84 }
85 }
86
87 if is_writable && !info.is_writable {
88 return Err(ProgramError::InvalidAccountData);
89 }
90
91 Ok(())
92}
93
94pub fn load_uninitialized_pda<'a, 'info>(
98 info: &'a AccountInfo<'info>,
99 seeds: &[&[u8]],
100 bump: u8,
101 program_id: &Pubkey,
102) -> Result<(), ProgramError> {
103 let pda = Pubkey::find_program_address(seeds, program_id);
104
105 if info.key.ne(&pda.0) {
106 return Err(ProgramError::InvalidSeeds);
107 }
108
109 if bump.ne(&pda.1) {
110 return Err(ProgramError::InvalidSeeds);
111 }
112
113 load_system_account(info, true)
114}
115
116pub fn load_system_account<'a, 'info>(
121 info: &'a AccountInfo<'info>,
122 is_writable: bool,
123) -> Result<(), ProgramError> {
124 if info.owner.ne(&system_program::id()) {
125 return Err(ProgramError::InvalidAccountOwner);
126 }
127
128 if !info.data_is_empty() {
129 return Err(ProgramError::AccountAlreadyInitialized);
130 }
131
132 if is_writable && !info.is_writable {
133 return Err(ProgramError::InvalidAccountData);
134 }
135
136 Ok(())
137}
138
139pub fn load_sysvar<'a, 'info>(
143 info: &'a AccountInfo<'info>,
144 key: Pubkey,
145) -> Result<(), ProgramError> {
146 if info.owner.ne(&sysvar::id()) {
147 return Err(ProgramError::InvalidAccountOwner);
148 }
149
150 load_account(info, key, false)
151}
152
153pub fn load_account<'a, 'info>(
157 info: &'a AccountInfo<'info>,
158 key: Pubkey,
159 is_writable: bool,
160) -> Result<(), ProgramError> {
161 if info.key.ne(&key) {
162 return Err(ProgramError::InvalidAccountData);
163 }
164
165 if is_writable && !info.is_writable {
166 return Err(ProgramError::InvalidAccountData);
167 }
168
169 Ok(())
170}
171
172pub fn load_program<'a, 'info>(
176 info: &'a AccountInfo<'info>,
177 key: Pubkey,
178) -> Result<(), ProgramError> {
179 if info.key.ne(&key) {
180 return Err(ProgramError::IncorrectProgramId);
181 }
182
183 if !info.executable {
184 return Err(ProgramError::InvalidAccountData);
185 }
186
187 Ok(())
188}
189
190pub fn load_any<'a, 'info>(
193 info: &'a AccountInfo<'info>,
194 is_writable: bool,
195) -> Result<(), ProgramError> {
196 if is_writable && !info.is_writable {
197 return Err(ProgramError::InvalidAccountData);
198 }
199
200 Ok(())
201}