本文へスキップ
BecomeCoder

Solanaコース · 第8章 トークンとNFT · レッスン30

Anchorからトークンを発行/送金する

ローカル実施

導入

第6章で学んだ CPI(Cross-Program Invocation) は、まさにトークン操作のために使われます。トークンの発行(ミント)や送金は、あなたのプログラムが自分でロジックを書くのではなく、Token Programという別のプログラムを呼び出して実行してもらいます。

説明

Anchorには anchor_spl::token というクレートがあり、Token ProgramへのCPI呼び出しをラップした関数が用意されています。代表的なのが mint_to(新規発行)と transfer(送金)です。

use anchor_lang::prelude::*;
use anchor_spl::token::{self, Mint, Token, TokenAccount, MintTo};

pub fn mint_reward(ctx: Context<MintReward>, amount: u64) -> Result<()> {
    let cpi_accounts = MintTo {
        mint: ctx.accounts.mint.to_account_info(),
        to: ctx.accounts.destination.to_account_info(),
        authority: ctx.accounts.mint_authority.to_account_info(),
    };
    let cpi_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
    token::mint_to(cpi_ctx, amount)?;
    Ok(())
}

#[derive(Accounts)]
pub struct MintReward<'info> {
    #[account(mut)]
    pub mint: Account<'info, Mint>,
    #[account(mut)]
    pub destination: Account<'info, TokenAccount>,
    pub mint_authority: Signer<'info>,
    pub token_program: Program<'info, Token>,
}

流れを図にすると、あなたのプログラムが「橋渡し役」になっていることが分かります。

sequenceDiagram
    participant Client as クライアント
    participant Prog as あなたのプログラム
    participant Token as Token Program(CPI先)
    Client->>Prog: mint_reward(amount) を呼び出す
    Prog->>Prog: CpiContextを組み立てる
    Prog->>Token: mint_toをCPIで呼び出す
    Token->>Token: destinationの残高を増やす
    Token-->>Prog: 成功を返す
    Prog-->>Client: Ok(())

送金も同じパターンです。Transfer { from, to, authority } を組み立てて token::transfer(cpi_ctx, amount) を呼びます。あなたのプログラムは残高の増減ロジック自体を持たず、「いつ・誰に・いくら」という条件判断だけを担当し、実際の帳簿操作はToken Programに委ねるという役割分担がポイントです。

演習

mint_authoritySigner<'info> として要求されているのはなぜでしょうか。もしこの制約がなかったら、誰でもトークンを無限に発行できてしまう、という視点で考えてみましょう。

ヒント1を見る

Mintアカウントには「誰が新規発行してよいか」を表す mint authority という設定があります。

ヒント2を見る

Signer<'info> によって「そのmint authorityの秘密鍵を持つ本人が署名している」ことをAnchorが検証します。