`upgrades.deployProxy` hangs indefinitely on `hh coverage`

upgrades.deployProxy works as expected on npx hardhat test (or hh test), but hangs indefinitely in my project on hh coverage until the test fails with:

Error: Timed out waiting for implementation contract deployment to address 0x5FbDB2315678afecb367f032d93F642f64180aa3 with transaction 0xa4921ba0e4fd298aa1ddc2e35d440a92d213ece0d0eb44251632a96f19edef7d

Run the function again to continue waiting for the transaction confirmation. If the problem persists, adjust the polling parameters with the timeout and pollingInterval options.
      at waitAndValidateDeployment (node_modules/@openzeppelin/upgrades-core/src/deployment.ts:169:17)
      at async fetchOrDeployGeneric (node_modules/@openzeppelin/upgrades-core/src/impl-store.ts:70:5)
      at async deployImpl (node_modules/@openzeppelin/hardhat-upgrades/src/utils/deploy-impl.ts:114:16)
      at async Proxy.deployProxy (node_modules/@openzeppelin/hardhat-upgrades/src/deploy-proxy.ts:42:28)

The issue seems to be with the eth_sendTransaction call to deploy the implementation contract not getting mined, because eth_getTransactionReceipt for that transaction returns null after each poll.

After the error, my .openzeppelin/unknown-31337.json file contains "impls" with an "address" and "txHash" but an empty "proxies" array:

{
  "manifestVersion": "3.2",
  "proxies": [],
  "impls": {
    "5f2a9f5431308d48b9e3e2766e716f7ecec632d6781db87ed48a296f48c257f7": {
      "address": "0x6c198aa7D4817c62dE7A338316769Be784167646",
      "txHash": "0x7969483ee49bd905044a6b609d930d39e0404271f4c102cb5d5494325ff68b10",

Here's my test and attempted deployment:

import { ethers, upgrades } from "hardhat";

describe("Tests", () => {
  it("works", async () => {
    const factory = await ethers.getContractFactory("MyContractV1");
    await upgrades.deployProxy(factory, [40, 20], { kind: "uups" });
    console.log("deployed"); // outputs on `hh test` but not `hh coverage`
  });
});

And when running in debug mode (DEBUG='*' hh coverage), the following lines are outputted:

  @openzeppelin:upgrades:core initiated deployment transaction hash: 0x704ccf5054e6c77ed09654bc78e3ab2a29f113e74ca3d894b4bdc82d8cc9558e merge: undefined +211ms
  @openzeppelin:upgrades:core polling timeout 60000 polling interval 5000 +2ms
  @openzeppelin:upgrades:core verifying deployment tx mined 0x704ccf5054e6c77ed09654bc78e3ab2a29f113e74ca3d894b4bdc82d8cc9558e +0ms
  @openzeppelin:upgrades:core waiting for deployment tx mined 0x704ccf5054e6c77ed09654bc78e3ab2a29f113e74ca3d894b4bdc82d8cc9558e +73ms
  @openzeppelin:upgrades:core verifying deployment tx mined 0x704ccf5054e6c77ed09654bc78e3ab2a29f113e74ca3d894b4bdc82d8cc9558e +5s
  @openzeppelin:upgrades:core waiting for deployment tx mined 0x704ccf5054e6c77ed09654bc78e3ab2a29f113e74ca3d894b4bdc82d8cc9558e +178ms

Unfortunately, I've been unable to produce an MRE; otherwise, I would share it. deployProxy seems to work ok in hh coverage in a fresh project.

Packages:

"@nomiclabs/hardhat-ethers": "^2.0.5",
 "@openzeppelin/hardhat-upgrades": "^1.17.0",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.6.2",
"hardhat": "^2.9.2",
"mocha": "^9.2.2",
"solidity-coverage": "^0.7.20",
"@openzeppelin/contracts-upgradeable": "4.3.3"

I'm hoping someone would be able to point me in the right direction, as I've come up empty-handed after endless hours of debugging. Thanks.

Does the address and/or txHash in the timeout message match with any address and/or txHash in the .openzeppelin/unknown-31337.json file? It's not clear to me how the contract at the address 0x6c198aa7D4817c62dE7A338316769Be784167646 in your file was deployed (unless it was from a previous run).

Would you be able to share your project by any chance? I was not able to reproduce this in my testing.

Hi @ericglau. After running rm -rf .openzeppelin && yarn coverage, the implementation addresses in the timeout error and .json file match:

Error: Timed out waiting for implementation contract deployment to address 0x6c198aa7D4817c62dE7A338316769Be784167646 with transaction 0x9ddceb751327de2497c680be9c2f2194561226383f13f16e721f467561276d0f.

{
  "manifestVersion": "3.2",
  "proxies": [],
  "impls": {
    "276222b1cf8b724a26df50488888f1b9f5a7f3a4f1b5eed221ab14f3856a2f4f": {
      "address": "0x6c198aa7D4817c62dE7A338316769Be784167646",
      "txHash": "0x9ddceb751327de2497c680be9c2f2194561226383f13f16e721f467561276d0f",

Hardhat logs:

eth_sendTransaction
  Contract deployment: MyContract
  Contract address:    0x6c198aa7d4817c62de7a338316769be784167646
  Transaction:         0x9ddceb751327de2497c680be9c2f2194561226383f13f16e721f467561276d0f
  From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  Value:               0 ETH
  Gas used:            4767988 of 4767988
  Block #29687341:     0xb0c1f9c112fbfc65803ecef4e6d019b697859c4ae3ce174a8cef2e6befc7f786

eth_chainId
eth_getTransactionByHash
eth_getTransactionReceipt (3)

Wondering if this is an issue with @openzeppelin/upgrades or solidity-coverage's in-process ganache server.

Hi @dtp5, thanks for that information. Can you check whether the address is written to the .json file before or after the timeout occurs (and have you tried increasing the timeout)? If you are using ganache, can you try using Hardhat network instead?

@ericglau, the address is written to the .json file before the timeout occurs. I've tried disabling the timeout altogether by setting it to 0. Strangely enough, the test succeeds in Hardhat with hh test but not with hh coverage (solidity-coverage apparently spins up its own ganache server; running hh coverage against a localhost Hardhat node throws Error in plugin solidity-coverage: Error: Cannot find module 'ganache-cli'.).

This sounds like it could be an issue with the node where the transaction isn't being mined. From the solidity-coverage docs, it uses a Hardhat network by default so I'm not sure what is the difference with hardhat test.

In order to look into this further, could you share a repo that we can use to reproduce this?