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

feat: allow both variants #58

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
64 changes: 60 additions & 4 deletions src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,25 @@ import {ProxyAdmin} from './ProxyAdmin.sol';
abstract contract TransparentProxyFactoryBase is ITransparentProxyFactory {
/// @inheritdoc ITransparentProxyFactory
function create(address logic, ProxyAdmin admin, bytes calldata data) external returns (address) {
address proxy = address(new TransparentUpgradeableProxy(logic, admin, data));
return _create(logic, address(admin), data, true);
}

/// @inheritdoc ITransparentProxyFactory
function createAndDeployNewAdmin(
address logic,
address initialOwner,
bytes calldata data
) external returns (address) {
return _create(logic, initialOwner, data, false);
}

function _create(
address logic,
address admin,
bytes calldata data,
bool reuseAdmin
) internal returns (address) {
address proxy = address(new TransparentUpgradeableProxy(logic, admin, data, reuseAdmin));

emit ProxyCreated(proxy, logic, address(admin));
return proxy;
Expand All @@ -37,9 +55,31 @@ abstract contract TransparentProxyFactoryBase is ITransparentProxyFactory {
bytes calldata data,
bytes32 salt
) external returns (address) {
address proxy = address(new TransparentUpgradeableProxy{salt: salt}(logic, admin, data));
return _createDeterministic(logic, address(admin), data, true, salt);
}

/// @inheritdoc ITransparentProxyFactory
function createDeterministicAndDeployNewAdmin(
address logic,
address initialOwner,
bytes calldata data,
bytes32 salt
) external returns (address) {
return _createDeterministic(logic, initialOwner, data, false, salt);
}

emit ProxyDeterministicCreated(proxy, logic, address(admin), salt);
function _createDeterministic(
address logic,
address ownerOrAdmin,
bytes calldata data,
bool reuseAdmin,
bytes32 salt
) internal returns (address) {
address proxy = address(
new TransparentUpgradeableProxy{salt: salt}(logic, ownerOrAdmin, data, reuseAdmin)
);

emit ProxyDeterministicCreated(proxy, logic, address(ownerOrAdmin), salt);
return proxy;
}

Expand All @@ -66,7 +106,23 @@ abstract contract TransparentProxyFactoryBase is ITransparentProxyFactory {
address(this),
salt,
type(TransparentUpgradeableProxy).creationCode,
abi.encode(logic, address(admin), data)
abi.encode(logic, address(admin), data, true)
);
}

/// @inheritdoc ITransparentProxyFactory
function predictCreateDeterministicAndDeployNewAdmin(
address logic,
address initialOwner,
bytes calldata data,
bytes32 salt
) public view returns (address) {
return
_predictCreate2Address(
address(this),
salt,
type(TransparentUpgradeableProxy).creationCode,
abi.encode(logic, address(initialOwner), data, false)
);
}

Expand Down
13 changes: 9 additions & 4 deletions src/contracts/transparent-proxy/TransparentUpgradeableProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,23 @@ contract TransparentUpgradeableProxy is ERC1967Proxy {
*/
constructor(
address _logic,
ProxyAdmin initialOwner,
bytes memory _data
address ownerOrAdmin,
bytes memory _data,
bool useExistingAdmin
) payable ERC1967Proxy(_logic, _data) {
_admin = address(initialOwner);
if (useExistingAdmin) {
_admin = ownerOrAdmin;
} else {
_admin = address(new ProxyAdmin(ownerOrAdmin));
}
// Set the storage value and emit an event for ERC-1967 compatibility
ERC1967Utils.changeAdmin(_proxyAdmin());
}

/**
* @dev Returns the admin of this proxy.
*/
function _proxyAdmin() internal virtual returns (address) {
function _proxyAdmin() internal view virtual returns (address) {
return _admin;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ interface ITransparentProxyFactory {
**/
function create(address logic, ProxyAdmin admin, bytes memory data) external returns (address);

/**
* @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 initialOwner The initial owner of the admin deployed by 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 createAndDeployNewAdmin(
address logic,
address initialOwner,
bytes memory data
) external returns (address);

/**
* @notice Creates a proxyAdmin instance, and transfers ownership to provided owner
* @dev Version using CREATE
Expand All @@ -56,6 +72,24 @@ interface ITransparentProxyFactory {
bytes32 salt
) 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 initialOwner The initial owner of the admin deployed by 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 createDeterministicAndDeployNewAdmin(
address logic,
address initialOwner,
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
Expand Down Expand Up @@ -85,6 +119,23 @@ interface ITransparentProxyFactory {
bytes32 salt
) external view 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 initialOwner The initial owner of the admin deployed by 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 predictCreateDeterministicAndDeployNewAdmin(
address logic,
address initialOwner,
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
Expand Down
Loading