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

Web3.js发起多笔交易遇Nonce错误,如何处理及追踪Nonce值?

解决Nonce不匹配问题及追踪方法

问题原因

你同时发起两笔交易时,两次web3.eth.getTransactionCount调用几乎同步执行,拿到的是同一个账户nonce值。当第一笔交易提交后,账户nonce已更新,但第二笔仍使用旧值,最终触发nonce不匹配错误。

解决方案

1. 串行执行交易(最可靠)

等第一笔交易确认后再发起第二笔,确保每次获取的nonce都是最新状态:

async function executeTransactions() {
  // 获取初始nonce
  let txCount = await web3.eth.getTransactionCount(ENV.account);

  // 第一笔认证交易
  const authTx = {
    nonce: web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(800000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    to: ENV.contractAddress,
    data: contract.methods.auth(ENV.deviceName, ENV.serialNumber).encodeABI()
  };
  const authRaw = txToRaw(authTx); // 修正你代码里的笔误toToRaw为txToRaw
  await new Promise((resolve, reject) => {
    web3.eth.sendSignedTransaction(authRaw, (err, txHash) => {
      if (err) return reject(err);
      console.log("认证交易哈希:", txHash);
      console.log("认证成功!");
      resolve();
    });
  });

  // 第二笔创建证明交易,nonce手动+1
  txCount += 1;
  const createTx = {
    nonce: web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(800000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    to: ENV.contractAddress,
    data: contract.methods.createAbstract(
      "2022",
      web3.utils.utf8ToHex(ENV.serialNumber),
      contexts.ipfsHash,
      web3.utils.utf8ToHex(soilData),
      "xx"
    ).encodeABI()
  };
  const createRaw = txToRaw(createTx);
  await new Promise((resolve, reject) => {
    web3.eth.sendSignedTransaction(createRaw, (err, txHash) => {
      if (err) return reject(err);
      console.log("创建证明交易哈希:", txHash);
      console.log("创建证明成功!");
      resolve();
    });
  });
}

executeTransactions().catch(err => console.error("交易失败:", err));

2. 手动维护nonce值

若不需要等待第一笔交易确认(适合链上确认慢的场景,Ganache中慎用),可先获取一次nonce再手动递增:

web3.eth.getTransactionCount(ENV.account).then((txCount) => {
  // 第一笔交易使用初始nonce
  const authTx = {
    nonce: web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(800000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    to: ENV.contractAddress,
    data: contract.methods.auth(ENV.deviceName, ENV.serialNumber).encodeABI()
  };
  const authRaw = txToRaw(authTx);
  web3.eth.sendSignedTransaction(authRaw, (err, txHash) => {
    if (err) console.error("认证错误:", err);
    else console.log("认证成功,哈希:", txHash);
  });

  // 第二笔交易直接使用nonce+1
  const createTx = {
    nonce: web3.utils.toHex(txCount + 1),
    gasLimit: web3.utils.toHex(800000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    to: ENV.contractAddress,
    data: contract.methods.createAbstract(
      "2022",
      web3.utils.utf8ToHex(ENV.serialNumber),
      contexts.ipfsHash,
      web3.utils.utf8ToHex(soilData),
      "xx"
    ).encodeABI()
  };
  const createRaw = txToRaw(createTx);
  web3.eth.sendSignedTransaction(createRaw, (err, txHash) => {
    if (err) console.error("创建证明错误:", err);
    else console.log("创建证明成功,哈希:", txHash);
  });
});

Nonce追踪方法

  • 已确认交易的nonce:执行web3.eth.getTransactionCount(ENV.account),返回账户已完成交易的数量,即下一笔交易的基础nonce。
  • 包含pending交易的nonce:执行web3.eth.getTransactionCount(ENV.account, 'pending'),返回包含未确认交易在内的总nonce值(Ganache交易确认快,需在交易提交后稍等再调用才能拿到正确值)。
  • Ganache界面查看:打开Ganache客户端,找到对应账户,直接查看交易记录和当前账户的nonce值,直观追踪。

关于pending参数无效的说明

Ganache作为本地测试链,交易确认速度极快,并行调用getTransactionCount时,第一笔交易可能还未进入pending池,两次调用会拿到同一个已确认的nonce值,因此pending参数无法解决并行交易的冲突问题,串行执行是最可靠的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:40:44