sss_token/instructions/
blacklist_remove.rs1use anchor_lang::prelude::*;
2use anchor_spl::{
3 token_2022::{self, ThawAccount, Token2022},
4 token_interface::TokenAccount,
5};
6
7use crate::errors::SssError;
8use crate::events::BlacklistRemoved;
9use crate::state::*;
10use crate::utils::require_role;
11
12#[derive(Accounts)]
13pub struct BlacklistRemove<'info> {
14 #[account(mut)]
15 pub authority: Signer<'info>,
16
17 #[account(
18 mut,
19 seeds = [StablecoinConfig::SEED_PREFIX, config.mint.as_ref()],
20 bump = config.bump,
21 )]
22 pub config: Account<'info, StablecoinConfig>,
23
24 #[account(
25 seeds = [RoleRegistry::SEED_PREFIX, config.key().as_ref()],
26 bump = role_registry.bump,
27 constraint = role_registry.config == config.key() @ SssError::InvalidAuthority,
28 )]
29 pub role_registry: Account<'info, RoleRegistry>,
30
31 #[account(
32 mut,
33 close = authority,
34 seeds = [BlacklistEntry::SEED_PREFIX, config.key().as_ref(), blacklist_entry.blocked_address.as_ref()],
35 bump = blacklist_entry.bump,
36 constraint = blacklist_entry.config == config.key(),
37 )]
38 pub blacklist_entry: Account<'info, BlacklistEntry>,
39
40 #[account(
42 address = config.mint,
43 constraint = mint.owner == &token_program.key() @ SssError::InvalidAuthority,
44 )]
45 pub mint: UncheckedAccount<'info>,
46
47 #[account(
49 mut,
50 token::mint = config.mint,
51 token::authority = blacklist_entry.blocked_address,
52 token::token_program = token_program,
53 )]
54 pub target_token_account: InterfaceAccount<'info, TokenAccount>,
55
56 pub token_program: Program<'info, Token2022>,
57}
58
59pub fn handler(ctx: Context<BlacklistRemove>) -> Result<()> {
60 let config = &ctx.accounts.config;
61
62 require!(
63 config.enable_permanent_delegate,
64 SssError::BlacklistNotEnabled
65 );
66
67 require_role(
68 &ctx.accounts.role_registry,
69 &ctx.accounts.authority.key(),
70 Role::Blacklister,
71 )?;
72
73 let clock = Clock::get()?;
74 let unblocked_address = ctx.accounts.blacklist_entry.blocked_address;
75
76 let mint_key = config.mint;
78 let signer_seeds: &[&[&[u8]]] = &[&[
79 StablecoinConfig::SEED_PREFIX,
80 mint_key.as_ref(),
81 &[config.bump],
82 ]];
83
84 token_2022::thaw_account(CpiContext::new_with_signer(
85 ctx.accounts.token_program.to_account_info(),
86 ThawAccount {
87 account: ctx.accounts.target_token_account.to_account_info(),
88 mint: ctx.accounts.mint.to_account_info(),
89 authority: ctx.accounts.config.to_account_info(),
90 },
91 signer_seeds,
92 ))?;
93
94 emit!(BlacklistRemoved {
97 config: config.key(),
98 unblocked_address,
99 removed_by: ctx.accounts.authority.key(),
100 timestamp: clock.unix_timestamp,
101 });
102
103 let config = &mut ctx.accounts.config;
104 config.updated_at = clock.unix_timestamp;
105
106 Ok(())
107}