NomicFoundation / hardhat

Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software.
https://hardhat.org
Other
7.07k stars 1.36k forks source link

hardhat-web3 and manual mining don't work in the in-process network #1444

Open fvictorio opened 3 years ago

fvictorio commented 3 years ago

Given this script:

// script.js
async function main() {
  const [a1, a2] = await web3.eth.getAccounts()

  await network.provider.send("evm_setAutomine", [false])

  web3.eth.sendTransaction({from: a1, to: a2})
  web3.eth.sendTransaction({from: a2, to: a1})

  await new Promise(res => setTimeout(res, 1000))

  await network.provider.send("evm_mine")
  let block = await web3.eth.getBlock("latest")
  console.log(block.transactions.length);

  await network.provider.send("evm_mine")
  block = await web3.eth.getBlock("latest")
  console.log(block.transactions.length);

  await network.provider.send("evm_mine")
  block = await web3.eth.getBlock("latest")
  console.log(block.transactions.length);
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

If you run hh run script.js, the output is 1 1 0, instead of the expected 2 0 0.

If you start a node in another terminal and then do hh run script.js --network localhost, you do get the expected output.

Lopol2010 commented 2 years ago

It also doesn't work in hardhat-ethers. Both node and in-process. Tests just hang until a timeout of 20sec is reached. Here is the code:

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Greeter", function () {
  it("Should return the new greeting once it's changed", async function () {

    ethers.provider.send("evm_setAutomine", [false]);
    ethers.provider.send("evm_setIntervalMining", [0]);

    ethers.provider.send("evm_increaseTime", [60]);
    ethers.provider.send("evm_mine");

    const Greeter = await ethers.getContractFactory("Greeter");
    const greeter = await Greeter.deploy("Hello, world!");
    await greeter.deployed();

    expect(await greeter.greet()).to.equal("Hello, world!");

    const setGreetingTx = await greeter.setGreeting("Hola, mundo!");

    // wait until the transaction is mined
    await setGreetingTx.wait();

    expect(await greeter.greet()).to.equal("Hola, mundo!");

    ethers.provider.send("evm_increaseTime", [60]);
    ethers.provider.send("evm_mine");

  });
});
fvictorio commented 2 years ago

@Lopol2010 it's because you are doing await greeter.deployed(); after deploying the contract. That will wait until the deploy transaction is mined, but since you call evm_mine after that, the test will hang forever.

Lopol2010 commented 2 years ago

@fvictorio thank you very much!

I also noticed that the same rule applies to wait() function.