From 87762126198589ae793b71937bb943c3d30edf23 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 25 Feb 2024 18:10:29 +0800 Subject: [PATCH 1/5] feat(protocol): update DeployOnL1 script based on `Ownable2StepUpgradeable` changes --- .../protocol/contracts/libs/LibDeploy.sol | 32 ++++++++++++ packages/protocol/script/DeployOnL1.s.sol | 49 +++++++++++++------ packages/protocol/test/DeployCapability.sol | 18 ++++++- 3 files changed, 83 insertions(+), 16 deletions(-) diff --git a/packages/protocol/contracts/libs/LibDeploy.sol b/packages/protocol/contracts/libs/LibDeploy.sol index 1965bc3ef70..007bb9a9969 100644 --- a/packages/protocol/contracts/libs/LibDeploy.sol +++ b/packages/protocol/contracts/libs/LibDeploy.sol @@ -16,6 +16,8 @@ pragma solidity 0.8.24; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; +import "../L1/gov/TaikoTimelockController.sol"; /// @title LibDeploy /// @dev Provides utilities for deploying contracts @@ -37,4 +39,34 @@ library LibDeploy { OwnableUpgradeable(proxy).transferOwnership(owner); } } + + function deployERC1967Proxy( + address impl, + address owner, + bytes memory data, + address timelock + ) + internal + returns (address proxy) + { + proxy = deployERC1967Proxy(impl, owner, data); + if ( + timelock != address(0) && owner != OwnableUpgradeable(proxy).owner() + && owner == timelock + ) { + acceptProxyOwnershipByTimelock(proxy, timelock); + } + } + + function acceptProxyOwnershipByTimelock(address proxy, address timelock) internal { + bytes32 salt = bytes32(block.timestamp); + + bytes memory payload = abi.encodeCall(Ownable2StepUpgradeable(proxy).acceptOwnership, ()); + + TaikoTimelockController timelockController = TaikoTimelockController(payable(timelock)); + + timelockController.schedule(proxy, 0, payload, bytes32(0), salt, 0); + + timelockController.execute(proxy, 0, payload, bytes32(0), salt); + } } diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index ac09cb47d28..1f81dbac079 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -200,21 +200,22 @@ contract DeployOnL1 is DeployCapability { // Setup time lock roles TaikoTimelockController _timelock = TaikoTimelockController(payable(timelock)); // Only the governer can make proposals after holders voting. + _timelock.grantRole(_timelock.PROPOSER_ROLE(), msg.sender); _timelock.grantRole(_timelock.PROPOSER_ROLE(), governor); _timelock.grantRole(_timelock.PROPOSER_ROLE(), securityCouncil); // Granting address(0) the executor role to allow open executation. + _timelock.grantRole(_timelock.EXECUTOR_ROLE(), msg.sender); _timelock.grantRole(_timelock.EXECUTOR_ROLE(), address(0)); // Cancelling is not supported by the implementation by default, therefore, no need to set // up this role. // _timelock.grantRole(_timelock.CANCELLER_ROLE(), securityCouncil); - _timelock.grantRole(_timelock.TIMELOCK_ADMIN_ROLE(), securityCouncil); + _timelock.grantRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), address(this)); - _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); - _timelock.transferOwnership(securityCouncil); + LibDeploy.acceptProxyOwnershipByTimelock(taikoToken, timelock); // Deploy Bridging contracts deployProxy({ @@ -222,7 +223,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new SignalService()), data: abi.encodeCall(SignalService.init, (sharedAddressManager)), registerTo: sharedAddressManager, - owner: address(0) + owner: address(0), + timelock: timelock }); deployProxy({ @@ -230,7 +232,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new Bridge()), data: abi.encodeCall(Bridge.init, (sharedAddressManager)), registerTo: sharedAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); console2.log("------------------------------------------"); @@ -248,7 +251,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new ERC20Vault()), data: abi.encodeCall(BaseVault.init, (sharedAddressManager)), registerTo: sharedAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); deployProxy({ @@ -256,7 +260,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new ERC721Vault()), data: abi.encodeCall(BaseVault.init, (sharedAddressManager)), registerTo: sharedAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); deployProxy({ @@ -264,7 +269,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new ERC1155Vault()), data: abi.encodeCall(BaseVault.init, (sharedAddressManager)), registerTo: sharedAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); console2.log("------------------------------------------"); @@ -309,7 +315,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new TaikoL1()), data: abi.encodeCall(TaikoL1.init, (rollupAddressManager, vm.envBytes32("L2_GENESIS_HASH"))), registerTo: rollupAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); deployProxy({ @@ -317,7 +324,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new AssignmentHook()), data: abi.encodeCall(AssignmentHook.init, (rollupAddressManager)), registerTo: address(0), - owner: timelock + owner: timelock, + timelock: timelock }); address tierProvider; @@ -332,7 +340,8 @@ contract DeployOnL1 is DeployCapability { impl: tierProvider, data: abi.encodeCall(TestnetTierProvider.init, ()), registerTo: rollupAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); deployProxy({ @@ -340,7 +349,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new GuardianVerifier()), data: abi.encodeCall(GuardianVerifier.init, (rollupAddressManager)), registerTo: rollupAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); deployProxy({ @@ -348,7 +358,8 @@ contract DeployOnL1 is DeployCapability { impl: address(new SgxVerifier()), data: abi.encodeCall(SgxVerifier.init, (rollupAddressManager)), registerTo: rollupAddressManager, - owner: timelock + owner: timelock, + timelock: timelock }); address guardianProver = deployProxy({ @@ -356,13 +367,15 @@ contract DeployOnL1 is DeployCapability { impl: address(new GuardianProver()), data: abi.encodeCall(GuardianProver.init, (rollupAddressManager)), registerTo: rollupAddressManager, - owner: address(0) + owner: address(0), + timelock: timelock }); address[] memory guardians = vm.envAddress("GUARDIAN_PROVERS", ","); uint8 minGuardians = uint8(vm.envUint("MIN_GUARDIANS")); GuardianProver(guardianProver).setGuardians(guardians, minGuardians); GuardianProver(guardianProver).transferOwnership(timelock); + LibDeploy.acceptProxyOwnershipByTimelock(guardianProver, timelock); // No need to proxy these, because they are 3rd party. If we want to modify, we simply // change the registerAddress("automata_dcap_attestation", address(attestation)); @@ -378,6 +391,14 @@ contract DeployOnL1 is DeployCapability { register( rollupAddressManager, "automata_dcap_attestation", address(automateDcapV3Attestation) ); + + // Revoke granted roles from the deployer + TaikoTimelockController _timelock = TaikoTimelockController(payable(timelock)); + _timelock.transferOwnership(securityCouncil); // Need the securityCouncil acccount to call + // the acceptOwnership() manually + _timelock.revokeRole(_timelock.PROPOSER_ROLE(), msg.sender); + _timelock.revokeRole(_timelock.EXECUTOR_ROLE(), msg.sender); + _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); } function deployAuxContracts() private { diff --git a/packages/protocol/test/DeployCapability.sol b/packages/protocol/test/DeployCapability.sol index 368112f62aa..ad0d6dcee30 100644 --- a/packages/protocol/test/DeployCapability.sol +++ b/packages/protocol/test/DeployCapability.sol @@ -20,12 +20,13 @@ abstract contract DeployCapability is Script { address impl, bytes memory data, address registerTo, - address owner + address owner, + address timelock ) internal returns (address proxy) { - proxy = LibDeploy.deployERC1967Proxy(impl, owner, data); + proxy = LibDeploy.deployERC1967Proxy(impl, owner, data, timelock); if (registerTo != address(0)) { AddressManager(registerTo).setAddress( @@ -46,6 +47,19 @@ abstract contract DeployCapability is Script { ); } + function deployProxy( + string memory name, + address impl, + bytes memory data, + address registerTo, + address owner + ) + internal + returns (address proxy) + { + return deployProxy(name, impl, data, registerTo, owner, address(0)); + } + function deployProxy( string memory name, address impl, From 2273f30022213a1485f29721105ddf7fe5ca91bf Mon Sep 17 00:00:00 2001 From: David Date: Sun, 25 Feb 2024 18:12:23 +0800 Subject: [PATCH 2/5] feat(protocol): update DeployOnL1 script based on `Ownable2StepUpgradeable` changes --- packages/protocol/script/DeployOnL1.s.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index 1f81dbac079..e45aa15fc7c 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -394,8 +394,7 @@ contract DeployOnL1 is DeployCapability { // Revoke granted roles from the deployer TaikoTimelockController _timelock = TaikoTimelockController(payable(timelock)); - _timelock.transferOwnership(securityCouncil); // Need the securityCouncil acccount to call - // the acceptOwnership() manually + _timelock.transferOwnership(securityCouncil); _timelock.revokeRole(_timelock.PROPOSER_ROLE(), msg.sender); _timelock.revokeRole(_timelock.EXECUTOR_ROLE(), msg.sender); _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); From 051a574dc74b74cf2b6fb0479c02e23c616f613d Mon Sep 17 00:00:00 2001 From: David Date: Sun, 25 Feb 2024 20:50:22 +0800 Subject: [PATCH 3/5] feat: updates based on feedbacks --- .../protocol/contracts/libs/LibDeploy.sol | 21 +++++++------- packages/protocol/script/DeployOnL1.s.sol | 29 +++++++++---------- packages/protocol/test/DeployCapability.sol | 6 ++-- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/packages/protocol/contracts/libs/LibDeploy.sol b/packages/protocol/contracts/libs/LibDeploy.sol index 007bb9a9969..bad80e786ca 100644 --- a/packages/protocol/contracts/libs/LibDeploy.sol +++ b/packages/protocol/contracts/libs/LibDeploy.sol @@ -44,29 +44,30 @@ library LibDeploy { address impl, address owner, bytes memory data, - address timelock + TimelockControllerUpgradeable timelock ) internal returns (address proxy) { proxy = deployERC1967Proxy(impl, owner, data); if ( - timelock != address(0) && owner != OwnableUpgradeable(proxy).owner() - && owner == timelock + address(timelock) != address(0) && owner != OwnableUpgradeable(proxy).owner() + && owner == address(timelock) ) { acceptProxyOwnershipByTimelock(proxy, timelock); } } - function acceptProxyOwnershipByTimelock(address proxy, address timelock) internal { + function acceptProxyOwnershipByTimelock( + address proxy, + TimelockControllerUpgradeable timelock + ) + internal + { bytes32 salt = bytes32(block.timestamp); - bytes memory payload = abi.encodeCall(Ownable2StepUpgradeable(proxy).acceptOwnership, ()); - TaikoTimelockController timelockController = TaikoTimelockController(payable(timelock)); - - timelockController.schedule(proxy, 0, payload, bytes32(0), salt, 0); - - timelockController.execute(proxy, 0, payload, bytes32(0), salt); + timelock.schedule(proxy, 0, payload, bytes32(0), salt, 0); + timelock.execute(proxy, 0, payload, bytes32(0), salt); } } diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index e45aa15fc7c..2e001dee0c2 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -215,7 +215,7 @@ contract DeployOnL1 is DeployCapability { _timelock.grantRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), address(this)); - LibDeploy.acceptProxyOwnershipByTimelock(taikoToken, timelock); + LibDeploy.acceptProxyOwnershipByTimelock(taikoToken, _timelock); // Deploy Bridging contracts deployProxy({ @@ -223,8 +223,7 @@ contract DeployOnL1 is DeployCapability { impl: address(new SignalService()), data: abi.encodeCall(SignalService.init, (sharedAddressManager)), registerTo: sharedAddressManager, - owner: address(0), - timelock: timelock + owner: address(0) }); deployProxy({ @@ -233,7 +232,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(Bridge.init, (sharedAddressManager)), registerTo: sharedAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); console2.log("------------------------------------------"); @@ -252,7 +251,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(BaseVault.init, (sharedAddressManager)), registerTo: sharedAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); deployProxy({ @@ -261,7 +260,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(BaseVault.init, (sharedAddressManager)), registerTo: sharedAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); deployProxy({ @@ -270,7 +269,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(BaseVault.init, (sharedAddressManager)), registerTo: sharedAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); console2.log("------------------------------------------"); @@ -303,6 +302,7 @@ contract DeployOnL1 is DeployCapability { { addressNotNull(_sharedAddressManager, "sharedAddressManager"); addressNotNull(timelock, "timelock"); + TaikoTimelockController _timelock = TaikoTimelockController(payable(timelock)); rollupAddressManager = deployProxy({ name: "rollup_address_manager", @@ -316,7 +316,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(TaikoL1.init, (rollupAddressManager, vm.envBytes32("L2_GENESIS_HASH"))), registerTo: rollupAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); deployProxy({ @@ -325,7 +325,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(AssignmentHook.init, (rollupAddressManager)), registerTo: address(0), owner: timelock, - timelock: timelock + timelock: _timelock }); address tierProvider; @@ -341,7 +341,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(TestnetTierProvider.init, ()), registerTo: rollupAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); deployProxy({ @@ -350,7 +350,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(GuardianVerifier.init, (rollupAddressManager)), registerTo: rollupAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); deployProxy({ @@ -359,7 +359,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(SgxVerifier.init, (rollupAddressManager)), registerTo: rollupAddressManager, owner: timelock, - timelock: timelock + timelock: _timelock }); address guardianProver = deployProxy({ @@ -368,14 +368,14 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall(GuardianProver.init, (rollupAddressManager)), registerTo: rollupAddressManager, owner: address(0), - timelock: timelock + timelock: _timelock }); address[] memory guardians = vm.envAddress("GUARDIAN_PROVERS", ","); uint8 minGuardians = uint8(vm.envUint("MIN_GUARDIANS")); GuardianProver(guardianProver).setGuardians(guardians, minGuardians); GuardianProver(guardianProver).transferOwnership(timelock); - LibDeploy.acceptProxyOwnershipByTimelock(guardianProver, timelock); + LibDeploy.acceptProxyOwnershipByTimelock(guardianProver, _timelock); // No need to proxy these, because they are 3rd party. If we want to modify, we simply // change the registerAddress("automata_dcap_attestation", address(attestation)); @@ -393,7 +393,6 @@ contract DeployOnL1 is DeployCapability { ); // Revoke granted roles from the deployer - TaikoTimelockController _timelock = TaikoTimelockController(payable(timelock)); _timelock.transferOwnership(securityCouncil); _timelock.revokeRole(_timelock.PROPOSER_ROLE(), msg.sender); _timelock.revokeRole(_timelock.EXECUTOR_ROLE(), msg.sender); diff --git a/packages/protocol/test/DeployCapability.sol b/packages/protocol/test/DeployCapability.sol index ad0d6dcee30..48e22b83c23 100644 --- a/packages/protocol/test/DeployCapability.sol +++ b/packages/protocol/test/DeployCapability.sol @@ -21,7 +21,7 @@ abstract contract DeployCapability is Script { bytes memory data, address registerTo, address owner, - address timelock + TimelockControllerUpgradeable timelock ) internal returns (address proxy) @@ -57,7 +57,9 @@ abstract contract DeployCapability is Script { internal returns (address proxy) { - return deployProxy(name, impl, data, registerTo, owner, address(0)); + return deployProxy( + name, impl, data, registerTo, owner, TimelockControllerUpgradeable(payable(address(0))) + ); } function deployProxy( From 55131988882f2082ecb1d6c944a05ad38eb40ae9 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 25 Feb 2024 20:57:03 +0800 Subject: [PATCH 4/5] feat: updates based on feedbacks --- packages/protocol/contracts/libs/LibDeploy.sol | 4 ++-- packages/protocol/script/DeployOnL1.s.sol | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/protocol/contracts/libs/LibDeploy.sol b/packages/protocol/contracts/libs/LibDeploy.sol index bad80e786ca..934586bdfd6 100644 --- a/packages/protocol/contracts/libs/LibDeploy.sol +++ b/packages/protocol/contracts/libs/LibDeploy.sol @@ -51,8 +51,8 @@ library LibDeploy { { proxy = deployERC1967Proxy(impl, owner, data); if ( - address(timelock) != address(0) && owner != OwnableUpgradeable(proxy).owner() - && owner == address(timelock) + address(timelock) != address(0) + && address(timelock) != OwnableUpgradeable(proxy).owner() ) { acceptProxyOwnershipByTimelock(proxy, timelock); } diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index 2e001dee0c2..2a62ca28631 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -367,8 +367,7 @@ contract DeployOnL1 is DeployCapability { impl: address(new GuardianProver()), data: abi.encodeCall(GuardianProver.init, (rollupAddressManager)), registerTo: rollupAddressManager, - owner: address(0), - timelock: _timelock + owner: address(0) }); address[] memory guardians = vm.envAddress("GUARDIAN_PROVERS", ","); From 8494b8f4fbe8d4ab5d6ef9f190403680aa704181 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 25 Feb 2024 21:29:04 +0800 Subject: [PATCH 5/5] feat: updates based on feedbacks --- .../protocol/contracts/libs/LibDeploy.sol | 21 +++++-------------- packages/protocol/script/DeployOnL1.s.sol | 4 ++-- packages/protocol/test/DeployCapability.sol | 6 +++++- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/packages/protocol/contracts/libs/LibDeploy.sol b/packages/protocol/contracts/libs/LibDeploy.sol index 934586bdfd6..5a5a34af2ff 100644 --- a/packages/protocol/contracts/libs/LibDeploy.sol +++ b/packages/protocol/contracts/libs/LibDeploy.sol @@ -42,28 +42,17 @@ library LibDeploy { function deployERC1967Proxy( address impl, - address owner, - bytes memory data, - TimelockControllerUpgradeable timelock + TimelockControllerUpgradeable timelock, + bytes memory data ) internal returns (address proxy) { - proxy = deployERC1967Proxy(impl, owner, data); - if ( - address(timelock) != address(0) - && address(timelock) != OwnableUpgradeable(proxy).owner() - ) { - acceptProxyOwnershipByTimelock(proxy, timelock); - } + proxy = deployERC1967Proxy(impl, address(timelock), data); + acceptOwnership(proxy, timelock); } - function acceptProxyOwnershipByTimelock( - address proxy, - TimelockControllerUpgradeable timelock - ) - internal - { + function acceptOwnership(address proxy, TimelockControllerUpgradeable timelock) internal { bytes32 salt = bytes32(block.timestamp); bytes memory payload = abi.encodeCall(Ownable2StepUpgradeable(proxy).acceptOwnership, ()); diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index 2a62ca28631..b41e14ede34 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -215,7 +215,7 @@ contract DeployOnL1 is DeployCapability { _timelock.grantRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), address(this)); - LibDeploy.acceptProxyOwnershipByTimelock(taikoToken, _timelock); + LibDeploy.acceptOwnership(taikoToken, _timelock); // Deploy Bridging contracts deployProxy({ @@ -374,7 +374,7 @@ contract DeployOnL1 is DeployCapability { uint8 minGuardians = uint8(vm.envUint("MIN_GUARDIANS")); GuardianProver(guardianProver).setGuardians(guardians, minGuardians); GuardianProver(guardianProver).transferOwnership(timelock); - LibDeploy.acceptProxyOwnershipByTimelock(guardianProver, _timelock); + LibDeploy.acceptOwnership(guardianProver, _timelock); // No need to proxy these, because they are 3rd party. If we want to modify, we simply // change the registerAddress("automata_dcap_attestation", address(attestation)); diff --git a/packages/protocol/test/DeployCapability.sol b/packages/protocol/test/DeployCapability.sol index 48e22b83c23..11c6e6d1313 100644 --- a/packages/protocol/test/DeployCapability.sol +++ b/packages/protocol/test/DeployCapability.sol @@ -26,7 +26,11 @@ abstract contract DeployCapability is Script { internal returns (address proxy) { - proxy = LibDeploy.deployERC1967Proxy(impl, owner, data, timelock); + if (address(timelock) == address(0)) { + proxy = LibDeploy.deployERC1967Proxy(impl, owner, data); + } else { + proxy = LibDeploy.deployERC1967Proxy(impl, timelock, data); + } if (registerTo != address(0)) { AddressManager(registerTo).setAddress(