Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Ganache mines two different transactions with the same "from" and "nonce" #3794

Open
olehmisar opened this issue Oct 12, 2022 · 3 comments · May be fixed by #3498
Open

Ganache mines two different transactions with the same "from" and "nonce" #3794

olehmisar opened this issue Oct 12, 2022 · 3 comments · May be fixed by #3498

Comments

@olehmisar
Copy link

olehmisar commented Oct 12, 2022

Reproduction. You need to fork repl (top right corner) to see the console.

Ethereum does not allow two different transactions with the same from and nonce. But ganache does. In the repro, we can verify that it indeed confirmed those two transactions because the balance of the destination address is 3 (1 + 2).

I want simulate transaction replacement behaviour locally but I can't because of this bug.

@jeffsmale90
Copy link
Contributor

Thanks @olehmisar for raising this issue!

@MicaiahReid and myself have looked into the problem, and have identified that the issue is only reproducible when Ganache is running in the same node process as the caller (in this case Ethers).

We were unable to reproduce the issue with:

  • Ganache running in a separate process
  • nor Interacting with Ganache directly as a provider (ganache.provider())

See PR #3498 that addresses similar transaction pool race conditions.

Here is a reproduction, against a locally running Ganache instance (with deterministic flag - ganache -d) that fails with the error the tx doesn't have the correct nonce. account has nonce of: 1 tx has nonce of: 0.

const ethers = require("ethers");

// this is the mnemonic generated by running Ganache in deterministic mode
// (ganache -d) and should only be used for development purposes.
// To run this reproduction, Ganache must be running locally (with this mnemonic)
const mnemonic =
  "myth like bonus scare over problem client lizard pioneer submit female collect";
const from = "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1";
const to = "0x14974A7C722E2dbA813519C026ba2D75718bd82D";
const port = 8545;

async function main() {
  const provider = new ethers.providers.StaticJsonRpcProvider(
    `http://localhost:${port}`
  );
  const wallet = new ethers.Wallet.fromMnemonic(mnemonic).connect(provider);

  const tx1 = await wallet.sendTransaction({
    from,
    to,
    nonce: 0,
    value: 1,
  });

  const tx2 = await wallet.sendTransaction({
    from,
    to,
    nonce: 0,
    value: 2,
  });

  await Promise.all([tx1.wait(), tx2.wait()]);
  console.log("balance:", (await provider.getBalance(destination)).toString());

  console.log({
    tx1,
    tx2,
  });
}

main();

@davidmurdoch
Copy link
Member

Looks like it is a duplicate of #2489. Let's keep this one open as well since it has good repro steps.

@davidmurdoch davidmurdoch linked a pull request Oct 12, 2022 that will close this issue
@MicaiahReid
Copy link
Contributor

@davidmurdoch I think it's a slightly different issue. #2489 is when Ganache is generating the nonce for the user. This one is when the user is specifying the same nonce for two transactions and Ganache doesn't reject it. Regardless, I think the new queue we've implemented in #3498 will resolve this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Status: Backlog
Development

Successfully merging a pull request may close this issue.

4 participants