如何修改Solana Anchor代码实现程序为铸币权限且用户付手续费?
Solana Anchor 铸币程序修改方案(PDA作为铸币权限+用户支付手续费)
核心修改要点
- 生成程序专属的PDA作为代币的铸币权限,无需传入外部权限账户
- 强制接收代币的用户(代币账户的所有者)作为签名者,同时提供其SOL账户承担交易手续费
- 添加账户约束,验证代币的铸币权确实是程序的PDA,防止非法调用
- 通过PDA签名种子完成铸币操作的CPI调用
修改后的完整代码
use anchor_lang::prelude::*; use anchor_spl::token; use anchor_spl::token::{Token, MintTo, Mint}; declare_id!("EcFTDXxknt3vRBi1pVZYN7SjZLcbHjJRAmCmjZ7Js3fd"); #[program] pub mod solana_ubi { use super::*; pub fn mint_token(ctx: Context<MintToken>) -> Result<()> { // 构建PDA签名种子 let sign_seeds = &[&[b"mint_authority", &[*ctx.bumps.get("mint_authority").unwrap()]]]; // 组装铸币CPI的账户参数 let cpi_accounts = MintTo { mint: ctx.accounts.mint.to_account_info(), to: ctx.accounts.token_account.to_account_info(), authority: ctx.accounts.mint_authority.to_account_info(), }; // 创建带PDA签名的CPI上下文 let cpi_ctx = CpiContext::new_with_signer( ctx.accounts.token_program.to_account_info(), cpi_accounts, sign_seeds, ); // 执行铸币操作(铸造10个代币,对应9位小数的10_000_000_000) token::mint_to(cpi_ctx, 10_000_000_000)?; Ok(()) } } #[derive(Accounts)] pub struct MintToken<'info> { // 代币铸币账户,验证其铸币权为程序PDA #[account( mut, constraint = mint.authority == mint_authority.key() )] pub mint: Account<'info, Mint>, // 程序专属的PDA铸币权限账户 /// CHECK: 已通过seeds约束验证归属程序 #[account( seeds = [b"mint_authority"], bump, seeds::program = program_id )] pub mint_authority: AccountInfo<'info>, // 用户的代币接收账户,验证所有者为付费用户 #[account( mut, constraint = token_account.owner == payer.key() )] pub token_account: Account<'info, token::TokenAccount>, // 支付手续费的用户SOL账户,必须为签名者 #[account(mut, signer)] pub payer: Signer<'info>, pub token_program: Program<'info, Token>, pub system_program: Program<'info, System>, }
关键说明
- PDA铸币权限配置:需提前通过Solana CLI或工具将代币mint的
authority更新为程序生成的PDA(通过find_program_address(&[b"mint_authority"], 程序ID)计算得到) - 手续费承担逻辑:
payer账户是用户的SOL账户,标记为mut和signer,确保用户签名并承担交易的SOL手续费 - 安全约束验证:通过账户约束确保代币铸币权归属程序PDA、代币接收账户的所有者为付费用户,避免非法调用
- PDA签名CPI:使用
new_with_signer传入PDA签名种子,让程序以PDA身份完成铸币授权
内容的提问来源于stack exchange,提问作者Depa
相关产品推荐
相关产品推荐

