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

使用Solnet与Solana交互创建代币时遇交易模拟失败问题

Solnet交易报错:Attempt to debit an account but found no record of a prior credit

问题描述

使用Solnet与Solana DevNet交互时,执行创建并初始化代币铸造账户的交易时触发以下错误:

Transaction simulation failed: Attempt to debit an account but found no record of a prior credit.

但通过solana-cli执行完全相同的操作时无任何问题。已验证GetRecentBlockHash和GetLatestBlockHash均能成功返回有效区块哈希,错误出现在Examples.SubmitTxSendAndLog(createAndInitializeMintToTx);代码行。

相关代码如下:

Wallet wallet = new Wallet(MnemonicWords);

IRpcClient RpcClient = ClientFactory.GetClient(Cluster.DevNet);

#region 创建并初始化代币铸造账户

RequestResult<ResponseValue<LatestBlockHash>> blockHash = RpcClient.GetLatestBlockHash(Solnet.Rpc.Types.Commitment.Finalized);

ulong minBalanceForExemptionAcc =
    RpcClient.GetMinimumBalanceForRentExemption(TokenProgram.TokenAccountDataSize).Result;
ulong minBalanceForExemptionMint =
    RpcClient.GetMinimumBalanceForRentExemption(TokenProgram.MintAccountDataSize).Result;

Console.WriteLine($"免租金最低余额(账户)>> {minBalanceForExemptionAcc}");
Console.WriteLine($"免租金最低余额(铸造账户)>> {minBalanceForExemptionMint}");

Account ownerAccount = wallet.GetAccount(10);
Account mintAccount = wallet.GetAccount(11);
Account initialAccount = wallet.GetAccount(12);
Console.WriteLine($"所有者账户: {ownerAccount}");
Console.WriteLine($"铸造账户: {mintAccount}");
Console.WriteLine($"初始代币账户: {initialAccount}");

byte[] createAndInitializeMintToTx = new TransactionBuilder().
    SetRecentBlockHash(blockHash.Result.Value.Blockhash).
    SetFeePayer(ownerAccount).
    AddInstruction(SystemProgram.CreateAccount(
        ownerAccount,
        mintAccount,
        minBalanceForExemptionMint,
        TokenProgram.MintAccountDataSize,
        TokenProgram.ProgramIdKey)).
    AddInstruction(TokenProgram.InitializeMint(
        mintAccount.PublicKey,
        2,
        ownerAccount.PublicKey,
        ownerAccount.PublicKey)).
    AddInstruction(SystemProgram.CreateAccount(
        ownerAccount,
        initialAccount,
        minBalanceForExemptionAcc,
        TokenProgram.TokenAccountDataSize,
        TokenProgram.ProgramIdKey)).
    AddInstruction(TokenProgram.InitializeAccount(
        initialAccount.PublicKey,
        mintAccount.PublicKey,
        ownerAccount.PublicKey)).
    AddInstruction(TokenProgram.MintTo(
        mintAccount.PublicKey,
        initialAccount.PublicKey,
        1_000_000,
        ownerAccount)).
    AddInstruction(MemoProgram.NewMemo(initialAccount, "Hello from Sol.Net")).
    Build(new List<Account> { ownerAccount, mintAccount, initialAccount });

string createAndInitializeMintToTxSignature = Examples.SubmitTxSendAndLog(createAndInitializeMintToTx);

if (!string.IsNullOrEmpty(createAndInitializeMintToTxSignature))
    Examples.PollConfirmedTx(createAndInitializeMintToTxSignature);

public static string SubmitTxSendAndLog(byte[] tx)
{
    Console.WriteLine($"交易数据: {Convert.ToBase64String(tx)}");

    RequestResult<ResponseValue<SimulationLogs>> txSim = RpcClient.SimulateTransaction(tx);
    string logs = PrettyPrintTransactionSimulationLogs(txSim.Result.Value.Logs);
    Console.WriteLine($"交易模拟:\n\t错误: {txSim.Result.Value.Error}\n\t日志: \n" + logs);

    RequestResult<string> txReq = RpcClient.SendTransaction(tx);
    Console.WriteLine($"交易签名: {txReq.Result}");

    Console.WriteLine(txReq.Reason);

    return txReq.Result;
}

问题分析

该错误核心是交易尝试从一个无余额/未正确初始化的账户扣款。结合你的场景,可能的原因包括:

  1. Memo指令签名者错误:使用initialAccount作为Memo的签名者,但该账户是刚通过SystemProgram.CreateAccount创建的,此时它仅拥有租金豁免的SOL,且在交易执行流程中尚未完成初始化,Solana节点会误判为尝试从该账户扣款。
  2. 费用支付账户余额不足:虽然cli操作正常,但需确认代码中ownerAccount(钱包第10个账户)在DevNet上的余额是否足够覆盖两个账户的租金豁免金额 + 交易手续费。
  3. 区块哈希的提交确认度设置过严:使用Commitment.Finalized获取区块哈希,可能导致哈希过期(Finalized区块的确认时间较长),间接引发交易验证问题。

解决方案

1. 修改Memo指令的签名者

将Memo的签名者替换为ownerAccount(已拥有足够SOL的费用支付账户),避免从新创建的空账户发起签名:

// 原代码
// AddInstruction(MemoProgram.NewMemo(initialAccount, "Hello from Sol.Net")).
// 修改后
AddInstruction(MemoProgram.NewMemo(ownerAccount, "Hello from Sol.Net")).

2. 验证费用支付账户余额

在solana-cli中执行以下命令,确认ownerAccount的地址余额:

solana balance <ownerAccount的公钥地址> --url devnet

确保余额 ≥ minBalanceForExemptionMint + minBalanceForExemptionAcc + 0.000005 SOL(手续费预留),如果不足可以通过DevNet水龙头领SOL:

solana airdrop 2 <ownerAccount的公钥地址> --url devnet

3. 调整区块哈希的提交确认度

将获取区块哈希的确认度从Finalized改为Confirmed,减少哈希过期的概率:

// 原代码
// RequestResult<ResponseValue<LatestBlockHash>> blockHash = RpcClient.GetLatestBlockHash(Solnet.Rpc.Types.Commitment.Finalized);
// 修改后
RequestResult<ResponseValue<LatestBlockHash>> blockHash = RpcClient.GetLatestBlockHash(Solnet.Rpc.Types.Commitment.Confirmed);

验证修改

重新运行代码,交易模拟和发送应该能正常执行,你可以通过solana-cli查询铸造账户和代币账户的状态:

solana token-supply <mintAccount的公钥地址> --url devnet
solana account <initialAccount的公钥地址> --url devnet

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:15:07