Unverified ERC1967 Proxy goerli

Hi

We are deploying some upgradeable contracts with ERC1967 proxies and get an error message that our proxy contracts cannot be verified:
Error 1: Failed to verify ERC1967Proxy contract at 0x59dB29840a092F43Df2D74514e5419Af2D4F4C8d: Bytecode does not match with the current version of ERC1967Proxy in the Hardhat Upgrades plugin.

In this forum post (How to verify a contract on Etherscan/BscScan/PolygonScan) I read that we should write here that you guys verify the proxy contracts.
We are not using any custom implementation, thus we assume that the etherscan "Similar Match" feature should kick in which it doesn't.

Can you verify the contract at address 0x59dB29840a092F43Df2D74514e5419Af2D4F4C8d (first deployment of this bytecode from 0x9a8b46e3f9d7ebfb60f37d28af3fe1681bede739 or give us a hint in the right direction?

The proxy we tried to verify is located at 0x59dB29840a092F43Df2D74514e5419Af2D4F4C8d with the implementation (verified) 0x9C4eFCfB1d880a06C6c14c397f0276AF1cB80Adf

:computer: Environment

Solidity: 0.8.17

NPM Package versions:
"@nomiclabs/hardhat-ethers": "^2.2.1",
"@nomiclabs/hardhat-etherscan": "^3.1.4",
"@openzeppelin/hardhat-upgrades": "^1.21.0",
"@openzeppelin/contracts": "4.8.1",
"@openzeppelin/contracts-upgradeable": "4.8.1"

Hi @mathewmeconry, can you share what version of @openzeppelin/upgrades-core you used to deploy the proxy, and are you using the same version to verify it?

You can run the following command to show the version:
npm list @openzeppelin/upgrades-core

Hi @ericglau

We use 1.20.5 of @openzeppelin/upgrades-core.

Yes we deployed the contracts with hardhat-deploy and tried to verify the proxies with the hardhat verify:verify task.

Also verifying it with npx hardhat verify --network goerli ADDR produces the same issue.

we deployed the contracts with hardhat-deploy

hardhat-deploy deploys its own proxy contracts that are different than the ones deployed by hardhat-upgrades, so you would need to use the proxy source code from hardhat-deploy to verify those proxies.

ohh didn't know that. let me check if we use their proxy or not.

In the meantime, something still seems off:
We have a factory deployed that uses the following file-level function to create upgradeable contracts:

// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity 0.8.17;

import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

/// @notice Free function to create a [ERC-1967](https://eips.ethereum.org/EIPS/eip-1967) proxy contract based on the passed base contract address.
/// @param _logic The base contract address.
/// @param _data The constructor arguments for this contract.
/// @return The address of the proxy contract created.
/// @dev Initializes the upgradeable proxy with an initial implementation specified by _logic. If _data is non-empty, it’s used as data in a delegate call to _logic. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor (see [OpenZepplin ERC1967Proxy-constructor](https://docs.openzeppelin.com/contracts/4.x/api/proxy#ERC1967Proxy-constructor-address-bytes-)).
function createERC1967Proxy(address _logic, bytes memory _data) returns (address) {
    return address(new ERC1967Proxy(_logic, _data));
}

The function that create the proxy in the factory looks like this:

...
    function _createPluginRepo(
        string calldata _subdomain,
        address _initialOwner
    ) internal returns (PluginRepo pluginRepo) {
        if (!(bytes(_subdomain).length > 0)) {
            revert EmptyPluginRepoSubdomain();
        }

        pluginRepo = PluginRepo(
            createERC1967Proxy(
                pluginRepoBase,
                abi.encodeWithSelector(PluginRepo.initialize.selector, _initialOwner)
            )
        );

        pluginRepoRegistry.registerPluginRepo(_subdomain, address(pluginRepo));
    }
...

This factory is currently deploy on Goerli at 0x160b35934f24B1b7eE238d37Ca2F495AB1a5a803 and we created new contracts with this factory in the tx's

  • 0x0698fbcf1b0ff99cfc9c34b0e587f7f095c30b6b1b28a450ca438685f61b3488
  • 0xbf028417bb4076fa029dcd522f12c9701226370691cf2129e0aba6e82012413b
  • 0xea6dbc319127ed5f81273be22cee3baae003da1a716f35f766444ba64a222f2f

which created the following contracts:

  • 0xAbcf728903C84Abad57320fd78A7bb21ae07A261
  • 0xb60fd6c478541ee150de7ae7bd379612b2626234
  • 0xe6eeca8428b36ab2e5a96d3f8a903f3c3f8c6938

All 3 of them are ERC1967 proxies and got created by the file-level function shown above. The bases are verified.

I assume that these proxies should use the source from @openzeppelin/contracts or not?
Trying to verify any of these 3 addresses with npx hardhat verify:verify --network goerli --contract "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy" 0xAbcf728903C84Abad57320fd78A7bb21ae07A261 fails with

Verifying implementation: 0xF8612cB696B03A99077292bdF7b55eB119A0dc01
Nothing to compile
No need to generate any newer typings.
Failed to verify implementation contract at 0xF8612cB696B03A99077292bdF7b55eB119A0dc01: The address provided as argument contains a contract, but its bytecode doesn't match the contract @openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy.

Possible causes are:
  - Contract code changed after the deployment was executed. This includes code for seemingly unrelated contracts.
  - A solidity file was added, moved, deleted or renamed after the deployment was executed. This includes files for seemingly unrelated contracts.
  - Solidity compiler settings were modified after the deployment was executed (like the optimizer, target EVM, etc.).
  - The given address is wrong.
  - The selected network (goerli) is wrong.
Verifying proxy: 0xAbcf728903C84Abad57320fd78A7bb21ae07A261
Failed to verify ERC1967Proxy contract at 0xAbcf728903C84Abad57320fd78A7bb21ae07A261: Bytecode does not match with the current version of ERC1967Proxy in the Hardhat Upgrades plugin.
Linking proxy 0xAbcf728903C84Abad57320fd78A7bb21ae07A261 with implementation
Successfully linked proxy to implementation.
An unexpected error occurred:

Error: Verification completed with the following errors.

Error 1: Failed to verify implementation contract at 0xF8612cB696B03A99077292bdF7b55eB119A0dc01: The address provided as argument contains a contract, but its bytecode doesn't match the contract @openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy.

Possible causes are:
  - Contract code changed after the deployment was executed. This includes code for seemingly unrelated contracts.
  - A solidity file was added, moved, deleted or renamed after the deployment was executed. This includes files for seemingly unrelated contracts.
  - Solidity compiler settings were modified after the deployment was executed (like the optimizer, target EVM, etc.).
  - The given address is wrong.
  - The selected network (goerli) is wrong.

Error 2: Failed to verify ERC1967Proxy contract at 0xAbcf728903C84Abad57320fd78A7bb21ae07A261: Bytecode does not match with the current version of ERC1967Proxy in the Hardhat Upgrades plugin.

If you compiled the proxy contracts along with your proxy factory which deploys the proxy, then that means the proxy is using your compiled bytecode. The Hardhat Upgrades plugin would not be able to verify it since the bytecode is different from what the plugin would normally deploy.

You could try using the regular Hardhat verify task by commenting out require("@openzeppelin/hardhat-upgrades"); from hardhat.config.js and then run npx hardhat verify --network goerli ADDR again.

Otherwise, you would need to manually verify the proxy source code using all of the following:

  • your compiler settings including compiler version and number optimizer runs
  • the ABI encoded compiler arguments from when you called new ERC1967Proxy(_logic, _data) -- e.g. use https://abi.hashex.org/ to encode constructor arguments for your _logic and _data addresses.
  • the proxy source code from the version of @openzeppelin/contracts that you used

You could try using the regular Hardhat verify task by commenting out require("@openzeppelin/hardhat-upgrades"); from hardhat.config.js and then run npx hardhat verify --network goerli ADDR again.

That did the trick. Thanks a lot :smiley:

1 Like