Verify Smart Contracts on ESC
After you deploy to Elastos Smart Chain (ESC), publishing verified source on the block explorer lets anyone confirm that on-chain bytecode matches your Solidity. ESC’s explorer is powered by Blockscout (Elixir-based; see the Elastos.ELA.SideChain.ESC.Blockscout repository). Verification is optional but strongly recommended for production contracts and public protocols.
Blockscout stores verified sources and compiler metadata so the UI can show Read Contract / Write Contract panels, decode input data where possible, and link proxy implementations when those patterns are used. None of that replaces a professional audit, but it removes the “black box” problem for everyday users.
Why Verify?
- Auditability: Published source is readable and can be reviewed against the deployed bytecode.
- Trust: Users and integrators can see what the contract does without decompiling.
- Better UX: Blockscout can decode calls, show ABI-driven “Read/Write Contract” tabs, and display human-readable events when the contract is verified.
- Mainnet: esc.elastos.io
- Testnet: esc-testnet.elastos.io
Method 1: Flattened Source Code (Manual)
Manual verification works everywhere: you paste a single .sol file whose imports are inlined (“flattened”) so the explorer does not need your full project layout.
- Deploy your contract to ESC (mainnet or testnet).
- Open the explorer: esc.elastos.io (mainnet) or esc-testnet.elastos.io (testnet).
- Search for your contract address.
- Open the Code tab, then choose Verify & Publish (wording may vary slightly by Blockscout version).
- Complete the form:
- Contract address: the
0x…deployment address. - Contract name: the Solidity contract name (e.g.
MyToken), not the file name. - Compiler: must match exactly (e.g.
v0.8.20+commit.a1b79de6). Copy from your build output or compiler settings. - EVM version: same as in your compiler config (often default unless you pinned one).
- Optimization: Yes/No to match your build.
- Optimization runs: e.g.
200if you used the common default; must match.
- Contract address: the
- Paste the flattened source into the text area. If the form asks for constructor arguments, supply them in the format the UI specifies (often ABI-encoded hex for manual flows).
- Submit and wait for the compiler run to finish. If verification fails, read the error text carefully; it usually names the first mismatch (compiler, runs, or bytecode).
Some teams keep a small checklist per deployment: compiler string from artifacts, optimizer flag, runs, and the exact solc binary Hardhat downloaded. That avoids “it worked on my machine” drift between deploy and verify.
From your project root:
npx hardhat flatten contracts/MyToken.sol > flattened.sol
Review flattened.sol for duplicate SPDX/license pragmas or artifacts some flatteners emit; trim if the UI requires a single license line.
Method 2: Hardhat Verification Plugin
Automated verification avoids paste errors and keeps compiler metadata aligned with your build.
Install the plugin:
npm install --save-dev @nomicfoundation/hardhat-verify
Add to hardhat.config.js:
require("@nomicfoundation/hardhat-verify");
module.exports = {
// ... existing config
etherscan: {
apiKey: {
esc: "no-api-key-needed",
},
customChains: [
{
network: "esc",
chainId: 20,
urls: {
apiURL: "https://esc.elastos.io/api",
browserURL: "https://esc.elastos.io",
},
},
],
},
};
If you use TypeScript config (hardhat.config.ts), the same etherscan / customChains structure applies; only the require vs import style changes.
Wire your networks entry (e.g. escMainnet) to ESC RPC as in Deploy a Smart Contract, then run:
npx hardhat verify --network escMainnet DEPLOYED_CONTRACT_ADDRESS "constructor_arg1" "constructor_arg2"
Omit constructor arguments if the constructor takes none. Use the same account/network you used to deploy.
For testnet (chain ID 21), add another customChains entry with chainId: 21, apiURL: "https://esc-testnet.elastos.io/api", and browserURL: "https://esc-testnet.elastos.io", and point your verify command at the matching --network alias.
ESC’s Blockscout instance does not require a paid API key; the string no-api-key-needed satisfies the plugin’s expectation of a non-empty key for the custom chain.
Method 3: Sourcify
Blockscout integrates Sourcify-style verification: you can upload metadata.json and the source files produced by Solidity’s standard JSON output (for example Hardhat’s artifacts/build-info flow).
Typical workflow:
- Compile with the same settings you used for deployment (do not change Solidity version or optimizer between deploy and verify).
- Locate the build info JSON under
artifacts/build-info/(Hardhat) or your toolchain’s equivalent. - In the explorer, choose the verification path that accepts metadata, standard JSON, or Sourcify (wording depends on Blockscout version).
- Upload
metadata.jsonplus the referenced sources so the compiler can reconstruct bytecode.
Sourcify shines when your contract spans multiple files and libraries: you avoid flattening and preserve original import paths, as long as the file layout matches what the metadata records.
- Works well with default Hardhat compilation output when you preserve build-info and sources.
- Prefer this when you want multi-file verification without flattening, as long as paths and settings match the deployment.
Check the explorer’s verification UI for the exact “Sourcify” or “metadata” upload path; labels follow upstream Blockscout releases.
Common Issues
| Symptom | What to check |
|---|---|
| Compiler mismatch | Full compiler string (version + commit) must match the binary used to compile. |
| Bytecode mismatch | Optimization on/off and runs must match; EVM version must match. |
| Wrong contract | Contract name is the specific contract Foo that was deployed at that address. |
| Constructor errors | Pass constructor args to hardhat verify in order; manual forms need ABI-encoded args if requested. |
| Imports / paths | Flatten or use Sourcify/metadata so the explorer sees a consistent file tree. |
| Linked libraries | Library addresses baked at deploy time must match; verify with the same library deployment metadata your toolchain recorded. |
| Proxies | Verify the implementation contract at its address; proxy patterns may need separate entries per Blockscout’s proxy plugin support. |
If you upgrade an implementation behind a proxy, repeat verification for the new implementation address. Users often forget this step after a timelock or multisig upgrade.
Verification compares recompiled bytecode to on-chain bytecode. Any difference in compiler, optimizer, libraries, or constructor arguments will fail; always reproduce the exact build you used for deployment.
See also: Deploy a Smart Contract · Add Network