Skip to content

Commit

Permalink
[WIP] feat: update contracts for zksync (#32)
Browse files Browse the repository at this point in the history
* feat: update proxy factory to zksync

* fix: added correct hashes for v0.8.19

* fix: added hashes with 1.5.0

* fix: 1.4.1 hashes

* fix: sepparate zksync contracts

* fix: added zksync configs

* fix: separate zksync contracts to specific profile

* fix: fixed missing conflict

* fix: removed fixed version

* fix: remove not needed diffs

* fix: prettier

* fix: added correct profiles

* Add TransparentProxyFactoryBase (#37)

* Add TransparentProxyFactoryBase

* cleanup ITransparentProxyFactoryZkSync

---------

Co-authored-by: sendra <[email protected]>
Co-authored-by: Andrey <[email protected]>
  • Loading branch information
3 people authored Jul 25, 2024
1 parent b42cacb commit 9e12156
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 50 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ RPC_METIS=https://andromeda.metis.io/?owner=1088
RPC_METIS_TESTNET=https://andromeda.metis.io/?owner=1088
RPC_BINANCE=https://bsc-dataseed.binance.org/
RPC_BINANCE_TESTNET=https://data-seed-prebsc-1-s1.binance.org:8545/
RPC_ZK_SYNC=https://mainnet.era.zksync.io
RPC_ZK_SYNC_TESTNET=https://sepolia.era.zksync.dev

# Etherscan api keys for verification & download utils
ETHERSCAN_API_KEY_MAINNET=
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ out/
broadcast
node_modules
package-lock.json
zkout/
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ Modified from https://github.com/lifinance/create3-factory/blob/main/src/CREATE3
- removal of named returns
- changed name of getDeployed for predictAddress
- usage of create3 lib by Agustin Aguilar instead of solmate

## ZkSync

As ZkSync network requires the use of a [forked](https://github.com/matter-labs/foundry-zksync) version of foundry we have created different profiles so that they can run
as expected.

- Contracts specific for ZkSync network can be found [here](src-zksync)
- Tests specific for ZkSync network can be found [here](test-zksync)

To build and test the contracts use `FOUNDRY_PROFILE=zksync` and the flag `--zksync`
- Example:
```solidity
FOUNDRY_PROFILE=zksync forge test -vvv --zksync
```
21 changes: 21 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ out = 'out'
libs = ['lib']
remappings = []

[profile.zksync]
src = 'src-zksync'
test = 'test-zksync'
libs = ['lib']
solc="0.8.19"

[profile.zksync.zksync]
fallback_oz = true
mode = "3"
zksolc="1.4.1"


# See more config options https://github.com/gakonst/foundry/tree/master/config
[rpc_endpoints]
ethereum = "${RPC_MAINNET}"
Expand All @@ -23,6 +35,8 @@ fantom = "${RPC_FANTOM}"
fantom-testnet = "${RPC_FANTOM_TESTNET}"
binance = "${RPC_BINANCE}"
binance-testnet = "${RPC_BINANCE_TESTNET}"
zksync = "${RPC_ZK_SYNC}"
zksync-testnet = "${RPC_ZK_SYNC_TESTNET}"

[etherscan]
ethereum = { key = "${ETHERSCAN_API_KEY_MAINNET}", chain = 1 }
Expand All @@ -41,3 +55,10 @@ fantom = { key = "${ETHERSCAN_API_KEY_FANTOM}", chain = 250 }
fantom-testnet = { key = "${ETHERSCAN_API_KEY_FANTOM}", chain = 250 }
binance = { key = "${ETHERSCAN_API_KEY_BINANCE}", chain = 56 }
binance-testnet = { key = "${ETHERSCAN_API_KEY_BINANCE}", chain = 56 }
zksync = { key = "${ETHERSCAN_API_KEY_ZK_SYNC}", chain = 324 }
zksync-testnet = { key = "${ETHERSCAN_API_KEY_ZK_SYNC}", chain = 300, url = 'https://api-sepolia-era.zksync.network/api'}

[fuzz]
no_zksync_reserved_addresses = true
[invariant]
no_zksync_reserved_addresses = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {TransparentProxyFactoryBase, ITransparentProxyFactory} from '../../../src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol';
import {ITransparentProxyFactoryZkSync} from './interfaces/ITransparentProxyFactoryZkSync.sol';

/**
* @title TransparentProxyFactoryZkSync
* @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
* @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,
ITransparentProxyFactoryZkSync
{
/// @inheritdoc ITransparentProxyFactoryZkSync
bytes32 public constant TRANSPARENT_UPGRADABLE_PROXY_INIT_CODE_HASH =
0x010001b73fa7f2c39ea2d9c597a419e15436fc9d3e00e032410072fb94ad95e1;

/// @inheritdoc ITransparentProxyFactoryZkSync
bytes32 public constant PROXY_ADMIN_INIT_CODE_HASH =
0x010000e7f9a8b61da13fe7e27804d9f641f5f8db05b07df720973af749a01ac1;

/// @inheritdoc ITransparentProxyFactoryZkSync
bytes32 public constant ZKSYNC_CREATE2_PREFIX = keccak256('zksyncCreate2');

/// @inheritdoc ITransparentProxyFactory
function predictCreateDeterministic(
address logic,
address admin,
bytes calldata data,
bytes32 salt
) public view override returns (address) {
return
_predictCreate2Address(
address(this),
salt,
TRANSPARENT_UPGRADABLE_PROXY_INIT_CODE_HASH,
abi.encode(logic, admin, data)
);
}

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

function _predictCreate2Address(
address sender,
bytes32 salt,
bytes32 creationCodeHash,
bytes memory constructorInput
) internal pure returns (address) {
bytes32 addressHash = keccak256(
bytes.concat(
ZKSYNC_CREATE2_PREFIX,
bytes32(uint256(uint160(sender))),
salt,
creationCodeHash,
keccak256(constructorInput)
)
);

return address(uint160(uint256(addressHash)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface ITransparentProxyFactoryZkSync {
/**
* @notice method to get the hash of creation bytecode of the TransparentUpgradableProxy contract
* @return hashed of creation bytecode of the TransparentUpgradableProxy contract
*/
function TRANSPARENT_UPGRADABLE_PROXY_INIT_CODE_HASH() external returns (bytes32);

/**
* @notice method to get the hash of creation bytecode of the ProxyAdmin contract
* @return hashed of creation bytecode of the ProxyAdmin contract
*/
function PROXY_ADMIN_INIT_CODE_HASH() external returns (bytes32);

/**
* @notice method to get the zksync create2 prefix used for create2 address derivation in zksync
* @return create2 prefix used for create2 address derivation
*/
function ZKSYNC_CREATE2_PREFIX() external returns (bytes32);
}
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

0 comments on commit 9e12156

Please sign in to comment.