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

Solana单交易内两次转账签名验证失败问题求助

问题:Solana单交易内两次Token转账签名验证失败

尝试在Solana的一笔交易中连续执行两次Token转账(A→B,再B→C),但触发交易签名验证失败提示。单独执行任意一笔转账均可成功,需排查失败原因、正确签名方式及是否存在平台限制。

失败场景代码

Account aWallet = new Account("4jNVZFAqR8Uo38pkF2D7VkrVkdkbQzYTyKwH8WVD3zFtRqVgqFk8RGv4jhbovbQJhwffsJArPm1f7zrEBBpz9wG6", "6Z8KwAWDiof9sRM4H9svhaR7kfJMNBxY143vXenr513p");
PublicKey aTokenAccount = new PublicKey("5Zf3vVtYBJWfQuKijSWLJUeg5ZjnTjf7wXJirGAMWHHL");

Account bWallet = new Account("5zRSNfYURSN8gBwqAJKhqQ3HcVDdfdQfD1o8bHGiFZdhzqtE85GHyqtHeCvjWwFNq3cz8fTEzWnyqfUqKfpJ4nDx", "6bUxHifHMYFTQva495nAFS4ShAtCKBAEV5Rya12nb4EE");
PublicKey bTokenAccount = new PublicKey("6TzpmTkmR76tKcYfT562QVonykyuvpAcWXGFsRJ8Mftt");

PublicKey cTokenAccount = new PublicKey("6mJTEchkfsKpVGAAnJRfrv6fhkh9n8x4zc1LziFMycgP");

var minBalanceForExemptionAcc = _rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.TokenAccountDataSize).Result;
var blockHash = _rpcClient.GetLatestBlockHash();

var txBytes = new TransactionBuilder().
    SetRecentBlockHash(blockHash.Result.Value.Blockhash).
    SetFeePayer(_adminWallet.Account).
    AddInstruction(TokenProgram.Transfer(
        aTokenAccount,
        bTokenAccount,
        1000,
        aWallet)).
    AddInstruction(TokenProgram.Transfer(
        bTokenAccount,
        cTokenAccount,
        5000,
        bWallet)).
    Build(new List<Account> { _adminWallet.Account, aWallet, bWallet });

RequestResult<string> sig = _rpcClient.SendTransaction(txBytes, commitment: Commitment.Finalized);
Console.WriteLine(sig.Reason);

成功场景代码

仅执行A→B转账

AddInstruction(TokenProgram.Transfer(
    aTokenAccount,
    bTokenAccount,
    1000,
    aWallet)).
Build(new List<Account> { _adminWallet.Account, aWallet });

仅执行B→C转账

AddInstruction(TokenProgram.Transfer(
    bTokenAccount,
    cTokenAccount,
    5000,
    bWallet)).
Build(new List<Account> { _adminWallet.Account, bWallet });

原因分析及解决方案

Solana完全支持单交易内多笔Token转账,不存在平台限制,失败核心原因集中在账户声明、签名顺序或交易预检查环节:

可能原因

  1. 账户列表未正确合并:TransactionBuilder自动收集账户时,可能遗漏重复账户的可写属性标记(如bTokenAccount在两次转账中都需要写入权限)。
  2. 签名顺序不匹配:交易签名者顺序必须与账户列表中的签名者顺序一致,若顺序错误会导致签名验证失败。
  3. 预检查余额误解:若B的Token账户初始余额不足5000,即使A→B会转入资金,Solana预检查会基于交易执行前的初始余额验证,导致指令不满足条件(但你单独执行B→C成功,此情况可排除)。

正确实现方式

1. 手动显式声明所有账户

避免依赖自动收集,手动添加所有涉及账户并标记属性,确保权限正确:

var txBytes = new TransactionBuilder()
    .SetRecentBlockHash(blockHash.Result.Value.Blockhash)
    .SetFeePayer(_adminWallet.Account)
    // 显式添加所有涉及账户,标记签名者/可写属性
    .AddAccount(_adminWallet.Account, isSigner: true, isWritable: true)
    .AddAccount(aWallet, isSigner: true, isWritable: false)
    .AddAccount(bWallet, isSigner: true, isWritable: false)
    .AddAccount(aTokenAccount, isSigner: false, isWritable: true)
    .AddAccount(bTokenAccount, isSigner: false, isWritable: true)
    .AddAccount(cTokenAccount, isSigner: false, isWritable: true)
    .AddAccount(TokenProgram.ProgramId, isSigner: false, isWritable: false)
    // 添加转账指令
    .AddInstruction(TokenProgram.Transfer(
        aTokenAccount,
        bTokenAccount,
        1000,
        aWallet))
    .AddInstruction(TokenProgram.Transfer(
        bTokenAccount,
        cTokenAccount,
        5000,
        bWallet))
    .Build(new List<Account> { _adminWallet.Account, aWallet, bWallet });

2. 手动签名排查问题

若自动签名仍失败,可手动生成交易消息并签名,排查自动签名流程的问题:

// 构建未签名的交易消息
var message = new TransactionBuilder()
    .SetRecentBlockHash(blockHash.Result.Value.Blockhash)
    .SetFeePayer(_adminWallet.Account)
    .AddInstruction(TokenProgram.Transfer(
        aTokenAccount,
        bTokenAccount,
        1000,
        aWallet))
    .AddInstruction(TokenProgram.Transfer(
        bTokenAccount,
        cTokenAccount,
        5000,
        bWallet))
    .BuildMessage();

// 手动按顺序签名
var sigAdmin = _adminWallet.Account.Sign(message);
var sigA = aWallet.Sign(message);
var sigB = bWallet.Sign(message);

// 组装交易并序列化
var transaction = new Transaction(message, new List<Signature> { sigAdmin, sigA, sigB });
var txBytes = transaction.Serialize();

// 发送交易
RequestResult<string> sig = _rpcClient.SendTransaction(txBytes, commitment: Commitment.Finalized);

3. 验证核心条件

  • 确认bWallet是bTokenAccount的所有者(可通过_rpcClient.GetTokenAccountInfo(bTokenAccount)查询)。
  • 确认bTokenAccount初始余额≥5000(通过_rpcClient.GetTokenAccountBalance(bTokenAccount)查询)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:10:31