You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Anchor 0.30.0使用TokenAccount报错:未实现Discriminator等问题求助

问题:Anchor 0.30.0开发中使用Account<'a, TokenAccount>处理非Anchor账户报错

环境信息:

  • Windows 10 64位 + Ubuntu WSL
  • rustc 1.78.0
  • anchor 0.30.0
  • solana 1.18.13

参考官方文档「使用Account<'a, T>处理非Anchor程序账户」编写程序,运行anchor test时出现以下错误:

  1. error[E0599]: TokenAccount找不到create_type关联项
  2. error[E0277]: TokenAccount未实现Discriminator trait
  3. error[E0599]: TokenAccount找不到insert_types关联项

示例代码

use anchor_lang::prelude::*;
use anchor_spl::token::TokenAccount;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
        if ctx.accounts.token_account.amount > 0 {
            ctx.accounts.my_account.data = data;
        }
        Ok(())
    }
}

#[account]
#[derive(Default)]
pub struct MyAccount {
    data: u64,
    mint: Pubkey,
}

#[derive(Accounts)]
pub struct SetData<'info> {
    #[account(mut)]
    pub my_account: Account<'info, MyAccount>,
    #[account(
        constraint = my_account.mint == token_account.mint,
        has_one = owner
    )]
    pub token_account: Account<'info, TokenAccount>,
    pub owner: Signer<'info>,
}

错误信息

error[E0599]: no function or associated item named `create_type` found for struct `anchor_spl::token::TokenAccount` in the current scope
   --> programs/sol-test/src/lib.rs
    |
    | #[derive(Accounts)]
    |          ^^^^^^^^ function or associated item not found in `TokenAccount`    
    |    = note: this error originates in the derive macro `Accounts` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `anchor_spl::token::TokenAccount: Discriminator` is not satisfied
   --> programs/sol-test/src/lib.rs
    |
    | pub token_account: Account<'info, TokenAccount>,
    |                                   ^^^^^^^^^^^^ the trait `Discriminator` is not implemented for `anchor_spl::token::TokenAccount`
    |    = help: the following other types implement trait `Discriminator`:
             MyAccount
             __idl::IdlAccount
             anchor_lang::ProgramData
             anchor_lang::idl::IdlAccount
             instruction::SetData

error[E0599]: no function or associated item named `insert_types` found for struct `anchor_spl::token::TokenAccount` in the current scope
   --> programs/sol-test/src/lib.rs
    |
    | #[derive(Accounts)]
    |          ^^^^^^^^ function or associated item not found in `TokenAccount`
    |    = note: this error originates in the derive macro `Accounts` (in Nightly builds, run with -Z macro-backtrace for more info)

解决方案

这是Anchor版本迭代导致的文档滞后问题,Anchor 0.26+版本对非Anchor程序账户的处理方式做了调整:

Account<'a, T>类型要求泛型T必须实现Anchor的Discriminator trait以及相关的账户类型关联方法,而原生的anchor_spl::token::TokenAccount是对应Solana Token程序的账户结构,并没有实现这些Anchor专属的trait,因此报错。

有两种可行的修改方式:

方式一:使用Anchor SPL提供的接口化TokenAccount

Anchor SPL在interface模块下提供了适配Anchor账户校验的TokenAccount类型,替换原导入即可解决问题:

修改后的代码:

use anchor_lang::prelude::*;
// 替换原TokenAccount导入为interface下的版本
use anchor_spl::token::interface::TokenAccount;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
        if ctx.accounts.token_account.amount > 0 {
            ctx.accounts.my_account.data = data;
        }
        Ok(())
    }
}

#[account]
#[derive(Default)]
pub struct MyAccount {
    data: u64,
    mint: Pubkey,
}

#[derive(Accounts)]
pub struct SetData<'info> {
    #[account(mut)]
    pub my_account: Account<'info, MyAccount>,
    #[account(
        constraint = my_account.mint == token_account.mint,
        has_one = owner
    )]
    pub token_account: InterfaceAccount<'info, TokenAccount>, // 用InterfaceAccount替代Account
    pub owner: Signer<'info>,
}

方式二:直接使用AccountInfo结合手动校验

如果不想依赖接口化类型,可以直接用AccountInfo,并手动添加Token账户的校验约束:

修改后的代码:

use anchor_lang::prelude::*;
use anchor_spl::token::{self, TokenAccount};
use solana_program::program_pack::Pack;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData>, data: u64) -> Result<()> {
        // 手动解析TokenAccount数据
        let token_account = TokenAccount::unpack(&ctx.accounts.token_account.data.borrow())?;
        if token_account.amount > 0 {
            ctx.accounts.my_account.data = data;
        }
        Ok(())
    }
}

#[account]
#[derive(Default)]
pub struct MyAccount {
    data: u64,
    mint: Pubkey,
}

#[derive(Accounts)]
pub struct SetData<'info> {
    #[account(mut)]
    pub my_account: Account<'info, MyAccount>,
    /// CHECK: 手动校验Token账户
    #[account(
        mut,
        constraint = token_account.owner == owner.key(),
        constraint = my_account.mint == TokenAccount::unpack(&token_account.data.borrow())?.mint,
        constraint = *token_account.owner == token::ID // 校验账户属于Token程序
    )]
    pub token_account: AccountInfo<'info>,
    pub owner: Signer<'info>,
}

关键说明

  • 第一种方式更简洁,是Anchor官方推荐的适配非Anchor程序账户的新方式
  • 第二种方式更底层,适合需要完全自定义校验逻辑的场景

内容的提问来源于stack exchange,提问作者puelo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 23:14:59