@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.
Files changed (229) hide show
  1. package/README.md +618 -0
  2. package/diamonds/README.md +3 -0
  3. package/dist/core/CallbackManager.d.ts +13 -0
  4. package/dist/core/CallbackManager.d.ts.map +1 -0
  5. package/dist/core/CallbackManager.js +95 -0
  6. package/dist/core/CallbackManager.js.map +1 -0
  7. package/dist/core/DeploymentManager.d.ts +10 -0
  8. package/dist/core/DeploymentManager.d.ts.map +1 -0
  9. package/dist/core/DeploymentManager.js +50 -0
  10. package/dist/core/DeploymentManager.js.map +1 -0
  11. package/dist/core/Diamond.d.ts +58 -0
  12. package/dist/core/Diamond.d.ts.map +1 -0
  13. package/dist/core/Diamond.js +146 -0
  14. package/dist/core/Diamond.js.map +1 -0
  15. package/dist/core/DiamondDeployer.d.ts +10 -0
  16. package/dist/core/DiamondDeployer.d.ts.map +1 -0
  17. package/dist/core/DiamondDeployer.js +33 -0
  18. package/dist/core/DiamondDeployer.js.map +1 -0
  19. package/dist/core/index.d.ts +5 -0
  20. package/dist/core/index.d.ts.map +1 -0
  21. package/dist/core/index.js +12 -0
  22. package/dist/core/index.js.map +1 -0
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +22 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/repositories/DBDeploymentRepository.d.ts +1 -0
  28. package/dist/repositories/DBDeploymentRepository.d.ts.map +1 -0
  29. package/dist/repositories/DBDeploymentRepository.js +20 -0
  30. package/dist/repositories/DBDeploymentRepository.js.map +1 -0
  31. package/dist/repositories/DeploymentRepository.d.ts +8 -0
  32. package/dist/repositories/DeploymentRepository.d.ts.map +1 -0
  33. package/dist/repositories/DeploymentRepository.js +7 -0
  34. package/dist/repositories/DeploymentRepository.js.map +1 -0
  35. package/dist/repositories/FileDeploymentRepository.d.ts +18 -0
  36. package/dist/repositories/FileDeploymentRepository.d.ts.map +1 -0
  37. package/dist/repositories/FileDeploymentRepository.js +58 -0
  38. package/dist/repositories/FileDeploymentRepository.js.map +1 -0
  39. package/dist/repositories/databaseHandler.d.ts +1 -0
  40. package/dist/repositories/databaseHandler.d.ts.map +1 -0
  41. package/dist/repositories/databaseHandler.js +13 -0
  42. package/dist/repositories/databaseHandler.js.map +1 -0
  43. package/dist/repositories/index.d.ts +4 -0
  44. package/dist/repositories/index.d.ts.map +1 -0
  45. package/dist/repositories/index.js +20 -0
  46. package/dist/repositories/index.js.map +1 -0
  47. package/dist/repositories/jsonFileHandler.d.ts +81 -0
  48. package/dist/repositories/jsonFileHandler.d.ts.map +1 -0
  49. package/dist/repositories/jsonFileHandler.js +223 -0
  50. package/dist/repositories/jsonFileHandler.js.map +1 -0
  51. package/dist/repositories/prismaDBHandler.d.ts +1 -0
  52. package/dist/repositories/prismaDBHandler.d.ts.map +1 -0
  53. package/dist/repositories/prismaDBHandler.js +11 -0
  54. package/dist/repositories/prismaDBHandler.js.map +1 -0
  55. package/dist/schemas/DeploymentSchema.d.ts +309 -0
  56. package/dist/schemas/DeploymentSchema.d.ts.map +1 -0
  57. package/dist/schemas/DeploymentSchema.js +56 -0
  58. package/dist/schemas/DeploymentSchema.js.map +1 -0
  59. package/dist/schemas/index.d.ts +2 -0
  60. package/dist/schemas/index.d.ts.map +1 -0
  61. package/dist/schemas/index.js +18 -0
  62. package/dist/schemas/index.js.map +1 -0
  63. package/dist/strategies/BaseDeploymentStrategy.d.ts +41 -0
  64. package/dist/strategies/BaseDeploymentStrategy.d.ts.map +1 -0
  65. package/dist/strategies/BaseDeploymentStrategy.js +545 -0
  66. package/dist/strategies/BaseDeploymentStrategy.js.map +1 -0
  67. package/dist/strategies/DeploymentStrategy.d.ts +19 -0
  68. package/dist/strategies/DeploymentStrategy.d.ts.map +1 -0
  69. package/dist/strategies/DeploymentStrategy.js +3 -0
  70. package/dist/strategies/DeploymentStrategy.js.map +1 -0
  71. package/dist/strategies/LocalDeploymentStrategy.d.ts +4 -0
  72. package/dist/strategies/LocalDeploymentStrategy.d.ts.map +1 -0
  73. package/dist/strategies/LocalDeploymentStrategy.js +8 -0
  74. package/dist/strategies/LocalDeploymentStrategy.js.map +1 -0
  75. package/dist/strategies/OZDefenderDeploymentStrategy.d.ts +62 -0
  76. package/dist/strategies/OZDefenderDeploymentStrategy.d.ts.map +1 -0
  77. package/dist/strategies/OZDefenderDeploymentStrategy.js +757 -0
  78. package/dist/strategies/OZDefenderDeploymentStrategy.js.map +1 -0
  79. package/dist/strategies/RPCDeploymentStrategy.d.ts +139 -0
  80. package/dist/strategies/RPCDeploymentStrategy.d.ts.map +1 -0
  81. package/dist/strategies/RPCDeploymentStrategy.js +710 -0
  82. package/dist/strategies/RPCDeploymentStrategy.js.map +1 -0
  83. package/dist/strategies/index.d.ts +6 -0
  84. package/dist/strategies/index.d.ts.map +1 -0
  85. package/dist/strategies/index.js +12 -0
  86. package/dist/strategies/index.js.map +1 -0
  87. package/dist/types/config.d.ts +26 -0
  88. package/dist/types/config.d.ts.map +1 -0
  89. package/dist/types/config.js +3 -0
  90. package/dist/types/config.js.map +1 -0
  91. package/dist/types/defender.d.ts +22 -0
  92. package/dist/types/defender.d.ts.map +1 -0
  93. package/dist/types/defender.js +3 -0
  94. package/dist/types/defender.js.map +1 -0
  95. package/dist/types/deployments.d.ts +71 -0
  96. package/dist/types/deployments.d.ts.map +1 -0
  97. package/dist/types/deployments.js +20 -0
  98. package/dist/types/deployments.js.map +1 -0
  99. package/dist/types/index.d.ts +5 -0
  100. package/dist/types/index.d.ts.map +1 -0
  101. package/dist/types/index.js +21 -0
  102. package/dist/types/index.js.map +1 -0
  103. package/dist/types/rpc.d.ts +35 -0
  104. package/dist/types/rpc.d.ts.map +1 -0
  105. package/dist/types/rpc.js +3 -0
  106. package/dist/types/rpc.js.map +1 -0
  107. package/dist/utils/common.d.ts +20 -0
  108. package/dist/utils/common.d.ts.map +1 -0
  109. package/dist/utils/common.js +45 -0
  110. package/dist/utils/common.js.map +1 -0
  111. package/dist/utils/configurationResolver.d.ts +30 -0
  112. package/dist/utils/configurationResolver.d.ts.map +1 -0
  113. package/dist/utils/configurationResolver.js +151 -0
  114. package/dist/utils/configurationResolver.js.map +1 -0
  115. package/dist/utils/contractMapping.d.ts +29 -0
  116. package/dist/utils/contractMapping.d.ts.map +1 -0
  117. package/dist/utils/contractMapping.js +224 -0
  118. package/dist/utils/contractMapping.js.map +1 -0
  119. package/dist/utils/defenderClients.d.ts +5 -0
  120. package/dist/utils/defenderClients.d.ts.map +1 -0
  121. package/dist/utils/defenderClients.js +21 -0
  122. package/dist/utils/defenderClients.js.map +1 -0
  123. package/dist/utils/defenderStore.d.ts +14 -0
  124. package/dist/utils/defenderStore.d.ts.map +1 -0
  125. package/dist/utils/defenderStore.js +92 -0
  126. package/dist/utils/defenderStore.js.map +1 -0
  127. package/dist/utils/diamondAbiGenerator.d.ts +113 -0
  128. package/dist/utils/diamondAbiGenerator.d.ts.map +1 -0
  129. package/dist/utils/diamondAbiGenerator.js +415 -0
  130. package/dist/utils/diamondAbiGenerator.js.map +1 -0
  131. package/dist/utils/diffDeployedFacets.d.ts +26 -0
  132. package/dist/utils/diffDeployedFacets.d.ts.map +1 -0
  133. package/dist/utils/diffDeployedFacets.js +106 -0
  134. package/dist/utils/diffDeployedFacets.js.map +1 -0
  135. package/dist/utils/index.d.ts +16 -0
  136. package/dist/utils/index.d.ts.map +1 -0
  137. package/dist/utils/index.js +35 -0
  138. package/dist/utils/index.js.map +1 -0
  139. package/dist/utils/loupe.d.ts +44 -0
  140. package/dist/utils/loupe.d.ts.map +1 -0
  141. package/dist/utils/loupe.js +128 -0
  142. package/dist/utils/loupe.js.map +1 -0
  143. package/dist/utils/rpcStore.d.ts +36 -0
  144. package/dist/utils/rpcStore.d.ts.map +1 -0
  145. package/dist/utils/rpcStore.js +166 -0
  146. package/dist/utils/rpcStore.js.map +1 -0
  147. package/dist/utils/signer.d.ts +36 -0
  148. package/dist/utils/signer.d.ts.map +1 -0
  149. package/dist/utils/signer.js +91 -0
  150. package/dist/utils/signer.js.map +1 -0
  151. package/dist/utils/txlogging.d.ts +13 -0
  152. package/dist/utils/txlogging.d.ts.map +1 -0
  153. package/dist/utils/txlogging.js +87 -0
  154. package/dist/utils/txlogging.js.map +1 -0
  155. package/dist/utils/workspaceSetup.d.ts +32 -0
  156. package/dist/utils/workspaceSetup.d.ts.map +1 -0
  157. package/dist/utils/workspaceSetup.js +311 -0
  158. package/dist/utils/workspaceSetup.js.map +1 -0
  159. package/docs/DIAMOND_ABI_CONFIGURATION_SUMMARY.md +40 -0
  160. package/docs/DIAMOND_ABI_GENERATION.md +220 -0
  161. package/docs/DIAMOND_ABI_GENERATOR_EXAMPLES.md +1204 -0
  162. package/docs/DIAMOND_ABI_GENERATOR_IMPLEMENTATION.md +947 -0
  163. package/docs/DIAMOND_ABI_GENERATOR_QUICK_REFERENCE.md +336 -0
  164. package/docs/README-DEFENDER.md +394 -0
  165. package/docs/README_DIAMOND_ABI_GENERATOR.md +303 -0
  166. package/docs/ROADMAP.md +250 -0
  167. package/docs/assets/image.png +0 -0
  168. package/docs/defender-integration.md +451 -0
  169. package/docs/diamond_module-BaseStrategy_design-v2.uxf +247 -0
  170. package/docs/diamond_module-BaseStrategy_design.uxf +272 -0
  171. package/docs/monitoring-troubleshooting.md +556 -0
  172. package/docs/testing-guide.md +713 -0
  173. package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/callbacks/ERC20ProxyFacet.ts +31 -0
  174. package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/proxydiamond.config.json +27 -0
  175. package/examples/Local_Hardhat_Deployer_Script_example/LocalDiamondDeployer.ts +180 -0
  176. package/examples/OZ_Defender_Deployer_Script_example/OZDiamondDeployer.ts +107 -0
  177. package/examples/OZ_Defender_Deployer_Script_example/run-oz-deploy.ts +17 -0
  178. package/examples/Test_examples/ProxyDiamondDeployment.test.ts +202 -0
  179. package/examples/defender-deployment/.env.example +35 -0
  180. package/examples/defender-deployment/README.md +415 -0
  181. package/examples/defender-deployment/contracts/ExampleDiamond.sol +41 -0
  182. package/examples/defender-deployment/contracts/ExampleFacet1.sol +84 -0
  183. package/examples/defender-deployment/contracts/ExampleFacet2.sol +104 -0
  184. package/examples/defender-deployment/contracts/UpgradeFacet.sol +92 -0
  185. package/examples/defender-deployment/deploy-script.ts +170 -0
  186. package/examples/defender-deployment/diamond-config.json +36 -0
  187. package/examples/defender-deployment/upgrade-script.ts +237 -0
  188. package/examples/hardhat-diamonds-config.example.ts +41 -0
  189. package/package.json +228 -0
  190. package/src/core/CallbackManager.ts +70 -0
  191. package/src/core/DeploymentManager.ts +64 -0
  192. package/src/core/Diamond.ts +197 -0
  193. package/src/core/DiamondDeployer.ts +36 -0
  194. package/src/core/index.ts +4 -0
  195. package/src/index.ts +5 -0
  196. package/src/repositories/DBDeploymentRepository.ts +22 -0
  197. package/src/repositories/DeploymentRepository.ts +12 -0
  198. package/src/repositories/FileDeploymentRepository.ts +67 -0
  199. package/src/repositories/databaseHandler.ts +14 -0
  200. package/src/repositories/index.ts +4 -0
  201. package/src/repositories/jsonFileHandler.ts +252 -0
  202. package/src/repositories/prismaDBHandler.ts +10 -0
  203. package/src/schemas/DeploymentSchema.ts +71 -0
  204. package/src/schemas/index.ts +1 -0
  205. package/src/strategies/BaseDeploymentStrategy.ts +649 -0
  206. package/src/strategies/DeploymentStrategy.ts +25 -0
  207. package/src/strategies/LocalDeploymentStrategy.ts +5 -0
  208. package/src/strategies/OZDefenderDeploymentStrategy.ts +849 -0
  209. package/src/strategies/RPCDeploymentStrategy.ts +881 -0
  210. package/src/strategies/index.ts +5 -0
  211. package/src/types/config.ts +34 -0
  212. package/src/types/defender.ts +24 -0
  213. package/src/types/deployments.ts +102 -0
  214. package/src/types/index.ts +4 -0
  215. package/src/types/rpc.ts +37 -0
  216. package/src/utils/common.ts +54 -0
  217. package/src/utils/configurationResolver.ts +141 -0
  218. package/src/utils/contractMapping.ts +220 -0
  219. package/src/utils/defenderClients.ts +22 -0
  220. package/src/utils/defenderStore.ts +62 -0
  221. package/src/utils/diamondAbiGenerator.ts +523 -0
  222. package/src/utils/diffDeployedFacets.ts +131 -0
  223. package/src/utils/index.ts +15 -0
  224. package/src/utils/loupe.ts +159 -0
  225. package/src/utils/rpcStore.ts +152 -0
  226. package/src/utils/signer.ts +93 -0
  227. package/src/utils/txlogging.ts +97 -0
  228. package/src/utils/workspaceSetup.ts +315 -0
  229. package/test/README.md +136 -0
@@ -0,0 +1,415 @@
1
+ # Defender Deployment Example
2
+
3
+ This example demonstrates how to deploy and upgrade a Diamond proxy contract using OpenZeppelin Defender.
4
+
5
+ ## Overview
6
+
7
+ This example includes:
8
+
9
+ - A complete Diamond implementation with multiple facets
10
+ - Configuration for Defender deployment
11
+ - Deployment and upgrade scripts
12
+ - Step-by-step instructions
13
+
14
+ ## Prerequisites
15
+
16
+ 1. OpenZeppelin Defender account with API credentials
17
+ 2. Testnet ETH for gas fees
18
+ 3. Node.js 16+ and npm
19
+
20
+ ## Setup
21
+
22
+ 1. **Clone and Install Dependencies**
23
+
24
+ ```bash
25
+ cd examples/defender-deployment
26
+ npm install
27
+ ```
28
+
29
+ 2. **Configure Environment**
30
+
31
+ ```bash
32
+ cp .env.example .env
33
+ # Edit .env with your Defender credentials
34
+ ```
35
+
36
+ 3. **Review Diamond Configuration**
37
+
38
+ ```bash
39
+ cat diamond-config.json
40
+ ```
41
+
42
+ ## Diamond Structure
43
+
44
+ ### Contracts
45
+
46
+ - `ExampleDiamond.sol`: Main diamond contract
47
+ - `ExampleFacet1.sol`: Basic functionality facet
48
+ - `ExampleFacet2.sol`: Advanced functionality facet
49
+ - `UpgradeFacet.sol`: New facet for upgrade demonstration
50
+
51
+ ### Configuration
52
+
53
+ ```json
54
+ {
55
+ "protocolVersion": 0.0,
56
+ "protocolInitFacet": "ExampleFacet1",
57
+ "facets": {
58
+ "DiamondCutFacet": {
59
+ "priority": 10,
60
+ "versions": { "0.0": {} }
61
+ },
62
+ "DiamondLoupeFacet": {
63
+ "priority": 20,
64
+ "versions": { "0.0": {} }
65
+ },
66
+ "ExampleFacet1": {
67
+ "priority": 30,
68
+ "versions": {
69
+ "0.0": {
70
+ "deployInit": "initialize()",
71
+ "callbacks": ["logDeployment"]
72
+ }
73
+ }
74
+ },
75
+ "ExampleFacet2": {
76
+ "priority": 40,
77
+ "versions": {
78
+ "0.0": {
79
+ "deployInit": "setup()",
80
+ "callbacks": ["validateSetup"]
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ ## Deployment Steps
89
+
90
+ ### 1. Initial Deployment
91
+
92
+ ```bash
93
+ # Deploy to Sepolia testnet
94
+ npm run deploy:sepolia
95
+
96
+ # Or deploy to local hardhat network
97
+ npm run deploy:local
98
+ ```
99
+
100
+ This will:
101
+
102
+ 1. Deploy DiamondCutFacet through Defender
103
+ 2. Deploy the main Diamond contract
104
+ 3. Deploy all configured facets
105
+ 4. Create a Defender proposal for the diamond cut
106
+ 5. Execute the proposal (if auto-approval is enabled)
107
+
108
+ ### 2. Verify Deployment
109
+
110
+ ```bash
111
+ # Check deployment status
112
+ npm run status
113
+
114
+ # Verify on block explorer
115
+ npm run verify
116
+ ```
117
+
118
+ ### 3. Upgrade Example
119
+
120
+ ```bash
121
+ # This adds UpgradeFacet and upgrades ExampleFacet1 to v1.0
122
+ npm run upgrade
123
+ ```
124
+
125
+ ## Script Explanations
126
+
127
+ ### deploy-script.ts
128
+
129
+ ```typescript
130
+ import { ethers } from 'hardhat';
131
+ import { Diamond, DiamondDeployer, FileDeploymentRepository } from '@diamonds/core';
132
+ import { OZDefenderDeploymentStrategy } from '@diamonds/strategies';
133
+
134
+ async function main() {
135
+ console.log('🚀 Starting Defender deployment...');
136
+
137
+ // Load configuration
138
+ const config = {
139
+ diamondName: 'ExampleDiamond',
140
+ networkName: 'sepolia',
141
+ chainId: 11155111,
142
+ deploymentsPath: './deployments',
143
+ contractsPath: './contracts',
144
+ callbacksPath: './callbacks',
145
+ configFilePath: './diamond-config.json',
146
+ deployedDiamondDataFilePath: './deployments/exampledianmond-sepolia-11155111.json'
147
+ };
148
+
149
+ // Create diamond instance
150
+ const repository = new FileDeploymentRepository(config);
151
+ const diamond = new Diamond(config, repository);
152
+
153
+ // Setup provider and signer
154
+ diamond.setProvider(ethers.provider);
155
+ diamond.setSigner(await ethers.getSigners()[0]);
156
+
157
+ // Create Defender strategy
158
+ const strategy = new OZDefenderDeploymentStrategy(
159
+ process.env.DEFENDER_API_KEY!,
160
+ process.env.DEFENDER_API_SECRET!,
161
+ process.env.DEFENDER_RELAYER_ADDRESS!,
162
+ process.env.AUTO_APPROVE === 'true',
163
+ process.env.DEFENDER_SAFE_ADDRESS!,
164
+ 'Safe',
165
+ true // verbose logging
166
+ );
167
+
168
+ // Execute deployment
169
+ const deployer = new DiamondDeployer(diamond, strategy);
170
+ await deployer.deployDiamond();
171
+
172
+ console.log('✅ Deployment completed!');
173
+
174
+ // Output deployment information
175
+ const deployedData = diamond.getDeployedDiamondData();
176
+ console.log('\n📊 Deployment Summary:');
177
+ console.log(`Diamond Address: ${deployedData.DiamondAddress}`);
178
+ console.log(`Deployer Address: ${deployedData.DeployerAddress}`);
179
+ console.log('\n📋 Deployed Facets:');
180
+
181
+ Object.entries(deployedData.DeployedFacets || {}).forEach(([name, facet]) => {
182
+ console.log(` ${name}: ${facet.address} (v${facet.version})`);
183
+ });
184
+ }
185
+
186
+ main()
187
+ .then(() => process.exit(0))
188
+ .catch((error) => {
189
+ console.error('❌ Deployment failed:', error);
190
+ process.exit(1);
191
+ });
192
+ ```
193
+
194
+ ### upgrade-script.ts
195
+
196
+ ```typescript
197
+ import { ethers } from 'hardhat';
198
+ import { Diamond, DiamondDeployer, FileDeploymentRepository } from '@diamonds/core';
199
+ import { OZDefenderDeploymentStrategy } from '@diamonds/strategies';
200
+ import * as fs from 'fs-extra';
201
+
202
+ async function main() {
203
+ console.log('♻️ Starting upgrade process...');
204
+
205
+ // Load and update configuration
206
+ const configPath = './diamond-config.json';
207
+ const config = await fs.readJson(configPath);
208
+
209
+ // Add new facet for upgrade
210
+ config.protocolVersion = 1.0;
211
+ config.facets['UpgradeFacet'] = {
212
+ priority: 50,
213
+ versions: {
214
+ "1.0": {
215
+ deployInit: "initialize()",
216
+ callbacks: ["logUpgrade"]
217
+ }
218
+ }
219
+ };
220
+
221
+ // Upgrade existing facet
222
+ config.facets['ExampleFacet1'].versions["1.0"] = {
223
+ upgradeInit: "upgradeToV1()",
224
+ callbacks: ["validateUpgrade"]
225
+ };
226
+
227
+ // Save updated configuration
228
+ await fs.writeJson(configPath, config, { spaces: 2 });
229
+
230
+ // Setup diamond with existing deployment data
231
+ const diamondConfig = {
232
+ diamondName: 'ExampleDiamond',
233
+ networkName: 'sepolia',
234
+ chainId: 11155111,
235
+ deploymentsPath: './deployments',
236
+ contractsPath: './contracts',
237
+ callbacksPath: './callbacks',
238
+ configFilePath: configPath,
239
+ deployedDiamondDataFilePath: './deployments/exampledianmond-sepolia-11155111.json'
240
+ };
241
+
242
+ const repository = new FileDeploymentRepository(diamondConfig);
243
+ const diamond = new Diamond(diamondConfig, repository);
244
+
245
+ diamond.setProvider(ethers.provider);
246
+ diamond.setSigner(await ethers.getSigners()[0]);
247
+
248
+ // Create strategy and execute upgrade
249
+ const strategy = new OZDefenderDeploymentStrategy(
250
+ process.env.DEFENDER_API_KEY!,
251
+ process.env.DEFENDER_API_SECRET!,
252
+ process.env.DEFENDER_RELAYER_ADDRESS!,
253
+ process.env.AUTO_APPROVE === 'true',
254
+ process.env.DEFENDER_SAFE_ADDRESS!,
255
+ 'Safe',
256
+ true
257
+ );
258
+
259
+ const deployer = new DiamondDeployer(diamond, strategy);
260
+ await deployer.deployDiamond(); // Automatically detects upgrade scenario
261
+
262
+ console.log('✅ Upgrade completed!');
263
+ }
264
+
265
+ main()
266
+ .then(() => process.exit(0))
267
+ .catch((error) => {
268
+ console.error('❌ Upgrade failed:', error);
269
+ process.exit(1);
270
+ });
271
+ ```
272
+
273
+ ## Callback Examples
274
+
275
+ ### callbacks/logDeployment.ts
276
+
277
+ ```typescript
278
+ export async function logDeployment(args: any) {
279
+ console.log('📝 Deployment callback executed');
280
+ console.log('Diamond Address:', args.diamondAddress);
281
+ console.log('Facet Address:', args.facetAddress);
282
+ console.log('Timestamp:', new Date().toISOString());
283
+ }
284
+ ```
285
+
286
+ ### callbacks/validateSetup.ts
287
+
288
+ ```typescript
289
+ import { ethers } from 'hardhat';
290
+
291
+ export async function validateSetup(args: any) {
292
+ console.log('🔍 Validating setup...');
293
+
294
+ // Connect to deployed diamond
295
+ const diamond = await ethers.getContractAt('ExampleFacet2', args.diamondAddress);
296
+
297
+ // Validate initialization
298
+ const isSetup = await diamond.isSetupComplete();
299
+ if (!isSetup) {
300
+ throw new Error('Setup validation failed');
301
+ }
302
+
303
+ console.log('✅ Setup validation passed');
304
+ }
305
+ ```
306
+
307
+ ## Expected Output
308
+
309
+ ### Successful Deployment
310
+
311
+ ```bash
312
+ 🚀 Starting Defender deployment...
313
+
314
+ 🪓 Pre-deploy diamond tasks for ExampleDiamond from OZDefenderDeploymentStrategy...
315
+ 📡 Submitted DiamondCutFacet deploy to Defender: defender-deploy-id-1
316
+ ✅ Deployment succeeded for deploy-diamondcutfacet.
317
+ 📡 Submitted Diamond deploy to Defender: defender-deploy-id-2
318
+ ✅ Deployment succeeded for deploy-diamond.
319
+
320
+ 🚀 Deploying facet: DiamondLoupeFacet to version 0
321
+ 📡 Submitted deployment for facet DiamondLoupeFacet: defender-deploy-id-3
322
+ ✅ Deployment succeeded for deploy-DiamondLoupeFacet.
323
+
324
+ 🚀 Deploying facet: ExampleFacet1 to version 0
325
+ 📡 Submitted deployment for facet ExampleFacet1: defender-deploy-id-4
326
+ ✅ Deployment succeeded for deploy-ExampleFacet1.
327
+
328
+ 🚀 Deploying facet: ExampleFacet2 to version 0
329
+ 📡 Submitted deployment for facet ExampleFacet2: defender-deploy-id-5
330
+ ✅ Deployment succeeded for deploy-ExampleFacet2.
331
+
332
+ 🪓 Performing DiamondCut with 3 cut(s):
333
+ - Add for facet DiamondLoupeFacet at 0x3456789012345678901234567890123456789012
334
+ - Add for facet ExampleFacet1 at 0x4567890123456789012345678901234567890123
335
+ - Add for facet ExampleFacet2 at 0x5678901234567890123456789012345678901234
336
+
337
+ 📡 Defender Proposal created: https://defender.openzeppelin.com/proposal/test-proposal-123
338
+ ⏳ Auto-approval enabled. Waiting for proposal to be ready for execution...
339
+ ✅ Proposal executed successfully.
340
+
341
+ 📝 Deployment callback executed
342
+ 🔍 Validating setup...
343
+ ✅ Setup validation passed
344
+
345
+ ✅ Deployment completed!
346
+
347
+ 📊 Deployment Summary:
348
+ Diamond Address: 0x1234567890123456789012345678901234567890
349
+ Deployer Address: 0x742d35Cc6634C0532925a3b8D50d97e7
350
+
351
+ 📋 Deployed Facets:
352
+ DiamondCutFacet: 0x2345678901234567890123456789012345678901 (v0)
353
+ DiamondLoupeFacet: 0x3456789012345678901234567890123456789012 (v0)
354
+ ExampleFacet1: 0x4567890123456789012345678901234567890123 (v0)
355
+ ExampleFacet2: 0x5678901234567890123456789012345678901234 (v0)
356
+ ```
357
+
358
+ ## Troubleshooting
359
+
360
+ ### Common Issues
361
+
362
+ 1. **API Authentication Error**
363
+
364
+ ```bash
365
+ Error: Invalid API credentials
366
+ ```
367
+
368
+ **Solution**: Verify your `DEFENDER_API_KEY` and `DEFENDER_API_SECRET` in `.env`
369
+
370
+ 2. **Insufficient Balance**
371
+
372
+ ```bash
373
+ Error: insufficient funds for gas
374
+ ```
375
+
376
+ **Solution**: Add testnet ETH to your deployer address
377
+
378
+ 3. **Network Configuration**
379
+
380
+ ```bash
381
+ Error: could not detect network
382
+ ```
383
+
384
+ **Solution**: Verify your RPC URL and network settings
385
+
386
+ 4. **Multi-sig Approval Required**
387
+
388
+ ```bash
389
+ Warning: Proposal awaiting approval
390
+ ```
391
+
392
+ **Solution**: Check Defender dashboard for pending proposals
393
+
394
+ ### Debug Mode
395
+
396
+ Enable verbose logging:
397
+
398
+ ```bash
399
+ DEBUG=diamonds:* npm run deploy:sepolia
400
+ ```
401
+
402
+ ## Next Steps
403
+
404
+ 1. **Customize Facets**: Modify the example facets for your use case
405
+ 2. **Add More Facets**: Extend the diamond with additional functionality
406
+ 3. **Production Deployment**: Configure for mainnet deployment
407
+ 4. **Monitoring**: Set up monitoring and alerting through Defender
408
+ 5. **Automation**: Create automated deployment pipelines
409
+
410
+ ## Resources
411
+
412
+ - [OpenZeppelin Defender Documentation](https://docs.openzeppelin.com/defender/)
413
+ - [ERC-2535 Diamond Standard](https://eips.ethereum.org/EIPS/eip-2535)
414
+ - [Hardhat Documentation](https://hardhat.org/docs)
415
+ - [Diamonds Module Documentation](../../docs/defender-integration.md)
@@ -0,0 +1,41 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import "../../../test/mocks/contracts/interfaces/IDiamondCut.sol";
5
+
6
+ contract ExampleDiamond {
7
+ address public owner;
8
+
9
+ event DiamondCreated(address indexed diamond, address indexed owner);
10
+
11
+ constructor(address _contractOwner, address _diamondCutFacet) {
12
+ owner = _contractOwner;
13
+
14
+ // Add the diamondCut external function from the diamondCutFacet
15
+ IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);
16
+ bytes4[] memory functionSelectors = new bytes4[](1);
17
+ functionSelectors[0] = IDiamondCut.diamondCut.selector;
18
+ cut[0] = IDiamondCut.FacetCut({
19
+ facetAddress: _diamondCutFacet,
20
+ action: IDiamondCut.FacetCutAction.Add,
21
+ functionSelectors: functionSelectors
22
+ });
23
+
24
+ emit DiamondCreated(address(this), _contractOwner);
25
+ }
26
+
27
+ // Fallback function to delegate calls to facets
28
+ fallback() external payable {
29
+ address facet = address(0); // This would be looked up from storage in a real implementation
30
+ assembly {
31
+ calldatacopy(0, 0, calldatasize())
32
+ let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
33
+ returndatacopy(0, 0, returndatasize())
34
+ switch result
35
+ case 0 { revert(0, returndatasize()) }
36
+ default { return(0, returndatasize()) }
37
+ }
38
+ }
39
+
40
+ receive() external payable {}
41
+ }
@@ -0,0 +1,84 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ contract ExampleFacet1 {
5
+ bytes32 constant STORAGE_POSITION = keccak256("example.facet1.storage");
6
+
7
+ struct FacetStorage {
8
+ uint256 value;
9
+ bool initialized;
10
+ address owner;
11
+ string name;
12
+ }
13
+
14
+ function facetStorage() internal pure returns (FacetStorage storage fs) {
15
+ bytes32 position = STORAGE_POSITION;
16
+ assembly {
17
+ fs.slot := position
18
+ }
19
+ }
20
+
21
+ event Initialized(address indexed owner, string name);
22
+ event ValueSet(uint256 oldValue, uint256 newValue);
23
+ event UpgradedToV1(uint256 timestamp);
24
+
25
+ function initialize() external {
26
+ FacetStorage storage fs = facetStorage();
27
+ require(!fs.initialized, "Already initialized");
28
+
29
+ fs.initialized = true;
30
+ fs.owner = msg.sender;
31
+ fs.name = "ExampleFacet1";
32
+ fs.value = 100;
33
+
34
+ emit Initialized(msg.sender, fs.name);
35
+ }
36
+
37
+ function setValue(uint256 _value) external {
38
+ FacetStorage storage fs = facetStorage();
39
+ require(fs.initialized, "Not initialized");
40
+ require(msg.sender == fs.owner, "Not owner");
41
+
42
+ uint256 oldValue = fs.value;
43
+ fs.value = _value;
44
+
45
+ emit ValueSet(oldValue, _value);
46
+ }
47
+
48
+ function getValue() external view returns (uint256) {
49
+ FacetStorage storage fs = facetStorage();
50
+ return fs.value;
51
+ }
52
+
53
+ function getName() external view returns (string memory) {
54
+ FacetStorage storage fs = facetStorage();
55
+ return fs.name;
56
+ }
57
+
58
+ function getOwner() external view returns (address) {
59
+ FacetStorage storage fs = facetStorage();
60
+ return fs.owner;
61
+ }
62
+
63
+ function isInitialized() external view returns (bool) {
64
+ FacetStorage storage fs = facetStorage();
65
+ return fs.initialized;
66
+ }
67
+
68
+ // Version 1.0 upgrade function
69
+ function upgradeToV1() external {
70
+ FacetStorage storage fs = facetStorage();
71
+ require(fs.initialized, "Not initialized");
72
+ require(msg.sender == fs.owner, "Not owner");
73
+
74
+ // Upgrade logic here
75
+ fs.name = "ExampleFacet1_V1";
76
+
77
+ emit UpgradedToV1(block.timestamp);
78
+ }
79
+
80
+ // Version selector for upgrades
81
+ function version() external pure returns (string memory) {
82
+ return "1.0.0";
83
+ }
84
+ }
@@ -0,0 +1,104 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ contract ExampleFacet2 {
5
+ bytes32 constant STORAGE_POSITION = keccak256("example.facet2.storage");
6
+
7
+ struct FacetStorage {
8
+ mapping(address => uint256) balances;
9
+ uint256 totalSupply;
10
+ bool setupComplete;
11
+ uint256 setupTimestamp;
12
+ }
13
+
14
+ function facetStorage() internal pure returns (FacetStorage storage fs) {
15
+ bytes32 position = STORAGE_POSITION;
16
+ assembly {
17
+ fs.slot := position
18
+ }
19
+ }
20
+
21
+ event Setup(uint256 timestamp);
22
+ event BalanceUpdated(address indexed account, uint256 oldBalance, uint256 newBalance);
23
+ event Transfer(address indexed from, address indexed to, uint256 amount);
24
+
25
+ function setup() external {
26
+ FacetStorage storage fs = facetStorage();
27
+ require(!fs.setupComplete, "Already setup");
28
+
29
+ fs.setupComplete = true;
30
+ fs.setupTimestamp = block.timestamp;
31
+ fs.totalSupply = 1000000; // 1M tokens
32
+ fs.balances[msg.sender] = fs.totalSupply;
33
+
34
+ emit Setup(block.timestamp);
35
+ emit BalanceUpdated(msg.sender, 0, fs.totalSupply);
36
+ }
37
+
38
+ function isSetupComplete() external view returns (bool) {
39
+ FacetStorage storage fs = facetStorage();
40
+ return fs.setupComplete;
41
+ }
42
+
43
+ function getSetupTimestamp() external view returns (uint256) {
44
+ FacetStorage storage fs = facetStorage();
45
+ return fs.setupTimestamp;
46
+ }
47
+
48
+ function balanceOf(address account) external view returns (uint256) {
49
+ FacetStorage storage fs = facetStorage();
50
+ return fs.balances[account];
51
+ }
52
+
53
+ function totalSupply() external view returns (uint256) {
54
+ FacetStorage storage fs = facetStorage();
55
+ return fs.totalSupply;
56
+ }
57
+
58
+ function transfer(address to, uint256 amount) external returns (bool) {
59
+ FacetStorage storage fs = facetStorage();
60
+ require(fs.setupComplete, "Not setup");
61
+ require(fs.balances[msg.sender] >= amount, "Insufficient balance");
62
+
63
+ uint256 fromBalance = fs.balances[msg.sender];
64
+ uint256 toBalance = fs.balances[to];
65
+
66
+ fs.balances[msg.sender] = fromBalance - amount;
67
+ fs.balances[to] = toBalance + amount;
68
+
69
+ emit BalanceUpdated(msg.sender, fromBalance, fs.balances[msg.sender]);
70
+ emit BalanceUpdated(to, toBalance, fs.balances[to]);
71
+ emit Transfer(msg.sender, to, amount);
72
+
73
+ return true;
74
+ }
75
+
76
+ function mint(address to, uint256 amount) external returns (bool) {
77
+ FacetStorage storage fs = facetStorage();
78
+ require(fs.setupComplete, "Not setup");
79
+
80
+ uint256 oldBalance = fs.balances[to];
81
+ fs.balances[to] = oldBalance + amount;
82
+ fs.totalSupply += amount;
83
+
84
+ emit BalanceUpdated(to, oldBalance, fs.balances[to]);
85
+ emit Transfer(address(0), to, amount);
86
+
87
+ return true;
88
+ }
89
+
90
+ function burn(uint256 amount) external returns (bool) {
91
+ FacetStorage storage fs = facetStorage();
92
+ require(fs.setupComplete, "Not setup");
93
+ require(fs.balances[msg.sender] >= amount, "Insufficient balance");
94
+
95
+ uint256 oldBalance = fs.balances[msg.sender];
96
+ fs.balances[msg.sender] = oldBalance - amount;
97
+ fs.totalSupply -= amount;
98
+
99
+ emit BalanceUpdated(msg.sender, oldBalance, fs.balances[msg.sender]);
100
+ emit Transfer(msg.sender, address(0), amount);
101
+
102
+ return true;
103
+ }
104
+ }