Anchor
Token2022 di Anchor

Token2022 di Anchor

Ekstensi Default Account State

Ekstensi DefaultAccountState adalah ekstensi Mint yang memungkinkan semua akun Token yang baru dibuat untuk mint tertentu dibekukan secara default. Kemudian, Freeze Authority dari mint dapat mencairkan (unfreeze) akun Token ini agar dapat digunakan.

Initializing the Mint Account

Karena Anchor tidak memiliki makro untuk ekstensi default_account_state, kita akan membuat akun Mint menggunakan CPI mentah.

Berikut cara membuat mint dengan ekstensi Default Account State:

rust
use anchor_lang::prelude::*;
use anchor_lang::system_program::{create_account, CreateAccount};
use anchor_spl::{
    token_2022::{
        initialize_mint2,
        spl_token_2022::{extension::ExtensionType, pod::PodMint, state::AccountState},
        InitializeMint2,
    },
    token_interface::{
        default_account_state_initialize, DefaultAccountStateInitialize, Mint, Token2022,
    },
};
 
#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
    #[account(mut)]
    pub mint_account: Signer<'info>,
    pub token_program: Program<'info, Token2022>,
    pub system_program: Program<'info, System>,
}
 
pub fn initialize_default_account_state_(
    ctx: Context<Initialize>,
) -> Result<()> {
    // Calculate space required for mint and extension data
    let mint_size =
        ExtensionType::try_calculate_account_len::<PodMint>(&[ExtensionType::DefaultAccountState])?;
 
    // Calculate minimum lamports required for size of mint account with extensions
    let lamports = (Rent::get()?).minimum_balance(mint_size);
 
    // Invoke System Program to create new account with space for mint and extension data
    create_account(
        CpiContext::new(
            ctx.accounts.system_program.to_account_info(),
            CreateAccount {
                from: ctx.accounts.payer.to_account_info(),
                to: ctx.accounts.mint_account.to_account_info(),
            },
        ),
        lamports,                          // Lamports
        mint_size as u64,                  // Space
        &ctx.accounts.token_program.key(), // Owner Program
    )?;
 
    // Initialize the NonTransferable extension
    // This instruction must come before the instruction to initialize the mint data
    default_account_state_initialize(
        CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            DefaultAccountStateInitialize {
                token_program_id: ctx.accounts.token_program.to_account_info(),
                mint: ctx.accounts.mint_account.to_account_info(),
            },
        ),
        &AccountState::Frozen, // default frozen token accounts
    )?;
 
    // Initialize the standard mint account data
    initialize_mint2(
        CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            InitializeMint2 {
                mint: ctx.accounts.mint_account.to_account_info(),
            },
        ),
        2,                               // decimals
        &ctx.accounts.payer.key(),       // mint authority
        Some(&ctx.accounts.payer.key()), // freeze authority
    )?;
 
    Ok(())
}

Ingat bahwa Freeze Authority pada Mint wajib ada untuk ekstensi ini atau kita tidak akan dapat mencairkan akun Token saat pembuatan.

Thawing the Token Account

Dengan adanya ekstensi DefaultAccountState berarti semua akun Token yang diinisialisasi akan frozen secara default.

Ini berarti tidak mungkin untuk melakukan Mint, Transfer atau hampir semua hal dengan akun Token tersebut jika kita tidak mencairkannya (unfreeze).

Kita dapat dengan mudah mencairkan akun Token menggunakan instruksi thaw_account() seperti ini:

rust
use anchor_lang::prelude::*;
use anchor_spl::{
    token_interface::{thaw_account, ThawAccount, Mint, Token, Token2022}
};
 
#[derive(Accounts)]
pub struct ThawAccount<'info> {
    #[account(mut)]
    pub freeze_authority: Signer<'info>,
    #[account(
        mut,
        mint::freeze_authority = freeze_authority,
    )]
    pub mint_account: InterfaceAccount<'info, Mint>,
    pub token_account: InterfaceAccount<'info, Token>,
    pub token_program: Program<'info, Token2022>,
    pub system_program: Program<'info, System>,
}
 
pub fn thaw_account(
    ctx: Context<UpdateState>,
) -> Result<()> {
    thaw_account(
        CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            ThawAccount {
                account: ctx.accounts.token_account.to_account_info(),
                mint: ctx.accounts.mint_account.to_account_info(),
                freeze_authority: ctx.accounts.freeze_authority.to_account_info(),
            },
        ),
        &account_state,
    )?;
    Ok(())
}

Changing the Default Account State

Ketika kita tidak lagi membutuhkan kontrol yang lebih besar atas distribusi token dan ingin membiarkan semua orang bebas memperdagangkan token kita, kita dapat mengubah status akun default menggunakan instruksi default_account_state_update() seperti berikut:

rust
use anchor_lang::prelude::*;
use anchor_spl::{
    token_interface::{default_account_state_update, DefaultAccountStateUpdate, Mint, Token2022}
    spl_token_2022::state::AccountState,   
};
 
#[derive(Accounts)]
pub struct UpdateState<'info> {
    #[account(mut)]
    pub freeze_authority: Signer<'info>,
    #[account(
        mut,
        mint::freeze_authority = freeze_authority,
    )]
    pub mint_account: InterfaceAccount<'info, Mint>,
    pub token_program: Program<'info, Token2022>,
    pub system_program: Program<'info, System>,
}
 
pub fn update_state(
    ctx: Context<UpdateState>,
    account_state: AnchorAccountState,
) -> Result<()> {
    // Convert AnchorAccountState to spl_token_2022::state::AccountState
    let account_state = account_state.to_spl_account_state();
 
    default_account_state_update(
        CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            DefaultAccountStateUpdate {
                token_program_id: ctx.accounts.token_program.to_account_info(),
                mint: ctx.accounts.mint_account.to_account_info(),
                freeze_authority: ctx.accounts.freeze_authority.to_account_info(),
            },
        ),
        &account_state,
    )?;
    Ok(())
}
 
// Custom enum to implement AnchorSerialize and AnchorDeserialize
// This is required to pass the enum as an argument to the instruction
#[derive(AnchorSerialize, AnchorDeserialize)]
pub enum AnchorAccountState {
    Uninitialized,
    Initialized,
    Frozen,
}
 
// Implement conversion from AnchorAccountState to spl_token_2022::state::AccountState
impl AnchorAccountState {
    pub fn to_spl_account_state(&self) -> AccountState {
        match self {
            AnchorAccountState::Uninitialized => AccountState::Uninitialized,
            AnchorAccountState::Initialized => AccountState::Initialized,
            AnchorAccountState::Frozen => AccountState::Frozen,
        }
    }
}
Daftar Isi
Lihat Sumber
Blueshift © 2025Commit: 96f50c6