Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TransparentProxyFactoryBase #37

Merged
merged 2 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {IOwnable} from '../../../src/contracts/transparent-proxy/interfaces/IOwnable.sol';
import {TransparentProxyFactoryBase, ITransparentProxyFactory} from '../../../src/contracts/transparent-proxy/TransparentProxyFactoryBase.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';

/**
* @title TransparentProxyFactoryZkSync
Expand All @@ -15,7 +13,10 @@ 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,
ITransparentProxyFactoryZkSync
{
/// @inheritdoc ITransparentProxyFactoryZkSync
bytes32 public constant TRANSPARENT_UPGRADABLE_PROXY_INIT_CODE_HASH =
0x010001b73fa7f2c39ea2d9c597a419e15436fc9d3e00e032410072fb94ad95e1;
Expand All @@ -27,55 +28,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
/// @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),
Expand All @@ -85,8 +44,13 @@ contract TransparentProxyFactoryZkSync is ITransparentProxyFactoryZkSync {
);
}

/// @inheritdoc ITransparentProxyFactoryZkSync
function predictCreateDeterministicProxyAdmin(bytes32 salt) public view returns (address) {
/// @inheritdoc ITransparentProxyFactory
function predictCreateDeterministicProxyAdmin(bytes32 salt)
public
view
override
returns (address)
{
return _predictCreate2Address(address(this), salt, PROXY_ADMIN_INIT_CODE_HASH, abi.encode());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
58 changes: 9 additions & 49 deletions src/contracts/transparent-proxy/TransparentProxyFactory.sol
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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),
Expand All @@ -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());
}

Expand Down
74 changes: 74 additions & 0 deletions src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol
Original file line number Diff line number Diff line change
@@ -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);
}
Loading