Developer Wanted. This guide applies to all Etherscan instances, including all of the following as well as their testnet explorers: etherscan.io (Ethereum) bscscan.com (Binance Smart Chain) polygonscan.com (Polygon) snowtrace.io (Avalanche) Recommendations Practice in testnet Be...">

How to verify a contract on Etherscan/BscScan/PolygonScan (original) (raw)

Make sure to read this post before asking a question about verification. If your issue is not addressed here, just leave a comment below.

If you want to pay someone to do the verification for you, create a post in Developer Wanted.

This guide applies to all Etherscan instances, including all of the following as well as their testnet explorers:

Recommendations

Practice in testnet

Before you deploy to production and risk losing hundreds of dollars to a deployment that you are not able to verify, deploy to a testnet and make sure you can verify the contract there.

Prefer Hardhat to deploy

In our experience, using Hardhat with the hardhat-etherscan plugin is the easiest way to guarantee smooth verification. Deploying with Remix will make things harder.

Make sure to read the documentation for hardhat-etherscan, particularly the part about complex arguments if you're having trouble specifying arguments in the console.

Use Remix plugins to help

Remix has plugins that you can activate by going to the plugin manager. There are two plugins that can help you verify: Etherscan and Flattener.

The Etherscan plugin requires that you configure an Etherscan API key, because it will try to verify using the Etherscan API. You can encode the constructor parameters using ABI Encoder Online.

The Flattener plugin can give you a flattened file that you can then use in Etherscan as Single file input.

Use versioned imports in Remix

If you use OpenZeppelin Contracts, your imports should include the version you want to import, for example 4.3.0. So it should look like either of these options:

import "@openzeppelin/contracts@4.3.0/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.0/contracts/token/ERC20/ERC20.sol;

While any of the following, using the master branch or a non-versioned import, are discouraged, and may result in non-reproducible deployments that can be extremely hard to verify.

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol;

Upgradeable Contracts and Proxies

Automated verification with Hardhat and OpenZeppelin Upgrades

Proxies that were deployed by the OpenZeppelin Upgrades Plugins can be fully verified using the Hardhat upgrades plugin's verify task.

Manual verification

When verifying an upgradeable deployment, there are at least two contracts involved: 1) the proxy, and 2) the implementation contract. If using a beacon proxy, a third contract (the beacon) is also involved. The proxy and beacon, if applicable, should be already verified if you deployed them using OpenZeppelin Upgrades Plugins (if not, see below). For full verification, however, you will need to verify the implementation contract, using any of the methods mentioned in this article.

In order to get the address of the implementation contract from a proxy, you can use the erc1967 module included in the plugins:

console.log(await upgrades.erc1967.getImplementationAddress(proxyAddress));

For beacon proxies, first get the beacon address from the proxy, then get the implementation address from the beacon. For example:

console.log(await upgrades.beacon.getImplementationAddress(await upgrades.erc1967.getBeaconAddress(proxyAddress)));

Both of the above examples provide the address that you need to verify against your contract code. Keep in mind that constructor arguments will be empty for verification, even if you have an initializer function with arguments.

Etherscan may not automatically recognize your contract as a proxy. In this case it is necessary to go to submit the contract address through the Proxy Contract Verification Page. A link to this page can be found under "More Options" in the top right of the contract source code:

Implementation contract was not detected for the proxy

Some kinds of proxies may need at least one transaction before they can be verified as a proxy on Etherscan.

If proxy is not verified

Proxy contracts, beacons, and the ProxyAdmin should be verified automatically as "Similar Match", because we have verified other instances of the same code. On some networks, there may not be a verified instance and the contract you deploy may show up as unverified. In that case, you can verify this contract using the Solc JSON Input shared below, or feel free to contact us in Upgrades to assist.

The compiler version is 0.8.20 and license is MIT.

Promote to Exact Match

If you would like to promote the contract from Similar Match to Exact Match you will need to contact Etherscan as explained on their documentation and send the JSON file attached above.

Common Errors

Unable to generate Contract ByteCode and ABI

This is a generic error that doesn't offer any indication of the cause.

When you meet this error, please check the following one by one, making sure that it matches what you used to deploy exactly: contract source code, compiler version, compiler optimizations and runs number, constructor parameters, address of libraries.

File import callback not supported

This happens when you try to verify a Solidity file that has imports (dependencies), and the imported files were not included in the code submitted for verification.

For example, if your file builds on OpenZeppelin Contracts ERC20, it will contain a statement like:

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

This imported file needs to be included in the verification request.

The fix depends on the tool you used to develop your contract.

  1. Remix: Verify manually by flattening the source code.
  2. Truffle: Use the verify plugin, or do it manually by flattening the source code.
  3. Hardhat: Use the Etherscan plugin.

Multiple SPDX license identifiers found in source file

This can happen when verifying a flattened contract. You need to remove the duplicate SPDX license comments manually, and only keep one valid SPDX license.If there are multiple different licenses in the file you can combine them into a single comment using the AND operator. There may be legal restrictions when combining different licenses.

You can find some discussion about the technical details and implications in https://github.com/nomiclabs/truffle-flattener/issues/55.

Definition of base has to precede definition of derived contract

This can happen when verifying a flattened contract. You should adjust the order of the contracts, putting the parent contracts first, and the child contract after them.

For example, the following is wrong:

contract Ownable is Context {}
contract Context {}

The right order should be:

contract Context {}
contract Ownable is Context {}

Expected library(ies) but one or more was not provided

This happens when your contract uses one or more public or external functions from a Solidity library. In this situation, the library has to be deployed on its own, and the resulting address is embedded in the final contract bytecode.

It only happens when you use Single or Multi-part files verification, because the library source code is available but not the address where the library is deployed is not known.

Etherscan requires that you specify the names and addresses of libraries in the section called "Contract Library Address".

If you deployed the contract with Remix, the library was deployed automatically without your intervention. In the console, you should find an entry that says creation of library <library> pending..., followed by the transaction that deploys the library, where you will find its address. If you can't find this entry in the console, it will be very difficult to retrieve the library address.

If you deployed the contract with Truffle migrations, this information is found in the corresponding build/contracts/<ContractName>.json file. In this file, there is a networks field that contains an entry for each network that you've ran your migrations on, indexed by network id. In the entry corresponding to the network you want to verify, you will find a field called links that contains name and address of each library that was used, and that you should input into Etherscan.

Resources

Tutorials

Documentation

Tools

Other

Alternative approaches that are not currently documented below but may be good to explore: