solr_token_whitelist/
processor.rs1use num_traits::FromPrimitive;
2use solana_program::{
3 account_info::{next_account_info, AccountInfo},
4 entrypoint::ProgramResult,
5 msg,
6 decode_error::DecodeError,
7 program_error::{PrintProgramError, ProgramError},
8 program_pack::{IsInitialized},
9 pubkey::Pubkey,
10 sysvar::{rent::Rent, Sysvar},
11};
12
13use crate::{error::TokenWhitelistError, instruction::TokenWhitelistInstruction, state::TokenWhitelist};
14
15pub struct Processor;
16impl Processor {
17 pub fn process(
18 program_id: &Pubkey,
19 accounts: &[AccountInfo],
20 instruction_data: &[u8],
21 ) -> ProgramResult {
22 let instruction = TokenWhitelistInstruction::unpack(instruction_data)?;
23
24 match instruction {
25 TokenWhitelistInstruction::InitTokenWhitelist { max_whitelist_size } => {
26 msg!("Instruction: InitTokenWhitelist");
27 Self::process_init_whitelist(
28 accounts,
29 max_whitelist_size,
30 program_id
31 )
32 }
33 TokenWhitelistInstruction::AddToWhitelist {} => {
34 msg!("Instruction: AddToWhitelist");
35 Self::process_add_whitelist(
36 accounts,
37 program_id
38 )
39 }
40 TokenWhitelistInstruction::RemoveFromWhitelist {} => {
41 msg!("Instruction: RemoveFromWhitelist");
42 Self::process_remove_whitelist(
43 accounts,
44 program_id
45 )
46 }
47 TokenWhitelistInstruction::SetAllocationToZero {} => {
48 msg!("Instruction: SetAllocationToZero");
49 Self::process_set_allocation_to_zero(
50 accounts,
51 program_id
52 )
53 }
54 }
55 }
56
57 fn process_init_whitelist(
58 accounts: &[AccountInfo],
59 max_whitelist_size: u64,
60 _program_id: &Pubkey,
61 ) -> ProgramResult {
62 let account_info_iter = &mut accounts.iter();
63
64 let whitelist_owner = next_account_info(account_info_iter)?;
65 if !whitelist_owner.is_signer {
66 return Err(ProgramError::MissingRequiredSignature);
67 }
68
69 let token_whitelist_account = next_account_info(account_info_iter)?;
70
71 let sysvar_rent_pubkey = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
72 if !sysvar_rent_pubkey.is_exempt(token_whitelist_account.lamports(), token_whitelist_account.data_len()) {
73 msg!("token whitelist account must be rent exempt");
74 return Err(TokenWhitelistError::NotRentExempt.into());
75 }
76
77 let mut token_whitelist_state = TokenWhitelist::unpack_from_slice(&token_whitelist_account.data.borrow())?;
78 if token_whitelist_state.is_initialized() {
79 msg!("token whitelist already initialized");
80 return Err(ProgramError::AccountAlreadyInitialized);
81 }
82
83 token_whitelist_state.is_initialized = true;
84 token_whitelist_state.init_pubkey = *whitelist_owner.key;
85 token_whitelist_state.max_whitelist_size = max_whitelist_size;
86
87 token_whitelist_state.pack_into_slice(&mut token_whitelist_account.data.borrow_mut());
88
89 Ok(())
90 }
91
92 fn process_add_whitelist(
93 accounts: &[AccountInfo],
94 _program_id: &Pubkey,
95 ) -> ProgramResult {
96 let account_info_iter = &mut accounts.iter();
97
98 let whitelist_owner = next_account_info(account_info_iter)?;
99 if !whitelist_owner.is_signer {
100 return Err(ProgramError::MissingRequiredSignature);
101 }
102
103 let token_whitelist_account = next_account_info(account_info_iter)?;
104 let account_to_add = next_account_info(account_info_iter)?;
105
106 let mut token_whitelist_state = TokenWhitelist::unpack_from_slice(&token_whitelist_account.data.borrow())?;
107 if !token_whitelist_state.is_initialized() {
108 msg!("token whitelist needs to be initialized before attempting to add");
109 return Err(TokenWhitelistError::TokenWhitelistNotInit.into());
110 }
111 if whitelist_owner.key != &token_whitelist_state.init_pubkey {
112 msg!("signer must be whitelist owner");
113 msg!("{}", whitelist_owner.key);
114 msg!("{}", token_whitelist_state.init_pubkey);
115 return Err(TokenWhitelistError::TokenWhitelistNotOwner.into());
116 }
117
118 let whitelist_amount: u64 = 250;
119 token_whitelist_state.add_keypair(&account_to_add.key.to_string(), &whitelist_amount);
120 token_whitelist_state.pack_into_slice(&mut token_whitelist_account.data.borrow_mut());
121
122 Ok(())
123 }
124
125 fn process_remove_whitelist(
126 accounts: &[AccountInfo],
127 _program_id: &Pubkey,
128 ) -> ProgramResult {
129 let account_info_iter = &mut accounts.iter();
130
131 let whitelist_owner = next_account_info(account_info_iter)?;
132 if !whitelist_owner.is_signer {
133 return Err(ProgramError::MissingRequiredSignature);
134 }
135
136 let token_whitelist_account = next_account_info(account_info_iter)?;
137 let account_to_remove = next_account_info(account_info_iter)?;
138
139 let mut token_whitelist_state = TokenWhitelist::unpack_from_slice(&token_whitelist_account.data.borrow())?;
140 if !token_whitelist_state.is_initialized() {
141 msg!("token whitelist needs to be initialized before attempting to remove");
142 return Err(TokenWhitelistError::TokenWhitelistNotInit.into());
143 }
144 if whitelist_owner.key != &token_whitelist_state.init_pubkey {
145 msg!("signer must be whitelist owner");
146 msg!("{}", whitelist_owner.key);
147 msg!("{}", token_whitelist_state.init_pubkey);
148 return Err(TokenWhitelistError::TokenWhitelistNotOwner.into());
149 }
150
151 token_whitelist_state.drop_key(&account_to_remove.key.to_string());
152 token_whitelist_state.pack_into_slice(&mut token_whitelist_account.data.borrow_mut());
153
154 Ok(())
155 }
156
157 fn process_set_allocation_to_zero(
158 accounts: &[AccountInfo],
159 _program_id: &Pubkey,
160 ) -> ProgramResult {
161 let account_info_iter = &mut accounts.iter();
162
163 let account_owner = next_account_info(account_info_iter)?;
164 if !account_owner.is_signer {
165 return Err(ProgramError::MissingRequiredSignature);
166 }
167
168 let token_whitelist_account = next_account_info(account_info_iter)?;
169 let account_to_reset = next_account_info(account_info_iter)?;
170
171 let mut token_whitelist_state = TokenWhitelist::unpack_from_slice(&token_whitelist_account.data.borrow())?;
172 if !token_whitelist_state.is_initialized() {
173 msg!("token whitelist needs to be initialized before attempting to update");
174 return Err(TokenWhitelistError::TokenWhitelistNotInit.into());
175 }
176 if account_owner.key != account_to_reset.key {
177 msg!("signer must be the owner of the account");
178 msg!("{}", account_owner.key);
179 msg!("{}", account_to_reset.key);
180 return Err(TokenWhitelistError::NotOwner.into());
181 }
182
183 let whitelist_amount: u64 = 0;
184 token_whitelist_state.add_keypair(&account_to_reset.key.to_string(), &whitelist_amount);
185 token_whitelist_state.pack_into_slice(&mut token_whitelist_account.data.borrow_mut());
186
187 Ok(())
188 }
189}
190
191impl PrintProgramError for TokenWhitelistError {
192 fn print<E>(&self)
193 where
194 E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
195 {
196 match self {
197 TokenWhitelistError::InvalidInstruction => msg!("Error: Invalid Instruction"),
198 TokenWhitelistError::NotRentExempt => msg!("Error: Not Rent Exempt"),
199 TokenWhitelistError::TokenWhitelistNotInit => msg!("Error: Token Whitelist Not Initialized"),
200 TokenWhitelistError::TokenWhitelistNotOwner => msg!("Error: Signer Not Token Whitelist Owner"),
201 TokenWhitelistError::TokenWhitelistSizeExceeds => msg!("Error: Token Whitelist Size Exceeds"),
202 TokenWhitelistError::NotOwner => msg!("Error: Signer Not Account Owner"),
203 }
204 }
205}