Why Verify Contracts?
Transparency
- Users can read and audit the contract code
- Builds trust in the protocol
- Enables community security review
Functionality
- Block explorers can decode function calls
- Events display with readable parameter names
- Users can interact with contracts directly via UI
Compliance
- Required for many DEX listings
- Necessary for security audits
- Standard practice for DeFi protocols
Automated Verification
The zkp2p-contracts repository includes automated verification scripts.Base Mainnet
- Reads all deployments from
deployments/base/ - Verifies each contract on Basescan
- Uses a 600ms delay between verifications (rate limiting)
- Skips already verified contracts
- Reports verification status
Base Sepolia Testnet
Base Staging
Manual Verification
Using Hardhat Verify Plugin
Single Contract
Example: Verify Escrow
Constructor Arguments from Deployment
Extract constructor args from deployment file:Using Basescan Web Interface
1. Navigate to Contract
Go to your contract on Basescan:2. Click “Verify and Publish”
On the contract page, select the “Contract” tab, then “Verify and Publish”.3. Fill Verification Form
Compiler Type: Solidity (Single file) or Solidity (Standard-JSON-Input) Compiler Version:v0.8.18+commit.87f61d96
Open Source License Type: MIT
Optimization: Enabled
Optimization Runs: 200
Via IR: Yes
These values match hardhat.config.ts:
4. Upload Contract Code
For Standard JSON Input:- Main contract source
- All imported dependencies
- OpenZeppelin contracts
- Interfaces
5. Submit for Verification
Basescan will:- Compile your source code
- Compare bytecode to deployed contract
- Display verification result
Verification Script Details
The automated verification task is defined intasks/etherscanVerifyWithDelay.ts:
How It Works
- Load Deployments: Reads all
.jsonfiles fromdeployments/<network>/ - Iterate Contracts: Processes each contract sequentially
- Verify: Calls Hardhat verify plugin with saved constructor args
- Handle Errors: Skips already-verified contracts, logs failures
- Rate Limiting: Waits specified delay between requests
- Summary: Reports verification statistics
Configuration
API Keys
Set your Basescan API key in.env:
- Basescan: basescan.org/apis
- Etherscan: etherscan.io/apis
Hardhat Config
Configure verification inhardhat.config.ts:
Verification Status
Check if a contract is verified:Via Block Explorer
Visit the contract page. Verified contracts show:- Green checkmark next to contract address
- “Contract Source Code Verified” badge
- Readable source code in “Contract” tab
Via API
Troubleshooting
”Already Verified” Error
Cause: Contract was previously verified Solution: No action needed. Contract is verified. Verify: Check block explorer for green checkmark”Invalid API Key” Error
Cause: Missing or incorrect Basescan API key Solution:- Get API key from basescan.org/apis
- Add to
.env:BASESCAN_API_KEY=your_key_here - Restart verification
”Bytecode Does Not Match” Error
Cause: Deployed bytecode differs from compiled source Possible Reasons:- Wrong compiler version
- Different optimization settings
- Wrong via IR setting
- Modified source code after deployment
- Incorrect constructor arguments
- Check compiler settings match
hardhat.config.ts - Verify constructor arguments from deployment JSON
- Ensure source code matches deployed version
- Try compiling locally and comparing bytecode:
“Max Rate Limit Reached” Error
Cause: Too many verification requests in short time Solution: Increase delay between verifications:”Contract Size Exceeds Limit” Error
Cause: Contract bytecode larger than 24KB Solution:- Refactor contract into smaller modules
- Use libraries for common functionality
- Enable optimizer with higher runs
- Remove unnecessary code
”Failed to Fetch Constructor Arguments” Error
Cause: Can’t automatically detect constructor args from blockchain Solution: Manually specify arguments:Verification Checklist
After verification, confirm:- Contract shows as verified on Basescan
- Source code is readable on “Contract” tab
- Constructor arguments are correct
- Read/Write functions work on block explorer UI
- Contract ABI matches deployment JSON
- All dependencies are verified (registries, etc.)
- Contract name matches source file
Best Practices
1. Verify Immediately After Deployment
Run verification right after deployment:2. Save Deployment Artifacts
Commitdeployments/ directory to version control:
- Contract addresses
- Constructor arguments
- Deployment transaction hashes
- ABIs
3. Document Verification
Record verification details:4. Test on Testnet First
Practice verification on Base Sepolia:5. Verify Dependencies
Ensure all registry contracts are verified:- PaymentVerifierRegistry
- NullifierRegistry
- EscrowRegistry
- RelayerRegistry
- PostIntentHookRegistry
Reading Verified Contracts
Once verified, anyone can:View Source Code
Interact with Contract
Read Contract State
View Events
Next Steps
After verifying contracts:Verification is a one-time process per deployment. Once verified, the contract remains verified permanently on the block explorer.