diff --git a/Makefile b/Makefile index df95031..18d9027 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ deploy-polygon :; forge script script/DeployTransparentProxyFactory.s.sol:Deploy deploy-avalanche :; forge script script/DeployTransparentProxyFactory.s.sol:DeployAvalanche --rpc-url avalanche --broadcast --legacy --ledger --mnemonic-indexes ${MNEMONIC_INDEX} --sender ${LEDGER_SENDER} --verify -vvvv deploy-optimism :; forge script script/DeployTransparentProxyFactory.s.sol:DeployOptimism --rpc-url optimism --broadcast --legacy --ledger --mnemonic-indexes ${MNEMONIC_INDEX} --sender ${LEDGER_SENDER} --verify -vvvv deploy-arbitrum :; forge script script/DeployTransparentProxyFactory.s.sol:DeployArbitrum --rpc-url arbitrum --broadcast --legacy --ledger --mnemonic-indexes ${MNEMONIC_INDEX} --sender ${LEDGER_SENDER} --verify -vvvv +deploy-zksync :; FOUNDRY_PROFILE=zksync forge script zksync/script/DeployTransparentProxyFactoryZkSync.s.sol:DeployZkSync --zksync --system-mode=true --rpc-url zksync --broadcast --ledger --mnemonic-indexes ${MNEMONIC_INDEX} --sender ${LEDGER_SENDER} --verify -vvvv # ---------------------------------------------- BASE SCRIPT CONFIGURATION --------------------------------------------- diff --git a/foundry.toml b/foundry.toml index b4d39e4..f5c4a30 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,21 +1,22 @@ [profile.default] src = 'src' tests = 'tests' +script = 'script' out = 'out' libs = ['lib'] remappings = [] [profile.zksync] -src = 'src-zksync' -test = 'test-zksync' +src = 'zksync/src' +test = 'zksync/test' +script = 'zksync/script' libs = ['lib'] -solc="0.8.19" +solc = '0.8.24' [profile.zksync.zksync] fallback_oz = true mode = "3" -zksolc="1.4.1" - +zksolc = "1.4.1" # See more config options https://github.com/gakonst/foundry/tree/master/config [rpc_endpoints] diff --git a/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol b/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol deleted file mode 100644 index b114b79..0000000 --- a/src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol +++ /dev/null @@ -1,75 +0,0 @@ -// 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))); - } -} diff --git a/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol b/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol deleted file mode 100644 index 72e61e4..0000000 --- a/src-zksync/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol +++ /dev/null @@ -1,22 +0,0 @@ -// 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); -} diff --git a/src/contracts/transparent-proxy/TransparentProxyFactory.sol b/src/contracts/transparent-proxy/TransparentProxyFactory.sol index 3524ea8..099d2ef 100644 --- a/src/contracts/transparent-proxy/TransparentProxyFactory.sol +++ b/src/contracts/transparent-proxy/TransparentProxyFactory.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0; -import {TransparentProxyFactoryBase, ITransparentProxyFactory, ProxyAdmin, TransparentUpgradeableProxy} from './TransparentProxyFactoryBase.sol'; +import {TransparentProxyFactoryBase} from './TransparentProxyFactoryBase.sol'; /** * @title TransparentProxyFactory @@ -12,44 +12,18 @@ import {TransparentProxyFactoryBase, ITransparentProxyFactory, ProxyAdmin, Trans * @dev Highly recommended to pass as `admin` on creation an OZ ProxyAdmin instance **/ contract TransparentProxyFactory is TransparentProxyFactoryBase { - /// @inheritdoc ITransparentProxyFactory - function predictCreateDeterministic( - address logic, - address admin, - bytes calldata data, - bytes32 salt - ) public view override returns (address) { - return - _predictCreate2Address( - address(this), - salt, - type(TransparentUpgradeableProxy).creationCode, - abi.encode(logic, admin, data) - ); - } - - /// @inheritdoc ITransparentProxyFactory - function predictCreateDeterministicProxyAdmin(bytes32 salt) - public - view - override - returns (address) - { - return _predictCreate2Address(address(this), salt, type(ProxyAdmin).creationCode, abi.encode()); - } - function _predictCreate2Address( address creator, bytes32 salt, bytes memory creationCode, - bytes memory contructorArgs - ) internal pure returns (address) { + bytes memory constructorArgs + ) internal pure override returns (address) { bytes32 hash = keccak256( abi.encodePacked( bytes1(0xff), creator, salt, - keccak256(abi.encodePacked(creationCode, contructorArgs)) + keccak256(abi.encodePacked(creationCode, constructorArgs)) ) ); diff --git a/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol b/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol index 0d25a5f..41c8b06 100644 --- a/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol +++ b/src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol @@ -67,8 +67,25 @@ abstract contract TransparentProxyFactoryBase is ITransparentProxyFactory { address admin, bytes calldata data, bytes32 salt - ) public view virtual returns (address); + ) public view returns (address) { + return + _predictCreate2Address( + address(this), + salt, + type(TransparentUpgradeableProxy).creationCode, + abi.encode(logic, admin, data) + ); + } /// @inheritdoc ITransparentProxyFactory - function predictCreateDeterministicProxyAdmin(bytes32 salt) public view virtual returns (address); + function predictCreateDeterministicProxyAdmin(bytes32 salt) public view returns (address) { + return _predictCreate2Address(address(this), salt, type(ProxyAdmin).creationCode, abi.encode()); + } + + function _predictCreate2Address( + address creator, + bytes32 salt, + bytes memory creationCode, + bytes memory constructorArgs + ) internal pure virtual returns (address); } diff --git a/zksync/script/DeployTransparentProxyFactoryZkSync.s.sol b/zksync/script/DeployTransparentProxyFactoryZkSync.s.sol new file mode 100644 index 0000000..df4e9b8 --- /dev/null +++ b/zksync/script/DeployTransparentProxyFactoryZkSync.s.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Script} from 'forge-std/Script.sol'; +import {TransparentProxyFactoryZkSync} from '../src/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol'; + +contract DeployZkSync is Script { + function run() external { + vm.startBroadcast(); + new TransparentProxyFactoryZkSync(); + vm.stopBroadcast(); + } +} diff --git a/zksync/src/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol b/zksync/src/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol new file mode 100644 index 0000000..4e31015 --- /dev/null +++ b/zksync/src/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import {TransparentProxyFactoryBase} from '../../../../src/contracts/transparent-proxy/TransparentProxyFactoryBase.sol'; +import {ITransparentProxyFactoryZkSync} from './interfaces/ITransparentProxyFactoryZkSync.sol'; + +/** + * @title TransparentProxyFactoryZkSync + * @author BGD Labs + * @notice Factory contract specific to zkSync 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 + **/ +contract TransparentProxyFactoryZkSync is + TransparentProxyFactoryBase, + ITransparentProxyFactoryZkSync +{ + /// @inheritdoc ITransparentProxyFactoryZkSync + bytes32 public constant ZKSYNC_CREATE2_PREFIX = keccak256('zksyncCreate2'); + + function _predictCreate2Address( + address sender, + bytes32 salt, + bytes memory creationCode, + bytes memory constructorInput + ) internal pure override returns (address) { + bytes32 addressHash = keccak256( + bytes.concat( + ZKSYNC_CREATE2_PREFIX, + bytes32(uint256(uint160(sender))), + salt, + bytes32(_sliceBytes(creationCode, 36, 32)), + keccak256(constructorInput) + ) + ); + + return address(uint160(uint256(addressHash))); + } + + function _sliceBytes( + bytes memory data, + uint256 start, + uint256 length + ) internal pure returns (bytes memory) { + require(start + length <= data.length, 'Slice out of bounds'); + + bytes memory result = new bytes(length); + assembly { + let dataPtr := add(data, 32) + let resultPtr := add(result, 32) + + // Use mcopy to efficiently copy the slice + mcopy(resultPtr, add(dataPtr, start), length) + + mstore(result, length) + } + return result; + } +} diff --git a/zksync/src/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol b/zksync/src/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol new file mode 100644 index 0000000..89865f2 --- /dev/null +++ b/zksync/src/contracts/transparent-proxy/interfaces/ITransparentProxyFactoryZkSync.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +interface ITransparentProxyFactoryZkSync { + /** + * @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); +} diff --git a/test-zksync/TransparentProxyFactoryZkSync.t.sol b/zksync/test/TransparentProxyFactoryZkSync.t.sol similarity index 88% rename from test-zksync/TransparentProxyFactoryZkSync.t.sol rename to zksync/test/TransparentProxyFactoryZkSync.t.sol index fb35839..852b1d8 100644 --- a/test-zksync/TransparentProxyFactoryZkSync.t.sol +++ b/zksync/test/TransparentProxyFactoryZkSync.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.24; import {Test} from 'forge-std/Test.sol'; -import {TransparentProxyFactoryZkSync} from '../src-zksync/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol'; -import {TransparentUpgradeableProxy} from '../src/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; -import {IOwnable} from '../src/contracts/transparent-proxy/interfaces/IOwnable.sol'; -import {MockImpl} from '../src/mocks/MockImpl.sol'; +import {TransparentProxyFactoryZkSync} from '../src/contracts/transparent-proxy/TransparentProxyFactoryZkSync.sol'; +import {TransparentUpgradeableProxy} from '../../src/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; +import {IOwnable} from '../../src/contracts/transparent-proxy/interfaces/IOwnable.sol'; +import {MockImpl} from '../../src/mocks/MockImpl.sol'; contract TestTransparentProxyFactoryZkSync is Test { TransparentProxyFactoryZkSync internal factory;