Anchor与传统代币转账签名权限报错原因咨询
问题原因及修复方案
核心错误点
PDA种子不匹配
传统方法里生成PDA用的是sender_account.key.to_bytes()作为种子,但Anchor代码里错误换成了vault.key.to_bytes()。这会导致你签名用的PDA和实际需要授权的PDA不是同一个,SPL Token程序自然不认这个签名,直接抛出权限错误。CPI调用的目标程序错了
token_transfer是SPL Token程序的指令,但你在Anchor的CpiContext里传的是system_program,不是token_program。跨程序调用找错了目标程序,权限校验肯定过不了。签名逻辑和授权方不匹配
传统方法明确指定了授权方是vault.key,同时用对应正确的PDA种子签名;但Anchor这边种子写错、程序传错,导致整个签名逻辑完全偏离,SPL Token程序无法识别合法的签名者。
修正后的Anchor代码
let (_account_address, bump) = Pubkey::find_program_address( &[&ctx.accounts.sender_account.key.to_bytes()], ctx.program_id ); // 修正PDA种子,和find_program_address的参数保持一致 let pda_signer_seeds: &[&[&[_]]] = &[&[&ctx.accounts.sender_account.key.to_bytes(), &[bump]]]; let transfer_ix = Token_Transfer{ from: ctx.accounts.vault_associated_info.to_account_info(), to: ctx.accounts.receiver_associated_info.to_account_info(), authority: ctx.accounts.vault.to_account_info() }; // 修正CPI上下文,传入token_program而非system_program let cpi_ctx = CpiContext::new_with_signer( ctx.accounts.token_program.to_account_info(), transfer_ix, pda_signer_seeds, ); token_transfer(cpi_ctx, amount)?;
补充说明
你用receiver_account当签名者时出错,是因为实际需要的签名者是程序派生的PDA,receiver_account根本不是这个PDA的合法签名主体;改用vault_account能解决可能是巧合,但本质上正确的做法是确保PDA种子、签名逻辑、CPI调用的程序三者完全匹配。
内容的提问来源于stack exchange,提问作者Roshan Shrestha
相关产品推荐
相关产品推荐

