Proxy-Contracts revert with CALL_EXCEPTION when loaded via hardhat and openzeppelin-upgrades

When I deploy a proxy contract and want to call a function on the proxy, I get a revert CALL_EXCEPTION.

:1234: Code to reproduce

Below the code how I deploy the Contract and load it as a fixture for tests. At this time, I can successfully query the balanceOf function:

async function deployNFT() {
  const [owner] = await ethers.getSigners();

  const tokenFactory = (await ethers.getContractFactory(‘Nft1155Upgradeable')) as Nft1155Upgradeable__factory;

  const token = (await upgrades.deployProxy(tokenFactory, ['ipfs://'], {initializer: 'initialize'})) as Nft1155Upgradeable;
  await token.deployed();

  expect(await token.balanceOf(owner.address, 1)).to.equal(0);

  return { token, owner };
}

But when I load this fixture in another tests, the same function-call will revert:

it("Should fetch balance of a Nft1155Upgradeable", async function () {
  const {token, owner} = await loadFixture(deployNFT);

   expect(await token.balanceOf(owner.address, 1)).to.equal(0);
});

The token is a valid contract-object. I can even query its address token.address and everything seems to be as expected. However, the call to balanceOf now reverts with:

Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="balanceOf(address,uint256)", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)

The actual SmartContract looks like this:

contract Nft1155Upgradeable is
    ERC1155BurnableUpgradeable,
    ERC1155SupplyUpgradeable,
    AccessControlEnumerableUpgradeable
{
    using ECDSAUpgradeable for bytes32;

   function initialize(string memory baseUri_) public initializer {
    __ERC1155Burnable_init_unchained();
    __ERC1155Supply_init_unchained();
    __AccessControlEnumerable_init_unchained();
    __ERC1155_init_unchained(baseUri_);

    _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
    _setupRole(MINTER_ROLE, _msgSender());
}


// … and so on 

}

When I don't use upgradeable contract (an exact copy without Upgradeable in contract-names and -imports and constructors instead of initialize-function) it works as expected. It must have something to do with the Upgradeable-Stuff.

What could that be?

:computer: Environment

    "@nomicfoundation/hardhat-network-helpers": "^1.0.6",
    "@nomiclabs/hardhat-etherscan": "^3.1.0",
    "@typechain/ethers-v5": "^10.1.0",
    "@typechain/hardhat": "^6.1.3",
    "@nomicfoundation/hardhat-chai-matchers": "^1.0.3",
    "@nomicfoundation/hardhat-toolbox": "^2.0.0",
    "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
    "@openzeppelin/contracts-upgradeable": "4.7.3",
    "@openzeppelin/hardhat-upgrades": "^1.21.0",
1 Like

Can you check the common causes in the ethers doc, for example to make sure there is indeed a contract at the address that you are loading (and that the address is the correct proxy address)? Are you using a local development network or a testnet?