sss_token/instructions/
allowlist_remove.rs1use anchor_lang::prelude::*;
2
3use crate::errors::SssError;
4use crate::events::AllowlistRemoved;
5use crate::state::*;
6use crate::utils::require_role;
7
8#[derive(Accounts)]
9pub struct AllowlistRemove<'info> {
10 #[account(mut)]
11 pub authority: Signer<'info>,
12
13 #[account(
14 mut,
15 seeds = [StablecoinConfig::SEED_PREFIX, config.mint.as_ref()],
16 bump = config.bump,
17 )]
18 pub config: Account<'info, StablecoinConfig>,
19
20 #[account(
21 seeds = [RoleRegistry::SEED_PREFIX, config.key().as_ref()],
22 bump = role_registry.bump,
23 constraint = role_registry.config == config.key() @ SssError::InvalidAuthority,
24 )]
25 pub role_registry: Account<'info, RoleRegistry>,
26
27 pub address_to_remove: UncheckedAccount<'info>,
29
30 #[account(
33 mut,
34 seeds = [AllowlistEntry::SEED_PREFIX, config.key().as_ref(), address_to_remove.key().as_ref()],
35 bump,
36 )]
37 pub allowlist_entry: UncheckedAccount<'info>,
38}
39
40pub fn handler(ctx: Context<AllowlistRemove>) -> Result<()> {
41 let config = &ctx.accounts.config;
42
43 require!(
44 config.enable_permanent_delegate,
45 SssError::BlacklistNotEnabled
46 );
47
48 require_role(
49 &ctx.accounts.role_registry,
50 &ctx.accounts.authority.key(),
51 Role::Blacklister,
52 )?;
53
54 let allowlist_entry_info = ctx.accounts.allowlist_entry.to_account_info();
55 require!(
56 allowlist_entry_info.owner == &crate::ID && !allowlist_entry_info.data_is_empty(),
57 SssError::AllowlistEntryNotFound
58 );
59
60 let clock = Clock::get()?;
61 let allowlist_entry = {
62 let data = allowlist_entry_info.try_borrow_data()?;
63 let mut data_slice: &[u8] = &data;
64 AllowlistEntry::try_deserialize(&mut data_slice)?
65 };
66 require!(
67 allowlist_entry.config == config.key(),
68 SssError::InvalidAuthority
69 );
70 let address = allowlist_entry.address;
71 let lamports = allowlist_entry_info.lamports();
72 **ctx
73 .accounts
74 .authority
75 .to_account_info()
76 .try_borrow_mut_lamports()? = ctx
77 .accounts
78 .authority
79 .to_account_info()
80 .lamports()
81 .checked_add(lamports)
82 .ok_or(SssError::Overflow)?;
83 **allowlist_entry_info.try_borrow_mut_lamports()? = 0;
84 allowlist_entry_info.assign(&anchor_lang::solana_program::system_program::ID);
85 allowlist_entry_info.realloc(0, false)?;
86
87 emit!(AllowlistRemoved {
88 config: config.key(),
89 address,
90 removed_by: ctx.accounts.authority.key(),
91 timestamp: clock.unix_timestamp,
92 });
93
94 let config = &mut ctx.accounts.config;
95 config.updated_at = clock.unix_timestamp;
96
97 Ok(())
98}