使用PDA作为权限执行SPL Token转账时遇ProgramFailedToComplete错误
我尝试通过程序PDA权限将SPL Token从一个账户转到另一个账户,代码如下:
if source_account.amount > 0 { invoke_signed( &spl_token::instruction::transfer( &token_program_info.key, &source_account_info.key, &dest_account_info.key, &transfer_authority_info.key, &[], source_account.amount, )?, &[ token_program_info.clone(), token_pot_info.clone(), dest_account_info.clone(), transfer_authority_info.clone(), ], &[authority_seeds], )?; }
移除这段代码程序运行正常,添加后触发错误:Err value: TransactionError(InstructionError(0, ProgramFailedToComplete))。已确认:转账权限正确(修改权限会触发PrivelegeEscaltion错误)、账户已初始化、两账户属于同一铸币、余额可正常打印。
排查与修复方案
修正账户列表参数
你的invoke_signed账户数组里错误传入了token_pot_info,但SPL Token的transfer指令要求必须传入源账户(source_account_info)。把token_pot_info.clone()替换成source_account_info.clone()即可。确认PDA签名种子完整性
确保authority_seeds是生成transfer_authority这个PDA的完整种子数组,必须包含对应的bump值。比如PDA由["transfer_auth", mint.key().as_ref()]生成,那seeds格式必须是&[b"transfer_auth", mint.key().as_ref(), &[bump]],缺少任何部分都会导致签名无效,触发执行失败。验证账户可变性标记
确保传入的账户标记了正确的可变性:源账户、目标账户需要是mut类型,transfer_authority需要标记为signer,token_program为只读程序账户。比如账户参数定义时,source_account_info应声明为AccountInfo<'info>并带有mut修饰。
修复后的代码示例
if source_account.amount > 0 { invoke_signed( &spl_token::instruction::transfer( &token_program_info.key, &source_account_info.key, &dest_account_info.key, &transfer_authority_info.key, &[], source_account.amount, )?, &[ token_program_info.clone(), source_account_info.clone(), dest_account_info.clone(), transfer_authority_info.clone(), ], &[authority_seeds], )?; }
内容的提问来源于stack exchange,提问作者LUK3ARK

