matter-labs / hardhat-zksync

Apache License 2.0
281 stars 226 forks source link

Current nonce not fetched on transaction calls #655

Closed timbrinded closed 8 months ago

timbrinded commented 11 months ago

🐛 Bug Report for hardaht-zksync plugins

💥 Plugin name

@matterlabs/hardhat-zksync-ethers

📝 Description

When using the zksync hardhat stack for ethers6, the nonce for write txns are not automatically updated.

🔄 Reproduction Steps

Consider the test file:

import { expect } from "chai";
import { Wallet } from "zksync-ethers";
import { RICH_ACCOUNTS } from "../utils";
import * as hre from "hardhat";

const getWallet = (privateKey?: string) => {
  const wallet = new Wallet(
    privateKey ?? process.env.WALLET_PRIVATE_KEY ?? RICH_ACCOUNTS[0].privateKey,
    hre.zksyncEthers.provider
  );

  return wallet;
};

describe("Unit: Basic Test", async function () {
  let ownerWallet: Wallet;
  let userWallet: Wallet;

  before(async function () {
    ownerWallet = getWallet(RICH_ACCOUNTS[0].privateKey);
    userWallet = getWallet(RICH_ACCOUNTS[9].privateKey);
  });

  it("Should send bal", async function () {
    await ownerWallet.transfer({
      to: userWallet.address,
      amount: 1000000000000000000n,
    });

    expect(true).to.be.true;
  });

  it("Should send bal", async function () {
    await ownerWallet.transfer({
      to: userWallet.address,
      amount: 1000000000000000000n,
    });

    expect(true).to.be.true;
  });
});

[!NOTE]
The only custom code here is RICH_ACCOUNTS which is just a const map of private keys and addresses as strings

🤔 Expected Behavior

Given the two trivial expects, two successful txns and passes.

😯 Current Behavior

> hardhat test

Unit: Basic Test
✔ Should be send money (146ms)
1) Should be send money

1 passing (231ms)
1 failing

1) Unit: Basic Test
Should be send money:
Error: could not coalesce error (error={ "code": 3, "data": "0x8b5742b069a6749baf046db7ec0ae35f9149b912bcc274349a498a5fda347701", "message": "Execution error: Transaction HALT: Account validation error: Reusing the same nonce twice" }, payload={ "id": 16, "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [ "0xf86e80840ee6b280830b19c194e90e12261ccb0f3f7976ae611a29e84a6a85f424880de0b6b3a76400008082022ba062f1baf2e03d1618452d065c17ad489e29fb21fac2c5689d4681d13863c2c525a067762c9d3903636d580818b2bd73c1d24ba427ba37f2671823137b28a77f50de" ] }, code=UNKNOWN_ERROR, version=6.9.2)
at makeError (node_modules/.pnpm/ethers@6.9.2/node_modules/ethers/src.ts/utils/errors.ts:694:21)
at Provider.getRpcError (node_modules/.pnpm/ethers@6.9.2/node_modules/ethers/src.ts/providers/provider-jsonrpc.ts:1049:25)
at /home/timbo/workspaces/tradable/zksync-pkg-test/node_modules/.pnpm/ethers@6.9.2/node_modules/ethers/src.ts/providers/provider-jsonrpc.ts:563:45
at processTicksAndRejections (node:internal/process/task_queues:95:5)

adding the following will make the tests pass as expected:

   overrides: {
     nonce: await hre.zksyncEthers.provider.getTransactionCount(
       ownerWallet.address
     ),
   },

🖥️ Environment

📋 Additional Context

[!IMPORTANT]
I have noticed that this library doesn't implement getNonce() alias for getTransactionCount() which might be causing this issue.

package.json:

{
  "name": "zksync-pkg-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "hardhat test",
    "compile": "hardhat compile"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@matterlabs/hardhat-zksync-chai-matchers": "^1.2.1",
    "@matterlabs/hardhat-zksync-deploy": "1.1.2",
    "@matterlabs/hardhat-zksync-ethers": "0.0.1-beta.2",
    "@matterlabs/hardhat-zksync-node": "1.0.1",
    "@matterlabs/hardhat-zksync-solc": "1.0.6",
    "@matterlabs/hardhat-zksync-verify": "^1.2.2",
    "@matterlabs/zksync-contracts": "0.6.1",
    "@openzeppelin/contracts": "5.0.1",
    "@openzeppelin/contracts-upgradeable": "5.0.1",
    "@typechain/ethers-v6": "0.5.1",
    "@typechain/hardhat": "9.1.0",
    "@types/chai": "4.3.11",
    "@types/chai-as-promised": "^7.1.8",
    "@types/mocha": "10.0.6",
    "chai": "4.2.0",
    "chai-as-promised": "^7.1.1",
    "dotenv": "16.3.1",
    "ethers": "^6.9.2",
    "hardhat": "2.19.4",
    "ts-node": "10.9.2",
    "typechain": "8.3.2",
    "typescript": "5.3.3",
    "zksync-ethers": "6.0.0"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "outDir": "tmp",
    "incremental": true,
    "target": "ES2020",
    "module": "commonjs",
    "noEmit": true,
    "esModuleInterop": true,
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "skipDefaultLibCheck": true
  },
  "include": ["deploy", "test", "./hardhat.config.ts", "utils"],
  "exclude": ["node_modules", "artifacts-zk", "cache", "cache-zk"]
}

hardhat.config.ts:

import "@matterlabs/hardhat-zksync-node";
import "@matterlabs/hardhat-zksync-deploy";
import "@matterlabs/hardhat-zksync-solc";
import "@matterlabs/hardhat-zksync-ethers";
import "@matterlabs/hardhat-zksync-verify"
import "@matterlabs/hardhat-zksync-chai-matchers";
import "@typechain/hardhat";
import { HardhatUserConfig } from "hardhat/config";

export const inMemoryNode = "http://127.0.0.1:8011";

const config: HardhatUserConfig = {
  defaultNetwork: "hardhat",
  networks: {
    hardhat: {
      zksync: true,
    },
    inMemoryNode: {
      url: "http://127.0.0.1:8011",
      ethNetwork: "", // in-memory node doesn't support eth node; removing this line will cause an error
      zksync: true,
    },
    dockerizedNode: {
      url: "http://localhost:3050",
      ethNetwork: "http://localhost:8545",
      zksync: true,
    },
    zkSyncTestnet: {
      url: "https://sepolia.era.zksync.dev", // The testnet RPC URL of zkSync Era network.
      ethNetwork: "sepolia", // The Ethereum Web3 RPC URL, or the identifier of the network (e.g. `mainnet` or `sepolia`)
      zksync: true,
      verifyURL: "https://explorer.sepolia.era.zksync.dev/contract_verification",
    },
    zkSyncTestnetGoerli: {
      url: "https://testnet.era.zksync.dev",
      ethNetwork: "goerli",
      zksync: true,
      verifyURL: "https://zksync2-testnet-explorer.zksync.dev/contract_verification",
    },
    zkSyncMainnet: {
      url: "https://mainnet.era.zksync.io",
      ethNetwork: "mainnet",
      zksync: true,
      verifyURL: "https://zksync2-mainnet-explorer.zksync.io/contract_verification",
    },
  },
  zksolc: {
    version: "1.3.19",
    settings: {
      // find all available options in the official documentation
      // https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-solc.html#configuration
      optimizer: {
        enabled: true,
        mode: "3",
      },
    },
  },
  solidity: {
    version: "0.8.21",
  },
};

export default config;
nikola-bozin-txfusion commented 11 months ago

Hey @timbrinded, could you share your hardhat.config please?

timbrinded commented 11 months ago

@nikola-bozin-txfusion Updated ticket with HH config

tahos81 commented 10 months ago

I am also having the same issue

mpopovac-txfusion commented 10 months ago

Hey @timbrinded , I think this is not connected to the plugin itself, as I tried using the Provider from zksync-ethers and it was still the same. This is probably related to this issue with the era-test-node against which the tests are run. We will let you know when this is resolved.

uF4No commented 8 months ago

Duplicated from #714.

Just for visibility, see the workaround for this issue