How to set gasLimit and gasPrice with Hardhat upgrades plugin?

I'm trying to deploy an upgradeable smart contract using "@openzeppelin/contracts-upgradeable": "^4.5.2". Since I can't pass gas parameters to the upgrades.deployProxy(foo), I have to overwrite the default Hardhat's provider. Once I do it, the call still uses the default Hardhat provider. Is there a way to force the call to use the overwritten provider?

In the accompanying code the line const token = await upgrades.deployProxy(Token); already fails. The txParams() are working as expected and provide the desired values. The overwritten provider is an operational and verified provider, so there should be no issues with it.

:1234: Code to reproduce

const { ethers, upgrades } = require("hardhat");
const { txParams } = require("../utils/transactionHelpers.js");
const { EvmRpcProvider } = require("@acala-network/eth-providers");

async function main() {
  const ethParams = await txParams();
  /* -------------------------------------------------------------------------------------- */
  // https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/85#issuecomment-1028435049

  // Wrap the provider so we can override fee data.
  const provider = EvmRpcProvider.from('ws://localhost:9944');
  await provider.isReady();

  provider.getFeeData = async () => ({
    gasPrice: ethParams.txGasPrice,
    gasLimit: ethParams.txGasLimit,
  });

  // Create the signer for the mnemonic, connected to the provider with hardcoded fee data
  const signer = ethers.Wallet.fromMnemonic(process.env.MNEMONIC).connect(provider);
  
  /* -------------------------------------------------------------------------------------- */

  // Deploy FooToken
  const Token = await ethers.getContractFactory("FooTokenV2", signer);
  const token = await upgrades.deployProxy(Token);
  await token.deployed();
  console.log('Token deployed')

  // Protocol contract args: penaltyPerc=10, lockingPeriod=51840 (3 days in 5 sec block's amount)
  const Protocol = await ethers.getContractFactory("FooProtocol", signer);
  const protocol = await upgrades.deployProxy(Protocol, [10, 51840, token.address]);
  await protocol.deployed();
  console.log('Protocol deployed')

  // Deploy FooGovernor with FooToken address as argument
  const Governor = await ethers.getContractFactory("FooGovernor", signer);
  const governor = await Governor.deploy(token.address, 5, 5, ethers.utils.parseEther('1000'), [4, 25, 50]);
  // const governor = await Governor.deploy(token.address, 17280 /* 1 day */, 17280 /* 1 day */, ethers.utils.parseEther('5000000'), [4, 25, 50]);
  await governor.deployed();
  console.log('Governor deployed')

  // Grant governor admin role in the protocol contract
  await protocol.grantRole('0x0000000000000000000000000000000000000000000000000000000000000000', governor.address);

  console.log("FooToken deployed at:", token.address);
  console.log("FooProtocol deployed at:", protocol.address);
  console.log("FooGovernor deployed at:", governor.address);
}

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

:computer: Environment

These are the dependencies that I'm using:

  "dependencies": {
    "@acala-network/eth-providers": "^2.4.1",
    "@nomiclabs/hardhat-waffle": "^2.0.3",
    "@openzeppelin/contracts": "^4.5.0",
    "@openzeppelin/contracts-upgradeable": "^4.5.2",
    "@openzeppelin/hardhat-upgrades": "^1.17.0",
    "chai": "^4.3.6",
    "dotenv": "^16.0.0",
    "hardhat": "^2.9.3",
    "hardhat-contract-sizer": "^2.5.1",
    "solidity-bytes-utils": "^0.8.0"
  }

I'm trying to run the deploy script on a local Acala EVM+ (https://evmdocs.acala.network/network/node-setup).
My device is a M1 Max Apple silicon device with 64 GB of unified memory and macOS Monterey v 12.1. I also have Rosetta 2 installed.

Hi @ThunderDeliverer,

provider.getFeeData is of type FeeData from the ethers API. This only supports gasPrice (for legacy transactions), or maxFeePerGas and maxPriorityFeePerGas (for EIP-1559 transactions).

If you want to set the gasLimit, you can override signer.estimateGas instead.

So for your example, you can do something like:

  ...

  provider.getFeeData = async () => ({
      gasPrice: ethParams.txGasPrice
  });

  const signer = ethers.Wallet.fromMnemonic(process.env.MNEMONIC).connect(provider);

  signer.estimateGas = async(transaction) => {
    return ethParams.txGasLimit;
  }

  // Deploy FooToken
  const Token = await ethers.getContractFactory("FooTokenV2", signer);
  const token = await upgrades.deployProxy(Token);
  ...