Contract Verification Best Practices

Make verification succeed on the first attempt — every time.

Almost every failed verification comes down to a handful of avoidable mistakes. These practices eliminate them.


Capture settings at deploy time

The single most important habit: record the exact compilation settings when you deploy, not when you later decide to verify. Store alongside your deployment artifacts:

  • Compiler version (full string, including commit hash: v0.8.24+commit.e11b9ed9)
  • Optimizer enabled flag and runs
  • EVM version (default, paris, shanghai, cancun, …)
  • Constructor arguments (ABI-encoded)
  • Linked library addresses

Hardhat’s artifacts/build-info/ and Foundry’s out/ already contain all of this — commit or archive them.

Prefer standard JSON input

When verifying by hand or via API, use standard JSON input whenever possible. It embeds every compiler setting, so there’s nothing to misremember. Flattened-source verification forces you to restate settings manually — every restated field is a chance to be wrong.

Get constructor arguments right

Constructor arguments are ABI-encoded and appended to the init bytecode in the deployment transaction. To extract them:

  1. Open the deployment transaction on the explorer.
  2. Compare the input data against your compiled bytecode.
  3. The trailing bytes after the bytecode are the encoded constructor arguments.

Or encode them directly: cast abi-encode "constructor(string,uint256)" "MyToken" 1000000.

Declare libraries explicitly

If your contract links external libraries, the deployed bytecode contains their addresses in place of placeholders. Verification needs each library name mapped to its deployed address — collect these at deploy time.

Don’t hand-edit flattened source

Flattening tools sometimes reorder or alter pragmas. If you must flatten:

  • Use the toolchain’s own flattener (hardhat flatten, forge flatten) — not copy-paste.
  • Keep a single pragma solidity statement at the top.
  • Don’t “clean up” the flattened output; even whitespace-adjacent changes can shift the metadata hash (partial match) or worse.

Verify immediately after deployment

Fold verification into the deploy pipeline (forge script --verify, or a Hardhat task). Immediate verification:

  • Uses settings that are still in context — nothing to reconstruct later.
  • Catches toolchain misconfigurations while the deployer is still watching.
  • Means users never see an unverified contract.

Aim for exact (full) match

Partial matches work fine in the explorer, but exact matches are the strongest signal. Keep the metadata hash intact by verifying with the original build info rather than reconstructed settings.

Verify on testnets first

If your project deploys to a testnet, rehearse the full deploy-and-verify flow there. Every lesson is cheaper on a testnet.

Common failure messages and fixes

SymptomLikely cause
Bytecode mismatchWrong compiler version or optimizer runs
Mismatch only in metadata sectionSettings close but not exact — use standard JSON
”Contract not found in provided sources”contract_name ≠ declared name (or wrong file set)
Placeholder left in librariesMissing library address mapping
Constructor argument decoding errorArguments not ABI-encoded, or 0x prefix issues

Next steps