Deploy upgradable contract with hardhat-upgrades fails on mainnet

Hello :slight_smile:

I’m using an upgradeable contract (uups) and want to deploy it with @openzeppelinopenzeppelin/hardhat-upgrades. It works correctly on Testnets (Sepolia, Amoy) and on my local Hardhat/Ganache network. However, when I deploy ti to mainnet it throws an error—I only see one transaction sent on mainnet, and nothing is generated in the .openzeppelin folder. Probably Something is going wrong inside the deployProxy method. Detailed Error is down, any help appreciated please. If this i a bug, any other way to deploy it while keeping the benefits of @openzeppelin/hardhat-upgrades . Thank you

:1234: Code to reproduce

Contract header:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
contract MyContract is Initializable, UUPSUpgradeable, AccessControlUpgradeable {
  using SafeERC20 for IERC20;
  constructor() {
    _disableInitializers();
  }
  function initialize(
    address x,
    address y,
    address z
  ) public initializer {
    __UUPSUpgradeable_init();
    __AccessControl_init();
    _grantRole(DEFAULT_ADMIN_ROLE, x);
    _grantRole(Y_ROLE, y);
    _grantRole(Z_ROLE, z);
  }
  function _authorizeUpgrade(
    address newContractAddress
  ) internal view override onlyRole(DEFAULT_ADMIN_ROLE) {}
//extra code
}

hardhat config

import "@nomicfoundation/hardhat-toolbox"
import "@openzeppelin/hardhat-upgrades"
import { HardhatUserConfig } from "hardhat/config"

const config: HardhatUserConfig = {
  defaultNetwork: "hardhat",
  networks: {
    hardhat: {
      blockGasLimit: 15000000,
      accounts: {
        mnemonic: "<MNEMONIC PLACEHOLDER>",
        count: 20
      }
    },
   alchemyEthereumSepolia: {
      url: "<ALCHEMY_ENDPOINT_PLACEHOLDER_SEPOLIA>",
      accounts: {
        mnemonic: "<24 WORDS MNEMONIC PLACEHOLDER>",
        count: 1
      },
      chainId: 11155111,
    },
    mainnet: {
      url: "<ALCHEMY_ENDPOINT_PLACEHOLDER>",
      accounts: {
        mnemonic: "<24 WORDS MNEMONIC PLACEHOLDER>",
        count: 1
      },
      chainId: 1,
    }
  },
  solidity: {
    version: "0.8.20",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },
  paths: {
    sources: "./contracts",
    tests: "./test",
    cache: "./cache",
    artifacts: "./artifacts"
  }
}

Deployment script

const hre = require("hardhat")
import { ethers, upgrades } from "hardhat"

async function main() {
  console.log(`Deploy MyContract to network ${hre.network.name}`)
  let x: any
  let y: any
  let z: any

 x = { address: "0xd095651387CA5645d79CFC865C84C21c4fe3C3b0" }
 y = { address: "0x45B870DaBCF34d4D767B7618E3dCCBEe092B4B0F" }
 z = { address: "0x223feD4f227cEc0cf672db674b3BB3b15393D861" }

  const MyContractV1 = await ethers.getContractFactory("MyContract")
  const myContractInstance = await upgrades.deployProxy(
    MyContractV1,
    [x.address, y.address, z.address],
    { kind: "uups", timeout:300000 }
  )
  await myContractInstance.waitForDeployment()

  console.log(
    `The proxy of MyContractV1 Contract deployed to address ${await myContractInstance.getAddress()}`
  )
}

main().catch((error) => {
  console.error(error)
  process.exitCode = 1
})

package.json

"deploy:mainnet": "npx hardhat run scripts/deploy_V1.ts --network mainnet", 
"deploy:alchemyEthereumSepolia": "npx hardhat run scripts/deploy_V1.ts --network alchemyEthereumSepolia",

When I run "npm run deploy:alchemyEthereumSepolia" it runs successfully and deploy proxy and impl. contracts and generate correct file in .openzeppelin folder.

When I run "npm run deploy:mainnet" it fails, no mainnet file generated in .openzeppelin and I see only 1 send tx (no revert) on etherscan

Deploy MyContract to network mainnet
  @openzeppelin:upgrades:core manifest file: .openzeppelin/mainnet.json fallback file: .openzeppelin/unknown-1.json +0ms
  @openzeppelin:upgrades:core manifest file: .openzeppelin/mainnet.json fallback file: .openzeppelin/unknown-1.json +168ms
  @openzeppelin:upgrades:core fetching deployment of implementation 69883a2bfafc894e21d92e1c2577976561d90c8c06ad9b44cd763ffeeb9431da +1ms

Error: invalid value for value.to (invalid address (argument="address", value="", code=INVALID_ARGUMENT, version=6.14.3)) (value={ "accessList": [  ], "blockHash": null, "blockNumber": null, "chainId": "0x1", "from": "0xcf3b7F1c803A1d9A43a1977c071cC03206d48F6f", "gas": "0x136393", "gasPrice": "0x1409d202", "hash": "0xe25725a2ee55f014f0901847a6bfc3d90cc63da58113ef9529bc9726dd15924a", "input": "0x60a06040523060805234801561001457600080fd5b5061001d610022565b6100d4565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100725760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d15780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200..........4602087016111c2565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680004f8ef0399d0eb67797e5a6fba786b56991342d35be1970865da94e87499c073a26469706673582212207ab9333cbec9332398b135a8048aadf01d195564619c36ad68131eb044d6d49d64736f6c63430008140033", "maxFeePerGas": "0x1409d202", "maxPriorityFeePerGas": "0x78ebac8", "nonce": "0x2", "r": "0x0", "s": "0x0", "to": "", "transactionIndex": null, "type": "0x2", "v": "0x0", "value": "0x0" }, code=BAD_DATA, version=6.14.3)
    at makeError (/Users/xxx/_Local/___Git/xx-xx-platform/x-solidity/node_modules/ethers/src.ts/utils/errors.ts:698:21)
    at assert (/Users/xxx/_Local/___Git/xx-xx-platform/x-solidity/node_modules/ethers/src.ts/utils/errors.ts:719:25)
    at /Users/xxx/_Local/___Git/xx-xx-platform/x-solidity/node_modules/@nomicfoundation/hardhat-ethers/src/internal/ethers-utils.ts:170:15
    at formatTransactionResponse (/Users/xxx/_Local/___Git/xx-xx-platform/x-solidity/node_modules/@nomicfoundation/hardhat-ethers/src/internal/ethers-utils.ts:251:4)
    at HardhatEthersProvider.getTransaction (/Users/xxx/_Local/___Git/xxx-platform/x-solidity/node_modules/@nomicfoundation/hardhat-ethers/src/internal/hardhat-ethers-provider.ts:327:32)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async checkTx (/Users/xxx/_Local/___Git/xxx-platform/x-solidity/node_modules/@nomicfoundation/hardhat-ethers/src/signers.ts:191:26) {
  code: 'BAD_DATA',
  value: {
    blockHash: null,
    blockNumber: null,
    from: '0xcf3b7F1c803A1d9A43a1977c071cC03206d48F6f',
    gas: '0x136393',
    gasPrice: '0x1409d202',
    maxFeePerGas: '0x1409d202',
    maxPriorityFeePerGas: '0x78ebac8',
    hash: '0xe25725a2ee55f014f0901847a6bfc3d90cc63da58113ef9529bc9726dd15924a',
    input: '0x60a06040523060805234801561001457600080fd5b5061001d610022565b6100d4565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561007257604...........001600160a01b038116811461123057600080fd5b919050565b6000806040838503121561124857600080fd5b8235915061125860208401611219565b90509250929050565b6000806000806080858703121561127757600080fd5b8435935061128760208601611219565b9250'... 1436 more characters,
    nonce: '0x2',
    to: '',
    transactionIndex: null,
    value: '0x0',
    type: '0x2',
    accessList: [],
    chainId: '0x1',
    v: '0x0',
    r: '0x0',
    s: '0x0'
  },
  shortMessage: 'invalid value for value.to (invalid address (argument="address", value="", code=INVALID_ARGUMENT, version=6.15.3))'
}

#### 💻 Environment

I'm using hardhat typescript project with Nodejs v22 on MacOs 15.5 (tested on 2 devices with enough ether balance)

```json
  "devDependencies": {
    "@nomicfoundation/hardhat-ethers": "3.1.0",
    "@nomicfoundation/hardhat-toolbox": "6.1.0",
    "@openzeppelin/contracts": "5.0.2",
    "@openzeppelin/contracts-upgradeable": "5.0.2",
    "@openzeppelin/hardhat-upgrades": "^3.9.1",
    "@types/uuid": "^10.0.0",
    "dotenv": "^16.5.0",
    "ethereumjs-util": "^7.1.5",
    "ethers": "^6.15.0",
  },
  "dependencies": {
    "hardhat": "^2.26.2"
  }
```
Tested also with hardhat 2.25.0 and ether 6.14.0

Thank you.

I also tried to deploy the implementation separately

async function main() {
  const MyContractV1 = await ethers.getContractFactory("MyContractV1");
  console.log("Deploying implementation..."); 
  const implementation = await upgrades.deployImplementation(MyContractV1, { kind: 'uups' }); 
  console.log("Implementation deployed to:", implementation);

Works on Sepolia. However, the library throws an error when deploying to mainnet with the same message as shown in the question. BUT I can see that the implementation contract is deployed on mainnet and No file in .openzeppelin is generated.

using the address of the implementation contract (from etherscan) and call this other script

async function main() {
  let x = { address: "0xd095651387CA5645d79CFC865C84C21c4fe3C3b0" }
  let y = { address: "0x45B870DaBCF34d4D767B7618E3dCCBEe092B4B0F" }
  let z = { address: "0x223feD4f227cEc0cf672db674b3BB3b15393D861" }
  const initData = MyContractV1.interface.encodeFunctionData('initialize', [x.address, y.address, z.address]);
  const ERC1967Proxy = await ethers.getContractFactory("ERC1967Proxy");
  // Deploy the proxy pointing to the implementation
  const proxy = await ERC1967Proxy.deploy(“0xaddressofimplementationcontract”, initData);
  await proxy.waitForDeployment();
  const proxyAddress = await proxy.getAddress();
  console.log("Proxy deployed to:", proxyAddress);
  const contract = MyContractV1.attach(proxyAddress);
  await upgrades.forceImport(proxyAddress, MyContractV1, { kind: 'uups' });
} 

It works on Sepolia. However, the library throws the same error when deploying on mainnet, but I can see that the transaction was successful and the proxy contract is deployed, pointing to the implementation contract and No file in .openzeppelin is generated

Another try with Infura instead of alchemy node fixed the issue. It is weird that this happens only on the mainnet and not on Sepolia