sss_token/instructions/
allowlist_add.rs1use anchor_lang::prelude::*;
2
3use crate::errors::SssError;
4use crate::events::AllowlistAdded;
5use crate::state::*;
6use crate::utils::require_role;
7
8#[derive(AnchorSerialize, AnchorDeserialize)]
9pub struct AllowlistAddParams {
10 pub reason: String,
11}
12
13#[derive(Accounts)]
14#[instruction(_params: AllowlistAddParams)]
15pub struct AllowlistAdd<'info> {
16 #[account(mut)]
17 pub authority: Signer<'info>,
18
19 #[account(
20 mut,
21 seeds = [StablecoinConfig::SEED_PREFIX, config.mint.as_ref()],
22 bump = config.bump,
23 )]
24 pub config: Account<'info, StablecoinConfig>,
25
26 #[account(
27 seeds = [RoleRegistry::SEED_PREFIX, config.key().as_ref()],
28 bump = role_registry.bump,
29 constraint = role_registry.config == config.key() @ SssError::InvalidAuthority,
30 )]
31 pub role_registry: Account<'info, RoleRegistry>,
32
33 #[account(
34 init_if_needed,
35 payer = authority,
36 space = AllowlistEntry::SPACE,
37 seeds = [AllowlistEntry::SEED_PREFIX, config.key().as_ref(), address_to_allowlist.key().as_ref()],
38 bump,
39 constraint = allowlist_entry.config == config.key() || allowlist_entry.config == Pubkey::default() @ SssError::InvalidAuthority,
40 )]
41 pub allowlist_entry: Account<'info, AllowlistEntry>,
42
43 pub address_to_allowlist: UncheckedAccount<'info>,
45
46 pub system_program: Program<'info, System>,
47}
48
49pub fn handler(ctx: Context<AllowlistAdd>, params: AllowlistAddParams) -> Result<()> {
50 let config = &ctx.accounts.config;
51
52 require!(
53 config.enable_permanent_delegate,
54 SssError::BlacklistNotEnabled
55 );
56
57 require_role(
58 &ctx.accounts.role_registry,
59 &ctx.accounts.authority.key(),
60 Role::Blacklister,
61 )?;
62
63 require!(
64 params.reason.len() <= AllowlistEntry::MAX_REASON_LEN,
65 SssError::AllowlistReasonTooLong
66 );
67
68 let entry = &ctx.accounts.allowlist_entry;
69 require!(
70 entry.config == Pubkey::default(),
71 SssError::AllowlistEntryExists
72 );
73
74 let clock = Clock::get()?;
75
76 let entry = &mut ctx.accounts.allowlist_entry;
77 entry.bump = ctx.bumps.allowlist_entry;
78 entry.config = config.key();
79 entry.address = ctx.accounts.address_to_allowlist.key();
80 entry.added_by = ctx.accounts.authority.key();
81 entry.added_at = clock.unix_timestamp;
82 entry.reason = params.reason.clone();
83
84 emit!(AllowlistAdded {
85 config: config.key(),
86 address: ctx.accounts.address_to_allowlist.key(),
87 added_by: ctx.accounts.authority.key(),
88 reason: params.reason,
89 timestamp: clock.unix_timestamp,
90 });
91
92 let config = &mut ctx.accounts.config;
93 config.updated_at = clock.unix_timestamp;
94
95 Ok(())
96}