Why Verify Smart Contracts?
When you deploy a smart contract to Ethereum, the bytecode on-chain is opaque. Users and other developers can't easily audit what the contract does without the original source code. Verifying your contract on Etherscan bridges that gap — it links your human-readable Solidity (or Vyper) source to the bytecode on-chain, so anyone can read and trust the logic.
But doing this manually through Etherscan's web UI for every deployment is tedious. Let's automate it.
The Etherscan API
Etherscan provides a Contract Verification API endpoint. You POST the source code, compiler version, optimization settings, and constructor arguments, and Etherscan does the hard work of checking that the compiled bytecode matches what's on-chain.
Here's the endpoint:
POST https://api.etherscan.io/api
?module=contract
&action=verifysourcecode
&apikey=YOUR_API_KEY
Python Implementation
Let's build a reusable verify_contract() function using requests:
import requests
def verify_contract(
api_key: str,
contract_address: str,
source_code: str,
contract_name: str,
compiler_version: str,
optimization_used: int = 0,
runs: int = 200,
constructor_args: str = "",
license_type: int = 3, # MIT
) -> dict:
"""
Submit a smart contract for verification on Etherscan.
Args:
api_key: Your Etherscan API key
contract_address: Deployed contract address (0x...)
source_code: Full Solidity source code as a string
contract_name: Name of the main contract to verify
compiler_version: Solidity compiler version, e.g. v0.8.24+commit.e11b9ed9
optimization_used: 1 if optimizer was enabled, else 0
runs: Number of optimizer runs (default 200)
constructor_args: ABI-encoded constructor arguments (hex, without 0x)
license_type: SPDX license type code (1=None, 2=Unlicense, 3=MIT, ...)
Returns:
API response as a dict with verification GUID
"""
url = "https://api.etherscan.io/api"
payload = {
"apikey": api_key,
"module": "contract",
"action": "verifysourcecode",
"contractaddress": contract_address,
"sourceCode": source_code,
"codeformat": "solidity-single-file",
"contractname": contract_name,
"compilerversion": compiler_version,
"optimizationUsed": optimization_used,
"runs": runs,
"constructorArguements": constructor_args,
"licenseType": license_type,
}
resp = requests.post(url, data=payload, timeout=30)
resp.raise_for_status()
return resp.json()
Checking Verification Status
Etherscan verification is asynchronous — you get a GUID back and need to poll for the result:
import time
def check_verification_status(api_key: str, guid: str) -> dict:
"""Poll until verification completes or fails."""
url = "https://api.etherscan.io/api"
params = {
"apikey": api_key,
"module": "contract",
"action": "checkverifystatus",
"guid": guid,
}
for attempt in range(20):
resp = requests.get(url, params=params, timeout=10)
data = resp.json()
status = data.get("result", "")
if status == "Pass - Verified":
print(f"✅ Contract verified: {data}")
return data
elif status.startswith("Fail"):
print(f"❌ Verification failed: {data}")
return data
print(f"⏳ Attempt {attempt+1}/20 — still pending...")
time.sleep(5)
return {"result": "Timeout — check manually"}
Usage Example
def main():
API_KEY = "your-etherscan-api-key"
contract_addr = "0xYourDeployedContractAddress"
# Read your Solidity source
with open("MyToken.sol", "r") as f:
source = f.read()
result = verify_contract(
api_key=API_KEY,
contract_address=contract_addr,
source_code=source,
contract_name="MyToken",
compiler_version="v0.8.24+commit.e11b9ed9",
optimization_used=1,
runs=200,
)
guid = result.get("result")
if guid and guid != "Max rate limit reached":
check_verification_status(API_KEY, guid)
else:
print(f"Submission failed: {result}")
if __name__ == "__main__":
main()
Multi-Chain Support
Etherscan's API also works across other EVM chains. Swap the base URL for:
| Chain | API URL |
|---|---|
| Ethereum Mainnet | api.etherscan.io |
| Polygon | api.polygonscan.com |
| BSC | api.bscscan.com |
| Arbitrum | api.arbiscan.io |
| Optimism | api-optimistic.etherscan.io |
| Base | api.basescan.org |
Why It Matters
Verified contracts build trust. Users can inspect the code before interacting. Tools like Dune Analytics and The Graph can index verified contracts more reliably. And it's a professional standard — serious projects don't skip verification.
Automation ensures every deployment — whether from CI, Hardhat, or Foundry — gets verified without manual steps. That's one less thing to forget after a late-night deploy.
Useful Resources:
- 🔗 GitHub: github.com/Byaigo
- 💰 Support:
0x18da907cb9d981bc798acb87ac27b03a2dc3cbb7
Happy building! 🚀
Top comments (0)