From 8a07620fd7f4623d2f188428bedb27afab7c5ec3 Mon Sep 17 00:00:00 2001 From: Andrei Kozlov Date: Thu, 25 Jul 2024 13:40:58 +0300 Subject: [PATCH 1/2] Add TransparentProxyFactoryBase --- .../TransparentProxyFactoryZkSync.sol | 58 +++------------ .../TransparentProxyFactory.sol | 58 +++------------ .../TransparentProxyFactoryBase.sol | 74 +++++++++++++++++++ 3 files changed, 92 insertions(+), 98 deletions(-) create mode 100644 src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol diff --git a/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol b/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol index c08d90d..5ad31cd 100644 --- a/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol +++ b/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol @@ -1,10 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import {IOwnable} from '../../../src/contracts/transparent-proxy/interfaces/IOwnable.sol'; -import {ITransparentProxyFactoryZkSync} from './interfaces/ITransparentProxyFactoryZkSync.sol'; -import {TransparentUpgradeableProxy} from '../../../src/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; -import {ProxyAdmin} from '../../../src/contracts/transparent-proxy/ProxyAdmin.sol'; +import {TransparentProxyFactoryBase, ITransparentProxyFactory} from '../../../src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol'; /** * @title TransparentProxyFactoryZkSync @@ -15,7 +12,7 @@ import {ProxyAdmin} from '../../../src/contracts/transparent-proxy/ProxyAdmin.so * @dev Highly recommended to pass as `admin` on creation an OZ ProxyAdmin instance * @dev This contract needs solc=0.8.19 and zksolc=1.4.1 as codeHashes are specifically made for those versions **/ -contract TransparentProxyFactoryZkSync is ITransparentProxyFactoryZkSync { +contract TransparentProxyFactoryZkSync is TransparentProxyFactoryBase { /// @inheritdoc ITransparentProxyFactoryZkSync bytes32 public constant TRANSPARENT_UPGRADABLE_PROXY_INIT_CODE_HASH = 0x010001b73fa7f2c39ea2d9c597a419e15436fc9d3e00e032410072fb94ad95e1; @@ -27,55 +24,13 @@ contract TransparentProxyFactoryZkSync is ITransparentProxyFactoryZkSync { /// @inheritdoc ITransparentProxyFactoryZkSync bytes32 public constant ZKSYNC_CREATE2_PREFIX = keccak256('zksyncCreate2'); - /// @inheritdoc ITransparentProxyFactoryZkSync - function create(address logic, address admin, bytes calldata data) external returns (address) { - address proxy = address(new TransparentUpgradeableProxy(logic, admin, data)); - - emit ProxyCreated(proxy, logic, admin); - return proxy; - } - - /// @inheritdoc ITransparentProxyFactoryZkSync - function createProxyAdmin(address adminOwner) external returns (address) { - address proxyAdmin = address(new ProxyAdmin()); - IOwnable(proxyAdmin).transferOwnership(adminOwner); - - emit ProxyAdminCreated(proxyAdmin, adminOwner); - return proxyAdmin; - } - - /// @inheritdoc ITransparentProxyFactoryZkSync - function createDeterministic( - address logic, - address admin, - bytes calldata data, - bytes32 salt - ) external returns (address) { - address proxy = address(new TransparentUpgradeableProxy{salt: salt}(logic, admin, data)); - - emit ProxyDeterministicCreated(proxy, logic, admin, salt); - return proxy; - } - - /// @inheritdoc ITransparentProxyFactoryZkSync - function createDeterministicProxyAdmin( - address adminOwner, - bytes32 salt - ) external returns (address) { - address proxyAdmin = address(new ProxyAdmin{salt: salt}()); - IOwnable(proxyAdmin).transferOwnership(adminOwner); - - emit ProxyAdminDeterministicCreated(proxyAdmin, adminOwner, salt); - return proxyAdmin; - } - /// @inheritdoc ITransparentProxyFactoryZkSync function predictCreateDeterministic( address logic, address admin, bytes calldata data, bytes32 salt - ) public view returns (address) { + ) public view override returns (address) { return _predictCreate2Address( address(this), @@ -86,7 +41,12 @@ contract TransparentProxyFactoryZkSync is ITransparentProxyFactoryZkSync { } /// @inheritdoc ITransparentProxyFactoryZkSync - function predictCreateDeterministicProxyAdmin(bytes32 salt) public view returns (address) { + function predictCreateDeterministicProxyAdmin(bytes32 salt) + public + view + override + returns (address) + { return _predictCreate2Address(address(this), salt, PROXY_ADMIN_INIT_CODE_HASH, abi.encode()); } diff --git a/src/contracts/transparent-proxy/TransparentProxyFactory.sol b/src/contracts/transparent-proxy/TransparentProxyFactory.sol index 855fcdb..3524ea8 100644 --- a/src/contracts/transparent-proxy/TransparentProxyFactory.sol +++ b/src/contracts/transparent-proxy/TransparentProxyFactory.sol @@ -1,10 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import {IOwnable} from './interfaces/IOwnable.sol'; -import {ITransparentProxyFactory} from './interfaces/ITransparentProxyFactory.sol'; -import {TransparentUpgradeableProxy} from './TransparentUpgradeableProxy.sol'; -import {ProxyAdmin} from './ProxyAdmin.sol'; +import {TransparentProxyFactoryBase, ITransparentProxyFactory, ProxyAdmin, TransparentUpgradeableProxy} from './TransparentProxyFactoryBase.sol'; /** * @title TransparentProxyFactory @@ -14,56 +11,14 @@ import {ProxyAdmin} from './ProxyAdmin.sol'; * time allowing `createDeterministic()` with salt == 0 * @dev Highly recommended to pass as `admin` on creation an OZ ProxyAdmin instance **/ -contract TransparentProxyFactory is ITransparentProxyFactory { - /// @inheritdoc ITransparentProxyFactory - function create(address logic, address admin, bytes calldata data) external returns (address) { - address proxy = address(new TransparentUpgradeableProxy(logic, admin, data)); - - emit ProxyCreated(proxy, logic, admin); - return proxy; - } - - /// @inheritdoc ITransparentProxyFactory - function createProxyAdmin(address adminOwner) external returns (address) { - address proxyAdmin = address(new ProxyAdmin()); - IOwnable(proxyAdmin).transferOwnership(adminOwner); - - emit ProxyAdminCreated(proxyAdmin, adminOwner); - return proxyAdmin; - } - - /// @inheritdoc ITransparentProxyFactory - function createDeterministic( - address logic, - address admin, - bytes calldata data, - bytes32 salt - ) external returns (address) { - address proxy = address(new TransparentUpgradeableProxy{salt: salt}(logic, admin, data)); - - emit ProxyDeterministicCreated(proxy, logic, admin, salt); - return proxy; - } - - /// @inheritdoc ITransparentProxyFactory - function createDeterministicProxyAdmin( - address adminOwner, - bytes32 salt - ) external returns (address) { - address proxyAdmin = address(new ProxyAdmin{salt: salt}()); - IOwnable(proxyAdmin).transferOwnership(adminOwner); - - emit ProxyAdminDeterministicCreated(proxyAdmin, adminOwner, salt); - return proxyAdmin; - } - +contract TransparentProxyFactory is TransparentProxyFactoryBase { /// @inheritdoc ITransparentProxyFactory function predictCreateDeterministic( address logic, address admin, bytes calldata data, bytes32 salt - ) public view returns (address) { + ) public view override returns (address) { return _predictCreate2Address( address(this), @@ -74,7 +29,12 @@ contract TransparentProxyFactory is ITransparentProxyFactory { } /// @inheritdoc ITransparentProxyFactory - function predictCreateDeterministicProxyAdmin(bytes32 salt) public view returns (address) { + function predictCreateDeterministicProxyAdmin(bytes32 salt) + public + view + override + returns (address) + { return _predictCreate2Address(address(this), salt, type(ProxyAdmin).creationCode, abi.encode()); } diff --git a/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol b/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol new file mode 100644 index 0000000..0d25a5f --- /dev/null +++ b/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import {IOwnable} from './interfaces/IOwnable.sol'; +import {ITransparentProxyFactory} from './interfaces/ITransparentProxyFactory.sol'; +import {TransparentUpgradeableProxy} from './TransparentUpgradeableProxy.sol'; +import {ProxyAdmin} from './ProxyAdmin.sol'; + +/** + * @title TransparentProxyFactory + * @author BGD Labs + * @notice Factory contract to create transparent proxies, both with CREATE and CREATE2 + * @dev `create()` and `createDeterministic()` are not unified for clearer interface, and at the same + * time allowing `createDeterministic()` with salt == 0 + * @dev Highly recommended to pass as `admin` on creation an OZ ProxyAdmin instance + **/ +abstract contract TransparentProxyFactoryBase is ITransparentProxyFactory { + /// @inheritdoc ITransparentProxyFactory + function create( + address logic, + address admin, + bytes calldata data + ) external returns (address) { + address proxy = address(new TransparentUpgradeableProxy(logic, admin, data)); + + emit ProxyCreated(proxy, logic, admin); + return proxy; + } + + /// @inheritdoc ITransparentProxyFactory + function createProxyAdmin(address adminOwner) external returns (address) { + address proxyAdmin = address(new ProxyAdmin()); + IOwnable(proxyAdmin).transferOwnership(adminOwner); + + emit ProxyAdminCreated(proxyAdmin, adminOwner); + return proxyAdmin; + } + + /// @inheritdoc ITransparentProxyFactory + function createDeterministic( + address logic, + address admin, + bytes calldata data, + bytes32 salt + ) external returns (address) { + address proxy = address(new TransparentUpgradeableProxy{salt: salt}(logic, admin, data)); + + emit ProxyDeterministicCreated(proxy, logic, admin, salt); + return proxy; + } + + /// @inheritdoc ITransparentProxyFactory + function createDeterministicProxyAdmin(address adminOwner, bytes32 salt) + external + returns (address) + { + address proxyAdmin = address(new ProxyAdmin{salt: salt}()); + IOwnable(proxyAdmin).transferOwnership(adminOwner); + + emit ProxyAdminDeterministicCreated(proxyAdmin, adminOwner, salt); + return proxyAdmin; + } + + /// @inheritdoc ITransparentProxyFactory + function predictCreateDeterministic( + address logic, + address admin, + bytes calldata data, + bytes32 salt + ) public view virtual returns (address); + + /// @inheritdoc ITransparentProxyFactory + function predictCreateDeterministicProxyAdmin(bytes32 salt) public view virtual returns (address); +} From c01b20f661cb7cd9ccf0a144b06bbd8b2c411b6e Mon Sep 17 00:00:00 2001 From: Andrei Kozlov Date: Thu, 25 Jul 2024 13:47:46 +0300 Subject: [PATCH 2/2] cleanup ITransparentProxyFactoryZkSync --- .../TransparentProxyFactoryZkSync.sol | 10 ++- .../ITransparentProxyFactoryZkSync.sol | 88 ------------------- 2 files changed, 7 insertions(+), 91 deletions(-) diff --git a/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol b/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol index 5ad31cd..b114b79 100644 --- a/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol +++ b/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import {TransparentProxyFactoryBase, ITransparentProxyFactory} from '../../../src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol'; +import {ITransparentProxyFactoryZkSync} from './interfaces/ITransparentProxyFactoryZkSync.sol'; /** * @title TransparentProxyFactoryZkSync @@ -12,7 +13,10 @@ import {TransparentProxyFactoryBase, ITransparentProxyFactory} from '../../../sr * @dev Highly recommended to pass as `admin` on creation an OZ ProxyAdmin instance * @dev This contract needs solc=0.8.19 and zksolc=1.4.1 as codeHashes are specifically made for those versions **/ -contract TransparentProxyFactoryZkSync is TransparentProxyFactoryBase { +contract TransparentProxyFactoryZkSync is + TransparentProxyFactoryBase, + ITransparentProxyFactoryZkSync +{ /// @inheritdoc ITransparentProxyFactoryZkSync bytes32 public constant TRANSPARENT_UPGRADABLE_PROXY_INIT_CODE_HASH = 0x010001b73fa7f2c39ea2d9c597a419e15436fc9d3e00e032410072fb94ad95e1; @@ -24,7 +28,7 @@ contract TransparentProxyFactoryZkSync is TransparentProxyFactoryBase { /// @inheritdoc ITransparentProxyFactoryZkSync bytes32 public constant ZKSYNC_CREATE2_PREFIX = keccak256('zksyncCreate2'); - /// @inheritdoc ITransparentProxyFactoryZkSync + /// @inheritdoc ITransparentProxyFactory function predictCreateDeterministic( address logic, address admin, @@ -40,7 +44,7 @@ contract TransparentProxyFactoryZkSync is TransparentProxyFactoryBase { ); } - /// @inheritdoc ITransparentProxyFactoryZkSync + /// @inheritdoc ITransparentProxyFactory function predictCreateDeterministicProxyAdmin(bytes32 salt) public view diff --git a/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol b/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol index 873f4bb..72e61e4 100644 --- a/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol +++ b/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol @@ -2,20 +2,6 @@ pragma solidity >=0.8.0; interface ITransparentProxyFactoryZkSync { - event ProxyCreated(address proxy, address indexed logic, address indexed proxyAdmin); - event ProxyAdminCreated(address proxyAdmin, address indexed adminOwner); - event ProxyDeterministicCreated( - address proxy, - address indexed logic, - address indexed admin, - bytes32 indexed salt - ); - event ProxyAdminDeterministicCreated( - address proxyAdmin, - address indexed adminOwner, - bytes32 indexed salt - ); - /** * @notice method to get the hash of creation bytecode of the TransparentUpgradableProxy contract * @return hashed of creation bytecode of the TransparentUpgradableProxy contract @@ -33,78 +19,4 @@ interface ITransparentProxyFactoryZkSync { * @return create2 prefix used for create2 address derivation */ function ZKSYNC_CREATE2_PREFIX() external returns (bytes32); - - /** - * @notice Creates a transparent proxy instance, doing the first initialization in construction - * @dev Version using CREATE - * @param logic The address of the implementation contract - * @param admin The admin of the proxy. - * @param data abi encoded call to the function with `initializer` (or `reinitializer`) modifier. - * E.g. `abi.encodeWithSelector(mockImpl.initialize.selector, 2)` - * for an `initialize` function being `function initialize(uint256 foo) external initializer;` - * @return address The address of the proxy deployed - **/ - function create(address logic, address admin, bytes memory data) external returns (address); - - /** - * @notice Creates a proxyAdmin instance, and transfers ownership to provided owner - * @dev Version using CREATE - * @param adminOwner The owner of the proxyAdmin deployed. - * @return address The address of the proxyAdmin deployed - **/ - function createProxyAdmin(address adminOwner) external returns (address); - - /** - * @notice Creates a transparent proxy instance, doing the first initialization in construction - * @dev Version using CREATE2, so deterministic - * @param logic The address of the implementation contract - * @param admin The admin of the proxy. - * @param data abi encoded call to the function with `initializer` (or `reinitializer`) modifier. - * E.g. `abi.encodeWithSelector(mockImpl.initialize.selector, 2)` - * for an `initialize` function being `function initialize(uint256 foo) external initializer;` - * @param salt Value to be used in the address calculation, to be chosen by the account calling this function - * @return address The address of the proxy deployed - **/ - function createDeterministic( - address logic, - address admin, - bytes memory data, - bytes32 salt - ) external returns (address); - - /** - * @notice Deterministically create a proxy admin instance and transfers ownership to provided owner. - * @dev Version using CREATE2, so deterministic - * @param adminOwner The owner of the ProxyAdmin deployed. - * @param salt Value to be used in the address calculation, to be chosen by the account calling this function - * @return address The address of the proxy admin deployed - **/ - function createDeterministicProxyAdmin( - address adminOwner, - bytes32 salt - ) external returns (address); - - /** - * @notice Pre-calculates and return the address on which `createDeterministic` will deploy a proxy - * @param logic The address of the implementation contract - * @param admin The admin of the proxy - * @param data abi encoded call to the function with `initializer` (or `reinitializer`) modifier. - * E.g. `abi.encodeWithSelector(mockImpl.initialize.selector, 2)` - * for an `initialize` function being `function initialize(uint256 foo) external initializer;` - * @param salt Value to be used in the address calculation, to be chosen by the account calling this function - * @return address The pre-calculated address - **/ - function predictCreateDeterministic( - address logic, - address admin, - bytes calldata data, - bytes32 salt - ) external view returns (address); - - /** - * @notice Pre-calculates and return the address on which `createDeterministic` will deploy the proxyAdmin - * @param salt Value to be used in the address calculation, to be chosen by the account calling this function - * @return address The pre-calculated address - **/ - function predictCreateDeterministicProxyAdmin(bytes32 salt) external view returns (address); }