@lukso/lsp23-contracts 0.15.0-rc.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.
@@ -0,0 +1,192 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.4;
3
+
4
+ interface ILSP23LinkedContractsFactory {
5
+ /**
6
+ * @dev Emitted when a primary and secondary contract are deployed.
7
+ * @param primaryContract Address of the deployed primary contract.
8
+ * @param secondaryContract Address of the deployed secondary contract.
9
+ * @param primaryContractDeployment Parameters used for the primary contract deployment.
10
+ * @param secondaryContractDeployment Parameters used for the secondary contract deployment.
11
+ * @param postDeploymentModule Address of the post-deployment module.
12
+ * @param postDeploymentModuleCalldata Calldata passed to the post-deployment module.
13
+ */
14
+ event DeployedContracts(
15
+ address indexed primaryContract,
16
+ address indexed secondaryContract,
17
+ PrimaryContractDeployment primaryContractDeployment,
18
+ SecondaryContractDeployment secondaryContractDeployment,
19
+ address postDeploymentModule,
20
+ bytes postDeploymentModuleCalldata
21
+ );
22
+
23
+ /**
24
+ * @dev Emitted when proxies of a primary and secondary contract are deployed.
25
+ * @param primaryContract Address of the deployed primary contract proxy.
26
+ * @param secondaryContract Address of the deployed secondary contract proxy.
27
+ * @param primaryContractDeploymentInit Parameters used for the primary contract proxy deployment.
28
+ * @param secondaryContractDeploymentInit Parameters used for the secondary contract proxy deployment.
29
+ * @param postDeploymentModule Address of the post-deployment module.
30
+ * @param postDeploymentModuleCalldata Calldata passed to the post-deployment module.
31
+ */
32
+ event DeployedERC1167Proxies(
33
+ address indexed primaryContract,
34
+ address indexed secondaryContract,
35
+ PrimaryContractDeploymentInit primaryContractDeploymentInit,
36
+ SecondaryContractDeploymentInit secondaryContractDeploymentInit,
37
+ address postDeploymentModule,
38
+ bytes postDeploymentModuleCalldata
39
+ );
40
+
41
+ /**
42
+ * @param salt A unique value used to ensure each created proxies are unique (used for deterministic deployments).
43
+ * @param fundingAmount The value to be sent with the deployment transaction.
44
+ * @param creationBytecode The bytecode of the contract with the constructor params.
45
+ */
46
+ struct PrimaryContractDeployment {
47
+ bytes32 salt;
48
+ uint256 fundingAmount;
49
+ bytes creationBytecode;
50
+ }
51
+
52
+ /**
53
+ * @param fundingAmount The value to be sent with the deployment transaction.
54
+ * @param creationBytecode The bytecode for contract creation, up to but not including the primary contract address (if it needs to be appended).
55
+ * @param addPrimaryContractAddress If set to `true`, this will append the primary contract's address + the `extraConstructorParams` to the `creationBytecode`.
56
+ * @param extraConstructorParams Params to be appended to the `creationBytecode` (after the primary contract address) if `addPrimaryContractAddress` is set to `true`.
57
+ */
58
+ struct SecondaryContractDeployment {
59
+ uint256 fundingAmount;
60
+ bytes creationBytecode;
61
+ bool addPrimaryContractAddress;
62
+ bytes extraConstructorParams;
63
+ }
64
+
65
+ /**
66
+ * @param salt A unique value used to ensure each created proxies are unique. (Can be used to deploy the contract at a desired address.)
67
+ * @param fundingAmount The value to be sent with the deployment transaction.
68
+ * @param implementationContract The address of the contract that will be used as a base contract for the proxy.
69
+ * @param initializationCalldata The calldata used to initialize the contract.
70
+ */
71
+ struct PrimaryContractDeploymentInit {
72
+ bytes32 salt;
73
+ uint256 fundingAmount;
74
+ address implementationContract;
75
+ bytes initializationCalldata;
76
+ }
77
+
78
+ /**
79
+ * @param fundingAmount The value to be sent with the deployment transaction.
80
+ * @param implementationContract The address of the contract that will be used as a base contract for the proxy.
81
+ * @param initializationCalldata Initialization calldata up to, but not including, the primary contract address (if it needs to be appended).
82
+ * @param addPrimaryContractAddress If set to `true`, this will append the primary contract's address + the `extraInitializationParams` to the `initializationCalldata`.
83
+ * @param extraInitializationParams Params to be appended to the `initializationCalldata` (after the primary contract address) if `addPrimaryContractAddress` is set to `true`
84
+ */
85
+ struct SecondaryContractDeploymentInit {
86
+ uint256 fundingAmount;
87
+ address implementationContract;
88
+ bytes initializationCalldata;
89
+ bool addPrimaryContractAddress;
90
+ bytes extraInitializationParams;
91
+ }
92
+
93
+ /**
94
+ * @dev Deploys a primary and a secondary linked contract.
95
+ * @notice Contracts deployed. Contract Address: `primaryContractAddress`. Primary Contract Address: `primaryContractAddress`
96
+ *
97
+ * @param primaryContractDeployment Contains the needed parameter to deploy a contract. (`salt`, `fundingAmount`, `creationBytecode`)
98
+ * @param secondaryContractDeployment Contains the needed parameter to deploy the secondary contract. (`fundingAmount`, `creationBytecode`, `addPrimaryContractAddress`, `extraConstructorParams`)
99
+ * @param postDeploymentModule The optional module to be executed after deployment
100
+ * @param postDeploymentModuleCalldata The data to be passed to the post deployment module
101
+ *
102
+ * @return primaryContractAddress The address of the primary contract.
103
+ * @return secondaryContractAddress The address of the secondary contract.
104
+ */
105
+ function deployContracts(
106
+ PrimaryContractDeployment calldata primaryContractDeployment,
107
+ SecondaryContractDeployment calldata secondaryContractDeployment,
108
+ address postDeploymentModule,
109
+ bytes calldata postDeploymentModuleCalldata
110
+ )
111
+ external
112
+ payable
113
+ returns (
114
+ address primaryContractAddress,
115
+ address secondaryContractAddress
116
+ );
117
+
118
+ /**
119
+ * @dev Deploys ERC1167 proxies of a primary contract and a secondary linked contract
120
+ * @notice Contract proxies deployed. Primary Proxy Address: `primaryContractAddress`. Secondary Contract Proxy Address: `secondaryContractAddress`
121
+ *
122
+ * @param primaryContractDeploymentInit Contains the needed parameters to deploy a proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`)
123
+ * @param secondaryContractDeploymentInit Contains the needed parameters to deploy the secondary proxy contract. (`fundingAmount`, `implementationContract`, `initializationCalldata`, `addPrimaryContractAddress`, `extraInitializationParams`)
124
+ * @param postDeploymentModule The optional module to be executed after deployment.
125
+ * @param postDeploymentModuleCalldata The data to be passed to the post deployment module.
126
+ *
127
+ * @return primaryContractAddress The address of the deployed primary contract proxy
128
+ * @return secondaryContractAddress The address of the deployed secondary contract proxy
129
+ */
130
+ function deployERC1167Proxies(
131
+ PrimaryContractDeploymentInit calldata primaryContractDeploymentInit,
132
+ SecondaryContractDeploymentInit
133
+ calldata secondaryContractDeploymentInit,
134
+ address postDeploymentModule,
135
+ bytes calldata postDeploymentModuleCalldata
136
+ )
137
+ external
138
+ payable
139
+ returns (
140
+ address primaryContractAddress,
141
+ address secondaryContractAddress
142
+ );
143
+
144
+ /**
145
+ * @dev Computes the addresses of a primary contract and a secondary linked contract
146
+ *
147
+ * @param primaryContractDeployment Contains the needed parameter to deploy the primary contract. (`salt`, `fundingAmount`, `creationBytecode`)
148
+ * @param secondaryContractDeployment Contains the needed parameter to deploy the secondary contract. (`fundingAmount`, `creationBytecode`, `addPrimaryContractAddress`, `extraConstructorParams`)
149
+ * @param postDeploymentModule The optional module to be executed after deployment
150
+ * @param postDeploymentModuleCalldata The data to be passed to the post deployment module
151
+ *
152
+ * @return primaryContractAddress The address of the deployed primary contract.
153
+ * @return secondaryContractAddress The address of the deployed secondary contract.
154
+ */
155
+ function computeAddresses(
156
+ PrimaryContractDeployment calldata primaryContractDeployment,
157
+ SecondaryContractDeployment calldata secondaryContractDeployment,
158
+ address postDeploymentModule,
159
+ bytes calldata postDeploymentModuleCalldata
160
+ )
161
+ external
162
+ view
163
+ returns (
164
+ address primaryContractAddress,
165
+ address secondaryContractAddress
166
+ );
167
+
168
+ /**
169
+ * @dev Computes the addresses of a primary and a secondary linked contracts ERC1167 proxies to be created
170
+ *
171
+ * @param primaryContractDeploymentInit Contains the needed parameters to deploy a primary proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`)
172
+ * @param secondaryContractDeploymentInit Contains the needed parameters to deploy the secondary proxy contract. (`fundingAmount`, `implementationContract`, `initializationCalldata`, `addPrimaryContractAddress`, `extraInitializationParams`)
173
+ * @param postDeploymentModule The optional module to be executed after deployment.
174
+ * @param postDeploymentModuleCalldata The data to be passed to the post deployment module.
175
+ *
176
+ * @return primaryContractAddress The address of the deployed primary contract proxy
177
+ * @return secondaryContractAddress The address of the deployed secondary contract proxy
178
+ */
179
+ function computeERC1167Addresses(
180
+ PrimaryContractDeploymentInit calldata primaryContractDeploymentInit,
181
+ SecondaryContractDeploymentInit
182
+ calldata secondaryContractDeploymentInit,
183
+ address postDeploymentModule,
184
+ bytes calldata postDeploymentModuleCalldata
185
+ )
186
+ external
187
+ view
188
+ returns (
189
+ address primaryContractAddress,
190
+ address secondaryContractAddress
191
+ );
192
+ }
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.4;
3
+
4
+ interface IPostDeploymentModule {
5
+ /**
6
+ * @dev Executes post-deployment logic for the primary and secondary contracts.
7
+ * @notice This function can be used to perform any additional setup or configuration after the primary and secondary contracts have been deployed.
8
+ *
9
+ * @param primaryContract The address of the deployed primary contract.
10
+ * @param secondaryContract The address of the deployed secondary contract.
11
+ * @param calldataToPostDeploymentModule Calldata to be passed for the post-deployment execution.
12
+ */
13
+ function executePostDeployment(
14
+ address primaryContract,
15
+ address secondaryContract,
16
+ bytes calldata calldataToPostDeploymentModule
17
+ ) external;
18
+ }
@@ -0,0 +1,24 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.4;
3
+
4
+ /**
5
+ * @dev Reverts when the `msg.value` sent is not equal to the sum of value used for the deployment of the contract & its owner contract.
6
+ * @notice Invalid value sent.
7
+ */
8
+ error InvalidValueSum();
9
+
10
+ /**
11
+ * @dev Reverts when the deployment & intialization of the contract has failed.
12
+ * @notice Failed to deploy & initialize the Primary Contract Proxy. Error: `errorData`.
13
+ *
14
+ * @param errorData Potentially information about why the deployment & intialization have failed.
15
+ */
16
+ error PrimaryContractProxyInitFailureError(bytes errorData);
17
+
18
+ /**
19
+ * @dev Reverts when the deployment & intialization of the secondary contract has failed.
20
+ * @notice Failed to deploy & initialize the Secondary Contract Proxy. Error: `errorData`.
21
+ *
22
+ * @param errorData Potentially information about why the deployment & intialization have failed.
23
+ */
24
+ error SecondaryContractProxyInitFailureError(bytes errorData);
@@ -0,0 +1,396 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.4;
3
+
4
+ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
5
+ import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
6
+ import {IPostDeploymentModule} from "./IPostDeploymentModule.sol";
7
+ import {ILSP23LinkedContractsFactory} from "./ILSP23LinkedContractsFactory.sol";
8
+ import {
9
+ InvalidValueSum,
10
+ PrimaryContractProxyInitFailureError,
11
+ SecondaryContractProxyInitFailureError
12
+ } from "./LSP23Errors.sol";
13
+
14
+ contract LSP23LinkedContractsFactory is ILSP23LinkedContractsFactory {
15
+ /**
16
+ * @inheritdoc ILSP23LinkedContractsFactory
17
+ */
18
+ function deployContracts(
19
+ PrimaryContractDeployment calldata primaryContractDeployment,
20
+ SecondaryContractDeployment calldata secondaryContractDeployment,
21
+ address postDeploymentModule,
22
+ bytes calldata postDeploymentModuleCalldata
23
+ )
24
+ public
25
+ payable
26
+ override
27
+ returns (
28
+ address primaryContractAddress,
29
+ address secondaryContractAddress
30
+ )
31
+ {
32
+ /* check that the msg.value is equal to the sum of the values of the primary and secondary contracts */
33
+ if (
34
+ msg.value !=
35
+ primaryContractDeployment.fundingAmount +
36
+ secondaryContractDeployment.fundingAmount
37
+ ) {
38
+ revert InvalidValueSum();
39
+ }
40
+
41
+ primaryContractAddress = _deployPrimaryContract(
42
+ primaryContractDeployment,
43
+ secondaryContractDeployment,
44
+ postDeploymentModule,
45
+ postDeploymentModuleCalldata
46
+ );
47
+
48
+ secondaryContractAddress = _deploySecondaryContract(
49
+ secondaryContractDeployment,
50
+ primaryContractAddress
51
+ );
52
+
53
+ emit DeployedContracts(
54
+ primaryContractAddress,
55
+ secondaryContractAddress,
56
+ primaryContractDeployment,
57
+ secondaryContractDeployment,
58
+ postDeploymentModule,
59
+ postDeploymentModuleCalldata
60
+ );
61
+
62
+ /* execute the post deployment logic in the postDeploymentModule if postDeploymentModule is not address(0) */
63
+ if (postDeploymentModule != address(0)) {
64
+ /* execute the post deployment module logic in the postDeploymentModule */
65
+ IPostDeploymentModule(postDeploymentModule).executePostDeployment(
66
+ primaryContractAddress,
67
+ secondaryContractAddress,
68
+ postDeploymentModuleCalldata
69
+ );
70
+ }
71
+ }
72
+
73
+ /**
74
+ * @inheritdoc ILSP23LinkedContractsFactory
75
+ */
76
+ function deployERC1167Proxies(
77
+ PrimaryContractDeploymentInit calldata primaryContractDeploymentInit,
78
+ SecondaryContractDeploymentInit
79
+ calldata secondaryContractDeploymentInit,
80
+ address postDeploymentModule,
81
+ bytes calldata postDeploymentModuleCalldata
82
+ )
83
+ public
84
+ payable
85
+ override
86
+ returns (
87
+ address primaryContractAddress,
88
+ address secondaryContractAddress
89
+ )
90
+ {
91
+ /* check that the msg.value is equal to the sum of the values of the primary and secondary contracts */
92
+ if (
93
+ msg.value !=
94
+ primaryContractDeploymentInit.fundingAmount +
95
+ secondaryContractDeploymentInit.fundingAmount
96
+ ) {
97
+ revert InvalidValueSum();
98
+ }
99
+
100
+ /* deploy the primary contract proxy with the primaryContractGeneratedSalt */
101
+ primaryContractAddress = _deployAndInitializePrimaryContractProxy(
102
+ primaryContractDeploymentInit,
103
+ secondaryContractDeploymentInit,
104
+ postDeploymentModule,
105
+ postDeploymentModuleCalldata
106
+ );
107
+
108
+ /* deploy the secondary contract proxy */
109
+ secondaryContractAddress = _deployAndInitializeSecondaryContractProxy(
110
+ secondaryContractDeploymentInit,
111
+ primaryContractAddress
112
+ );
113
+
114
+ emit DeployedERC1167Proxies(
115
+ primaryContractAddress,
116
+ secondaryContractAddress,
117
+ primaryContractDeploymentInit,
118
+ secondaryContractDeploymentInit,
119
+ postDeploymentModule,
120
+ postDeploymentModuleCalldata
121
+ );
122
+
123
+ /* execute the post deployment logic in the postDeploymentModule if postDeploymentModule is not address(0) */
124
+ if (postDeploymentModule != address(0)) {
125
+ /* execute the post deployment logic in the postDeploymentModule */
126
+ IPostDeploymentModule(postDeploymentModule).executePostDeployment(
127
+ primaryContractAddress,
128
+ secondaryContractAddress,
129
+ postDeploymentModuleCalldata
130
+ );
131
+ }
132
+ }
133
+
134
+ /**
135
+ * @inheritdoc ILSP23LinkedContractsFactory
136
+ */
137
+ function computeAddresses(
138
+ PrimaryContractDeployment calldata primaryContractDeployment,
139
+ SecondaryContractDeployment calldata secondaryContractDeployment,
140
+ address postDeploymentModule,
141
+ bytes calldata postDeploymentModuleCalldata
142
+ )
143
+ public
144
+ view
145
+ override
146
+ returns (
147
+ address primaryContractAddress,
148
+ address secondaryContractAddress
149
+ )
150
+ {
151
+ bytes32 primaryContractGeneratedSalt = _generatePrimaryContractSalt(
152
+ primaryContractDeployment,
153
+ secondaryContractDeployment,
154
+ postDeploymentModule,
155
+ postDeploymentModuleCalldata
156
+ );
157
+
158
+ primaryContractAddress = Create2.computeAddress(
159
+ primaryContractGeneratedSalt,
160
+ keccak256(primaryContractDeployment.creationBytecode)
161
+ );
162
+
163
+ bytes memory secondaryContractByteCodeWithAllParams;
164
+ if (secondaryContractDeployment.addPrimaryContractAddress) {
165
+ secondaryContractByteCodeWithAllParams = abi.encodePacked(
166
+ secondaryContractDeployment.creationBytecode,
167
+ abi.encode(primaryContractAddress),
168
+ secondaryContractDeployment.extraConstructorParams
169
+ );
170
+ } else {
171
+ secondaryContractByteCodeWithAllParams = secondaryContractDeployment
172
+ .creationBytecode;
173
+ }
174
+
175
+ secondaryContractAddress = Create2.computeAddress(
176
+ keccak256(abi.encodePacked(primaryContractAddress)),
177
+ keccak256(secondaryContractByteCodeWithAllParams)
178
+ );
179
+ }
180
+
181
+ /**
182
+ * @inheritdoc ILSP23LinkedContractsFactory
183
+ */
184
+ function computeERC1167Addresses(
185
+ PrimaryContractDeploymentInit calldata primaryContractDeploymentInit,
186
+ SecondaryContractDeploymentInit
187
+ calldata secondaryContractDeploymentInit,
188
+ address postDeploymentModule,
189
+ bytes calldata postDeploymentModuleCalldata
190
+ )
191
+ public
192
+ view
193
+ override
194
+ returns (
195
+ address primaryContractAddress,
196
+ address secondaryContractAddress
197
+ )
198
+ {
199
+ bytes32 primaryContractGeneratedSalt = _generatePrimaryContractProxySalt(
200
+ primaryContractDeploymentInit,
201
+ secondaryContractDeploymentInit,
202
+ postDeploymentModule,
203
+ postDeploymentModuleCalldata
204
+ );
205
+
206
+ primaryContractAddress = Clones.predictDeterministicAddress(
207
+ primaryContractDeploymentInit.implementationContract,
208
+ primaryContractGeneratedSalt
209
+ );
210
+
211
+ secondaryContractAddress = Clones.predictDeterministicAddress(
212
+ secondaryContractDeploymentInit.implementationContract,
213
+ keccak256(abi.encodePacked(primaryContractAddress))
214
+ );
215
+ }
216
+
217
+ function _deployPrimaryContract(
218
+ PrimaryContractDeployment calldata primaryContractDeployment,
219
+ SecondaryContractDeployment calldata secondaryContractDeployment,
220
+ address postDeploymentModule,
221
+ bytes calldata postDeploymentModuleCalldata
222
+ ) internal returns (address primaryContractAddress) {
223
+ bytes32 primaryContractGeneratedSalt = _generatePrimaryContractSalt(
224
+ primaryContractDeployment,
225
+ secondaryContractDeployment,
226
+ postDeploymentModule,
227
+ postDeploymentModuleCalldata
228
+ );
229
+
230
+ /* deploy the primary contract */
231
+ primaryContractAddress = Create2.deploy(
232
+ primaryContractDeployment.fundingAmount,
233
+ primaryContractGeneratedSalt,
234
+ primaryContractDeployment.creationBytecode
235
+ );
236
+ }
237
+
238
+ function _deploySecondaryContract(
239
+ SecondaryContractDeployment calldata secondaryContractDeployment,
240
+ address primaryContractAddress
241
+ ) internal returns (address secondaryContractAddress) {
242
+ /**
243
+ * If `addPrimaryContractAddress` is `true`, the following will be appended to the constructor params:
244
+ * - The primary contract address
245
+ * - `extraConstructorParams`
246
+ */
247
+ bytes memory secondaryContractByteCode = secondaryContractDeployment
248
+ .creationBytecode;
249
+
250
+ if (secondaryContractDeployment.addPrimaryContractAddress) {
251
+ secondaryContractByteCode = abi.encodePacked(
252
+ secondaryContractByteCode,
253
+ abi.encode(primaryContractAddress),
254
+ secondaryContractDeployment.extraConstructorParams
255
+ );
256
+ }
257
+
258
+ secondaryContractAddress = Create2.deploy(
259
+ secondaryContractDeployment.fundingAmount,
260
+ keccak256(abi.encodePacked(primaryContractAddress)),
261
+ secondaryContractByteCode
262
+ );
263
+ }
264
+
265
+ function _deployAndInitializePrimaryContractProxy(
266
+ PrimaryContractDeploymentInit calldata primaryContractDeploymentInit,
267
+ SecondaryContractDeploymentInit
268
+ calldata secondaryContractDeploymentInit,
269
+ address postDeploymentModule,
270
+ bytes calldata postDeploymentModuleCalldata
271
+ ) internal returns (address primaryContractAddress) {
272
+ bytes32 primaryContractGeneratedSalt = _generatePrimaryContractProxySalt(
273
+ primaryContractDeploymentInit,
274
+ secondaryContractDeploymentInit,
275
+ postDeploymentModule,
276
+ postDeploymentModuleCalldata
277
+ );
278
+
279
+ /* deploy the primary contract proxy with the primaryContractGeneratedSalt */
280
+ primaryContractAddress = Clones.cloneDeterministic(
281
+ primaryContractDeploymentInit.implementationContract,
282
+ primaryContractGeneratedSalt
283
+ );
284
+
285
+ /* initialize the primary contract proxy */
286
+ (bool success, bytes memory returnedData) = primaryContractAddress.call{
287
+ value: primaryContractDeploymentInit.fundingAmount
288
+ }(primaryContractDeploymentInit.initializationCalldata);
289
+ if (!success) {
290
+ revert PrimaryContractProxyInitFailureError(returnedData);
291
+ }
292
+ }
293
+
294
+ function _deployAndInitializeSecondaryContractProxy(
295
+ SecondaryContractDeploymentInit
296
+ calldata secondaryContractDeploymentInit,
297
+ address primaryContractAddress
298
+ ) internal returns (address secondaryContractAddress) {
299
+ /* deploy the secondary contract proxy with the primaryContractGeneratedSalt */
300
+ secondaryContractAddress = Clones.cloneDeterministic(
301
+ secondaryContractDeploymentInit.implementationContract,
302
+ keccak256(abi.encodePacked(primaryContractAddress))
303
+ );
304
+
305
+ /**
306
+ * If `addPrimaryContractAddress` is `true`, the following will be appended to the `initializationCalldata`:
307
+ * - The primary contract address
308
+ * - `extraInitializationBytes`
309
+ */
310
+ bytes
311
+ memory secondaryInitializationBytes = secondaryContractDeploymentInit
312
+ .initializationCalldata;
313
+
314
+ if (secondaryContractDeploymentInit.addPrimaryContractAddress) {
315
+ secondaryInitializationBytes = abi.encodePacked(
316
+ secondaryInitializationBytes,
317
+ abi.encode(primaryContractAddress),
318
+ secondaryContractDeploymentInit.extraInitializationParams
319
+ );
320
+ }
321
+
322
+ /* initialize the primary contract proxy */
323
+ (bool success, bytes memory returnedData) = secondaryContractAddress
324
+ .call{value: secondaryContractDeploymentInit.fundingAmount}(
325
+ secondaryInitializationBytes
326
+ );
327
+ if (!success) {
328
+ revert SecondaryContractProxyInitFailureError(returnedData);
329
+ }
330
+ }
331
+
332
+ function _generatePrimaryContractSalt(
333
+ PrimaryContractDeployment calldata primaryContractDeployment,
334
+ SecondaryContractDeployment calldata secondaryContractDeployment,
335
+ address postDeploymentModule,
336
+ bytes calldata postDeploymentModuleCalldata
337
+ ) internal pure virtual returns (bytes32 primaryContractGeneratedSalt) {
338
+ /* generate salt for the primary contract
339
+ * the salt is generated by hashing the following elements:
340
+ * - the salt
341
+ * - the secondary contract bytecode
342
+ * - the secondary addPrimaryContractAddress boolean
343
+ * - the secondary extraConstructorParams
344
+ * - the postDeploymentModule address
345
+ * - the postDeploymentModuleCalldata
346
+ *
347
+ */
348
+ primaryContractGeneratedSalt = keccak256(
349
+ abi.encode(
350
+ primaryContractDeployment.salt,
351
+ secondaryContractDeployment.creationBytecode,
352
+ secondaryContractDeployment.addPrimaryContractAddress,
353
+ secondaryContractDeployment.extraConstructorParams,
354
+ postDeploymentModule,
355
+ postDeploymentModuleCalldata
356
+ )
357
+ );
358
+ }
359
+
360
+ function _generatePrimaryContractProxySalt(
361
+ PrimaryContractDeploymentInit calldata primaryContractDeploymentInit,
362
+ SecondaryContractDeploymentInit
363
+ calldata secondaryContractDeploymentInit,
364
+ address postDeploymentModule,
365
+ bytes calldata postDeploymentModuleCalldata
366
+ )
367
+ internal
368
+ pure
369
+ virtual
370
+ returns (bytes32 primaryContractProxyGeneratedSalt)
371
+ {
372
+ /**
373
+ * Generate the salt for the primary contract
374
+ * The salt is generated by hashing the following elements:
375
+ * - the salt
376
+ * - the secondary implementation contract address
377
+ * - the secondary contract initialization calldata
378
+ * - the secondary contract addPrimaryContractAddress boolean
379
+ * - the secondary contract extra initialization params (if any)
380
+ * - the postDeploymentModule address
381
+ * - the callda to the post deployment module
382
+ *
383
+ */
384
+ primaryContractProxyGeneratedSalt = keccak256(
385
+ abi.encode(
386
+ primaryContractDeploymentInit.salt,
387
+ secondaryContractDeploymentInit.implementationContract,
388
+ secondaryContractDeploymentInit.initializationCalldata,
389
+ secondaryContractDeploymentInit.addPrimaryContractAddress,
390
+ secondaryContractDeploymentInit.extraInitializationParams,
391
+ postDeploymentModule,
392
+ postDeploymentModuleCalldata
393
+ )
394
+ );
395
+ }
396
+ }
@@ -0,0 +1,23 @@
1
+ # LSP23 Linked Contracts Deployment Module
2
+
3
+ This folder contains modules related to the deployment of LSP23 Linked Contracts. The modules are essential for initializing and post-deploying actions for Universal Profiles.
4
+
5
+ ## Modules
6
+
7
+ - **UniversalProfileInitPostDeploymentModule**: This module is responsible for the initial setup after the deployment of a Universal Profile Init contract.
8
+
9
+ - **Standardized Address**: `0x000000000066093407b6704B89793beFfD0D8F00`
10
+ - **Standardized Salt**: `0x12a6712f113536d8b01d99f72ce168c7e10901240d73e80eeb821d01aa4c2b1a`
11
+ - [More Details](./deployment-UP-init-module.md)
12
+
13
+ - **UniversalProfilePostDeploymentModule**: This module is responsible for the initial setup after the deployment of a Universal Profile contract.
14
+ - **Standardized Address**: `0x0000005aD606bcFEF9Ea6D0BbE5b79847054BcD7`
15
+ - **Standardized Salt**: `0x42ff55d7957589c62da54a4368b10a2bc549f2038bbb6880ec6b3e0ecae2ba58`
16
+ - [More Details](./deployment-UP-module.md)
17
+
18
+ ## Setup
19
+
20
+ Before deploying any of these modules, make sure that the following contracts are already deployed on the same network:
21
+
22
+ - [Nick's Factory contract](https://github.com/Arachnid/deterministic-deployment-proxy/tree/master)
23
+ - [LSP23 Linked Contracts Factory](https://github.com/lukso-network/LIPs/blob/main/LSPs/LSP-23-LinkedContractsFactory.md#lsp23linkedcontractsfactory-deployment)