Skip to content

Commit 547d76f

Browse files
committed
use .env.template only
1 parent fe7c621 commit 547d76f

File tree

7 files changed

+316
-3107
lines changed

7 files changed

+316
-3107
lines changed

pnpm-lock.yaml

Lines changed: 3 additions & 3040 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 90 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,90 @@
1-
# Network Config
2-
MIGRATIONS_DIR= # ./migrations/prod-receiver
3-
MIGRATIONS_NETWORK= # xyz
4-
MAINNET=
5-
6-
# The duration that a price feed stored in the contract is considered to be
7-
# valid, after this duration, the price feed is stale and will be invalid.
8-
# This value should derive from Pyth to wormhole latency, and target chain blocktime and latency.
9-
VALID_TIME_PERIOD_SECONDS= # 60
10-
11-
WORMHOLE_CHAIN_NAME= # ethereum, defined in <repo-root>/governance/xc_admin/packages/xc_admin_common/src/chains.ts
12-
13-
CLUSTER= #mainnet/testnet The configs below are read from the cluster file
14-
15-
# Pyth Migrations # Example Format. If deployed on mainnet/testnet it is available in env.cluster.{cluster}
16-
SOLANA_CHAIN_ID= # 0x1
17-
SOLANA_EMITTER= # 0xf346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0
18-
PYTHNET_CHAIN_ID= # 0x1a
19-
PYTHNET_EMITTER= # 0xa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6
20-
GOVERNANCE_CHAIN_ID= # 0x1
21-
GOVERNANCE_EMITTER= # 0x63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385
22-
GOVERNANCE_INITIAL_SEQUENCE=0 # This is optional and default is 0
23-
SINGLE_UPDATE_FEE_IN_WEI=0
1+
# =============================================================================
2+
# FOUNDRY DEPLOYMENT CONFIGURATION TEMPLATE
3+
# Copy this file to .env and fill in your actual values
4+
# =============================================================================
5+
6+
# Deployment Configuration
7+
# Example: PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
8+
PRIVATE_KEY=YOUR_PRIVATE_KEY_HERE
9+
# Example: RPC_URL=https://rpc.ankr.com/eth (or http://localhost:8545 for local)
10+
RPC_URL=YOUR_RPC_URL_HERE
11+
# Example: ETHERSCAN_API_KEY=your_etherscan_api_key_here
12+
ETHERSCAN_API_KEY=YOUR_ETHERSCAN_API_KEY_HERE
13+
14+
# =============================================================================
15+
# WORMHOLE CONFIGURATION
16+
# =============================================================================
17+
18+
# Initial Guardian Configuration (comma-separated addresses - Foundry native)
19+
# For single guardian: INIT_SIGNERS=0xYourGuardianAddress
20+
# For multiple guardians: INIT_SIGNERS=0xAddress1,0xAddress2,0xAddress3
21+
# Example: INIT_SIGNERS=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5
22+
INIT_SIGNERS=YOUR_GUARDIAN_ADDRESSES_HERE
23+
# Example: INIT_CHAIN_ID=1
24+
INIT_CHAIN_ID=YOUR_CHAIN_ID_HERE
25+
# Example: INIT_GOV_CHAIN_ID=1
26+
INIT_GOV_CHAIN_ID=YOUR_GOV_CHAIN_ID_HERE
27+
# Example: INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
28+
INIT_GOV_CONTRACT=YOUR_GOV_CONTRACT_ADDRESS_HERE
29+
30+
# Guardian Set Sync Configuration (set after deployment)
31+
# Example: WORMHOLE_ADDRESS=0x0000000000000000000000000000000000000000
32+
WORMHOLE_ADDRESS=DEPLOYED_WORMHOLE_ADDRESS_HERE
33+
34+
# =============================================================================
35+
# PYTH CONFIGURATION
36+
# =============================================================================
37+
38+
# Data Source Configuration
39+
# Example: SOLANA_CHAIN_ID=1
40+
SOLANA_CHAIN_ID=YOUR_SOLANA_CHAIN_ID_HERE
41+
# Example: SOLANA_EMITTER=0xf346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0
42+
SOLANA_EMITTER=YOUR_SOLANA_EMITTER_ADDRESS_HERE
43+
# Example: PYTHNET_CHAIN_ID=26
44+
PYTHNET_CHAIN_ID=YOUR_PYTHNET_CHAIN_ID_HERE
45+
# Example: PYTHNET_EMITTER=0xa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6
46+
PYTHNET_EMITTER=YOUR_PYTHNET_EMITTER_ADDRESS_HERE
47+
48+
# Governance Configuration
49+
# Example: GOVERNANCE_CHAIN_ID=1
50+
GOVERNANCE_CHAIN_ID=YOUR_GOVERNANCE_CHAIN_ID_HERE
51+
# Example: GOVERNANCE_EMITTER=0x63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385
52+
GOVERNANCE_EMITTER=YOUR_GOVERNANCE_EMITTER_ADDRESS_HERE
53+
# Example: GOVERNANCE_INITIAL_SEQUENCE=0
54+
GOVERNANCE_INITIAL_SEQUENCE=YOUR_INITIAL_SEQUENCE_HERE
55+
56+
# Price Feed Configuration
57+
# Example: VALID_TIME_PERIOD_SECONDS=60
58+
VALID_TIME_PERIOD_SECONDS=YOUR_VALID_TIME_PERIOD_HERE
59+
# Example: SINGLE_UPDATE_FEE_IN_WEI=1000000000000000
60+
SINGLE_UPDATE_FEE_IN_WEI=YOUR_UPDATE_FEE_HERE
61+
62+
# =============================================================================
63+
# LEGACY CONFIGURATION (for backward compatibility)
64+
# =============================================================================
65+
66+
# Example: WORMHOLE_CHAIN_NAME=ethereum
67+
WORMHOLE_CHAIN_NAME=YOUR_CHAIN_NAME_HERE
68+
# Example: CLUSTER=mainnet
69+
CLUSTER=YOUR_CLUSTER_HERE
70+
71+
# =============================================================================
72+
# EXAMPLE VALUES FOR REFERENCE
73+
# =============================================================================
74+
#
75+
# For local testing (Anvil), you can use:
76+
# PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
77+
# RPC_URL=http://localhost:8545
78+
# INIT_SIGNERS=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5
79+
# INIT_CHAIN_ID=2
80+
# INIT_GOV_CHAIN_ID=1
81+
# INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
82+
#
83+
# For testnet/mainnet deployment:
84+
# - Get your private key from your wallet (never commit this!)
85+
# - Use appropriate RPC URL (Alchemy, Infura, QuickNode, etc.)
86+
# - Get Etherscan API key from https://etherscan.io/apis
87+
# - Use actual guardian addresses from your network
88+
# - Set proper chain IDs and governance contracts
89+
#
90+
# ⚠️ SECURITY WARNING: Never commit your actual .env file to version control!
Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,49 @@
1-
# Migrations Metadata
2-
MIGRATIONS_DIR=./migrations/test
1+
# =============================================================================
2+
# FOUNDRY TEST CONFIGURATION
3+
# This file contains test values for local development and testing
4+
# Uses Foundry-native environment variable formats
5+
# =============================================================================
36

4-
# Wormhole Core Migrations
5-
INIT_SIGNERS=["0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe"]
6-
INIT_CHAIN_ID=0x2
7-
INIT_GOV_CHAIN_ID=0x1
7+
# Deployment Configuration (Anvil/Local Testing)
8+
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
9+
RPC_URL=http://localhost:8545
10+
ETHERSCAN_API_KEY=test_api_key_not_needed_for_local
11+
12+
# =============================================================================
13+
# WORMHOLE TEST CONFIGURATION
14+
# =============================================================================
15+
16+
# Guardian Configuration (comma-separated addresses - Foundry native)
17+
INIT_SIGNERS=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5,0x025ceeba2ab2a27d53d963393999eeebe83dc4ae
18+
INIT_CHAIN_ID=2
19+
INIT_GOV_CHAIN_ID=1
820
INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
921

10-
# Bridge Migrations
11-
BRIDGE_INIT_CHAIN_ID=0x2
12-
BRIDGE_INIT_GOV_CHAIN_ID=0x1
13-
BRIDGE_INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
14-
BRIDGE_INIT_WETH=0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E
22+
# Guardian Set Sync Configuration (will be set after deployment)
23+
WORMHOLE_ADDRESS=0x0000000000000000000000000000000000000000
24+
25+
# =============================================================================
26+
# PYTH TEST CONFIGURATION
27+
# =============================================================================
1528

16-
#Pyth
17-
SOLANA_CHAIN_ID=0x1
29+
# Test Data Source Configuration
30+
SOLANA_CHAIN_ID=1
1831
SOLANA_EMITTER=0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b
32+
PYTHNET_CHAIN_ID=26
33+
PYTHNET_EMITTER=0xa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6
1934

20-
VALID_TIME_PERIOD_SECONDS=60
35+
# Test Governance Configuration
36+
GOVERNANCE_CHAIN_ID=1
37+
GOVERNANCE_EMITTER=0x0000000000000000000000000000000000000000000000000000000000001234
38+
GOVERNANCE_INITIAL_SEQUENCE=0
2139

40+
# Test Price Feed Configuration
41+
VALID_TIME_PERIOD_SECONDS=60
42+
SINGLE_UPDATE_FEE_IN_WEI=1
2243

23-
GOVERNANCE_CHAIN_ID=0x1
24-
GOVERNANCE_EMITTER=0x0000000000000000000000000000000000000000000000000000000000001234
44+
# =============================================================================
45+
# LEGACY CONFIGURATION (for backward compatibility)
46+
# =============================================================================
2547

2648
WORMHOLE_CHAIN_NAME=ethereum
27-
SINGLE_UPDATE_FEE_IN_WEI=1
49+
CLUSTER=testnet
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# Foundry Environment Variables Guide
2+
3+
This guide shows the **recommended Foundry-native approaches** for reading environment variables in deployment scripts, without custom parsers.
4+
5+
## 🎯 Recommended Approaches
6+
7+
### 1. **Comma-Separated Arrays****BEST FOR MOST CASES**
8+
9+
**Use Case:** Arrays of addresses, numbers, or simple types
10+
11+
**Environment Format:**
12+
```bash
13+
# Multiple addresses
14+
INIT_SIGNERS=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5,0x025ceeba2ab2a27d53d963393999eeebe83dc4ae
15+
16+
# Multiple numbers
17+
CHAIN_IDS=1,137,56,43114
18+
19+
# Multiple strings (if supported)
20+
NETWORKS=ethereum,polygon,bsc
21+
```
22+
23+
**Solidity Code:**
24+
```solidity
25+
// Read address array
26+
address[] memory signers = vm.envAddress("INIT_SIGNERS", ",");
27+
28+
// Read uint array
29+
uint256[] memory chainIds = vm.envUint("CHAIN_IDS", ",");
30+
31+
// Convert addresses to bytes32 if needed
32+
bytes32[] memory guardians = new bytes32[](signers.length);
33+
for (uint i = 0; i < signers.length; i++) {
34+
guardians[i] = bytes32(uint256(uint160(signers[i])));
35+
}
36+
```
37+
38+
**✅ Advantages:**
39+
- Native Foundry support
40+
- Clean, readable format
41+
- No parsing needed
42+
- Works with all basic types
43+
44+
### 2. **JSON with vm.parseJson** (For Complex Data)
45+
46+
**Use Case:** Complex nested data structures
47+
48+
**Environment Format:**
49+
```bash
50+
# Simple array
51+
INIT_SIGNERS='["0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5","0x025ceeba2ab2a27d53d963393999eeebe83dc4ae"]'
52+
53+
# Complex object
54+
CONFIG='{"guardians":["0x..."],"chainId":1,"enabled":true}'
55+
```
56+
57+
**Solidity Code:**
58+
```solidity
59+
// Simple array
60+
string memory signersJson = vm.envString("INIT_SIGNERS");
61+
address[] memory signers = abi.decode(vm.parseJson(signersJson), (address[]));
62+
63+
// Complex object with key selection
64+
string memory configJson = vm.envString("CONFIG");
65+
address[] memory guardians = abi.decode(vm.parseJson(configJson, ".guardians"), (address[]));
66+
uint256 chainId = abi.decode(vm.parseJson(configJson, ".chainId"), (uint256));
67+
bool enabled = abi.decode(vm.parseJson(configJson, ".enabled"), (bool));
68+
```
69+
70+
**⚠️ Requirements:**
71+
- JSON must be properly formatted
72+
- Use single quotes in .env files to prevent shell parsing issues
73+
- May need escaping for complex nested structures
74+
75+
### 3. **Individual Environment Variables** (Simple & Reliable)
76+
77+
**Use Case:** When you have a known, small number of values
78+
79+
**Environment Format:**
80+
```bash
81+
GUARDIAN_1=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5
82+
GUARDIAN_2=0x025ceeba2ab2a27d53d963393999eeebe83dc4ae
83+
GUARDIAN_COUNT=2
84+
```
85+
86+
**Solidity Code:**
87+
```solidity
88+
uint256 guardianCount = vm.envUint("GUARDIAN_COUNT");
89+
bytes32[] memory guardians = new bytes32[](guardianCount);
90+
91+
for (uint i = 0; i < guardianCount; i++) {
92+
string memory key = string(abi.encodePacked("GUARDIAN_", vm.toString(i + 1)));
93+
address guardian = vm.envAddress(key);
94+
guardians[i] = bytes32(uint256(uint160(guardian)));
95+
}
96+
```
97+
98+
**✅ Advantages:**
99+
- Most reliable
100+
- Easy to debug
101+
- No parsing issues
102+
- Clear variable names
103+
104+
## 📋 Available Foundry VM Methods
105+
106+
```solidity
107+
// Basic types
108+
vm.envString("KEY") // string
109+
vm.envAddress("KEY") // address
110+
vm.envUint("KEY") // uint256
111+
vm.envInt("KEY") // int256
112+
vm.envBytes32("KEY") // bytes32
113+
vm.envBytes("KEY") // bytes
114+
vm.envBool("KEY") // bool
115+
116+
// Arrays with delimiter
117+
vm.envAddress("KEY", ",") // address[]
118+
vm.envUint("KEY", ",") // uint256[]
119+
vm.envInt("KEY", ",") // int256[]
120+
vm.envBytes32("KEY", ",") // bytes32[]
121+
vm.envString("KEY", ",") // string[]
122+
123+
// With default values
124+
vm.envOr("KEY", defaultValue)
125+
126+
// JSON parsing
127+
vm.parseJson(jsonString) // Parse entire JSON
128+
vm.parseJson(jsonString, ".key") // Parse specific key
129+
```
130+
131+
## 🛠️ Our Implementation
132+
133+
**Current Deploy.s.sol uses Approach #1 (Comma-Separated):**
134+
135+
```solidity
136+
// ✅ Clean, native Foundry approach
137+
address[] memory signerAddresses = vm.envAddress("INIT_SIGNERS", ",");
138+
139+
// Convert to bytes32 for Wormhole
140+
bytes32[] memory initialSigners = new bytes32[](signerAddresses.length);
141+
for (uint i = 0; i < signerAddresses.length; i++) {
142+
initialSigners[i] = bytes32(uint256(uint160(signerAddresses[i])));
143+
}
144+
```
145+
146+
**Environment Format:**
147+
```bash
148+
INIT_SIGNERS=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5,0x025ceeba2ab2a27d53d963393999eeebe83dc4ae
149+
```
150+
151+
## 🚫 What to Avoid
152+
153+
- ❌ Custom string parsing functions
154+
- ❌ Complex regex operations
155+
- ❌ Manual hex conversion (use vm.envAddress instead)
156+
- ❌ Hardcoded values in scripts
157+
- ❌ Unescaped JSON in environment files
158+
159+
## 💡 Best Practices
160+
161+
1. **Use comma-separated for simple arrays**
162+
2. **Use individual vars for small, known sets**
163+
3. **Use JSON only for complex nested data**
164+
4. **Always validate environment variables exist**
165+
5. **Use `vm.envOr()` for optional values with defaults**
166+
6. **Keep environment files well-documented**
167+
7. **Test with different environment configurations**
168+
169+
## 🧪 Testing
170+
171+
```bash
172+
# Test with current environment
173+
forge script script/Deploy.s.sol
174+
175+
# Test with specific environment file
176+
cp .env.test .env && forge script script/Deploy.s.sol
177+
178+
# Test individual components
179+
forge script script/Deploy.s.sol --sig "deployWormhole()"
180+
```

target_chains/ethereum/contracts/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ To deploy the contracts, you'll need to set up your environment variables and us
4141
1. Copy the environment template and fill in your values:
4242

4343
```bash
44-
cp deploy.env.example .env
44+
cp .env.template .env
4545
# Edit .env with your configuration
4646
```
4747

target_chains/ethereum/contracts/deploy.env.example

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

0 commit comments

Comments
 (0)