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

Anchor实现双签名者交易 指定公司方支付员工注册手续费

Anchor 双签名者员工注册交易实现(公司承担手续费)

现有代码问题

  • #[account(init)] 修饰的新建employee_account缺少signer约束,不符合Solana链上强制规则:新创建的普通账户必须作为签名者参与交易才能完成初始化。
  • 结构体冗余定义了authority: Signer字段,但测试代码的签名列表中没有传入对应密钥,交易执行时会直接抛出缺少签名的错误。
  • 前端代码没有显式指定交易手续费支付方,默认会使用provider连接的钱包支付手续费,不符合公司付费的需求。

注意:#[account(init, payer = company_account)]仅指定新员工账户的租金支付方,和交易手续费的支付方没有绑定关系,手续费需要在交易构造时单独指定。

修正后的链上账户结构体

#[derive(Accounts)]
pub struct SignupEmployee<'info> {
    #[account(
        init,
        payer = company_account,
        space = 8 + 32 + 32,
        signer // 新建账户必须加签名校验
    )]
    pub employee_account: Account<'info, EmployeeState>,

    #[account(mut)]
    pub company_account: Signer<'info>,

    pub system_program: Program<'info, System>,
}

这里去掉了冗余的authority字段,当前测试逻辑里新生成的employeeAccount密钥对就是员工持有的签名密钥,员工通过对该交易签名完成注册授权,不需要额外的authority字段。如果后续业务调整为员工使用已有独立钱包签名、员工状态账户为PDA的场景,再单独加员工签名字段即可。

修正后的前端测试代码

核心是显式指定feePayer为公司账户,保证交易手续费从公司账户扣除,签名列表只传入实际需要的两个签名密钥:

const employeeAccount = anchor.web3.Keypair.generate();

// 构造交易
const tx = await program.methods.signupEmployee()
  .accounts({
    companyAccount: companyAccount.publicKey,
    employeeAccount: employeeAccount.publicKey,
    systemProgram: anchor.web3.SystemProgram.programId,
  })
  .transaction();

// 明确指定交易手续费由公司账户支付
tx.feePayer = companyAccount.publicKey;
// 获取最新区块哈希
tx.recentBlockhash = (await provider.connection.getLatestBlockhash()).blockhash;

// 传入两个签名者:员工账户密钥、公司账户密钥,完成签名并上链
await anchor.web3.sendAndConfirmTransaction(
  provider.connection,
  tx,
  [employeeAccount, companyAccount]
);

关键校验点

  • 所有标记为Signer类型、以及添加#[account(signer)]约束的账户,必须在交易签名列表中传入对应密钥,否则链上会直接拒绝交易。
  • 交易手续费永远从tx.feePayer指定的账户扣除,和账户结构体里的租金支付方配置无关,你可以根据业务需求将两者设为同一账户,也可以分开设置。
  • 新创建的普通账户(非PDA)必须作为签名者参与初始化交易,这是Solana网络的底层规则,没有绕过方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:39:19