"the tx doesn't have the correct nonce":使用hardhat调用ganache上部署的合约遇到的一个错误

发布时间 2023-12-18 10:28:52作者: 肥兔子爱豆畜子
完整的报错
==================>查询存证请求
存证请求内容, datahash:0xaad2171441bd73b773e9a9e062753909360bdfcabbddbe93c6c58b13c5c0feaa, 创建人:0xF7A1938Fecc594aaF126d46fd173cE74A659ad9A, 附加信息:0x66656974757a6920616920646f756368757a69, 已投票:0n, 共需投票:2n
==================>存证请求需要两个以上地址vote

Error: could not coalesce error (error={ "code": -32000, "message": "the tx doesn't have the correct nonce. account has nonce of: 21 tx has nonce of: 20", "stack": "Error: the tx doesn't have the correct nonce. account has nonce of: 21 tx has nonce of: 20\n    at TransactionPool.prepareTransaction (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:122021)" }, payload={ "id": 23, "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [ "0x02f89182053914843b9aca008445c21fcc830123d8941ea80e037af8715c7837638e1f4ed6d729029a9380a4ab9beda7aad2171441bd73b773e9a9e062753909360bdfcabbddbe93c6c58b13c5c0feaac080a0d596794b96bd555c3cf682d7968e02e986a7bf00ee6064b9112833f19cbfa57ea0090e9ba12302f6ab20108e2e0ab16248bb5d99e130bffdbb4daa3b39ae129f92" ] }, code=UNKNOWN_ERROR, version=6.9.0)
    at makeError (C:\Users\linyang\evidence\node_modules\ethers\src.ts\utils\errors.ts:694:21)
    at JsonRpcProvider.getRpcError (C:\Users\linyang\evidence\node_modules\ethers\src.ts\providers\provider-jsonrpc.ts:1007:25)
    at C:\Users\linyang\evidence\node_modules\ethers\src.ts\providers\provider-jsonrpc.ts:527:45
    at processTicksAndRejections (node:internal/process/task_queues:95:5) {
  code: 'UNKNOWN_ERROR',
  error: {
    message: "the tx doesn't have the correct nonce. account has nonce of: 21 tx has nonce of: 20",
    stack: "Error: the tx doesn't have the correct nonce. account has nonce of: 21 tx has nonce of: 20\n" +
      '    at TransactionPool.prepareTransaction (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:122021)',
    code: -32000
  },
  payload: {
    method: 'eth_sendRawTransaction',
    params: [
      '0x02f89182053914843b9aca008445c21fcc830123d8941ea80e037af8715c7837638e1f4ed6d729029a9380a4ab9beda7aad2171441bd73b773e9a9e062753909360bdfcabbddbe93c6c58b13c5c0feaac080a0d596794b96bd555c3cf682d7968e02e986a7bf00ee6064b9112833f19cbfa57ea0090e9ba12302f6ab20108e2e0ab16248bb5d99e130bffdbb4daa3b39ae129f92'
    ],
    id: 23,
    jsonrpc: '2.0'
  },
  shortMessage: 'could not coalesce error'
}
对应的Hardhat JavaScript代码
let evidenceContract = await new ethers.Contract(contractAddress, contractABI, provider);
let signer = await new ethers.Wallet("0x624cfb2cb9b9c3212abfa2800fd8de8e2501c84500336007f4459c50198c69f7", provider);
let evidenceContractConnected = await evidenceContract.connect(signer);
    //创建一个存证请求
    console.log("==================>新建存证请求");
    const ext = ethers.toUtf8Bytes("feituzi ai douchuzi");
    let txn = await evidenceContractConnected.createSaveRequest(sha256hash, ext);
    console.log("创建存证请求, 交易结果: %s", txn);
    await new Promise(r => setInterval(r, 1000));

    console.log("==================>查询存证请求");
    let request = await evidenceContractConnected.getRequestData(sha256hash);
    //bytes32, address creator, bytes memory ext, uint8 voted, uint8 threshold
    console.log("存证请求内容, datahash:%s, 创建人:%s, 附加信息:%s, 已投票:%s, 共需投票:%s", 
        request[0], request[1], request[2], request[3], request[4]);
    await new Promise(r => setInterval(r, 1000));

    //存证请求需要两个以上地址vote,第一个投票
    console.log("==================>存证请求需要两个以上地址vote");
    let result = await evidenceContractConnected.voteSaveRequest(sha256hash);
    console.log("%s对存证请求的投票结果%s", await signer.getAddress(), result);
    await new Promise(r => setInterval(r, 1000));
分析与解决

上面evidenceContractConnected是连了signer的合约对象,可以调用合约的写方法。然后在后面复用这个对象调用了多个方法,其中createSaveRequest,voteSaveRequest都是写方法。

the tx doesn't have the correct nonce. account has nonce of: 21 tx has nonce of: 20

上面这个报错意思是tx的nonce比account的落后1,google了一下都是建议两次调用之间加一下time wait,所以可以使用如下代码解决:

await new Promise(r => setInterval(r, 1000));