Skip to content

Commit a2a0c02

Browse files
authored
refactor hardhat cct (#128)
* refactor * refactor * refactor * refactor
1 parent 053648b commit a2a0c02

33 files changed

Lines changed: 364 additions & 341 deletions

ccip/cct/hardhat/README.md

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,22 @@ All tasks in this project use Hardhat's global options. The most important one i
2323

2424
The following networks are configured and available for use:
2525

26-
| Network Name | Description | Environment Variable |
27-
| ----------------- | ------------------------ | -------------------------- |
28-
| `avalancheFuji` | Avalanche Fuji Testnet | `AVALANCHE_FUJI_RPC_URL` |
29-
| `arbitrumSepolia` | Arbitrum Sepolia Testnet | `ARBITRUM_SEPOLIA_RPC_URL` |
30-
| `sepolia` | Ethereum Sepolia Testnet | `ETHEREUM_SEPOLIA_RPC_URL` |
31-
| `baseSepolia` | Base Sepolia Testnet | `BASE_SEPOLIA_RPC_URL` |
32-
| `polygonAmoy` | Polygon Amoy Testnet | `POLYGON_AMOY_RPC_URL` |
26+
| Network Name | Description | Environment Variable | Type |
27+
| ----------------- | ------------------------ | -------------------------- | ------- |
28+
| `avalancheFuji` | Avalanche Fuji Testnet | `AVALANCHE_FUJI_RPC_URL` | EVM |
29+
| `arbitrumSepolia` | Arbitrum Sepolia Testnet | `ARBITRUM_SEPOLIA_RPC_URL` | EVM |
30+
| `ethereumSepolia` | Ethereum Sepolia Testnet | `ETHEREUM_SEPOLIA_RPC_URL` | EVM |
31+
| `baseSepolia` | Base Sepolia Testnet | `BASE_SEPOLIA_RPC_URL` | EVM |
32+
| `polygonAmoy` | Polygon Amoy Testnet | `POLYGON_AMOY_RPC_URL` | EVM |
33+
| `solanaDevnet` | Solana Devnet | N/A (destination only) | Non-EVM |
3334

3435
### Network Configuration
3536

36-
Network configurations are defined in:
37+
Network configurations use a **professional single source of truth architecture**:
3738

38-
- **Network settings**: `/config/networks.ts`
39-
- **Chain parameters**: `/config/config.json`
40-
- **Contract addresses**: Automatically loaded per network
39+
- **All network settings**: `/config/networks.ts` (consolidated configuration)
40+
- **Types auto-generated**: From the network configuration data
41+
- **Zero maintenance**: No manual enum synchronization needed
4142

4243
To use a network, ensure:
4344

@@ -84,12 +85,136 @@ npx env-enc remove VARIABLE_NAME
8485
- `BASE_SEPOLIA_RPC_URL`: RPC URL for Base Sepolia testnet
8586
- `POLYGON_AMOY_RPC_URL`: RPC URL for Polygon Amoy testnet
8687

88+
**Optional (for contract verification):**
89+
90+
- `ETHERSCAN_API_KEY`: Single API key for all Etherscan-compatible explorers (Etherscan V2)
91+
- Works across Ethereum, Arbitrum, Base, Polygon, and other Etherscan-compatible networks
92+
- Get your API key from [Etherscan](https://etherscan.io/apis)
93+
- No need for separate API keys per network (Etherscan V2 improvement)
94+
8795
**Security Notes:**
8896

8997
- The `.env.enc` file should be included in `.gitignore`
9098
- Your encryption password is required each time you start a new terminal session
9199
- Never commit your `.env.enc` file to version control
92100

101+
## Adding New Networks
102+
103+
The network configuration system uses a single source of truth architecture that automatically generates TypeScript types and Hardhat network configurations from the network data.
104+
105+
### Adding a Network
106+
107+
To add a new CCIP-supported network, add the network configuration to the `configData` object in `config/networks.ts`:
108+
109+
```typescript
110+
export const configData = {
111+
// ... existing networks
112+
newNetwork: {
113+
chainFamily: "evm", // or "svm" for non-EVM chains
114+
chainId: 12345,
115+
chainSelector: "1234567890123456789",
116+
router: "0xRouterAddress",
117+
rmnProxy: "0xRMNProxyAddress",
118+
tokenAdminRegistry: "0xTokenAdminRegistryAddress",
119+
registryModuleOwnerCustom: "0xRegistryModuleOwnerAddress",
120+
link: "0xLinkTokenAddress",
121+
confirmations: 2,
122+
nativeCurrencySymbol: "NEW",
123+
// chainType auto-defaults to "l1" for most chains, "op" for Base/Optimism
124+
},
125+
};
126+
```
127+
128+
The network becomes available in:
129+
130+
- All task `--network` options
131+
132+
### CCIP Configuration Sources
133+
134+
Obtain the required addresses and chain selectors from the official CCIP directories:
135+
136+
- **Mainnet Networks**: [https://docs.chain.link/ccip/directory/mainnet](https://docs.chain.link/ccip/directory/mainnet)
137+
- **Testnet Networks**: [https://docs.chain.link/ccip/directory/testnet](https://docs.chain.link/ccip/directory/testnet)
138+
139+
Required information from these directories:
140+
141+
- Router contract addresses
142+
- Chain selectors (unique CCIP identifiers)
143+
- RMN Proxy addresses
144+
- Token Admin Registry addresses
145+
- LINK token addresses
146+
147+
### Environment Variable
148+
149+
The system automatically generates environment variable names from network names using this pattern:
150+
- Convert camelCase to SNAKE_CASE
151+
- Add `_RPC_URL` suffix
152+
153+
**Examples:**
154+
- `newNetwork``NEW_NETWORK_RPC_URL`
155+
- `optimismSepolia``OPTIMISM_SEPOLIA_RPC_URL`
156+
- `bscTestnet``BSC_TESTNET_RPC_URL`
157+
158+
Set the RPC URL environment variable:
159+
160+
```bash
161+
npx env-enc set NEW_NETWORK_RPC_URL
162+
```
163+
164+
**For the example network above:**
165+
```bash
166+
npx env-enc set OPTIMISM_SEPOLIA_RPC_URL
167+
```
168+
169+
### Contract Verification (Optional)
170+
171+
**Automatic Verification (Natively Supported):**
172+
Most standard networks are natively supported by Hardhat for contract verification. Check [Hardhat's chain descriptors](https://github.com/NomicFoundation/hardhat/blob/main/v-next/hardhat/src/internal/builtin-plugins/network-manager/chain-descriptors.ts) for the complete list of supported networks.
173+
174+
**Custom Chain Descriptors Required:**
175+
For networks not natively supported by Hardhat, add a chain descriptor to `hardhat.config.ts`. This is particularly useful for:
176+
- Newer networks not yet added to Hardhat
177+
- Private/enterprise chains
178+
- Custom testnets
179+
180+
```typescript
181+
chainDescriptors: {
182+
12345: { // Your network's chainId
183+
name: "New Network",
184+
chainType: "generic",
185+
blockExplorers: {
186+
etherscan: {
187+
name: "NewScan",
188+
url: "https://newscan.io",
189+
apiUrl: "https://api.newscan.io/api",
190+
},
191+
},
192+
},
193+
}
194+
```
195+
196+
Note: With Etherscan V2, a single `ETHERSCAN_API_KEY` works across all Etherscan-compatible networks.
197+
198+
### Example: Adding Optimism Sepolia
199+
200+
```typescript
201+
optimismSepolia: {
202+
chainFamily: "evm",
203+
chainId: 11155420,
204+
chainSelector: "5224473277236331295",
205+
router: "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57",
206+
rmnProxy: "0x...",
207+
tokenAdminRegistry: "0x...",
208+
registryModuleOwnerCustom: "0x...",
209+
link: "0x...",
210+
confirmations: 2,
211+
nativeCurrencySymbol: "ETH",
212+
// chainType auto-defaults to "op" (detected from "optimism" in name)
213+
}
214+
```
215+
216+
All tasks will support `--network optimismSepolia` after adding this configuration.
217+
93218
### Example Usage
94219

95220
```bash
@@ -112,6 +237,7 @@ npx hardhat transferTokens --tokenaddress 0x123... --amount 1000 --destinationch
112237
- [Supported Networks](#supported-networks)
113238
- [Network Configuration](#network-configuration)
114239
- [Environment Variable Setup](#environment-variable-setup)
240+
- [Adding New Networks](#adding-new-networks)
115241
- [Example Usage](#example-usage)
116242

117243
**EOA**:

ccip/cct/hardhat/config/config.json

Lines changed: 0 additions & 73 deletions
This file was deleted.

ccip/cct/hardhat/config/index.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,38 @@
1-
import { Chains, EVMChains } from "./types";
2-
import { networks } from "./networks";
3-
1+
import type { Chains, EVMChains } from "./types";
2+
import { configData, networks } from "./networks";
43
export {
5-
Chains,
6-
EVMChains,
74
PoolType,
85
TokenContractName,
96
TokenPoolContractName,
107
CCIPContractName,
118
} from "./types";
12-
13-
export type { Networks } from "./types";
14-
export { networks, configData } from "./networks";
9+
export type { Chains, EVMChains, Networks } from "./types";
10+
export { configData, networks } from "./networks";
1511
export { logger } from "./logger";
1612

13+
/**
14+
* Type guard to check if a string is a valid chain name
15+
*/
16+
export function isValidChain(chain: string): chain is Chains {
17+
return chain in configData;
18+
}
19+
1720
/**
1821
* Type guard to check if a chain is an EVM chain
1922
*/
20-
export function isEVMChain(chain: string): boolean {
21-
return Object.values(EVMChains).includes(chain as EVMChains);
23+
export function isEVMChain(chain: string): chain is EVMChains {
24+
if (!isValidChain(chain)) return false;
25+
return configData[chain].chainFamily === "evm";
26+
}
27+
28+
/**
29+
* Validates and returns a typed network name from Hardhat runtime environment
30+
*/
31+
export function validateNetworkName(networkName: string): Chains {
32+
if (!isValidChain(networkName)) {
33+
throw new Error(`Unsupported network: ${networkName}`);
34+
}
35+
return networkName;
2236
}
2337

2438
/**

0 commit comments

Comments
 (0)