@diamondslab/diamonds 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +618 -0
- package/diamonds/README.md +3 -0
- package/dist/core/CallbackManager.d.ts +13 -0
- package/dist/core/CallbackManager.d.ts.map +1 -0
- package/dist/core/CallbackManager.js +95 -0
- package/dist/core/CallbackManager.js.map +1 -0
- package/dist/core/DeploymentManager.d.ts +10 -0
- package/dist/core/DeploymentManager.d.ts.map +1 -0
- package/dist/core/DeploymentManager.js +50 -0
- package/dist/core/DeploymentManager.js.map +1 -0
- package/dist/core/Diamond.d.ts +58 -0
- package/dist/core/Diamond.d.ts.map +1 -0
- package/dist/core/Diamond.js +146 -0
- package/dist/core/Diamond.js.map +1 -0
- package/dist/core/DiamondDeployer.d.ts +10 -0
- package/dist/core/DiamondDeployer.d.ts.map +1 -0
- package/dist/core/DiamondDeployer.js +33 -0
- package/dist/core/DiamondDeployer.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/repositories/DBDeploymentRepository.d.ts +1 -0
- package/dist/repositories/DBDeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/DBDeploymentRepository.js +20 -0
- package/dist/repositories/DBDeploymentRepository.js.map +1 -0
- package/dist/repositories/DeploymentRepository.d.ts +8 -0
- package/dist/repositories/DeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/DeploymentRepository.js +7 -0
- package/dist/repositories/DeploymentRepository.js.map +1 -0
- package/dist/repositories/FileDeploymentRepository.d.ts +18 -0
- package/dist/repositories/FileDeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/FileDeploymentRepository.js +58 -0
- package/dist/repositories/FileDeploymentRepository.js.map +1 -0
- package/dist/repositories/databaseHandler.d.ts +1 -0
- package/dist/repositories/databaseHandler.d.ts.map +1 -0
- package/dist/repositories/databaseHandler.js +13 -0
- package/dist/repositories/databaseHandler.js.map +1 -0
- package/dist/repositories/index.d.ts +4 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +20 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/jsonFileHandler.d.ts +81 -0
- package/dist/repositories/jsonFileHandler.d.ts.map +1 -0
- package/dist/repositories/jsonFileHandler.js +223 -0
- package/dist/repositories/jsonFileHandler.js.map +1 -0
- package/dist/repositories/prismaDBHandler.d.ts +1 -0
- package/dist/repositories/prismaDBHandler.d.ts.map +1 -0
- package/dist/repositories/prismaDBHandler.js +11 -0
- package/dist/repositories/prismaDBHandler.js.map +1 -0
- package/dist/schemas/DeploymentSchema.d.ts +309 -0
- package/dist/schemas/DeploymentSchema.d.ts.map +1 -0
- package/dist/schemas/DeploymentSchema.js +56 -0
- package/dist/schemas/DeploymentSchema.js.map +1 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +18 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/strategies/BaseDeploymentStrategy.d.ts +41 -0
- package/dist/strategies/BaseDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/BaseDeploymentStrategy.js +545 -0
- package/dist/strategies/BaseDeploymentStrategy.js.map +1 -0
- package/dist/strategies/DeploymentStrategy.d.ts +19 -0
- package/dist/strategies/DeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/DeploymentStrategy.js +3 -0
- package/dist/strategies/DeploymentStrategy.js.map +1 -0
- package/dist/strategies/LocalDeploymentStrategy.d.ts +4 -0
- package/dist/strategies/LocalDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/LocalDeploymentStrategy.js +8 -0
- package/dist/strategies/LocalDeploymentStrategy.js.map +1 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.d.ts +62 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.js +757 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.js.map +1 -0
- package/dist/strategies/RPCDeploymentStrategy.d.ts +139 -0
- package/dist/strategies/RPCDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/RPCDeploymentStrategy.js +710 -0
- package/dist/strategies/RPCDeploymentStrategy.js.map +1 -0
- package/dist/strategies/index.d.ts +6 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +12 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/types/config.d.ts +26 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +3 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/defender.d.ts +22 -0
- package/dist/types/defender.d.ts.map +1 -0
- package/dist/types/defender.js +3 -0
- package/dist/types/defender.js.map +1 -0
- package/dist/types/deployments.d.ts +71 -0
- package/dist/types/deployments.d.ts.map +1 -0
- package/dist/types/deployments.js +20 -0
- package/dist/types/deployments.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/rpc.d.ts +35 -0
- package/dist/types/rpc.d.ts.map +1 -0
- package/dist/types/rpc.js +3 -0
- package/dist/types/rpc.js.map +1 -0
- package/dist/utils/common.d.ts +20 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +45 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/configurationResolver.d.ts +30 -0
- package/dist/utils/configurationResolver.d.ts.map +1 -0
- package/dist/utils/configurationResolver.js +151 -0
- package/dist/utils/configurationResolver.js.map +1 -0
- package/dist/utils/contractMapping.d.ts +29 -0
- package/dist/utils/contractMapping.d.ts.map +1 -0
- package/dist/utils/contractMapping.js +224 -0
- package/dist/utils/contractMapping.js.map +1 -0
- package/dist/utils/defenderClients.d.ts +5 -0
- package/dist/utils/defenderClients.d.ts.map +1 -0
- package/dist/utils/defenderClients.js +21 -0
- package/dist/utils/defenderClients.js.map +1 -0
- package/dist/utils/defenderStore.d.ts +14 -0
- package/dist/utils/defenderStore.d.ts.map +1 -0
- package/dist/utils/defenderStore.js +92 -0
- package/dist/utils/defenderStore.js.map +1 -0
- package/dist/utils/diamondAbiGenerator.d.ts +113 -0
- package/dist/utils/diamondAbiGenerator.d.ts.map +1 -0
- package/dist/utils/diamondAbiGenerator.js +415 -0
- package/dist/utils/diamondAbiGenerator.js.map +1 -0
- package/dist/utils/diffDeployedFacets.d.ts +26 -0
- package/dist/utils/diffDeployedFacets.d.ts.map +1 -0
- package/dist/utils/diffDeployedFacets.js +106 -0
- package/dist/utils/diffDeployedFacets.js.map +1 -0
- package/dist/utils/index.d.ts +16 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +35 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/loupe.d.ts +44 -0
- package/dist/utils/loupe.d.ts.map +1 -0
- package/dist/utils/loupe.js +128 -0
- package/dist/utils/loupe.js.map +1 -0
- package/dist/utils/rpcStore.d.ts +36 -0
- package/dist/utils/rpcStore.d.ts.map +1 -0
- package/dist/utils/rpcStore.js +166 -0
- package/dist/utils/rpcStore.js.map +1 -0
- package/dist/utils/signer.d.ts +36 -0
- package/dist/utils/signer.d.ts.map +1 -0
- package/dist/utils/signer.js +91 -0
- package/dist/utils/signer.js.map +1 -0
- package/dist/utils/txlogging.d.ts +13 -0
- package/dist/utils/txlogging.d.ts.map +1 -0
- package/dist/utils/txlogging.js +87 -0
- package/dist/utils/txlogging.js.map +1 -0
- package/dist/utils/workspaceSetup.d.ts +32 -0
- package/dist/utils/workspaceSetup.d.ts.map +1 -0
- package/dist/utils/workspaceSetup.js +311 -0
- package/dist/utils/workspaceSetup.js.map +1 -0
- package/docs/DIAMOND_ABI_CONFIGURATION_SUMMARY.md +40 -0
- package/docs/DIAMOND_ABI_GENERATION.md +220 -0
- package/docs/DIAMOND_ABI_GENERATOR_EXAMPLES.md +1204 -0
- package/docs/DIAMOND_ABI_GENERATOR_IMPLEMENTATION.md +947 -0
- package/docs/DIAMOND_ABI_GENERATOR_QUICK_REFERENCE.md +336 -0
- package/docs/README-DEFENDER.md +394 -0
- package/docs/README_DIAMOND_ABI_GENERATOR.md +303 -0
- package/docs/ROADMAP.md +250 -0
- package/docs/assets/image.png +0 -0
- package/docs/defender-integration.md +451 -0
- package/docs/diamond_module-BaseStrategy_design-v2.uxf +247 -0
- package/docs/diamond_module-BaseStrategy_design.uxf +272 -0
- package/docs/monitoring-troubleshooting.md +556 -0
- package/docs/testing-guide.md +713 -0
- package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/callbacks/ERC20ProxyFacet.ts +31 -0
- package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/proxydiamond.config.json +27 -0
- package/examples/Local_Hardhat_Deployer_Script_example/LocalDiamondDeployer.ts +180 -0
- package/examples/OZ_Defender_Deployer_Script_example/OZDiamondDeployer.ts +107 -0
- package/examples/OZ_Defender_Deployer_Script_example/run-oz-deploy.ts +17 -0
- package/examples/Test_examples/ProxyDiamondDeployment.test.ts +202 -0
- package/examples/defender-deployment/.env.example +35 -0
- package/examples/defender-deployment/README.md +415 -0
- package/examples/defender-deployment/contracts/ExampleDiamond.sol +41 -0
- package/examples/defender-deployment/contracts/ExampleFacet1.sol +84 -0
- package/examples/defender-deployment/contracts/ExampleFacet2.sol +104 -0
- package/examples/defender-deployment/contracts/UpgradeFacet.sol +92 -0
- package/examples/defender-deployment/deploy-script.ts +170 -0
- package/examples/defender-deployment/diamond-config.json +36 -0
- package/examples/defender-deployment/upgrade-script.ts +237 -0
- package/examples/hardhat-diamonds-config.example.ts +41 -0
- package/package.json +228 -0
- package/src/core/CallbackManager.ts +70 -0
- package/src/core/DeploymentManager.ts +64 -0
- package/src/core/Diamond.ts +197 -0
- package/src/core/DiamondDeployer.ts +36 -0
- package/src/core/index.ts +4 -0
- package/src/index.ts +5 -0
- package/src/repositories/DBDeploymentRepository.ts +22 -0
- package/src/repositories/DeploymentRepository.ts +12 -0
- package/src/repositories/FileDeploymentRepository.ts +67 -0
- package/src/repositories/databaseHandler.ts +14 -0
- package/src/repositories/index.ts +4 -0
- package/src/repositories/jsonFileHandler.ts +252 -0
- package/src/repositories/prismaDBHandler.ts +10 -0
- package/src/schemas/DeploymentSchema.ts +71 -0
- package/src/schemas/index.ts +1 -0
- package/src/strategies/BaseDeploymentStrategy.ts +649 -0
- package/src/strategies/DeploymentStrategy.ts +25 -0
- package/src/strategies/LocalDeploymentStrategy.ts +5 -0
- package/src/strategies/OZDefenderDeploymentStrategy.ts +849 -0
- package/src/strategies/RPCDeploymentStrategy.ts +881 -0
- package/src/strategies/index.ts +5 -0
- package/src/types/config.ts +34 -0
- package/src/types/defender.ts +24 -0
- package/src/types/deployments.ts +102 -0
- package/src/types/index.ts +4 -0
- package/src/types/rpc.ts +37 -0
- package/src/utils/common.ts +54 -0
- package/src/utils/configurationResolver.ts +141 -0
- package/src/utils/contractMapping.ts +220 -0
- package/src/utils/defenderClients.ts +22 -0
- package/src/utils/defenderStore.ts +62 -0
- package/src/utils/diamondAbiGenerator.ts +523 -0
- package/src/utils/diffDeployedFacets.ts +131 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/loupe.ts +159 -0
- package/src/utils/rpcStore.ts +152 -0
- package/src/utils/signer.ts +93 -0
- package/src/utils/txlogging.ts +97 -0
- package/src/utils/workspaceSetup.ts +315 -0
- package/test/README.md +136 -0
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
# OpenZeppelin Defender Monitoring and Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
This guide provides comprehensive instructions for monitoring Diamond deployments and troubleshooting common issues when using OpenZeppelin Defender integration.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Monitoring Diamond Deployments](#monitoring-diamond-deployments)
|
|
8
|
+
2. [Common Issues and Solutions](#common-issues-and-solutions)
|
|
9
|
+
3. [Performance Optimization](#performance-optimization)
|
|
10
|
+
4. [Debugging Techniques](#debugging-techniques)
|
|
11
|
+
5. [Emergency Procedures](#emergency-procedures)
|
|
12
|
+
6. [Best Practices](#best-practices)
|
|
13
|
+
|
|
14
|
+
## Monitoring Diamond Deployments
|
|
15
|
+
|
|
16
|
+
### 1. Defender Dashboard Monitoring
|
|
17
|
+
|
|
18
|
+
#### Setting Up Monitoring
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Check deployment status
|
|
22
|
+
npm run defender:status
|
|
23
|
+
|
|
24
|
+
# Monitor specific diamond
|
|
25
|
+
npx defender-cli status --diamond MyDiamond --verbose
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### Key Metrics to Monitor
|
|
29
|
+
|
|
30
|
+
- **Proposal Status**: Track proposal creation, approval, and execution
|
|
31
|
+
- **Gas Usage**: Monitor gas consumption for diamond cuts
|
|
32
|
+
- **Transaction Confirmations**: Ensure transactions are properly confirmed
|
|
33
|
+
- **Contract Verification**: Verify all contracts are verified on Etherscan
|
|
34
|
+
|
|
35
|
+
### 2. Real-time Monitoring Scripts
|
|
36
|
+
|
|
37
|
+
Create monitoring scripts for continuous deployment tracking:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// scripts/monitor-deployment.ts
|
|
41
|
+
import { Diamond } from '../src/core/Diamond';
|
|
42
|
+
import { FileDeploymentRepository } from '../src/repositories/FileDeploymentRepository';
|
|
43
|
+
import { diffDeployedFacets } from '../src/utils/diffDeployedFacets';
|
|
44
|
+
import { ethers } from 'hardhat';
|
|
45
|
+
|
|
46
|
+
async function monitorDiamond(diamondName: string) {
|
|
47
|
+
const config = {
|
|
48
|
+
diamondName,
|
|
49
|
+
networkName: process.env.NETWORK_NAME!,
|
|
50
|
+
chainId: parseInt(process.env.CHAIN_ID!),
|
|
51
|
+
deploymentsPath: 'diamonds',
|
|
52
|
+
contractsPath: 'contracts',
|
|
53
|
+
writeDeployedDiamondData: true
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const repository = new FileDeploymentRepository(config);
|
|
57
|
+
const diamond = new Diamond(config, repository);
|
|
58
|
+
const deployedData = diamond.getDeployedDiamondData();
|
|
59
|
+
|
|
60
|
+
if (!deployedData.DiamondAddress) {
|
|
61
|
+
console.log('❌ Diamond not deployed');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check on-chain state vs local deployment data
|
|
66
|
+
const provider = ethers.provider;
|
|
67
|
+
const isConsistent = await diffDeployedFacets(deployedData, provider, true);
|
|
68
|
+
|
|
69
|
+
if (isConsistent) {
|
|
70
|
+
console.log('✅ Diamond state is consistent');
|
|
71
|
+
} else {
|
|
72
|
+
console.log('⚠️ Diamond state inconsistency detected');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Run monitoring
|
|
77
|
+
monitorDiamond(process.argv[2] || 'MyDiamond');
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3. Automated Health Checks
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// scripts/health-check.ts
|
|
84
|
+
import { AdminClient } from '@openzeppelin/defender-sdk';
|
|
85
|
+
|
|
86
|
+
async function performHealthCheck() {
|
|
87
|
+
const client = new AdminClient({
|
|
88
|
+
apiKey: process.env.DEFENDER_API_KEY!,
|
|
89
|
+
apiSecret: process.env.DEFENDER_API_SECRET!
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
// Check API connectivity
|
|
94
|
+
const proposals = await client.listProposals();
|
|
95
|
+
console.log(`✅ API Connection: ${proposals.length} proposals found`);
|
|
96
|
+
|
|
97
|
+
// Check recent proposals
|
|
98
|
+
const recentProposals = proposals.filter(p =>
|
|
99
|
+
Date.now() - new Date(p.createdAt).getTime() < 24 * 60 * 60 * 1000
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
console.log(`📊 Recent Proposals (24h): ${recentProposals.length}`);
|
|
103
|
+
|
|
104
|
+
// Check failed proposals
|
|
105
|
+
const failedProposals = proposals.filter(p => p.status === 'failed');
|
|
106
|
+
if (failedProposals.length > 0) {
|
|
107
|
+
console.log(`⚠️ Failed Proposals: ${failedProposals.length}`);
|
|
108
|
+
failedProposals.forEach(p => {
|
|
109
|
+
console.log(` - ${p.title}: ${p.description}`);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('❌ Health Check Failed:', error.message);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
performHealthCheck();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Common Issues and Solutions
|
|
122
|
+
|
|
123
|
+
### 1. Proposal Creation Failures
|
|
124
|
+
|
|
125
|
+
#### Issue: "Insufficient permissions" Error
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
Error: Insufficient permissions to create proposal
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Solution:**
|
|
132
|
+
|
|
133
|
+
1. Verify API key permissions in Defender dashboard
|
|
134
|
+
2. Ensure relayer has sufficient ETH balance
|
|
135
|
+
3. Check that the Safe/multisig has proper signers
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Check relayer balance
|
|
139
|
+
npx hardhat run scripts/check-relayer-balance.ts
|
|
140
|
+
|
|
141
|
+
# Verify API permissions
|
|
142
|
+
curl -H "Authorization: Bearer $DEFENDER_API_KEY" \
|
|
143
|
+
https://defender-api.openzeppelin.com/admin/proposals
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Issue: "Contract not found" Error
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
Error: Contract not found at address 0x...
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Solution:**
|
|
153
|
+
|
|
154
|
+
1. Verify contract address in deployment files
|
|
155
|
+
2. Ensure contract is deployed on correct network
|
|
156
|
+
3. Check if contract is verified on Etherscan
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// Verify contract exists
|
|
160
|
+
const code = await ethers.provider.getCode(contractAddress);
|
|
161
|
+
if (code === '0x') {
|
|
162
|
+
console.error('Contract not deployed at address');
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 2. Diamond Cut Execution Issues
|
|
167
|
+
|
|
168
|
+
#### Issue: Diamond Cut Fails with "Selector Collision"
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
Error: Function selector collision detected
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Solution:**
|
|
175
|
+
|
|
176
|
+
1. Check for duplicate function selectors across facets
|
|
177
|
+
2. Use `deployExclude` to remove conflicting selectors
|
|
178
|
+
3. Verify function selector registry
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// Debug selector collisions
|
|
182
|
+
import { getSighash } from '../src/utils/common';
|
|
183
|
+
|
|
184
|
+
function checkSelectorCollisions(facets: any[]) {
|
|
185
|
+
const selectors = new Map();
|
|
186
|
+
|
|
187
|
+
for (const facet of facets) {
|
|
188
|
+
for (const selector of facet.funcSelectors) {
|
|
189
|
+
if (selectors.has(selector)) {
|
|
190
|
+
console.error(`Collision: ${selector} in ${facet.name} and ${selectors.get(selector)}`);
|
|
191
|
+
} else {
|
|
192
|
+
selectors.set(selector, facet.name);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Issue: "Orphaned Selectors" Error
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
Error: Orphaned selectors found for facet TestFacet
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Solution:**
|
|
206
|
+
|
|
207
|
+
1. Ensure all function selectors are properly mapped
|
|
208
|
+
2. Remove old facet addresses from registry
|
|
209
|
+
3. Use the validation utility to check state
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Check for orphaned selectors
|
|
213
|
+
await strategy.validateNoOrphanedSelectors(facetCuts);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 3. Network and Connectivity Issues
|
|
217
|
+
|
|
218
|
+
#### Issue: "Network timeout" Error
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
Error: Network timeout - operation took too long
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Solution:**
|
|
225
|
+
|
|
226
|
+
1. Increase timeout values in strategy configuration
|
|
227
|
+
2. Check network congestion and gas prices
|
|
228
|
+
3. Use retry mechanisms
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
// Configure timeouts
|
|
232
|
+
const strategy = new OZDefenderDeploymentStrategy(
|
|
233
|
+
apiKey,
|
|
234
|
+
apiSecret,
|
|
235
|
+
relayerAddress,
|
|
236
|
+
autoApprove,
|
|
237
|
+
via,
|
|
238
|
+
viaType,
|
|
239
|
+
verbose,
|
|
240
|
+
{
|
|
241
|
+
timeout: 300000, // 5 minutes
|
|
242
|
+
retries: 3,
|
|
243
|
+
retryDelay: 5000 // 5 seconds
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Issue: Rate Limiting
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
Error: Rate limit exceeded (429)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Solution:**
|
|
255
|
+
|
|
256
|
+
1. Implement exponential backoff
|
|
257
|
+
2. Reduce concurrent operations
|
|
258
|
+
3. Contact OpenZeppelin for rate limit increases
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// Implement rate limiting handling
|
|
262
|
+
async function withRetry(operation: () => Promise<any>, maxRetries = 3) {
|
|
263
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
264
|
+
try {
|
|
265
|
+
return await operation();
|
|
266
|
+
} catch (error) {
|
|
267
|
+
if (error.response?.status === 429 && i < maxRetries - 1) {
|
|
268
|
+
const delay = Math.pow(2, i) * 1000; // Exponential backoff
|
|
269
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### 4. Gas and Transaction Issues
|
|
279
|
+
|
|
280
|
+
#### Issue: "Gas estimation failed"
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
Error: Gas estimation failed for diamond cut
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Solution:**
|
|
287
|
+
|
|
288
|
+
1. Check if all facets are properly deployed
|
|
289
|
+
2. Verify initialization parameters
|
|
290
|
+
3. Test with hardhat fork before mainnet
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Debug gas estimation
|
|
294
|
+
try {
|
|
295
|
+
const gasEstimate = await contract.estimateGas.diamondCut(
|
|
296
|
+
facetCuts,
|
|
297
|
+
initAddress,
|
|
298
|
+
initCalldata
|
|
299
|
+
);
|
|
300
|
+
console.log(`Estimated gas: ${gasEstimate.toString()}`);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
console.error('Gas estimation failed:', error);
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Performance Optimization
|
|
307
|
+
|
|
308
|
+
### 1. Batch Operations
|
|
309
|
+
|
|
310
|
+
Optimize large deployments by batching operations:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// Batch facet deployments
|
|
314
|
+
async function batchDeployFacets(facets: string[], batchSize = 5) {
|
|
315
|
+
const batches = [];
|
|
316
|
+
for (let i = 0; i < facets.length; i += batchSize) {
|
|
317
|
+
batches.push(facets.slice(i, i + batchSize));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
for (const batch of batches) {
|
|
321
|
+
const deploymentPromises = batch.map(facet => deployFacet(facet));
|
|
322
|
+
await Promise.all(deploymentPromises);
|
|
323
|
+
|
|
324
|
+
// Wait between batches to avoid rate limiting
|
|
325
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### 2. Parallel Proposal Creation
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// Create proposals in parallel with rate limiting
|
|
334
|
+
async function createProposalsInParallel(proposals: any[], concurrency = 3) {
|
|
335
|
+
const semaphore = new Semaphore(concurrency);
|
|
336
|
+
|
|
337
|
+
return Promise.all(proposals.map(async (proposal) => {
|
|
338
|
+
await semaphore.acquire();
|
|
339
|
+
try {
|
|
340
|
+
return await adminClient.createProposal(proposal);
|
|
341
|
+
} finally {
|
|
342
|
+
semaphore.release();
|
|
343
|
+
}
|
|
344
|
+
}));
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### 3. Caching and State Management
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// Cache deployment state
|
|
352
|
+
class DeploymentCache {
|
|
353
|
+
private cache = new Map();
|
|
354
|
+
private ttl = 5 * 60 * 1000; // 5 minutes
|
|
355
|
+
|
|
356
|
+
async get(key: string) {
|
|
357
|
+
const entry = this.cache.get(key);
|
|
358
|
+
if (entry && Date.now() - entry.timestamp < this.ttl) {
|
|
359
|
+
return entry.value;
|
|
360
|
+
}
|
|
361
|
+
this.cache.delete(key);
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
set(key: string, value: any) {
|
|
366
|
+
this.cache.set(key, {
|
|
367
|
+
value,
|
|
368
|
+
timestamp: Date.now()
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Debugging Techniques
|
|
375
|
+
|
|
376
|
+
### 1. Enable Detailed Logging
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// Enable verbose logging
|
|
380
|
+
process.env.DEBUG = 'diamonds:*';
|
|
381
|
+
|
|
382
|
+
// Custom debug logging
|
|
383
|
+
import debug from 'debug';
|
|
384
|
+
const log = debug('diamonds:deployment');
|
|
385
|
+
|
|
386
|
+
log('Starting deployment process');
|
|
387
|
+
log('Configuration: %O', config);
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### 2. Transaction Tracing
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Trace transaction execution
|
|
394
|
+
async function traceTransaction(txHash: string) {
|
|
395
|
+
const trace = await ethers.provider.send('debug_traceTransaction', [
|
|
396
|
+
txHash,
|
|
397
|
+
{ tracer: 'callTracer' }
|
|
398
|
+
]);
|
|
399
|
+
|
|
400
|
+
console.log('Transaction trace:', JSON.stringify(trace, null, 2));
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### 3. State Inspection
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
// Inspect diamond state
|
|
408
|
+
async function inspectDiamondState(diamondAddress: string) {
|
|
409
|
+
const loupeContract = await ethers.getContractAt('DiamondLoupeFacet', diamondAddress);
|
|
410
|
+
|
|
411
|
+
const facets = await loupeContract.facets();
|
|
412
|
+
console.log('Current facets:', facets);
|
|
413
|
+
|
|
414
|
+
const interfaces = await loupeContract.supportsInterface('0x48e2b093'); // ERC165
|
|
415
|
+
console.log('Supports ERC165:', interfaces);
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Emergency Procedures
|
|
420
|
+
|
|
421
|
+
### 1. Emergency Stop
|
|
422
|
+
|
|
423
|
+
If a deployment goes wrong, you can implement emergency stops:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
// Emergency stop script
|
|
427
|
+
async function emergencyStop(diamondAddress: string) {
|
|
428
|
+
const ownershipFacet = await ethers.getContractAt('OwnershipFacet', diamondAddress);
|
|
429
|
+
|
|
430
|
+
// Transfer ownership to emergency multisig
|
|
431
|
+
const emergencyMultisig = process.env.EMERGENCY_MULTISIG_ADDRESS;
|
|
432
|
+
await ownershipFacet.transferOwnership(emergencyMultisig);
|
|
433
|
+
|
|
434
|
+
console.log(`Ownership transferred to emergency multisig: ${emergencyMultisig}`);
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### 2. Rollback Procedures
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// Rollback to previous state
|
|
442
|
+
async function rollbackDeployment(diamondName: string, targetVersion: number) {
|
|
443
|
+
const backupPath = `./backups/${diamondName}-v${targetVersion}.json`;
|
|
444
|
+
const backupData = await fs.readJson(backupPath);
|
|
445
|
+
|
|
446
|
+
// Restore previous deployment state
|
|
447
|
+
const repository = new FileDeploymentRepository(config);
|
|
448
|
+
await repository.saveDeployedDiamondData(backupData);
|
|
449
|
+
|
|
450
|
+
console.log(`Rolled back to version ${targetVersion}`);
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### 3. Recovery Scripts
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
// Recover from partial deployment
|
|
458
|
+
async function recoverPartialDeployment(diamondName: string) {
|
|
459
|
+
const diamond = await createDiamond(config);
|
|
460
|
+
const deployedData = diamond.getDeployedDiamondData();
|
|
461
|
+
|
|
462
|
+
// Check which facets are missing
|
|
463
|
+
const expectedFacets = Object.keys(diamond.getDeployConfig().facets);
|
|
464
|
+
const deployedFacets = Object.keys(deployedData.DeployedFacets || {});
|
|
465
|
+
const missingFacets = expectedFacets.filter(f => !deployedFacets.includes(f));
|
|
466
|
+
|
|
467
|
+
if (missingFacets.length > 0) {
|
|
468
|
+
console.log('Missing facets:', missingFacets);
|
|
469
|
+
// Deploy missing facets
|
|
470
|
+
for (const facet of missingFacets) {
|
|
471
|
+
await deployFacet(facet);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Best Practices
|
|
478
|
+
|
|
479
|
+
### 1. Pre-deployment Checks
|
|
480
|
+
|
|
481
|
+
Always run comprehensive checks before deployment:
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
# Pre-deployment checklist
|
|
485
|
+
npm run compile # Ensure contracts compile
|
|
486
|
+
npm run test # Run all tests
|
|
487
|
+
npm run lint # Check code quality
|
|
488
|
+
npx defender-cli status # Check current state
|
|
489
|
+
npm run test:integration # Run integration tests
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### 2. Monitoring Setup
|
|
493
|
+
|
|
494
|
+
Set up continuous monitoring:
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
// Continuous monitoring
|
|
498
|
+
setInterval(async () => {
|
|
499
|
+
try {
|
|
500
|
+
await performHealthCheck();
|
|
501
|
+
await monitorDiamond('MyDiamond');
|
|
502
|
+
} catch (error) {
|
|
503
|
+
console.error('Monitoring error:', error);
|
|
504
|
+
// Send alert to monitoring system
|
|
505
|
+
}
|
|
506
|
+
}, 5 * 60 * 1000); // Every 5 minutes
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### 3. Backup Strategies
|
|
510
|
+
|
|
511
|
+
Implement regular backups:
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
// Automated backup
|
|
515
|
+
async function createBackup(diamondName: string) {
|
|
516
|
+
const timestamp = new Date().toISOString().split('T')[0];
|
|
517
|
+
const backupPath = `./backups/${diamondName}-${timestamp}.json`;
|
|
518
|
+
|
|
519
|
+
const diamond = await createDiamond(config);
|
|
520
|
+
const deployedData = diamond.getDeployedDiamondData();
|
|
521
|
+
|
|
522
|
+
await fs.writeJson(backupPath, deployedData, { spaces: 2 });
|
|
523
|
+
console.log(`Backup created: ${backupPath}`);
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### 4. Documentation and Change Management
|
|
528
|
+
|
|
529
|
+
- Document all configuration changes
|
|
530
|
+
- Use version control for all diamond configurations
|
|
531
|
+
- Maintain change logs for each deployment
|
|
532
|
+
- Create runbooks for common operations
|
|
533
|
+
|
|
534
|
+
### 5. Testing in Production-like Environments
|
|
535
|
+
|
|
536
|
+
Always test in environments that closely mirror production:
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
# Test on mainnet fork
|
|
540
|
+
npm run hardhat:fork:mainnet
|
|
541
|
+
npm run test:integration
|
|
542
|
+
|
|
543
|
+
# Test with realistic gas prices
|
|
544
|
+
export GAS_PRICE=30000000000 # 30 gwei
|
|
545
|
+
npm run defender:deploy
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
## Conclusion
|
|
549
|
+
|
|
550
|
+
Proper monitoring and troubleshooting procedures are essential for successful Diamond deployments with OpenZeppelin Defender. This guide provides the foundation for maintaining robust, reliable diamond proxy deployments in production environments.
|
|
551
|
+
|
|
552
|
+
For additional support:
|
|
553
|
+
|
|
554
|
+
- OpenZeppelin Defender Documentation: <https://docs.openzeppelin.com/defender/>
|
|
555
|
+
- Diamond Standard (ERC-2535): <https://eips.ethereum.org/EIPS/eip-2535>
|
|
556
|
+
- Community Support: <https://forum.openzeppelin.com/>
|