Skip to main content

sss_token/instructions/
thaw.rs

1use 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::AccountThawed;
9use crate::state::*;
10use crate::utils::require_freeze_authority;
11
12#[derive(Accounts)]
13pub struct ThawTokenAccount<'info> {
14    pub authority: Signer<'info>,
15
16    #[account(
17        mut,
18        seeds = [StablecoinConfig::SEED_PREFIX, config.mint.as_ref()],
19        bump = config.bump,
20    )]
21    pub config: Account<'info, StablecoinConfig>,
22
23    #[account(
24        seeds = [RoleRegistry::SEED_PREFIX, config.key().as_ref()],
25        bump = role_registry.bump,
26        constraint = role_registry.config == config.key() @ SssError::InvalidAuthority,
27    )]
28    pub role_registry: Account<'info, RoleRegistry>,
29
30    /// CHECK: The Token-2022 mint account. Address validated against config, owner against Token-2022.
31    #[account(
32        address = config.mint,
33        constraint = mint.owner == &token_program.key() @ SssError::InvalidAuthority,
34    )]
35    pub mint: UncheckedAccount<'info>,
36
37    #[account(
38        mut,
39        token::mint = config.mint,
40        token::token_program = token_program,
41    )]
42    pub target_token_account: InterfaceAccount<'info, TokenAccount>,
43
44    pub token_program: Program<'info, Token2022>,
45}
46
47pub fn handler(ctx: Context<ThawTokenAccount>) -> Result<()> {
48    let config = &ctx.accounts.config;
49    require_freeze_authority(&ctx.accounts.role_registry, &ctx.accounts.authority.key())?;
50
51    let clock = Clock::get()?;
52    let mint_key = config.mint;
53    let signer_seeds: &[&[&[u8]]] = &[&[
54        StablecoinConfig::SEED_PREFIX,
55        mint_key.as_ref(),
56        &[config.bump],
57    ]];
58
59    token_2022::thaw_account(CpiContext::new_with_signer(
60        ctx.accounts.token_program.to_account_info(),
61        ThawAccount {
62            account: ctx.accounts.target_token_account.to_account_info(),
63            mint: ctx.accounts.mint.to_account_info(),
64            authority: ctx.accounts.config.to_account_info(),
65        },
66        signer_seeds,
67    ))?;
68
69    emit!(AccountThawed {
70        config: config.key(),
71        authority: ctx.accounts.authority.key(),
72        target_account: ctx.accounts.target_token_account.key(),
73        timestamp: clock.unix_timestamp,
74    });
75
76    let config = &mut ctx.accounts.config;
77    config.updated_at = clock.unix_timestamp;
78
79    Ok(())
80}