Skip to main content
Contract verification makes your contract source code publicly available on block explorers, enabling transparency and allowing users to interact with contracts directly through explorer interfaces.

Why Verify Contracts?

  • Transparency: Users can inspect contract source code
  • Trust: Verification proves deployed bytecode matches public source
  • Interaction: Block explorers provide UI for contract interaction
  • Debugging: Easier to debug transactions with verified contracts
  • Integration: Required for some integration tools and services

Automated Verification

Using Verification Script

The easiest way to verify all deployed contracts:
# Verify all contracts from deployment file
./scripts/verifyRoutes.sh
This script will:
  • Read deployment data from CSV file
  • Load verification API keys from configuration
  • Verify each contract on its respective block explorer
  • Retry failed verifications automatically
  • Provide detailed verification summary

Prerequisites for Automated Verification

1

Deployment Results File

Ensure RESULTS_FILE exists with deployment data:
cat $RESULTS_FILE
Expected format:
ChainID,ContractAddress,ContractPath,ContractArguments
1,0x742d35Cc6634C0532925a3b844Bc454e4438f44e,contracts/Portal.sol:Portal,0x
2

Configure Verification Keys

Create verification keys file or set environment variable:Option 1: JSON File
verification-keys.json
{
  "1": "your_etherscan_api_key",
  "8453": "your_basescan_api_key",
  "10": "your_optimistic_etherscan_api_key"
}
Option 2: Environment Variable
export VERIFICATION_KEYS='{"1":"etherscan_key","8453":"basescan_key"}'
3

Set Environment Variables

.env
# Path to deployment results
RESULTS_FILE=out/deploy.csv

# Verification keys (file or JSON string)
VERIFICATION_KEYS_FILE=verification-keys.json
# OR
VERIFICATION_KEYS='{"1":"key1","8453":"key2"}'

# Chain data for RPC URLs (optional but recommended)
CHAIN_DATA_URL="https://raw.githubusercontent.com/eco/eco-chains/refs/heads/main/src/assets/chain.json"

Verification Script Features

Automatic Header Removal
  • Detects and removes CSV headers before processing
Retry Logic
  • Retries failed verifications with 5-second delay
  • Useful for rate limiting or temporary explorer issues
RPC URL Integration
  • Uses chain data for more reliable verification
  • Falls back to explorer defaults if not available
Progress Tracking
  • Shows verification progress (e.g., “2 of 5”)
  • Provides summary statistics at end
Constructor Arguments
  • Automatically includes constructor args from deployment data
  • Handles contracts with no constructor args

Manual Verification

Verify Using Forge

Verify a single contract manually:
# Verify Portal contract
forge verify-contract \
  --chain mainnet \
  --etherscan-api-key $ETHERSCAN_API_KEY \
  --watch \
  0x742d35Cc6634C0532925a3b844Bc454e4438f44e \
  contracts/Portal.sol:Portal

Verification Flags Explained

FlagDescription
--chainNetwork name or chain ID (e.g., mainnet, 1, sepolia, 11155111)
--etherscan-api-keyAPI key for block explorer
--constructor-argsABI-encoded constructor arguments
--watchWait for verification to complete
--rpc-urlCustom RPC endpoint for the chain

Constructor Arguments

For contracts with constructor parameters, you need to provide ABI-encoded arguments. HyperProver Constructor
constructor(
    address mailbox,
    address portal,
    bytes32[] memory provers
)
Encode Constructor Args
# Extract args from deployment CSV
CONSTRUCTOR_ARGS=$(grep "HyperProver" out/deploy.csv | cut -d',' -f4)

# Or encode manually
cast abi-encode "constructor(address,address,bytes32[])" \
  $MAILBOX_ADDRESS \
  $PORTAL_ADDRESS \
  "[0x1234...]"
MetaProver Constructor
constructor(
    address router,
    address portal,
    bytes32[] memory provers,
    uint256 minGasLimit  // 200000
)
LayerZeroProver Constructor
constructor(
    address layerZeroEndpoint,
    address layerZeroDelegate,
    address portal,
    bytes32[] memory provers,
    uint256 minGasLimit  // 200000
)
PolymerProver Constructor
constructor(
    address portal,
    address polymerCrossL2ProverV2,
    bytes32[] memory provers
)

Block Explorer API Keys

Obtaining API Keys

Get free API keys from block explorers:
1

Ethereum (Etherscan)

  1. Visit Etherscan API
  2. Create an account
  3. Generate API key
  4. Same key works for Sepolia testnet
2

Base (Basescan)

  1. Visit Basescan API
  2. Create account (separate from Etherscan)
  3. Generate API key
3

Optimism

  1. Visit Optimistic Etherscan
  2. Create account
  3. Generate API key
4

Arbitrum

  1. Visit Arbiscan
  2. Create account
  3. Generate API key

Supported Block Explorers

ChainExplorerAPI Documentation
EthereumEtherscanhttps://etherscan.io/apis
BaseBasescanhttps://basescan.org/apis
OptimismOptimistic Etherscanhttps://optimistic.etherscan.io/apis
ArbitrumArbiscanhttps://arbiscan.io/apis
PolygonPolygonscanhttps://polygonscan.com/apis
BSCBscScanhttps://bscscan.com/apis
AvalancheSnowtracehttps://snowtrace.io/apis

Verification Status

Check Verification Status

Verify a contract was successfully verified:
# Check on Etherscan
open "https://etherscan.io/address/0x742d35Cc6634C0532925a3b844Bc454e4438f44e#code"

# Or use API
curl "https://api.etherscan.io/api
?module=contract
&action=getsourcecode
&address=0x742d35Cc6634C0532925a3b844Bc454e4438f44e
&apikey=$ETHERSCAN_API_KEY"
Successfully verified contracts will show:
  • ✅ Verified contract source code
  • Compiler version
  • Optimization settings
  • Contract ABI
  • Constructor arguments

Verification Success Indicators

In Script Output
✅ Verification succeeded for HyperProver on chain 1
On Block Explorer
  • Green checkmark next to contract
  • “Contract Source Code Verified” message
  • Readable source code tabs
  • Read/Write Contract interface available

Troubleshooting

Already Verified Error

If contract is already verified:
Contract is already verified
This is expected for:
  • Re-running verification script
  • Contracts deployed with same bytecode
Solution: Check block explorer to confirm verification is correct.

Invalid API Key

Error: Invalid API key
Solutions:
  1. Verify API key is correct in .env or verification keys file
  2. Check API key is for the correct network (Etherscan vs Basescan)
  3. Ensure API key is activated (check email for verification link)

Constructor Arguments Mismatch

Error: Invalid constructor arguments
Solutions:
  1. Extract constructor args from deployment CSV:
    grep "ContractName" out/deploy.csv | cut -d',' -f4
    
  2. Verify args match deployment transaction
  3. Check ABI encoding is correct

Rate Limiting

Error: Rate limit exceeded
Solutions:
  1. Wait 5-10 seconds between verifications
  2. Use --slow flag in deployment to add delays
  3. Upgrade to premium API key for higher limits
  4. Verification script includes automatic retry with delay

Compiler Settings Mismatch

Error: Compiler version mismatch
Ensure your foundry.toml matches deployment:
foundry.toml
[profile.default]
solc_version="0.8.27"
optimizer = true
optimizer_runs = 1000000
via_ir = true
evm_version = "paris"
cbor_metadata = false
bytecode_hash = "none"
Forge should automatically use these settings for verification.

Verification Timeout

Error: Verification timeout
Solutions:
  1. Increase timeout with --timeout 300 (5 minutes)
  2. Retry verification after a few minutes
  3. Check if block explorer is experiencing issues
  4. Use --watch flag to wait for completion

Contract Not Found

Error: Contract creation code not found
Solutions:
  1. Wait a few blocks for explorer to index the contract
  2. Verify contract address is correct
  3. Check transaction was successful
  4. Ensure contract was deployed on the correct network

Advanced Verification

Verify with Standard JSON Input

For complex build configurations:
# Generate standard JSON input
forge verify-contract \
  --chain mainnet \
  --etherscan-api-key $ETHERSCAN_API_KEY \
  --standard-json-input \
  0x742d35Cc6634C0532925a3b844Bc454e4438f44e \
  contracts/Portal.sol:Portal

Verify via Sourcify

Sourcify provides decentralized contract verification:
# Verify on Sourcify
forge verify-contract \
  --verifier sourcify \
  --chain-id 1 \
  0x742d35Cc6634C0532925a3b844Bc454e4438f44e \
  contracts/Portal.sol:Portal

Multi-Chain Verification Tracking

Track verification across multiple chains:
# Create verification tracking file
cat > verification-status.md << 'EOF'
# Verification Status

## Portal
- [x] Ethereum (1): https://etherscan.io/address/0x742d35...
- [x] Base (8453): https://basescan.org/address/0x742d35...
- [x] Optimism (10): https://optimistic.etherscan.io/address/0x742d35...
- [ ] Arbitrum (42161): Pending

## HyperProver
- [x] Ethereum (1): https://etherscan.io/address/0x8464135...
- [x] Base (8453): https://basescan.org/address/0x8464135...
EOF

Verification Best Practices

1

Verify Immediately After Deployment

Verify contracts as soon as deployment completes to ensure accuracy.
2

Use Automated Scripts

Use verifyRoutes.sh for consistent, repeatable verification.
3

Keep Deployment Records

Maintain deployment CSV files for verification and auditing.
4

Verify on Multiple Explorers

Verify on both Etherscan-based and Sourcify for broader coverage.
5

Document Verification Links

Share verification links with users and integrators.

Next Steps

Integration Guide

Integrate verified contracts into your application

Testing

Test deployed and verified contracts

Build docs developers (and LLMs) love