Skip to content

Commit b3e96b4

Browse files
jadijadiDanL0
andauthored
verify-contract upgrade to V2 and improvements (#1844) (#1807)
Co-authored-by: DanL0 <159833747+DanL0@users.noreply.github.com>
1 parent 2c3a0b2 commit b3e96b4

15 files changed

Lines changed: 1094 additions & 181 deletions

File tree

‎.changeset/neat-coats-matter.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@layerzerolabs/verify-contract": minor
3+
---
4+
5+
Moving to Etherscan API v2

‎packages/verify-contract/README.md‎

Lines changed: 248 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,129 +16,317 @@
1616
<a href="https://www.npmjs.com/package/@layerzerolabs/verify-contract"><img alt="NPM License" src="https://img.shields.io/npm/l/@layerzerolabs/verify-contract"/></a>
1717
</p>
1818

19+
## Overview
20+
21+
A comprehensive tool for verifying smart contracts on block explorers. Supports both CLI and programmatic usage, with built-in support for Etherscan API v2 and 60+ EVM networks.
22+
23+
### Etherscan API v2 Support
24+
25+
This package supports **Etherscan API v2**, providing a unified multichain experience:
26+
27+
- **Unified API URL**: All Etherscan-compatible chains use `https://api.etherscan.io/v2/api`
28+
- **Single API Key**: One Etherscan API key works across all supported chains
29+
- **Automatic Chain ID**: Chain IDs are automatically set for well-known networks
30+
1931
## Installation
2032

2133
```bash
34+
npm install @layerzerolabs/verify-contract
35+
# or
2236
yarn add @layerzerolabs/verify-contract
23-
37+
# or
2438
pnpm add @layerzerolabs/verify-contract
25-
26-
npm install @layerzerolabs/verify-contract
2739
```
2840

29-
## Usage
41+
## Quick Start
3042

3143
### CLI
3244

33-
This package comes with a CLI interface:
45+
```bash
46+
# Verify all contracts on Ethereum
47+
npx @layerzerolabs/verify-contract target \
48+
--network ethereum \
49+
--api-key YOUR_ETHERSCAN_API_KEY \
50+
--deployments ./deployments
51+
```
52+
53+
### Programmatic
54+
55+
```typescript
56+
import { verifyHardhatDeployTarget } from "@layerzerolabs/verify-contract";
57+
58+
verifyHardhatDeployTarget({
59+
paths: { deployments: "./deployments" },
60+
networks: {
61+
ethereum: {
62+
apiUrl: "https://api.etherscan.io/v2/api",
63+
apiKey: "your-etherscan-api-key",
64+
},
65+
},
66+
});
67+
```
68+
69+
## CLI Usage
70+
71+
The CLI provides two verification modes: `target` (default) and `non-target`.
72+
73+
### Target Verification
74+
75+
Verifies contracts that have their own deployment files (most common case).
76+
77+
#### Basic Usage
78+
79+
```bash
80+
# Verify all contracts in a network
81+
npx @layerzerolabs/verify-contract target \
82+
--network ethereum \
83+
--api-key YOUR_ETHERSCAN_API_KEY \
84+
--deployments ./deployments
85+
```
86+
87+
#### Options
88+
89+
**Common Options:**
90+
- `-n, --network <network>` - Network name (required) - e.g., `ethereum`, `polygon`, `arbitrum`
91+
- `-k, --api-key <key>` - Scan API Key (or use environment variable)
92+
- `-u, --api-url <url>` - Custom scan API URL (auto-detected for known networks)
93+
- `--chain-id <id>` - Chain ID for Etherscan API v2 (auto-detected for known networks)
94+
- `-d, --deployments <path>` - Path to deployments folder
95+
- `--dry-run` - Preview verification without executing
96+
- `-l, --log-level <level>` - Log level: `error`, `warn`, `info`, `verbose`, `debug` (default: `info`)
97+
98+
**Target-Specific Options:**
99+
- `-c, --contracts <names>` - Comma-separated list of contract names to verify
100+
101+
#### Examples
102+
103+
```bash
104+
# Verify specific contracts only
105+
npx @layerzerolabs/verify-contract target \
106+
--network ethereum \
107+
--api-key YOUR_ETHERSCAN_API_KEY \
108+
--deployments ./deployments \
109+
--contracts FRNTAdapter,DefaultProxyAdmin
110+
111+
# Dry run (preview without actually verifying)
112+
npx @layerzerolabs/verify-contract target \
113+
--network ethereum \
114+
--api-key YOUR_ETHERSCAN_API_KEY \
115+
--deployments ./deployments \
116+
--dry-run
117+
118+
# Custom explorer (non-Etherscan networks)
119+
npx @layerzerolabs/verify-contract target \
120+
--network aurora \
121+
--api-url https://explorer.mainnet.aurora.dev/api \
122+
--api-key YOUR_AURORA_API_KEY \
123+
--deployments ./deployments
124+
```
125+
126+
### Non-Target Verification
127+
128+
Verifies contracts without deployment files (e.g., deployed dynamically by factory contracts).
129+
130+
#### Basic Usage
34131

35132
```bash
36-
npx @layerzerolabs/verify-contract --help
133+
npx @layerzerolabs/verify-contract non-target \
134+
--network ethereum \
135+
--api-key YOUR_ETHERSCAN_API_KEY \
136+
--deployments ./deployments \
137+
--address 0x123... \
138+
--name "contracts/MyContract.sol:MyContract" \
139+
--deployment MyFactory.json \
140+
--arguments '[1000, "0x456..."]'
37141
```
38142

39-
Using the CLI, contracts can be verified one network at a time.
143+
#### Options
144+
145+
**Non-Target-Specific Options:**
146+
- `--address <address>` - Contract address to verify (required)
147+
- `--name <contract name>` - Fully qualified contract name (required)
148+
- `--deployment <file>` - Deployment file name to use as source (required)
149+
- `--arguments <args>` - Constructor arguments as JSON array or encoded hex
40150

41-
### Programmatic usage
151+
#### Examples
42152

43-
The package provides two types of verification for hardhat deploy: _target_ and _non-target_.
153+
```bash
154+
# With JSON constructor arguments
155+
npx @layerzerolabs/verify-contract non-target \
156+
--network ethereum \
157+
--api-key YOUR_ETHERSCAN_API_KEY \
158+
--deployments ./deployments \
159+
--address 0x123... \
160+
--name "contracts/MyContract.sol:MyContract" \
161+
--deployment MyFactory.json \
162+
--arguments '[1000, "0x456..."]'
163+
164+
# With encoded constructor arguments
165+
npx @layerzerolabs/verify-contract non-target \
166+
--network ethereum \
167+
--api-key YOUR_ETHERSCAN_API_KEY \
168+
--deployments ./deployments \
169+
--address 0x123... \
170+
--name "contracts/MyContract.sol:MyContract" \
171+
--deployment MyFactory.json \
172+
--arguments 0x000000000000000000000000...
173+
```
44174

45-
#### Target verification
175+
### Environment Variables
46176

47-
This is suitable for verifying contracts that have been the compilation targets for a deployment, i.e. they have their own deployment file.
48-
This is the default and easiest case for which we know all the information we need from the deployment file.
177+
Instead of passing API keys on the command line, use environment variables:
178+
179+
```bash
180+
# Set environment variables
181+
export SCAN_API_KEY_ethereum="your-etherscan-api-key"
182+
export SCAN_API_KEY_polygon="your-etherscan-api-key"
183+
184+
# Then just specify the network
185+
npx @layerzerolabs/verify-contract target \
186+
--network ethereum \
187+
--deployments ./deployments
188+
```
189+
190+
The CLI automatically:
191+
- Uses the correct API URL for known networks
192+
- Sets the correct chain ID for Etherscan API v2
193+
- Pulls API keys from environment variables if not specified
194+
195+
## Programmatic Usage
196+
197+
The package provides two verification functions: `verifyHardhatDeployTarget` and `verifyHardhatDeployNonTarget`.
198+
199+
### Target Verification
200+
201+
Verifies contracts that have their own deployment files. This is the default and easiest case.
49202

50203
```typescript
51204
import { verifyHardhatDeployTarget } from "@layerzerolabs/verify-contract";
52205

53-
// Programmatic usage allows for more fine-grained and multi-network verification
54206
verifyHardhatDeployTarget({
55207
paths: {
56208
deployments: "./my/little/deployments/folder",
57209
},
58210
networks: {
211+
// Using Etherscan API v2 (recommended)
212+
ethereum: {
213+
// The v2 base URL is used by default for Etherscan-compatible chains
214+
apiUrl: "https://api.etherscan.io/v2/api",
215+
apiKey: "your-etherscan-api-key",
216+
// Chain ID is automatically set for well-known networks
217+
// For Ethereum mainnet, chainId: 1 is set automatically
218+
},
219+
polygon: {
220+
// For Etherscan v2, you can use the same API key and URL for all chains
221+
apiUrl: "https://api.etherscan.io/v2/api",
222+
apiKey: "your-etherscan-api-key",
223+
// Chain ID is automatically set for well-known networks
224+
// For Polygon, chainId: 137 is set automatically
225+
},
226+
// Custom network example
59227
whatachain: {
60228
apiUrl: "https://api.whatachain.io/api",
61229
apiKey: "david.hasselhoff.1234",
230+
// For custom networks, specify the chain ID explicitly
231+
chainId: 12345,
62232
},
63233
},
64-
// The filter option allows you to limit the scope of verification to
65-
// specific contracts
66-
//
67-
// It supports several ways of scoping the verification:
68-
//
234+
// Filter option allows you to limit verification scope
235+
// Supports multiple formats:
236+
69237
// A list of case-sensitive contract names
70238
filter: ["Factory", "Router"],
239+
71240
// A single contract name
72241
filter: "ONFT1155",
73-
// Boolean to toggle the verification as a whole
242+
243+
// Boolean to toggle verification
74244
filter: false,
75-
// A function that gets passed the contract name and an relative contract path and returns a boolean to signify the contract needs to be verified
245+
246+
// A function that receives contract name and path, returns boolean
76247
filter: (name, path) => name.startsWith("Potato721"),
77248
});
78249
```
79250

80-
#### Non-target verification
251+
### Non-Target Verification
81252

82-
This is suitable for verifying contracts that have been e.g. deployed dynamically from other contracts within the deployment.
83-
84-
In this case we need to know more information - the specific deployment file to use, the address of the contract and also its constructor arguments.
253+
Verifies contracts deployed dynamically (e.g., by factory contracts) that don't have their own deployment files.
85254

86255
```typescript
87256
import { verifyHardhatDeployNonTarget } from "@layerzerolabs/verify-contract";
88257

89-
// Programmatic usage allows for more fine-grained and multi-network verification
90258
verifyHardhatDeployNonTarget({
91259
paths: {
92260
deployments: "./my/little/deployments/folder",
93261
},
94262
networks: {
95263
whatachain: {
96-
apiUrl: "https://api.whatachain.io/api",
97-
apiKey: "david.hasselhoff.1234",
264+
// Using Etherscan API v2
265+
apiUrl: "https://api.etherscan.io/v2/api",
266+
apiKey: "your-etherscan-api-key",
267+
chainId: 12345, // Specify chain ID for custom networks
98268
},
99269
},
100-
// The contracts array is used to pass the contract details
270+
// The contracts array specifies which contracts to verify
101271
contracts: [
102272
{
103273
address: "0x0",
104274
network: "whatachain",
105-
// We'll need to pass the name of the deployment file to use (relative to the deployments path)
275+
// Deployment file name (relative to deployments path)
106276
deployment: "OtherContract.json",
277+
// Constructor arguments
107278
constructorArguments: [1000, "0x0"],
108-
// In this case we'll need to pass a fully-qualified contract name
279+
// Fully-qualified contract name
109280
contractName: "contracts/examples/Pool.sol",
110281
},
111282
],
112283
});
113284
```
114285

115-
### Default configuration
116-
117-
The package is preconfigured for scan API URLs for several well-known networks:
118-
119-
| Network | API URL |
120-
| -------------------------------------------------------------- | ------------------------------------------------ |
121-
| `avalanche`, `avalanche-mainnet` | `https://api.snowtrace.io/api` |
122-
| `fuji`, `avalanche-testnet` | `https://api-testnet.snowtrace.io/api` |
123-
| `bsc` | `https://api.bscscan.com/api` |
124-
| `bsc-testnet` | `https://api-testnet.bscscan.com/api` |
125-
| `ethereum` | `https://api.etherscan.io/api` |
126-
| `ethereum-goerli` | `https://api-goerli.etherscan.io/api` |
127-
| `goerli` | `https://api-goerli.etherscan.io/api` |
128-
| `fantom` | `https://api.ftmscan.com/api` |
129-
| `fantom-testnet` | `https://api-testnet.ftmscan.com/api` |
130-
| `arbitrum` | `https://api.arbiscan.io/api` |
131-
| `arbitrum-goerli` | `https://api-goerli.arbiscan.io/api` |
132-
| `polygon` | `https://api.polygonscan.com/api` |
133-
| `mumbai` | `https://api-testnet.polygonscan.com/api` |
134-
| `optimism` | `https://api-optimistic.etherscan.io/api` |
135-
| `optimism-goerli` | `https://api-goerli-optimistic.etherscan.io/api` |
136-
| `gnosis` | `https://api.gnosisscan.io/api` |
137-
| `zkpolygon`, `zkpolygon-mainnet` | `https://api-zkevm.polygonscan.com/api` |
138-
| `base`, `base-mainnet` | `https://api.basescan.org/api` |
139-
| `base-goerli` | `https://api-goerli.basescan.org/api` |
140-
| `zkconsensys`, `zkconsensys-mainnet`, `linea`, `linea-mainnet` | `https://api.lineascan.build/api` |
141-
| `moonbeam` | `https://api-moonbeam.moonscan.io/api` |
142-
| `moonbeam-testnet` | `https://api-moonbase.moonscan.io/api` |
143-
| `kava`, `kava-mainnet` | `https://kavascan.com/api` |
144-
| `kava-testnet` | `https://testnet.kavascan.com/api` |
286+
## Configuration
287+
288+
### Environment Variables
289+
290+
Configure API keys, URLs, browser URLs, and chain IDs using environment variables:
291+
292+
```bash
293+
# API Key - same key works for all Etherscan v2 compatible chains
294+
SCAN_API_KEY_ethereum=your-etherscan-api-key
295+
SCAN_API_KEY_polygon=your-etherscan-api-key
296+
297+
# API URL - uses v2 base URL by default for Etherscan chains
298+
SCAN_API_URL_ethereum=https://api.etherscan.io/v2/api
299+
SCAN_API_URL_polygon=https://api.etherscan.io/v2/api
300+
301+
# Chain ID - automatically set for well-known networks, but can be overridden
302+
SCAN_CHAIN_ID_ethereum=1
303+
SCAN_CHAIN_ID_polygon=137
304+
305+
# Browser URL for displaying verified contract links
306+
SCAN_BROWSER_URL_ethereum=https://etherscan.io
307+
SCAN_BROWSER_URL_polygon=https://polygonscan.com
308+
```
309+
310+
> **Note:**
311+
> Environment variable names for network configuration are **not case-sensitive** and support both hyphens (`-`) and underscores (`_`) in network names. For maximum compatibility across systems and shells, it is recommended to define variables using uppercase characters, underscores, and the canonical network name, e.g.:
312+
>
313+
> - `SCAN_API_KEY_ETHEREUM`
314+
> - `SCAN_API_KEY_BASE_SEPOLIA`
315+
316+
### Default Network Configuration
317+
318+
The package is preconfigured with scan API URLs and chain IDs for well-known networks.
319+
320+
#### Supported Networks
321+
322+
The package supports 60+ EVM networks with preconfigured scan API URLs and chain IDs. Most major EVM networks use the Etherscan API v2 unified endpoint (`https://api.etherscan.io/v2/api`) and can share a single API key.
323+
324+
**Examples:**
325+
326+
| Network | Chain ID | API URL (v2) |
327+
| -------------------- | -------- | --------------------------------- |
328+
| `ethereum` | 1 | `https://api.etherscan.io/v2/api` |
329+
| `polygon` | 137 | `https://api.etherscan.io/v2/api` |
330+
| `aurora` | 1313161554 | `https://explorer.mainnet.aurora.dev/api` |
331+
332+
For the complete list of supported networks, network aliases, and their configurations, see [`src/common/networks.ts`](src/common/networks.ts).

‎packages/verify-contract/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"license": "MIT",
1414
"main": "./dist/index.js",
1515
"module": "./dist/index.mjs",
16-
"types": "./dist.index.d.ts",
16+
"types": "./dist/index.d.ts",
1717
"bin": "./cli.js",
1818
"files": [
1919
"./dist/*",

0 commit comments

Comments
 (0)