Skip to main content

superstate_allowlist_interface/
instruction.rs

1use crate::{
2    get_admin_pda, get_allowlist_program_pda, get_private_allowed_account_pda,
3    get_private_allowlist_pda, get_public_allowed_account_pda,
4};
5use borsh::{BorshDeserialize, BorshSerialize};
6use solana_instruction::{AccountMeta, Instruction};
7use solana_program_error::ProgramError;
8use solana_pubkey::Pubkey;
9
10const SYSTEM_PROGRAM_ID: Pubkey = Pubkey::from_str_const("11111111111111111111111111111111");
11
12#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize)]
13pub enum AllowlistInstruction {
14    /// Initializes the allowlist admin account.
15    ///
16    /// It creates a new system account.
17    ///
18    /// This can only be called once.
19    ///
20    /// The `InitializeAdminAuthority` instruction MUST be in the same Transaction as the program deployment
21    /// Otherwise another party can acquire ownership of the uninitialized admin account.
22    ///
23    /// Accounts expected by this instruction:
24    ///
25    ///   0. `[signer]` The Admin Authority account
26    ///   1. `[writable]` The Admin's Program Derived Account
27    ///   2. `[]` System Program
28    InitializeAdminAuthority,
29
30    /// Updates the allowlist admin account.
31    ///
32    /// This can only be called by the existing admin authority.
33    ///
34    /// Accounts expected by this instruction:
35    ///
36    ///   0. `[signer]` The current Admin Authority account
37    ///   1. `[signer]` The new Admin Authority account
38    ///   2. `[writable]` The Admin's Program Derived Account
39    UpdateAdminAuthority,
40
41    /// Associates a Token Mint as a Private Instrument.
42    ///
43    /// This can only be called by the existing admin authority.
44    ///
45    /// Accounts expected by this instruction:
46    ///
47    ///   0. `[signer]` The Admin Authority account
48    ///   1. `[]` The Admin's Program Derived Account
49    ///   2. `[]` The token mint for the private instrument
50    ///   3. `[writable]` The Private Allowlist's Program Derived Account
51    ///   4. `[]` System Program
52    AdminAddPrivateAllowlist,
53
54    /// Changes Token Mint from a Public Instrument to a Private Instrument.
55    ///
56    /// This can only be called by the existing admin authority.
57    ///
58    /// Accounts expected by this instruction:
59    ///
60    ///   0. `[signer]` The Admin Authority account
61    ///   1. `[]` The Admin's Program Derived Account
62    ///   2. `[]` The token mint for the private instrument
63    ///   3. `[writable]` The Private Allowlist's Program Derived Account
64    ///   4. `[]` System Program
65    AdminRemovePrivateAllowlist,
66
67    /// Thaws the underlying Token Account of the provided system wallet account
68    /// if the wallet is on the allow list.
69    ///
70    /// Accounts expected by this instruction:
71    ///
72    ///   0. `[]` The token mint
73    ///   1. `[]` The wallet system account Program Derived Address for the Public Instrument Allowlist
74    ///   2. `[]` The wallet system account Program Derived Address for the Private Instrument Allowlist
75    ///   3. `[writable]` The wallet's Token Account for the Mint
76    ///   4. `[]` The token program
77    ///   5. `[]` The Allowlist PDA for the Freeze Authority
78    Thaw {
79        /// The wallet system account that is being thawed (e.g. the Token Account owner)
80        user_system_account: Pubkey,
81    },
82
83    /// Adds a new account to the Public Instrument Allowlist, and can only be called by the `Admin Authority`.
84    ///
85    /// Accounts expected by this instruction:
86    ///
87    ///   0. `[signer]` The Admin Authority account
88    ///   1. `[]` The Admin's Program Derived Account
89    ///   2. `[signer]` The wallet system account to add to the allow list. Note: this can optionally be a signer.
90    ///   3. `[]` The wallet system account Program Derived Address for the Private Instrument Allowlist
91    ///   4. `[]` System Program
92    AdminAddPublicAllowedAccount,
93
94    /// Adds a new account to the Private Instrument Allowlist, and can only be called by the `Admin Authority`.
95    ///
96    /// Accounts expected by this instruction:
97    ///
98    ///   0. `[signer]` The Admin Authority account
99    ///   1. `[]` The Admin's Program Derived Account
100    ///   2. `[signer]` The wallet system account to add to the allow list. Note: this can optionally be a signer.
101    ///   3. `[]` The wallet system account Program Derived Address for the Private Instrument Allowlist
102    ///   4. `[]` The token mint for the private instrument
103    ///   5. `[]` System Program
104    AdminAddPrivateAllowedAccount,
105
106    /// Removes an existing account from the allowlist, and can only be called by the `Admin Authority`.
107    ///
108    /// This instruction WILL NOT freeze existing Token Accounts, which is instead done via `AdminFreeze`.
109    ///
110    /// Accounts expected by this instruction:
111    ///
112    ///   0. `[signer]` The Admin Authority account
113    ///   1. `[]` The Admin's Program Derived Account
114    ///   2. `[]` The wallet system account to remove from the allow list.
115    ///   3. `[]` The wallet system account Program Derived Address for the allow list
116    AdminRemovePublicAllowedAccount,
117
118    /// Removes an existing account from the allowlist, and can only be called by the `Admin Authority`.
119    ///
120    /// This instruction WILL NOT freeze existing Token Accounts, which is instead done via `AdminFreeze`.
121    ///
122    /// Accounts expected by this instruction:
123    ///
124    ///   0. `[signer]` The Admin Authority account
125    ///   1. `[]` The Admin's Program Derived Account
126    ///   2. `[]` The wallet system account to remove from the allow list.
127    ///   3. `[]` The wallet system account Program Derived Address for the allow list
128    ///   4. `[]` The token mint for the private instrument
129    AdminRemovePrivateAllowedAccount,
130
131    /// Freezes an Token Account, and can only be called by the `Admin Authority`.
132    ///
133    /// Accounts expected by this instruction:
134    ///
135    ///   0. `[signer]` The Admin Authority account
136    ///   1. `[]` The Admin's Program Derived Account
137    ///   2. `[]` The wallet system account
138    ///   3. `[writable]` The wallet's Token Account for the Mint
139    ///   4. `[]` The token mint
140    ///   5. `[]` The token program
141    ///   6. `[]` The Allowlist PDA for the Freeze Authority
142    AdminFreeze,
143
144    /// Burns tokens by removing them from an account. If they account is
145    /// frozen, it will unfreeze it first, and then refreeze it.
146    ///
147    /// This instruction can only be called by the `Admin Authority`
148    ///
149    /// The wallet address does NOT need to be on the allowlist to be burned.
150    ///
151    /// Accounts expected by this instruction:
152    ///
153    ///   0. `[signer]` The Admin Authority account
154    ///   1. `[]` The Admin's Program Derived Account
155    ///   2. `[]` The wallet system account
156    ///   3. `[writable]` The wallet's Token Account for the Mint
157    ///   4. `[]` The token mint
158    ///   5. `[]` The token program
159    ///   6. `[]` The Allowlist PDA for the Freeze Authority
160    AdminBurn {
161        /// The amount of tokens to burn.
162        amount: u64,
163        /// Expected number of base 10 digits to the right of the decimal place.
164        decimals: u8,
165    },
166}
167
168pub fn initialize_admin_authority(
169    allowlist_program_id: &Pubkey,
170    admin_authority_pubkey: &Pubkey,
171) -> Result<Instruction, ProgramError> {
172    let data = borsh::to_vec(&AllowlistInstruction::InitializeAdminAuthority)?;
173
174    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
175
176    let accounts = vec![
177        AccountMeta::new(*admin_authority_pubkey, true),
178        AccountMeta::new(global_admin_pda, false),
179        AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
180    ];
181
182    Ok(Instruction {
183        program_id: *allowlist_program_id,
184        accounts,
185        data,
186    })
187}
188
189pub fn update_admin_authority(
190    allowlist_program_id: &Pubkey,
191    current_admin_authority_pubkey: &Pubkey,
192    new_admin_authority_pubkey: &Pubkey,
193) -> Result<Instruction, ProgramError> {
194    let data = borsh::to_vec(&AllowlistInstruction::UpdateAdminAuthority)?;
195
196    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
197
198    let accounts = vec![
199        AccountMeta::new(*current_admin_authority_pubkey, true),
200        AccountMeta::new(*new_admin_authority_pubkey, true),
201        AccountMeta::new(global_admin_pda, false),
202    ];
203
204    Ok(Instruction {
205        program_id: *allowlist_program_id,
206        accounts,
207        data,
208    })
209}
210
211pub fn admin_add_private_allowlist(
212    allowlist_program_id: &Pubkey,
213    admin_authority_pubkey: &Pubkey,
214    mint_pubkey: &Pubkey,
215    system_program_pubkey: &Pubkey,
216) -> Result<Instruction, ProgramError> {
217    let data = borsh::to_vec(&AllowlistInstruction::AdminAddPrivateAllowlist)?;
218
219    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
220    let (private_allowlist_pda, _) = get_private_allowlist_pda(mint_pubkey, allowlist_program_id);
221
222    let accounts = vec![
223        AccountMeta::new(*admin_authority_pubkey, true),
224        AccountMeta::new_readonly(global_admin_pda, false),
225        AccountMeta::new_readonly(*mint_pubkey, false),
226        AccountMeta::new(private_allowlist_pda, false),
227        AccountMeta::new_readonly(*system_program_pubkey, false),
228    ];
229
230    Ok(Instruction {
231        program_id: *allowlist_program_id,
232        accounts,
233        data,
234    })
235}
236
237pub fn admin_remove_private_allowlist(
238    allowlist_program_id: &Pubkey,
239    admin_authority_pubkey: &Pubkey,
240    mint_pubkey: &Pubkey,
241) -> Result<Instruction, ProgramError> {
242    let data = borsh::to_vec(&AllowlistInstruction::AdminRemovePrivateAllowlist)?;
243
244    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
245    let (private_allowlist_pda, _) = get_private_allowlist_pda(mint_pubkey, allowlist_program_id);
246
247    let accounts = vec![
248        AccountMeta::new(*admin_authority_pubkey, true),
249        AccountMeta::new_readonly(global_admin_pda, false),
250        AccountMeta::new_readonly(*mint_pubkey, false),
251        AccountMeta::new(private_allowlist_pda, false),
252    ];
253
254    Ok(Instruction {
255        program_id: *allowlist_program_id,
256        accounts,
257        data,
258    })
259}
260
261pub fn admin_add_public_allowed_account(
262    allowlist_program_id: &Pubkey,
263    admin_authority_pubkey: &Pubkey,
264    user_account_pubkey: &Pubkey,
265    user_account_is_payer: bool,
266    system_program_id: &Pubkey,
267) -> Result<Instruction, ProgramError> {
268    let data = borsh::to_vec(&AllowlistInstruction::AdminAddPublicAllowedAccount)?;
269
270    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
271    let (user_allowed_account_to_add, _) =
272        get_public_allowed_account_pda(user_account_pubkey, allowlist_program_id);
273
274    let user_account_meta = if user_account_is_payer {
275        AccountMeta::new(*user_account_pubkey, true)
276    } else {
277        AccountMeta::new_readonly(*user_account_pubkey, false)
278    };
279
280    let accounts = vec![
281        AccountMeta::new(*admin_authority_pubkey, true),
282        AccountMeta::new_readonly(global_admin_pda, false),
283        user_account_meta,
284        AccountMeta::new(user_allowed_account_to_add, false),
285        AccountMeta::new_readonly(*system_program_id, false),
286    ];
287
288    Ok(Instruction {
289        program_id: *allowlist_program_id,
290        accounts,
291        data,
292    })
293}
294
295pub fn admin_add_private_allowed_account(
296    allowlist_program_id: &Pubkey,
297    admin_authority_pubkey: &Pubkey,
298    user_account_pubkey: &Pubkey,
299    user_account_is_payer: bool,
300    mint_pubkey: &Pubkey,
301    system_program_pubkey: &Pubkey,
302) -> Result<Instruction, ProgramError> {
303    let data = borsh::to_vec(&AllowlistInstruction::AdminAddPrivateAllowedAccount)?;
304
305    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
306    let (user_allowed_account_to_add, _) =
307        get_private_allowed_account_pda(user_account_pubkey, mint_pubkey, allowlist_program_id);
308
309    let user_account_meta = if user_account_is_payer {
310        AccountMeta::new(*user_account_pubkey, true)
311    } else {
312        AccountMeta::new_readonly(*user_account_pubkey, false)
313    };
314
315    let accounts = vec![
316        AccountMeta::new(*admin_authority_pubkey, true),
317        AccountMeta::new_readonly(global_admin_pda, false),
318        user_account_meta,
319        AccountMeta::new(user_allowed_account_to_add, false),
320        AccountMeta::new_readonly(*mint_pubkey, false),
321        AccountMeta::new_readonly(*system_program_pubkey, false),
322    ];
323
324    Ok(Instruction {
325        program_id: *allowlist_program_id,
326        accounts,
327        data,
328    })
329}
330
331pub fn admin_remove_public_allowed_account(
332    allowlist_program_id: &Pubkey,
333    admin_authority_pubkey: &Pubkey,
334    user_account_pubkey: &Pubkey,
335) -> Result<Instruction, ProgramError> {
336    let data = borsh::to_vec(&AllowlistInstruction::AdminRemovePublicAllowedAccount)?;
337
338    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
339    let (user_allowed_account_to_remove, _) =
340        get_public_allowed_account_pda(user_account_pubkey, allowlist_program_id);
341
342    let accounts = vec![
343        AccountMeta::new(*admin_authority_pubkey, true),
344        AccountMeta::new_readonly(global_admin_pda, false),
345        AccountMeta::new_readonly(*user_account_pubkey, false),
346        AccountMeta::new(user_allowed_account_to_remove, false),
347    ];
348
349    Ok(Instruction {
350        program_id: *allowlist_program_id,
351        accounts,
352        data,
353    })
354}
355
356pub fn admin_remove_private_allowed_account(
357    allowlist_program_id: &Pubkey,
358    admin_authority_pubkey: &Pubkey,
359    user_account_pubkey: &Pubkey,
360    mint_pubkey: &Pubkey,
361) -> Result<Instruction, ProgramError> {
362    let data = borsh::to_vec(&AllowlistInstruction::AdminRemovePrivateAllowedAccount)?;
363
364    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
365    let (user_allowed_account_to_remove, _) =
366        get_private_allowed_account_pda(user_account_pubkey, mint_pubkey, allowlist_program_id);
367
368    let accounts = vec![
369        AccountMeta::new(*admin_authority_pubkey, true),
370        AccountMeta::new_readonly(global_admin_pda, false),
371        AccountMeta::new_readonly(*user_account_pubkey, false),
372        AccountMeta::new(user_allowed_account_to_remove, false),
373        AccountMeta::new_readonly(*mint_pubkey, false),
374    ];
375
376    Ok(Instruction {
377        program_id: *allowlist_program_id,
378        accounts,
379        data,
380    })
381}
382
383pub fn thaw(
384    allowlist_program_id: &Pubkey,
385    mint_pubkey: &Pubkey,
386    user_token_account_owner_pubkey: &Pubkey,
387    user_token_account_pubkey: &Pubkey,
388    token_program_id: &Pubkey,
389) -> Result<Instruction, ProgramError> {
390    let data = borsh::to_vec(&AllowlistInstruction::Thaw {
391        user_system_account: *user_token_account_owner_pubkey,
392    })?;
393
394    let (user_public_allowed_account_pda, _) =
395        get_public_allowed_account_pda(user_token_account_owner_pubkey, allowlist_program_id);
396
397    let (user_private_allowed_account_pda, _) = get_private_allowed_account_pda(
398        user_token_account_owner_pubkey,
399        mint_pubkey,
400        allowlist_program_id,
401    );
402
403    let (allowlist_pda, _) = get_allowlist_program_pda(allowlist_program_id);
404
405    let (private_allowlist_pda, _) = get_private_allowlist_pda(mint_pubkey, allowlist_program_id);
406
407    let accounts = vec![
408        AccountMeta::new_readonly(*mint_pubkey, false),
409        AccountMeta::new(*user_token_account_pubkey, false),
410        AccountMeta::new_readonly(user_public_allowed_account_pda, false),
411        AccountMeta::new_readonly(user_private_allowed_account_pda, false),
412        AccountMeta::new_readonly(private_allowlist_pda, false),
413        AccountMeta::new_readonly(*token_program_id, false),
414        AccountMeta::new_readonly(allowlist_pda, false),
415    ];
416
417    Ok(Instruction {
418        program_id: *allowlist_program_id,
419        accounts,
420        data,
421    })
422}
423
424pub fn admin_freeze(
425    allowlist_program_id: &Pubkey,
426    admin_authority_pubkey: &Pubkey,
427    user_token_account_owner_pubkey: &Pubkey,
428    user_token_account_pubkey: &Pubkey,
429    mint_pubkey: &Pubkey,
430    token_program_id: &Pubkey,
431) -> Result<Instruction, ProgramError> {
432    let data = borsh::to_vec(&AllowlistInstruction::AdminFreeze)?;
433
434    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
435
436    let (allowlist_pda, _) = get_allowlist_program_pda(allowlist_program_id);
437
438    let accounts = vec![
439        AccountMeta::new(*admin_authority_pubkey, true),
440        AccountMeta::new(global_admin_pda, false),
441        AccountMeta::new_readonly(*user_token_account_owner_pubkey, false),
442        AccountMeta::new(*user_token_account_pubkey, false),
443        AccountMeta::new_readonly(*mint_pubkey, false),
444        AccountMeta::new_readonly(*token_program_id, false),
445        AccountMeta::new_readonly(allowlist_pda, false),
446    ];
447
448    Ok(Instruction {
449        program_id: *allowlist_program_id,
450        accounts,
451        data,
452    })
453}
454
455#[allow(clippy::too_many_arguments)]
456pub fn admin_burn(
457    allowlist_program_id: &Pubkey,
458    admin_authority_pubkey: &Pubkey,
459    user_token_account_owner_pubkey: &Pubkey,
460    user_token_account_pubkey: &Pubkey,
461    mint_pubkey: &Pubkey,
462    token_program_id: &Pubkey,
463    amount: u64,
464    decimals: u8,
465) -> Result<Instruction, ProgramError> {
466    let data = borsh::to_vec(&AllowlistInstruction::AdminBurn { amount, decimals })?;
467
468    let (global_admin_pda, _) = get_admin_pda(allowlist_program_id);
469
470    let (allowlist_pda, _) = get_allowlist_program_pda(allowlist_program_id);
471
472    let accounts = vec![
473        AccountMeta::new(*admin_authority_pubkey, true),
474        AccountMeta::new_readonly(global_admin_pda, false),
475        AccountMeta::new_readonly(*user_token_account_owner_pubkey, false),
476        AccountMeta::new(*user_token_account_pubkey, false),
477        AccountMeta::new(*mint_pubkey, false),
478        AccountMeta::new_readonly(*token_program_id, false),
479        AccountMeta::new_readonly(allowlist_pda, false),
480    ];
481
482    Ok(Instruction {
483        program_id: *allowlist_program_id,
484        accounts,
485        data,
486    })
487}