Skip to content

Commit 1870046

Browse files
committed
docs: clarify example-specific tasks and native adapter instructions
- WORKFLOW.md: Add note clarifying lz:oft:send is a custom task defined in examples/oft/tasks/, not a core SDK task - native-oft-adapter README: Replace confusing mint instructions with accurate note about native token usage (no minting required)
1 parent ba9762f commit 1870046

2 files changed

Lines changed: 316 additions & 1 deletion

File tree

WORKFLOW.md

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
# LayerZero Deployment Workflow
2+
3+
This guide explains the complete workflow for deploying and configuring LayerZero OApps and OFTs.
4+
5+
## The Big Picture
6+
7+
```
8+
┌─────────────────────────────────────────────────────────────────────────────────┐
9+
│ Cross-Chain Message Flow │
10+
├─────────────────────────────────────────────────────────────────────────────────┤
11+
│ │
12+
│ Source Chain LayerZero Network Destination Chain │
13+
│ ──────────── ──────────────── ───────────────── │
14+
│ │
15+
│ ┌─────────┐ ┌─────────┐ │
16+
│ │ Your │ ──► ┌──────────┐ ┌─────┐ ┌──────────┐ ──► │ Your │ │
17+
│ │ OApp │ │ Endpoint │ ──► │ DVN │ ──► │ Endpoint │ │ OApp │ │
18+
│ └─────────┘ └──────────┘ └─────┘ └──────────┘ └─────────┘ │
19+
│ │ │ │ │ │
20+
│ │ │ │ │ │
21+
│ User calls DVNs verify Executor delivers │
22+
│ send() the message and calls receive │
23+
│ │
24+
└─────────────────────────────────────────────────────────────────────────────────┘
25+
```
26+
27+
## Transaction Model
28+
29+
A LayerZero deployment requires transactions on **every chain** in your configuration. Here's the breakdown:
30+
31+
### Phase 1: Deployment
32+
33+
| Action | Transactions | Description |
34+
|--------|--------------|-------------|
35+
| Deploy contract | 1 per chain | Deploy your OApp/OFT contract |
36+
| **Total** | **N chains** | N deployment transactions |
37+
38+
### Phase 2: Wiring (Configuration)
39+
40+
For each **pathway** (A ↔ B), the wire task generates:
41+
42+
| Action | Transactions | Description |
43+
|--------|--------------|-------------|
44+
| `setPeer` | 2 (A→B, B→A) | Set peer addresses |
45+
| `setConfig` (Send) | 2 | Configure send library (DVNs, etc.) |
46+
| `setConfig` (Receive) | 2 | Configure receive library |
47+
| `setEnforcedOptions` | 2 | Set minimum gas options |
48+
| **Total per pathway** | **~8 txs** | 4 on each chain |
49+
50+
### Example: 2-Chain Deployment (Base ↔ Arbitrum)
51+
52+
```
53+
Deployment Phase:
54+
- Deploy MyOFT on Base: 1 tx
55+
- Deploy MyOFT on Arbitrum: 1 tx
56+
Total: 2 txs
57+
58+
Wiring Phase:
59+
- setPeer (Base → Arb): 1 tx on Base
60+
- setPeer (Arb → Base): 1 tx on Arbitrum
61+
- setConfig (Base send): 1 tx on Base
62+
- setConfig (Base receive): 1 tx on Base
63+
- setConfig (Arb send): 1 tx on Arbitrum
64+
- setConfig (Arb receive): 1 tx on Arbitrum
65+
- setEnforcedOptions: 2 txs (1 per chain)
66+
Total: ~8 txs
67+
68+
Grand Total: ~10 transactions
69+
```
70+
71+
### Example: 3-Chain Deployment (A ↔ B ↔ C)
72+
73+
With 3 chains fully connected (3 pathways: A-B, A-C, B-C):
74+
- Deployment: 3 txs
75+
- Wiring: 3 pathways × ~8 txs = ~24 txs
76+
- **Total: ~27 transactions**
77+
78+
## Hardhat as Task Orchestration
79+
80+
**Key Insight**: In this repository, Hardhat is used as a **task orchestration system**, not just a Solidity compiler.
81+
82+
The LayerZero SDK exposes functionality through Hardhat tasks:
83+
84+
```bash
85+
# These are NOT just compile commands - they orchestrate multi-chain operations
86+
npx hardhat lz:deploy # Deploys to ALL configured networks
87+
npx hardhat lz:oapp:wire # Configures ALL pathways
88+
npx hardhat lz:oapp:config:get # Reads config from ALL chains
89+
```
90+
91+
### How It Works
92+
93+
1. `@layerzerolabs/toolbox-hardhat` registers custom tasks
94+
2. Tasks read your `hardhat.config.ts` for network definitions
95+
3. Tasks read your `layerzero.config.ts` for pathway configuration
96+
4. Tasks execute transactions across multiple networks
97+
98+
## Understanding layerzero.config.ts
99+
100+
The configuration file defines your **OmniGraph** - the topology of your omnichain application.
101+
102+
### Structure
103+
104+
```typescript
105+
// layerzero.config.ts exports an async function
106+
export default async function() {
107+
return {
108+
contracts: OmniNode[], // Which contracts on which chains
109+
connections: OmniEdge[], // Pathways between contracts
110+
}
111+
}
112+
```
113+
114+
### Why Is Config Async?
115+
116+
The config fetches **live metadata** at runtime:
117+
- DVN contract addresses per chain
118+
- Default configurations
119+
- Executor addresses
120+
121+
This ensures your config uses the latest deployed infrastructure.
122+
123+
### Key Types
124+
125+
```typescript
126+
// OmniPointHardhat - A contract location
127+
const myContract: OmniPointHardhat = {
128+
eid: EndpointId.BASESEP_V2_TESTNET, // Which chain
129+
contractName: 'MyOFT', // Contract name (from hardhat-deploy)
130+
}
131+
132+
// OmniNode - A contract with its configuration
133+
const node = {
134+
contract: myContract,
135+
config: { /* optional per-contract config */ }
136+
}
137+
138+
// OmniEdge - A pathway between two contracts
139+
const edge = {
140+
from: contractA,
141+
to: contractB,
142+
config: {
143+
sendConfig: { /* DVN, executor config */ },
144+
receiveConfig: { /* DVN config */ },
145+
enforcedOptions: [ /* gas options */ ],
146+
}
147+
}
148+
```
149+
150+
### Using generateConnectionsConfig()
151+
152+
The helper function simplifies bidirectional pathway configuration:
153+
154+
```typescript
155+
import { generateConnectionsConfig, TwoWayConfig } from '@layerzerolabs/metadata-tools'
156+
157+
const pathways: TwoWayConfig[] = [
158+
[
159+
contractA, // From
160+
contractB, // To
161+
[['LayerZero Labs'], []], // [requiredDVNs, [optionalDVNs, threshold]]
162+
[1, 1], // [A→B confirmations, B→A confirmations]
163+
[enforcedOptionsAtoB, enforcedOptionsBtoA],
164+
],
165+
]
166+
167+
const connections = await generateConnectionsConfig(pathways)
168+
```
169+
170+
## Pathway Lifecycle
171+
172+
A pathway goes through these states:
173+
174+
```
175+
1. DEPLOYED
176+
└── Contracts deployed, but not connected
177+
└── Cannot send messages
178+
179+
2. WIRED (Peer Set)
180+
└── setPeer() called on both ends
181+
└── Contracts know each other's addresses
182+
└── Still cannot send without proper config
183+
184+
3. CONFIGURED
185+
└── setConfig() called for send/receive
186+
└── DVNs and executors configured
187+
└── setEnforcedOptions() called
188+
189+
4. LIVE ✓
190+
└── All configuration complete
191+
└── Messages can flow in both directions
192+
```
193+
194+
### Checking Pathway Status
195+
196+
```bash
197+
# Check if peers are set
198+
npx hardhat lz:oapp:peers:get --oapp-config layerzero.config.ts
199+
200+
# Check full configuration
201+
npx hardhat lz:oapp:config:get --oapp-config layerzero.config.ts
202+
203+
# Compare with LayerZero defaults
204+
npx hardhat lz:oapp:config:get:default --oapp-config layerzero.config.ts
205+
```
206+
207+
## Common Workflows
208+
209+
### Workflow 1: Fresh Testnet Deployment
210+
211+
```bash
212+
# 1. Setup environment
213+
cp .env.example .env
214+
# Edit .env with MNEMONIC or PRIVATE_KEY
215+
216+
# 2. Install and build
217+
pnpm install
218+
pnpm compile
219+
220+
# 3. Deploy to all networks
221+
npx hardhat lz:deploy
222+
223+
# 4. Wire all pathways
224+
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts
225+
226+
# 5. Verify configuration
227+
npx hardhat lz:oapp:config:get --oapp-config layerzero.config.ts
228+
229+
# 6. Send test message/token (example-specific task)
230+
# Note: lz:oft:send is a custom task defined in examples/oft/tasks/, not a core SDK task
231+
# Each example may have its own send task implementation
232+
npx hardhat lz:oft:send --network base-sepolia --to arbitrum-sepolia --amount 1000000000000000000
233+
```
234+
235+
### Workflow 2: Adding a New Chain
236+
237+
1. **Update hardhat.config.ts**:
238+
```typescript
239+
networks: {
240+
// Existing networks...
241+
'new-chain': {
242+
eid: EndpointId.NEW_CHAIN_V2_MAINNET,
243+
url: process.env.RPC_URL_NEW_CHAIN,
244+
accounts,
245+
},
246+
}
247+
```
248+
249+
2. **Update layerzero.config.ts**:
250+
```typescript
251+
const newChainContract: OmniPointHardhat = {
252+
eid: EndpointId.NEW_CHAIN_V2_MAINNET,
253+
contractName: 'MyOFT',
254+
}
255+
256+
// Add to contracts array
257+
contracts: [
258+
{ contract: existingContract1 },
259+
{ contract: existingContract2 },
260+
{ contract: newChainContract }, // Add new
261+
]
262+
263+
// Add pathways to existing contracts
264+
const pathways: TwoWayConfig[] = [
265+
// Existing pathways...
266+
[existingContract1, newChainContract, ...],
267+
[existingContract2, newChainContract, ...],
268+
]
269+
```
270+
271+
3. **Deploy and wire**:
272+
```bash
273+
# Deploy only to new network
274+
npx hardhat deploy --network new-chain --tags MyOFT
275+
276+
# Wire all pathways (including new ones)
277+
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts
278+
```
279+
280+
### Workflow 3: Updating Configuration
281+
282+
If you need to change DVNs, confirmations, or enforced options:
283+
284+
1. Update `layerzero.config.ts` with new configuration
285+
2. Run wire again - it will only update changed values:
286+
```bash
287+
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts
288+
```
289+
290+
## Environment Variables
291+
292+
| Variable | Purpose | Example |
293+
|----------|---------|---------|
294+
| `MNEMONIC` | Wallet mnemonic phrase | `word1 word2 ... word12` |
295+
| `PRIVATE_KEY` | Alternative to mnemonic | `0xabc123...` |
296+
| `RPC_URL_<NETWORK>` | RPC endpoint per network | `https://rpc.example.com` |
297+
298+
### .env Example
299+
300+
```bash
301+
# Authentication (choose one)
302+
MNEMONIC="your twelve word mnemonic phrase goes here"
303+
# PRIVATE_KEY=0x...
304+
305+
# RPC URLs
306+
RPC_URL_BASE_SEPOLIA=https://base-sepolia.gateway.tenderly.co
307+
RPC_URL_ARB_SEPOLIA=https://arbitrum-sepolia.gateway.tenderly.co
308+
```
309+
310+
## See Also
311+
312+
- [DEBUGGING.md](./DEBUGGING.md) - Troubleshooting guide
313+
- [CHEATSHEET.md](./CHEATSHEET.md) - Quick reference
314+
- [examples/oft/](./examples/oft/) - OFT example with full config
315+
- [Official Documentation](https://docs.layerzero.network/)

examples/native-oft-adapter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ To deploy your contracts to your desired blockchains, run the following command
9595
npx hardhat lz:deploy
9696
```
9797

98-
> If you need initial tokens on testnet for the EVM OFT, open `contracts/MyOFT.sol` and uncomment `_mint(msg.sender, 100000 * (10 ** 18));` in the constructor. Ensure you remove this line for production.
98+
> **Note:** Native OFT Adapter uses native ETH (or chain's native token) on the source chain - no initial token minting is required. Simply ensure your deployer wallet has native tokens to send.
9999
100100
More information about available CLI arguments can be found using the `--help` flag:
101101

0 commit comments

Comments
 (0)