You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Serum Anchor中实现双账户向同一Vault转账时遇自定义程序错误0x3的排查求助

分析你的Solana智能合约错误(0x3)

错误码0x3在Solana自定义程序错误中对应ConstraintHasOne,也就是你的SecondSend结构体里的has_one约束检查失败了。我们一步步排查问题:

1. from账户的has_one = owner约束不满足

看你的测试代码:

await program.rpc.secondSend({
    accounts: {
        // ...
        "from": satan,
        "owner": program.provider.wallet.publicKey,
        // ...
    },
});

这里的fromsatan对应的TokenAccount,而TokenAccount的owner应该是satan的钱包公钥,不是program.provider.wallet.publicKey。你的合约里from字段标注了has_one = owner,意味着传入的owner必须等于from这个TokenAccount的owner字段值,这是当前最可能触发0x3错误的原因。

修复方案:把测试里的owner改成satan对应的钱包公钥,比如如果satan是你创建的测试钱包,就用satan.publicKey

2. 确认checkhas_one = vault约束

你的check账户标注了has_one = vault,需要确保测试中传入的vault公钥和创建支票时存入check.vault的公钥完全一致。如果创建支票时用的是另一个vault地址,这里就会触发约束错误。

可以在测试中打印check.account.vault和传入的vault.publicKey,对比是否相等。

3. 验证check_signer的PDA是否正确

合约中second_send用的是支票账户的PDA作为签名者,seeds是:

let seeds = &[
    ctx.accounts.check.to_account_info().key.as_ref(),
    &[ctx.accounts.check.nonce],
];

所以测试中的checkSigner必须是通过相同seeds生成的PDA:

const [checkSigner] = await web3.PublicKey.findProgramAddress(
    [check.publicKey.toBuffer(), Buffer.from([nonce])], // nonce是创建支票时用的那个nonce
    program.programId
);

如果你的checkSigner不是这么生成的,签名验证会失败,也可能间接触发约束错误。

4. 其他潜在问题

  • 确保satan的TokenAccount余额足够支付check.amount,余额不足也可能导致错误,但0x3更偏向约束问题。
  • 检查Check结构体中burned字段是否在创建时初始化为false,如果没有初始化,可能导致后续逻辑错误,但不是当前0x3的直接原因。

把这些点逐一排查,尤其是fromowner的匹配问题,应该就能解决这个错误了。

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

火山引擎 最新活动