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

Solana Metaplex铸造新版NFT时metadata与metadata_mint传值疑问

参数说明

你当前代码中两个参数重复传入同一个metadata公钥的写法是错误的,两个字段的正确取值如下:

  • metadata:传入主版本(Master Edition)NFT对应的元数据(Metadata)PDA账户公钥,也就是官方文档中提到的主版本元数据账户
  • metadata_mint:传入主版本NFT对应的Mint铸币账户公钥,即主版NFT本身的铸币地址,不是你新铸造的子版NFT的new_mint地址
传值依据

这个参数设计来自Metaplex Token Metadata程序的底层校验逻辑:

  1. Solana的PDA派生是单向规则:Metadata账户只能通过Mint地址派生得到,派生路径为["metadata", 元数据程序ID, Mint地址],程序无法从传入的Metadata账户反向推导其关联的Mint地址,因此必须单独传入metadata_mint作为校验基准
  2. 程序执行时会首先校验你传入的metadata账户,是否确实是metadata_mint派生出的合法Metadata账户,再校验该Metadata关联的Master Edition账户、持有主版NFT的代币账户是否匹配,从根源上避免恶意构造的账户传入。
你当前代码的其他问题

你现在的实现还有两个会直接导致调用失败的错误:

  1. 账户列表漏传了edition_mark_pda:你在账户结构体中定义了该字段,但没有加入传给invoke的账户列表,这个账户是打印子版NFT必须的版次标记PDA,缺失会直接报账户不匹配错误
  2. 账户列表漏传了主版本Mint账户:你当前的结构体没有定义主版本对应的Mint字段,也就是metadata_mint需要的取值来源,之前重复传metadata地址的写法会直接触发程序的PDA校验失败。
修正后的核心代码

首先补充账户结构体的缺失字段:

#[derive(Accounts)]
pub struct CreateNewEdition<'info> {
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub new_metadata: UncheckedAccount<'info>,
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub new_edition: UncheckedAccount<'info>,
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub master_edition: UncheckedAccount<'info>,
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub new_mint: UncheckedAccount<'info>,    
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub edition_mark_pda: UncheckedAccount<'info>,
    /// 主版本NFT对应的Mint铸币账户,即metadata_mint参数的取值来源
    /// CHECK: 由Metaplex元数据程序做合法性校验
    pub master_mint: UncheckedAccount<'info>,
    #[account(mut)]
    pub new_mint_authority: Signer<'info>,
    #[account(mut)]
    pub payer: AccountInfo<'info>,
    #[account(mut)]
    pub token_account_owner: UncheckedAccount<'info>,
    /// 持有主版本NFT的代币账户,必须归属master_mint
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub token_account: UncheckedAccount<'info>,
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub new_metadata_update_authority: UncheckedAccount<'info>,
    /// 主版本NFT对应的Metadata账户,即metadata参数的取值来源
    /// CHECK: 由Metaplex元数据程序做合法性校验
    #[account(mut)]
    pub master_metadata: UncheckedAccount<'info>,    
    pub token_program: Program<'info, Token>,
    pub system_program: Program<'info, System>,
    /// CHECK: 由Metaplex元数据程序做合法性校验
    pub rent: AccountInfo<'info>,
}

然后修正调用逻辑,补全缺失账户、传入正确参数:

pub fn create_new_edition_nft(
        ctx: Context<CreateNewEdition>,
        edition: u64,
    ) -> Result<()> {
        let edition_infos = vec![
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.new_metadata.to_account_info(),
            ctx.accounts.new_edition.to_account_info(),
            ctx.accounts.master_edition.to_account_info(),
            ctx.accounts.new_mint.to_account_info(),
            ctx.accounts.edition_mark_pda.to_account_info(),
            ctx.accounts.new_mint_authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.token_account_owner.to_account_info(),
            ctx.accounts.token_account.to_account_info(),
            ctx.accounts.new_metadata_update_authority.to_account_info(),
            ctx.accounts.master_metadata.to_account_info(),
            ctx.accounts.master_mint.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ];
        msg!("Edition Account Infos Assigned");
        invoke(
            &mint_new_edition_from_master_edition_via_token(
                ctx.accounts.token_program.key(),
                ctx.accounts.new_metadata.key(),
                ctx.accounts.new_edition.key(),
                ctx.accounts.master_edition.key(),
                ctx.accounts.new_mint.key(),
                ctx.accounts.edition_mark_pda.key(),
                ctx.accounts.new_mint_authority.key(),
                ctx.accounts.payer.key(),
                ctx.accounts.token_account_owner.key(),
                ctx.accounts.token_account.key(),
                ctx.accounts.new_metadata_update_authority.key(),
                ctx.accounts.master_metadata.key(),
                ctx.accounts.master_mint.key(),
                edition
            ),
            edition_infos.as_slice()
        )?;

        msg!("A New Edition Nft Minted !!!");
        Ok(())
    }

注:官方文档只提到主版本元数据账户,是从业务逻辑层面对必填关联账户做说明,没有展开讲指令底层为了做校验需要的冗余参数,属于文档表述的简化,不是参数设计矛盾。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:57:34