diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c2a38c4..18690536c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [0.11.0-rc.1](https://github.com/lukso-network/lsp-smart-contracts/compare/v0.1...v0.11.0-rc.1) (2023-08-08) + +### ⚠ BREAKING CHANGES + +- refactor: rename LSP23 to LinkedContractsFactory (#658) + +### Bug Fixes + +- build: add LSP23 in artifacts (#662) +- failing tests for lsp23 + add LSP23 test suite in CI ([#657](https://github.com/lukso-network/lsp-smart-contracts/issues/657)) ([0e5d9bf](https://github.com/lukso-network/lsp-smart-contracts/commit/0e5d9bf7f9b212976f5c754b28f96b37a8039076)) + ## [0.11.0-rc.0](https://github.com/lukso-network/lsp-smart-contracts/compare/v0.10.3...v0.11.0-rc.0) (2023-08-04) ### ⚠ BREAKING CHANGES diff --git a/contracts/LSP23LinkedContractsDeployment/ILinkedContractsFactory.sol b/contracts/LSP23LinkedContractsDeployment/ILinkedContractsFactory.sol new file mode 100644 index 000000000..3245fbd95 --- /dev/null +++ b/contracts/LSP23LinkedContractsDeployment/ILinkedContractsFactory.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +interface ILinkedContractsFactory { + event DeployedContracts( + address indexed primaryContract, + address indexed secondaryContract, + PrimaryContractDeployment primaryContractDeployment, + SecondaryContractDeployment secondaryContractDeployment, + address postDeploymentModule, + bytes postDeploymentModuleCalldata + ); + + event DeployedERC1167Proxies( + address indexed primaryContract, + address indexed secondaryContract, + PrimaryContractDeploymentInit primaryContractDeploymentInit, + SecondaryContractDeploymentInit secondaryContractDeploymentInit, + address postDeploymentModule, + bytes postDeploymentModuleCalldata + ); + + /** + * @param salt A unique value used to ensure each created proxies are unique. (Can be used to deploy the contract at a desired address.) + * @param fundingAmount The value to be sent with the deployment transaction. + * @param creationBytecode The bytecode of the contract with the constructor params. + */ + struct PrimaryContractDeployment { + bytes32 salt; + uint256 fundingAmount; + bytes creationBytecode; + } + + /** + * @param fundingAmount The value to be sent with the deployment transaction. + * @param creationBytecode The constructor + runtime bytecode (without the primary contract's address as param) + * @param addPrimaryContractAddress If set to `true`, this will append the primary contract's address + the `extraConstructorParams` to the `creationBytecode`. + * @param extraConstructorParams Params to be appended to the `creationBytecode` (after the primary contract address) if `addPrimaryContractAddress` is set to `true`. + */ + struct SecondaryContractDeployment { + uint256 fundingAmount; + bytes creationBytecode; + bool addPrimaryContractAddress; + bytes extraConstructorParams; + } + + /** + * @param salt A unique value used to ensure each created proxies are unique. (Can be used to deploy the contract at a desired address.) + * @param fundingAmount The value to be sent with the deployment transaction. + * @param implementationContract The address of the contract that will be used as a base contract for the proxy. + * @param initializationCalldata The calldata used to initialise the contract. (initialization should be similar to a constructor in a normal contract.) + */ + struct PrimaryContractDeploymentInit { + bytes32 salt; + uint256 fundingAmount; + address implementationContract; + bytes initializationCalldata; + } + + /** + * @param fundingAmount The value to be sent with the deployment transaction. + * @param implementationContract The address of the contract that will be used as a base contract for the proxy. + * @param initializationCalldata The first part of the initialisation calldata, everything before the primary contract address. + * @param addPrimaryContractAddress If set to `true`, this will append the primary contract's address + the `extraInitializationParams` to the `initializationCalldata`. + * @param extraInitializationParams Params to be appended to the `initializationCalldata` (after the primary contract address) if `addPrimaryContractAddress` is set to `true` + */ + struct SecondaryContractDeploymentInit { + uint256 fundingAmount; + address implementationContract; + bytes initializationCalldata; + bool addPrimaryContractAddress; + bytes extraInitializationParams; + } + + /** + * @dev Deploys a primary and a secondary linked contract. + * @notice Contracts deployed. Contract Address: `primaryContractAddress`. Primary Contract Address: `primaryContractAddress` + * + * @param primaryContractDeployment Contains the needed parameter to deploy a contract. (`salt`, `fundingAmount`, `creationBytecode`) + * @param secondaryContractDeployment Contains the needed parameter to deploy the secondary contract. (`fundingAmount`, `creationBytecode`, `addPrimaryContractAddress`, `extraConstructorParams`) + * @param postDeploymentModule The module to be executed after deployment + * @param postDeploymentModuleCalldata The data to be passed to the post deployment module + * + * @return primaryContractAddress The address of the primary contract. + * @return secondaryContractAddress The address of the secondary contract. + */ + function deployContracts( + PrimaryContractDeployment calldata primaryContractDeployment, + SecondaryContractDeployment calldata secondaryContractDeployment, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + external + payable + returns ( + address primaryContractAddress, + address secondaryContractAddress + ); + + /** + * @dev Deploys proxies of a primary contract and a secondary linked contract + * @notice Contract proxies deployed. Primary Proxy Address: `primaryContractAddress`. Secondary Contract Proxy Address: `secondaryContractAddress` + * + * @param primaryContractDeploymentInit Contains the needed parameters to deploy a proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`) + * @param secondaryContractDeploymentInit Contains the needed parameters to deploy the secondary proxy contract. (`fundingAmount`, `implementationContract`, `addPrimaryContractAddress`, `initializationCalldata`, `extraInitializationParams`) + * @param postDeploymentModule The module to be executed after deployment. + * @param postDeploymentModuleCalldata The data to be passed to the post deployment module. + * + * @return primaryContractAddress The address of the deployed primary contract proxy + * @return secondaryContractAddress The address of the deployed secondary contract proxy + */ + function deployERC1167Proxies( + PrimaryContractDeploymentInit calldata primaryContractDeploymentInit, + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + external + payable + returns ( + address primaryContractAddress, + address secondaryContractAddress + ); + + /** + * @dev Computes the addresses of a primary contract and a secondary linked contract + * + * @param primaryContractDeployment Contains the needed parameter to deploy the primary contract. (`salt`, `fundingAmount`, `creationBytecode`) + * @param secondaryContractDeployment Contains the needed parameter to deploy the secondary contract. (`fundingAmount`, `creationBytecode`, `addPrimaryContractAddress`, `extraConstructorParams`) + * @param postDeploymentModule The module to be executed after deployment + * @param postDeploymentModuleCalldata The data to be passed to the post deployment module + * + * @return primaryContractAddress The address of the deployed primary contract. + * @return secondaryContractAddress The address of the deployed secondary contract. + */ + function computeAddresses( + PrimaryContractDeployment calldata primaryContractDeployment, + SecondaryContractDeployment calldata secondaryContractDeployment, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + external + view + returns ( + address primaryContractAddress, + address secondaryContractAddress + ); + + /** + * @dev Computes the addresses of a primary and a secondary linked contracts proxies to be created + * + * @param primaryContractDeploymentInit Contains the needed parameters to deploy a primary proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`) + * @param secondaryContractDeploymentInit Contains the needed parameters to deploy the secondary proxy contract. (`fundingAmount`, `implementationContract`, `addPrimaryContractAddress`, `initializationCalldata`, `extraInitializationParams`) + * @param postDeploymentModule The module to be executed after deployment. + * @param postDeploymentModuleCalldata The data to be passed to the post deployment module. + * + * @return primaryContractAddress The address of the deployed primary contract proxy + * @return secondaryContractAddress The address of the deployed secondary contract proxy + */ + function computeERC1167Addresses( + PrimaryContractDeploymentInit calldata primaryContractDeploymentInit, + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + external + view + returns ( + address primaryContractAddress, + address secondaryContractAddress + ); +} diff --git a/contracts/LSP23MultiChainDeployment/IPostDeploymentModule.sol b/contracts/LSP23LinkedContractsDeployment/IPostDeploymentModule.sol similarity index 73% rename from contracts/LSP23MultiChainDeployment/IPostDeploymentModule.sol rename to contracts/LSP23LinkedContractsDeployment/IPostDeploymentModule.sol index 083051c57..5ed8b2301 100644 --- a/contracts/LSP23MultiChainDeployment/IPostDeploymentModule.sol +++ b/contracts/LSP23LinkedContractsDeployment/IPostDeploymentModule.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.4; interface IPostDeploymentModule { function executePostDeployment( - address ownerControlledContract, - address ownerContract, + address primaryContract, + address secondaryContract, bytes calldata calldataToPostDeploymentModule ) external; } diff --git a/contracts/LSP23MultiChainDeployment/LSP23Errors.sol b/contracts/LSP23LinkedContractsDeployment/LSP23Errors.sol similarity index 58% rename from contracts/LSP23MultiChainDeployment/LSP23Errors.sol rename to contracts/LSP23LinkedContractsDeployment/LSP23Errors.sol index 90eb8a440..3690fe9fb 100644 --- a/contracts/LSP23MultiChainDeployment/LSP23Errors.sol +++ b/contracts/LSP23LinkedContractsDeployment/LSP23Errors.sol @@ -9,16 +9,16 @@ error InvalidValueSum(); /** * @dev Reverts when the deployment & intialisation of the contract has failed. - * @notice Failed to deploy & initialise the Controlled Contract Proxy. Error: `errorData`. + * @notice Failed to deploy & initialise the Primary Contract Proxy. Error: `errorData`. * * @param errorData Potentially information about why the deployment & intialisation have failed. */ -error ControlledContractProxyInitFailureError(bytes errorData); +error PrimaryContractProxyInitFailureError(bytes errorData); /** - * @dev Reverts when the deployment & intialisation of the owner contract has failed. - * @notice Failed to deploy & initialise the Owner Contract Proxy. Error: `errorData`. + * @dev Reverts when the deployment & intialisation of the secondary contract has failed. + * @notice Failed to deploy & initialise the Secondary Contract Proxy. Error: `errorData`. * * @param errorData Potentially information about why the deployment & intialisation have failed. */ -error OwnerContractProxyInitFailureError(bytes errorData); +error SecondaryContractProxyInitFailureError(bytes errorData); diff --git a/contracts/LSP23LinkedContractsDeployment/LinkedContractsFactory.sol b/contracts/LSP23LinkedContractsDeployment/LinkedContractsFactory.sol new file mode 100644 index 000000000..434f30e79 --- /dev/null +++ b/contracts/LSP23LinkedContractsDeployment/LinkedContractsFactory.sol @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; +import {IPostDeploymentModule} from "./IPostDeploymentModule.sol"; +import {ILinkedContractsFactory} from "./ILinkedContractsFactory.sol"; +import { + InvalidValueSum, + PrimaryContractProxyInitFailureError, + SecondaryContractProxyInitFailureError +} from "./LSP23Errors.sol"; + +contract LinkedContractsFactory is ILinkedContractsFactory { + /** + * @inheritdoc ILinkedContractsFactory + */ + function deployContracts( + PrimaryContractDeployment calldata primaryContractDeployment, + SecondaryContractDeployment calldata secondaryContractDeployment, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + public + payable + returns ( + address primaryContractAddress, + address secondaryContractAddress + ) + { + /* check that the msg.value is equal to the sum of the values of the primary and secondary contracts */ + if ( + msg.value != + primaryContractDeployment.fundingAmount + + secondaryContractDeployment.fundingAmount + ) { + revert InvalidValueSum(); + } + + primaryContractAddress = _deployPrimaryContract( + primaryContractDeployment, + secondaryContractDeployment, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + secondaryContractAddress = _deploySecondaryContract( + secondaryContractDeployment, + primaryContractAddress + ); + + emit DeployedContracts( + primaryContractAddress, + secondaryContractAddress, + primaryContractDeployment, + secondaryContractDeployment, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + /* execute the post deployment module logic in the postDeploymentModule */ + IPostDeploymentModule(postDeploymentModule).executePostDeployment( + primaryContractAddress, + secondaryContractAddress, + postDeploymentModuleCalldata + ); + } + + /** + * @inheritdoc ILinkedContractsFactory + */ + function deployERC1167Proxies( + PrimaryContractDeploymentInit calldata primaryContractDeploymentInit, + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + public + payable + returns ( + address primaryContractAddress, + address secondaryContractAddress + ) + { + /* check that the msg.value is equal to the sum of the values of the primary and secondary contracts */ + if ( + msg.value != + primaryContractDeploymentInit.fundingAmount + + secondaryContractDeploymentInit.fundingAmount + ) { + revert InvalidValueSum(); + } + + /* deploy the primary contract proxy with the primaryContractGeneratedSalt */ + primaryContractAddress = _deployAndInitializePrimaryContractProxy( + primaryContractDeploymentInit, + secondaryContractDeploymentInit, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + /* deploy the secondary contract proxy */ + secondaryContractAddress = _deployAndInitializeSecondaryContractProxy( + secondaryContractDeploymentInit, + primaryContractAddress + ); + + emit DeployedERC1167Proxies( + primaryContractAddress, + secondaryContractAddress, + primaryContractDeploymentInit, + secondaryContractDeploymentInit, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + /* execute the post deployment logic in the postDeploymentModule */ + IPostDeploymentModule(postDeploymentModule).executePostDeployment( + primaryContractAddress, + secondaryContractAddress, + postDeploymentModuleCalldata + ); + } + + /** + * @inheritdoc ILinkedContractsFactory + */ + function computeAddresses( + PrimaryContractDeployment calldata primaryContractDeployment, + SecondaryContractDeployment calldata secondaryContractDeployment, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + public + view + returns ( + address primaryContractAddress, + address secondaryContractAddress + ) + { + bytes32 primaryContractGeneratedSalt = _generatePrimaryContractSalt( + primaryContractDeployment, + secondaryContractDeployment, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + primaryContractAddress = Create2.computeAddress( + primaryContractGeneratedSalt, + keccak256(primaryContractDeployment.creationBytecode) + ); + + bytes memory secondaryContractByteCodeWithAllParams; + if (secondaryContractDeployment.addPrimaryContractAddress) { + secondaryContractByteCodeWithAllParams = abi.encodePacked( + secondaryContractDeployment.creationBytecode, + abi.encode(primaryContractAddress), + secondaryContractDeployment.extraConstructorParams + ); + } else { + secondaryContractByteCodeWithAllParams = secondaryContractDeployment + .creationBytecode; + } + + secondaryContractAddress = Create2.computeAddress( + keccak256(abi.encodePacked(primaryContractAddress)), + keccak256(secondaryContractByteCodeWithAllParams) + ); + } + + /** + * @inheritdoc ILinkedContractsFactory + */ + function computeERC1167Addresses( + PrimaryContractDeploymentInit calldata primaryContractDeploymentInit, + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + public + view + returns ( + address primaryContractAddress, + address secondaryContractAddress + ) + { + bytes32 primaryContractGeneratedSalt = _generatePrimaryContractProxySalt( + primaryContractDeploymentInit, + secondaryContractDeploymentInit, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + primaryContractAddress = Clones.predictDeterministicAddress( + primaryContractDeploymentInit.implementationContract, + primaryContractGeneratedSalt + ); + + secondaryContractAddress = Clones.predictDeterministicAddress( + secondaryContractDeploymentInit.implementationContract, + keccak256(abi.encodePacked(primaryContractAddress)) + ); + } + + function _deployPrimaryContract( + PrimaryContractDeployment calldata primaryContractDeployment, + SecondaryContractDeployment calldata secondaryContractDeployment, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) internal returns (address primaryContractAddress) { + bytes32 primaryContractGeneratedSalt = _generatePrimaryContractSalt( + primaryContractDeployment, + secondaryContractDeployment, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + /* deploy the primary contract */ + primaryContractAddress = Create2.deploy( + primaryContractDeployment.fundingAmount, + primaryContractGeneratedSalt, + primaryContractDeployment.creationBytecode + ); + } + + function _deploySecondaryContract( + SecondaryContractDeployment calldata secondaryContractDeployment, + address primaryContractAddress + ) internal returns (address secondaryContractAddress) { + /** + * If `addPrimaryContractAddress` is `true`, the following will be appended to the constructor params: + * - The primary contract address + * - `extraConstructorParams` + */ + bytes memory secondaryContractByteCode = secondaryContractDeployment + .creationBytecode; + + if (secondaryContractDeployment.addPrimaryContractAddress) { + secondaryContractByteCode = abi.encodePacked( + secondaryContractByteCode, + abi.encode(primaryContractAddress), + secondaryContractDeployment.extraConstructorParams + ); + } + + secondaryContractAddress = Create2.deploy( + secondaryContractDeployment.fundingAmount, + keccak256(abi.encodePacked(primaryContractAddress)), + secondaryContractByteCode + ); + } + + function _deployAndInitializePrimaryContractProxy( + PrimaryContractDeploymentInit calldata primaryContractDeploymentInit, + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) internal returns (address primaryContractAddress) { + bytes32 primaryContractGeneratedSalt = _generatePrimaryContractProxySalt( + primaryContractDeploymentInit, + secondaryContractDeploymentInit, + postDeploymentModule, + postDeploymentModuleCalldata + ); + + /* deploy the primary contract proxy with the primaryContractGeneratedSalt */ + primaryContractAddress = Clones.cloneDeterministic( + primaryContractDeploymentInit.implementationContract, + primaryContractGeneratedSalt + ); + + /* initialize the primary contract proxy */ + (bool success, bytes memory returnedData) = primaryContractAddress.call{ + value: msg.value + }(primaryContractDeploymentInit.initializationCalldata); + if (!success) { + revert PrimaryContractProxyInitFailureError(returnedData); + } + } + + function _deployAndInitializeSecondaryContractProxy( + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address primaryContractAddress + ) internal returns (address secondaryContractAddress) { + /* deploy the secondary contract proxy with the primaryContractGeneratedSalt */ + secondaryContractAddress = Clones.cloneDeterministic( + secondaryContractDeploymentInit.implementationContract, + keccak256(abi.encodePacked(primaryContractAddress)) + ); + + /** + * If `addPrimaryContractAddress` is `true`, the following will be appended to the `initializationCalldata`: + * - The primary contract address + * - `extraInitialisationBytes` + */ + bytes + memory secondaryInitializationBytes = secondaryContractDeploymentInit + .initializationCalldata; + + if (secondaryContractDeploymentInit.addPrimaryContractAddress) { + secondaryInitializationBytes = abi.encodePacked( + secondaryInitializationBytes, + abi.encode(primaryContractAddress), + secondaryContractDeploymentInit.extraInitializationParams + ); + } + + /* initialize the primary contract proxy */ + (bool success, bytes memory returnedData) = secondaryContractAddress + .call{value: msg.value}(secondaryInitializationBytes); + if (!success) { + revert SecondaryContractProxyInitFailureError(returnedData); + } + } + + function _generatePrimaryContractSalt( + PrimaryContractDeployment calldata primaryContractDeployment, + SecondaryContractDeployment calldata secondaryContractDeployment, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) internal pure virtual returns (bytes32 primaryContractGeneratedSalt) { + /* generate salt for the primary contract + * the salt is generated by hashing the following elements: + * - the salt + * - the secondary contract bytecode + * - the secondary addPrimaryContractAddress boolean + * - the secondary extraConstructorParams + * - the postDeploymentModule address + * - the postDeploymentModuleCalldata + * + */ + primaryContractGeneratedSalt = keccak256( + abi.encode( + primaryContractDeployment.salt, + secondaryContractDeployment.creationBytecode, + secondaryContractDeployment.addPrimaryContractAddress, + secondaryContractDeployment.extraConstructorParams, + postDeploymentModule, + postDeploymentModuleCalldata + ) + ); + } + + function _generatePrimaryContractProxySalt( + PrimaryContractDeploymentInit calldata primaryContractDeploymentInit, + SecondaryContractDeploymentInit + calldata secondaryContractDeploymentInit, + address postDeploymentModule, + bytes calldata postDeploymentModuleCalldata + ) + internal + pure + virtual + returns (bytes32 primaryContractProxyGeneratedSalt) + { + /** + * Generate the salt for the primary contract + * The salt is generated by hashing the following elements: + * - the salt + * - the secondary implementation contract address + * - the secondary contract addPrimaryContractAddress boolean + * - the secondary contract initialization calldata + * - the secondary contract extra initialization params (if any) + * - the postDeploymentModule address + * - the callda to the post deployment module + * + */ + primaryContractProxyGeneratedSalt = keccak256( + abi.encode( + primaryContractDeploymentInit.salt, + secondaryContractDeploymentInit.implementationContract, + secondaryContractDeploymentInit.initializationCalldata, + secondaryContractDeploymentInit.addPrimaryContractAddress, + secondaryContractDeploymentInit.extraInitializationParams, + postDeploymentModule, + postDeploymentModuleCalldata + ) + ); + } +} diff --git a/contracts/LSP23MultiChainDeployment/modules/UniversalProfileInitPostDeploymentModule.sol b/contracts/LSP23LinkedContractsDeployment/modules/UniversalProfileInitPostDeploymentModule.sol similarity index 100% rename from contracts/LSP23MultiChainDeployment/modules/UniversalProfileInitPostDeploymentModule.sol rename to contracts/LSP23LinkedContractsDeployment/modules/UniversalProfileInitPostDeploymentModule.sol diff --git a/contracts/LSP23MultiChainDeployment/IOwnerControlledContractDeployer.sol b/contracts/LSP23MultiChainDeployment/IOwnerControlledContractDeployer.sol deleted file mode 100644 index 54b00cc6e..000000000 --- a/contracts/LSP23MultiChainDeployment/IOwnerControlledContractDeployer.sol +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -interface IOwnerControlledContractDeployer { - event DeployedContracts( - address indexed controlledContract, - address indexed ownerContract, - ControlledContractDeployment controlledContractDeployment, - OwnerContractDeployment ownerContractDeployment, - address postDeploymentModule, - bytes postDeploymentModuleCalldata - ); - - event DeployedERC1167Proxies( - address indexed controlledContract, - address indexed ownerContract, - ControlledContractDeploymentInit controlledContractDeploymentInit, - OwnerContractDeploymentInit ownerContractDeploymentInit, - address postDeploymentModule, - bytes postDeploymentModuleCalldata - ); - - /** - * @param salt A unique value used to ensure each created proxies are unique. (Can be used to deploy the contract at a desired address.) - * @param fundingAmount The value to be sent with the deployment transaction. - * @param creationBytecode The bytecode of the contract with the constructor params. - */ - struct ControlledContractDeployment { - bytes32 salt; - uint256 fundingAmount; - bytes creationBytecode; - } - - /** - * @param fundingAmount The value to be sent with the deployment transaction. - * @param creationBytecode The constructor + runtime bytecode (without the controlled contract's address as param) - * @param addControlledContractAddress If set to `true`, this will append the controlled contract's address + the `extraConstructorParams` to the `creationBytecode`. - * @param extraConstructorParams Params to be appended to the `creationBytecode` (after the controlled contract address) if `addControlledContractAddress` is set to `true`. - */ - struct OwnerContractDeployment { - uint256 fundingAmount; - bytes creationBytecode; - bool addControlledContractAddress; - bytes extraConstructorParams; - } - - /** - * @param salt A unique value used to ensure each created proxies are unique. (Can be used to deploy the contract at a desired address.) - * @param fundingAmount The value to be sent with the deployment transaction. - * @param implementationContract The address of the contract that will be used as a base contract for the proxy. - * @param initializationCalldata The calldata used to initialise the contract. (initialization should be similar to a constructor in a normal contract.) - */ - struct ControlledContractDeploymentInit { - bytes32 salt; - uint256 fundingAmount; - address implementationContract; - bytes initializationCalldata; - } - - /** - * @param fundingAmount The value to be sent with the deployment transaction. - * @param implementationContract The address of the contract that will be used as a base contract for the proxy. - * @param initializationCalldata The first part of the initialisation calldata, everything before the controlled contract address. - * @param addControlledContractAddress If set to `true`, this will append the controlled contract's address + the `extraInitializationParams` to the `initializationCalldata`. - * @param extraInitializationParams Params to be appended to the `initializationCalldata` (after the controlled contract address) if `addControlledContractAddress` is set to `true` - */ - struct OwnerContractDeploymentInit { - uint256 fundingAmount; - address implementationContract; - bytes initializationCalldata; - bool addControlledContractAddress; - bytes extraInitializationParams; - } - - /** - * @dev Deploys a contract and its owner contract. - * @notice Contracts deployed. Contract Address: `controlledContractAddress`. Owner Contract Address: `ownerContractAddress` - * - * @param controlledContractDeployment Contains the needed parameter to deploy a contract. (`salt`, `fundingAmount`, `creationBytecode`) - * @param ownerContractDeployment Contains the needed parameter to deploy the owner contract. (`fundingAmount`, `creationBytecode`, `addControlledContractAddress`, `extraConstructorParams`) - * @param postDeploymentModule The module to be executed after deployment - * @param postDeploymentModuleCalldata The data to be passed to the post deployment module - * - * @return controlledContractAddress The address of the deployed controlled contract. - * @return ownerContractAddress The address of the deployed owner contract. - */ - function deployContracts( - ControlledContractDeployment calldata controlledContractDeployment, - OwnerContractDeployment calldata ownerContractDeployment, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - external - payable - returns ( - address controlledContractAddress, - address ownerContractAddress - ); - - /** - * @dev Deploys proxies of a contract and its owner contract - * @notice Contract proxies deployed. Contract Proxy Address: `controlledContractAddress`. Owner Contract Proxy Address: `ownerContractAddress` - * - * @param controlledContractDeploymentInit Contains the needed parameter to deploy a proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`) - * @param ownerContractDeploymentInit Contains the needed parameter to deploy the owner proxy contract. (`fundingAmount`, `implementationContract`, `addControlledContractAddress`, `initializationCalldata`, `extraInitializationParams`) - * @param postDeploymentModule The module to be executed after deployment. - * @param postDeploymentModuleCalldata The data to be passed to the post deployment module. - * - * @return controlledContractAddress The address of the deployed controlled contract proxy - * @return ownerContractAddress The address of the deployed owner contract proxy - */ - function deployERC1167Proxies( - ControlledContractDeploymentInit - calldata controlledContractDeploymentInit, - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - external - payable - returns ( - address controlledContractAddress, - address ownerContractAddress - ); - - /** - * @dev Computes the addresses of the controlled and owner contracts to be created - * - * @param controlledContractDeployment Contains the needed parameter to deploy a contract. (`salt`, `fundingAmount`, `creationBytecode`) - * @param ownerContractDeployment Contains the needed parameter to deploy the owner contract. (`fundingAmount`, `creationBytecode`, `addControlledContractAddress`, `extraConstructorParams`) - * @param postDeploymentModule The module to be executed after deployment - * @param postDeploymentModuleCalldata The data to be passed to the post deployment module - * - * @return controlledContractAddress The address of the deployed controlled contract. - * @return ownerContractAddress The address of the deployed owner contract. - */ - function computeAddresses( - ControlledContractDeployment calldata controlledContractDeployment, - OwnerContractDeployment calldata ownerContractDeployment, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - external - view - returns ( - address controlledContractAddress, - address ownerContractAddress - ); - - /** - * @dev Computes the addresses of the controlled and owner contract proxies to be created. - * - * @param controlledContractDeploymentInit Contains the needed parameter to deploy a proxy contract. (`salt`, `fundingAmount`, `implementationContract`, `initializationCalldata`) - * @param ownerContractDeploymentInit Contains the needed parameter to deploy the owner proxy contract. (`fundingAmount`, `implementationContract`, `addControlledContractAddress`, `initializationCalldata`, `extraInitializationParams`) - * @param postDeploymentModule The module to be executed after deployment. - * @param postDeploymentModuleCalldata The data to be passed to the post deployment module. - * - * @return controlledContractAddress The address of the deployed controlled contract proxy - * @return ownerContractAddress The address of the deployed owner contract proxy - */ - function computeERC1167Addresses( - ControlledContractDeploymentInit - calldata controlledContractDeploymentInit, - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - external - view - returns ( - address controlledContractAddress, - address ownerContractAddress - ); -} diff --git a/contracts/LSP23MultiChainDeployment/OwnerControlledContractDeployer.sol b/contracts/LSP23MultiChainDeployment/OwnerControlledContractDeployer.sol deleted file mode 100644 index 85955a495..000000000 --- a/contracts/LSP23MultiChainDeployment/OwnerControlledContractDeployer.sol +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; -import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; -import {IPostDeploymentModule} from "./IPostDeploymentModule.sol"; -import { - IOwnerControlledContractDeployer -} from "./IOwnerControlledContractDeployer.sol"; -import { - InvalidValueSum, - ControlledContractProxyInitFailureError, - OwnerContractProxyInitFailureError -} from "./LSP23Errors.sol"; - -contract OwnerControlledContractDeployer is IOwnerControlledContractDeployer { - /** - * @inheritdoc IOwnerControlledContractDeployer - */ - function deployContracts( - ControlledContractDeployment calldata controlledContractDeployment, - OwnerContractDeployment calldata ownerContractDeployment, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - public - payable - returns ( - address controlledContractAddress, - address ownerContractAddress - ) - { - /* check that the msg.value is equal to the sum of the values of the controlled and owner contracts */ - if ( - msg.value != - controlledContractDeployment.fundingAmount + - ownerContractDeployment.fundingAmount - ) { - revert InvalidValueSum(); - } - - controlledContractAddress = _deployControlledContract( - controlledContractDeployment, - ownerContractDeployment, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - ownerContractAddress = _deployOwnerContract( - ownerContractDeployment, - controlledContractAddress - ); - - emit DeployedContracts( - controlledContractAddress, - ownerContractAddress, - controlledContractDeployment, - ownerContractDeployment, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - /* execute the post deployment module logic in the postDeploymentModule */ - IPostDeploymentModule(postDeploymentModule).executePostDeployment( - controlledContractAddress, - ownerContractAddress, - postDeploymentModuleCalldata - ); - } - - /** - * @inheritdoc IOwnerControlledContractDeployer - */ - function deployERC1167Proxies( - ControlledContractDeploymentInit - calldata controlledContractDeploymentInit, - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - public - payable - returns ( - address controlledContractAddress, - address ownerContractAddress - ) - { - /* check that the msg.value is equal to the sum of the values of the controlled and owner contracts */ - if ( - msg.value != - controlledContractDeploymentInit.fundingAmount + - ownerContractDeploymentInit.fundingAmount - ) { - revert InvalidValueSum(); - } - - /* deploy the controlled contract proxy with the controlledContractGeneratedSalt */ - controlledContractAddress = _deployAndInitializeControlledContractProxy( - controlledContractDeploymentInit, - ownerContractDeploymentInit, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - /* deploy the owner contract proxy */ - ownerContractAddress = _deployAndInitializeOwnerContractProxy( - ownerContractDeploymentInit, - controlledContractAddress - ); - - emit DeployedERC1167Proxies( - controlledContractAddress, - ownerContractAddress, - controlledContractDeploymentInit, - ownerContractDeploymentInit, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - /* execute the post deployment logic in the postDeploymentModule */ - IPostDeploymentModule(postDeploymentModule).executePostDeployment( - controlledContractAddress, - ownerContractAddress, - postDeploymentModuleCalldata - ); - } - - /** - * @inheritdoc IOwnerControlledContractDeployer - */ - function computeAddresses( - ControlledContractDeployment calldata controlledContractDeployment, - OwnerContractDeployment calldata ownerContractDeployment, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - public - view - returns ( - address controlledContractAddress, - address ownerContractAddress - ) - { - bytes32 controlledContractGeneratedSalt = _generateControlledContractSalt( - controlledContractDeployment, - ownerContractDeployment, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - controlledContractAddress = Create2.computeAddress( - controlledContractGeneratedSalt, - keccak256(controlledContractDeployment.creationBytecode) - ); - - bytes memory ownerContractByteCodeWithAllParams; - if (ownerContractDeployment.addControlledContractAddress) { - ownerContractByteCodeWithAllParams = abi.encodePacked( - ownerContractDeployment.creationBytecode, - abi.encode(controlledContractAddress), - ownerContractDeployment.extraConstructorParams - ); - } else { - ownerContractByteCodeWithAllParams = ownerContractDeployment - .creationBytecode; - } - - ownerContractAddress = Create2.computeAddress( - keccak256(abi.encodePacked(controlledContractAddress)), - keccak256(ownerContractByteCodeWithAllParams) - ); - } - - /** - * @inheritdoc IOwnerControlledContractDeployer - */ - function computeERC1167Addresses( - ControlledContractDeploymentInit - calldata controlledContractDeploymentInit, - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - public - view - returns ( - address controlledContractAddress, - address ownerContractAddress - ) - { - bytes32 controlledContractGeneratedSalt = _generateControlledProxyContractSalt( - controlledContractDeploymentInit, - ownerContractDeploymentInit, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - controlledContractAddress = Clones.predictDeterministicAddress( - controlledContractDeploymentInit.implementationContract, - controlledContractGeneratedSalt - ); - - ownerContractAddress = Clones.predictDeterministicAddress( - ownerContractDeploymentInit.implementationContract, - keccak256(abi.encodePacked(controlledContractAddress)) - ); - } - - function _deployControlledContract( - ControlledContractDeployment calldata controlledContractDeployment, - OwnerContractDeployment calldata ownerContractDeployment, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) internal returns (address controlledContractAddress) { - bytes32 controlledContractGeneratedSalt = _generateControlledContractSalt( - controlledContractDeployment, - ownerContractDeployment, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - /* deploy the controlled contract */ - controlledContractAddress = Create2.deploy( - controlledContractDeployment.fundingAmount, - controlledContractGeneratedSalt, - controlledContractDeployment.creationBytecode - ); - } - - function _deployOwnerContract( - OwnerContractDeployment calldata ownerContractDeployment, - address controlledContractAddress - ) internal returns (address ownerContractAddress) { - /** - * If `addControlledContractAddress` is `true`, the following will be appended to the constructor params: - * - The controlled contract address - * - `extraConstructorParams` - */ - bytes memory ownerContractByteCode = ownerContractDeployment - .creationBytecode; - - if (ownerContractDeployment.addControlledContractAddress) { - ownerContractByteCode = abi.encodePacked( - ownerContractByteCode, - abi.encode(controlledContractAddress), - ownerContractDeployment.extraConstructorParams - ); - } - - /* Here owner refers to the future owner of the controlled contract at the end of the transaction */ - ownerContractAddress = Create2.deploy( - ownerContractDeployment.fundingAmount, - keccak256(abi.encodePacked(controlledContractAddress)), - ownerContractByteCode - ); - } - - function _deployAndInitializeControlledContractProxy( - ControlledContractDeploymentInit - calldata controlledContractDeploymentInit, - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) internal returns (address controlledContractAddress) { - bytes32 controlledContractGeneratedSalt = _generateControlledProxyContractSalt( - controlledContractDeploymentInit, - ownerContractDeploymentInit, - postDeploymentModule, - postDeploymentModuleCalldata - ); - - /* deploy the controlled contract proxy with the controlledContractGeneratedSalt */ - controlledContractAddress = Clones.cloneDeterministic( - controlledContractDeploymentInit.implementationContract, - controlledContractGeneratedSalt - ); - - /* initialize the controlled contract proxy */ - (bool success, bytes memory returnedData) = controlledContractAddress - .call{value: msg.value}( - controlledContractDeploymentInit.initializationCalldata - ); - if (!success) { - revert ControlledContractProxyInitFailureError(returnedData); - } - } - - function _deployAndInitializeOwnerContractProxy( - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address controlledContractAddress - ) internal returns (address ownerContractAddress) { - /* deploy the controlled contract proxy with the controlledContractGeneratedSalt */ - ownerContractAddress = Clones.cloneDeterministic( - ownerContractDeploymentInit.implementationContract, - keccak256(abi.encodePacked(controlledContractAddress)) - ); - - /** - * If `addControlledContractAddress` is `true`, the following will be appended to the `initializationCalldata`: - * - The controlled contract address - * - `extraInitialisationBytes` - */ - bytes memory ownerInitializationBytes = ownerContractDeploymentInit - .initializationCalldata; - - if (ownerContractDeploymentInit.addControlledContractAddress) { - ownerInitializationBytes = abi.encodePacked( - ownerInitializationBytes, - abi.encode(controlledContractAddress), - ownerContractDeploymentInit.extraInitializationParams - ); - } - - /* initialize the controlled contract proxy */ - (bool success, bytes memory returnedData) = ownerContractAddress.call{ - value: msg.value - }(ownerInitializationBytes); - if (!success) { - revert OwnerContractProxyInitFailureError(returnedData); - } - } - - function _generateControlledContractSalt( - ControlledContractDeployment calldata controlledContractDeployment, - OwnerContractDeployment calldata ownerContractDeployment, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) internal pure virtual returns (bytes32 controlledContractGeneratedSalt) { - /* generate salt for the controlled contract - * the salt is generated by hashing the following elements: - * - the salt - * - the owner contract bytecode - * - the owner addControlledContractAddress boolean - * - the owner extraConstructorParams - * - the postDeploymentModule address - * - the postDeploymentModuleCalldata - * - */ - controlledContractGeneratedSalt = keccak256( - abi.encode( - controlledContractDeployment.salt, - controlledContractDeployment.creationBytecode, - ownerContractDeployment.creationBytecode, - ownerContractDeployment.addControlledContractAddress, - ownerContractDeployment.extraConstructorParams, - postDeploymentModule, - postDeploymentModuleCalldata - ) - ); - } - - function _generateControlledProxyContractSalt( - ControlledContractDeploymentInit - calldata controlledContractDeploymentInit, - OwnerContractDeploymentInit calldata ownerContractDeploymentInit, - address postDeploymentModule, - bytes calldata postDeploymentModuleCalldata - ) - internal - pure - virtual - returns (bytes32 controlledProxyContractGeneratedSalt) - { - /** - * Generate the salt for the controlled contract - * The salt is generated by hashing the following elements: - * - the salt - * - the owner implementation contract address - * - the owner contract addControlledContractAddress boolean - * - the owner contract initialization calldata - * - the owner contract extra initialization params (if any) - * - the postDeploymentModule address - * - the callda to the post deployment module - * - */ - controlledProxyContractGeneratedSalt = keccak256( - abi.encode( - controlledContractDeploymentInit.salt, - ownerContractDeploymentInit.implementationContract, - ownerContractDeploymentInit.initializationCalldata, - ownerContractDeploymentInit.addControlledContractAddress, - ownerContractDeploymentInit.extraInitializationParams, - postDeploymentModule, - postDeploymentModuleCalldata - ) - ); - } -} diff --git a/hardhat.config.ts b/hardhat.config.ts index 1e3944771..9d69635e0 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -150,6 +150,7 @@ const config: HardhatUserConfig = { // ------------------ 'Create2Factory', 'LSP16UniversalFactory', + 'LinkedContractsFactory', ], // Whether to include the TypeChain factories or not. // If this is enabled, you need to run the TypeChain files through the TypeScript compiler before shipping to the registry. diff --git a/package-lock.json b/package-lock.json index 4aab040ca..b2bbdebf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@lukso/lsp-smart-contracts", - "version": "0.11.0-rc.0", + "version": "0.11.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@lukso/lsp-smart-contracts", - "version": "0.11.0-rc.0", + "version": "0.11.0-rc.1", "license": "Apache-2.0", "dependencies": { "@erc725/smart-contracts": "^5.1.0", diff --git a/package.json b/package.json index 94cf5f5c0..2ac205c53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lukso/lsp-smart-contracts", - "version": "0.11.0-rc.0", + "version": "0.11.0-rc.1", "description": "The reference implementation for universal profiles smart contracts", "directories": { "test": "test" diff --git a/tests/LSP23MultiChainDeployment/LSP23MultiChainDeployment.test.ts b/tests/LSP23MultiChainDeployment/LSP23MultiChainDeployment.test.ts index 7a808074a..b9f27aca8 100644 --- a/tests/LSP23MultiChainDeployment/LSP23MultiChainDeployment.test.ts +++ b/tests/LSP23MultiChainDeployment/LSP23MultiChainDeployment.test.ts @@ -1,6 +1,7 @@ import { ethers } from 'hardhat'; import { expect } from 'chai'; -import { OwnerControlledContractDeployer } from '../../typechain-types'; + +import { LinkedContractsFactory } from '../../typechain-types'; import { ERC725YDataKeys } from '../../constants.ts'; import { calculateProxiesAddresses } from './helpers'; @@ -14,11 +15,9 @@ describe('UniversalProfileDeployer', function () { const UniversalProfileInitFactory = await ethers.getContractFactory('UniversalProfileInit'); const universalProfileInit = await UniversalProfileInitFactory.deploy(); - const OwnerControlledContractDeployerFactory = await ethers.getContractFactory( - 'OwnerControlledContractDeployer', - ); + const LinkedContractsFactoryFactory = await ethers.getContractFactory('LinkedContractsFactory'); - const ownerControlledContractDeployer = await OwnerControlledContractDeployerFactory.deploy(); + const LinkedContractsFactory = await LinkedContractsFactoryFactory.deploy(); const UPDelegatorPostDeploymentManagerFactory = await ethers.getContractFactory( 'UniversalProfileInitPostDeploymentModule', @@ -28,7 +27,7 @@ describe('UniversalProfileDeployer', function () { const salt = ethers.utils.randomBytes(32); - const ownerControlledDeploymentInit: OwnerControlledContractDeployer.ControlledContractDeploymentInitStruct = + const primaryContractDeploymentInit: LinkedContractsFactory.PrimaryContractDeploymentInitStruct = { salt, fundingAmount: 0, @@ -38,13 +37,14 @@ describe('UniversalProfileDeployer', function () { ]), }; - const ownerDeploymentInit: OwnerControlledContractDeployer.OwnerContractDeploymentInitStruct = { - fundingAmount: 0, - implementationContract: keyManagerInit.address, - addControlledContractAddress: true, - initializationCalldata: '0xc4d66de8', - extraInitializationParams: '0x', - }; + const secondaryContractDeploymentInit: LinkedContractsFactory.SecondaryContractDeploymentInitStruct = + { + fundingAmount: 0, + implementationContract: keyManagerInit.address, + addPrimaryContractAddress: true, + initializationCalldata: '0xc4d66de8', + extraInitializationParams: '0x', + }; const allPermissionsSignerPermissionsKey = '0x4b80742de2bf82acb3630000' + allPermissionsSigner.address.slice(2); @@ -91,16 +91,16 @@ describe('UniversalProfileDeployer', function () { // get the address of the UP and the KeyManager contracts const [upAddress, keyManagerAddress] = - await ownerControlledContractDeployer.callStatic.deployERC1167Proxies( - ownerControlledDeploymentInit, - ownerDeploymentInit, + await LinkedContractsFactory.callStatic.deployERC1167Proxies( + primaryContractDeploymentInit, + secondaryContractDeploymentInit, upPostDeploymentModule.address, encodedBytes, ); - await ownerControlledContractDeployer.deployERC1167Proxies( - ownerControlledDeploymentInit, - ownerDeploymentInit, + await LinkedContractsFactory.deployERC1167Proxies( + primaryContractDeploymentInit, + secondaryContractDeploymentInit, upPostDeploymentModule.address, encodedBytes, ); @@ -112,23 +112,23 @@ describe('UniversalProfileDeployer', function () { const keyManagerProxyOwner = await keyManagerProxy.target(); const [expectedUpProxyAddress, expectedKeyManagerProxyAddress] = - await ownerControlledContractDeployer.computeERC1167Addresses( - ownerControlledDeploymentInit, - ownerDeploymentInit, + await LinkedContractsFactory.computeERC1167Addresses( + primaryContractDeploymentInit, + secondaryContractDeploymentInit, upPostDeploymentModule.address, encodedBytes, ); const [calculatedUpProxyAddress, calculatedKMProxyAddress] = await calculateProxiesAddresses( - ownerControlledDeploymentInit.salt, - ownerControlledDeploymentInit.implementationContract, - ownerDeploymentInit.implementationContract, - ownerDeploymentInit.initializationCalldata, - ownerDeploymentInit.addControlledContractAddress, - ownerDeploymentInit.extraInitializationParams, + primaryContractDeploymentInit.salt, + primaryContractDeploymentInit.implementationContract, + secondaryContractDeploymentInit.implementationContract, + secondaryContractDeploymentInit.initializationCalldata, + secondaryContractDeploymentInit.addPrimaryContractAddress, + secondaryContractDeploymentInit.extraInitializationParams, upPostDeploymentModule.address, encodedBytes, - ownerControlledContractDeployer.address, + LinkedContractsFactory.address, ); expect(upAddress).to.equal(expectedUpProxyAddress);