From 6d37d40caa97c698c4d508ed58715a05ec41e087 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Mon, 2 Oct 2023 13:59:53 +0100 Subject: [PATCH 1/7] zk fmt --- docs/Overview.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Overview.md b/docs/Overview.md index 1ca07d81b9..1a8bddfe6c 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -126,6 +126,7 @@ function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Ad l2Address = address(uint160(l1Address) + offset); } } + ``` For most of the rollups the address aliasing needs to prevent cross-chain exploits that would otherwise be possible if @@ -285,6 +286,7 @@ struct Deposit { bool depositLimitation; uint256 depositCap; } + ``` Currently, the limit is used only for blocking deposits of the specific token (turning on the limitation and setting the From 30ce1c94f8b4eec138ad95b490044125eaf1ba58 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 4 Oct 2023 09:07:39 +0100 Subject: [PATCH 2/7] unit tests --- ethereum/contracts/bridge/L1ERC20Bridge.sol | 4 +- .../contracts/bridge/interfaces/IL2Bridge.sol | 6 +- .../bridge/interfaces/IL2ERC20Bridge.sol | 6 +- .../bridge/interfaces/IL2WethBridge.sol | 6 +- ethereum/contracts/bridgehead/Bridgehead.sol | 2 +- .../bridgehead-deps/BridgeheadMailbox.sol | 25 +- .../IBridgeheadForProof.sol | 6 +- .../IBridgeheadMailbox.sol | 6 +- .../bridgehead/chain-deps/ChainExecutor.sol | 10 +- .../bridgehead/chain-deps/Mailbox.sol | 58 +- ethereum/contracts/common/AllowListed.sol | 2 +- .../common/interfaces/IAllowList.sol | 27 +- .../common/interfaces/IL2ContractDeployer.sol | 6 +- .../contracts/common/libraries/Diamond.sol | 18 +- .../common/libraries/L2ContractHelper.sol | 2 +- .../dev-contracts/test/DummyExecutor.sol | 13 +- .../test/GovernanceFacetTest.sol | 4 + .../test/TransactionValidatorTest.sol | 8 +- .../dev-contracts/test/UnsafeBytesTest.sol | 27 +- ...ProofDiamondProxy.sol => DiamondProxy.sol} | 2 +- .../contracts/proof-system/ProofSystem.sol | 2 +- .../proof-system/ValidatorTimelock.sol | 10 +- .../chain-deps/facets/DiamondCut.sol | 11 +- .../chain-deps/facets/Executor.sol | 17 +- .../chain-deps/facets/Getters.sol | 2 +- .../chain-deps/facets/Governance.sol | 2 +- .../chain-interfaces/IDiamondCut.sol | 2 +- .../chain-interfaces/IExecutor.sol | 8 +- .../chain-interfaces/IGetters.sol | 2 +- .../chain-interfaces/IGovernance.sol | 2 +- .../chain-interfaces/IProofChain.sol | 2 +- .../proof-system-deps/ProofRegistry.sol | 4 +- .../contracts/upgrades/DefaultUpgrade.sol | 2 +- ethereum/src.ts/deploy-utils.ts | 2 +- ethereum/src.ts/deploy.ts | 94 ++- ethereum/src.ts/diamondCut.ts | 8 +- .../test/unit_tests/diamond_cut_test.spec.ts | 37 +- ...est.spec.ts => diamond_proxy_test.spec.ts} | 61 +- ...tor_test.spec.ts => executor_test.spec.ts} | 538 ++++++++++-------- .../test/unit_tests/governance_test.spec.ts | 2 +- .../unit_tests/l1_erc20_bridge_test.spec.ts | 215 ++++--- .../unit_tests/l1_weth_bridge_test.spec.ts | 183 ++++-- .../test/unit_tests/l2-upgrade.test.spec.ts | 259 ++++++--- ethereum/test/unit_tests/mailbox_test.spec.ts | 234 +++++--- ethereum/test/unit_tests/utils.ts | 59 +- .../validator_timelock_test.spec.ts | 2 +- .../test/unit_tests/zksync-upgrade.fork.ts | 14 +- zksync/contracts/L2ContractHelper.sol | 6 +- zksync/contracts/SystemContractsCaller.sol | 7 +- zksync/contracts/bridge/L2ERC20Bridge.sol | 12 +- zksync/contracts/bridge/L2WethBridge.sol | 12 +- .../contracts/bridge/interfaces/IL2Bridge.sol | 6 +- .../contracts/interfaces/IPaymasterFlow.sol | 6 +- 53 files changed, 1272 insertions(+), 789 deletions(-) rename ethereum/contracts/proof-system/{ProofDiamondProxy.sol => DiamondProxy.sol} (98%) rename ethereum/test/unit_tests/{proxy_test.spec.ts => diamond_proxy_test.spec.ts} (78%) rename ethereum/test/unit_tests/{proof_executor_test.spec.ts => executor_test.spec.ts} (68%) diff --git a/ethereum/contracts/bridge/L1ERC20Bridge.sol b/ethereum/contracts/bridge/L1ERC20Bridge.sol index 58792f0a62..6aae5ba49e 100644 --- a/ethereum/contracts/bridge/L1ERC20Bridge.sol +++ b/ethereum/contracts/bridge/L1ERC20Bridge.sol @@ -340,9 +340,7 @@ contract L1ERC20Bridge is IL1Bridge, IL1BridgeLegacy, AllowListed, ReentrancyGua bytes calldata _message, bytes32[] calldata _merkleProof ) external nonReentrant senderCanCallFunction(allowList) { - { - require(!isWithdrawalFinalized[_chainId][_l2BlockNumber][_l2MessageIndex], "pw"); - } + require(!isWithdrawalFinalized[_chainId][_l2BlockNumber][_l2MessageIndex], "pw"); L2Message memory l2ToL1Message = L2Message({ txNumberInBlock: _l2TxNumberInBlock, diff --git a/ethereum/contracts/bridge/interfaces/IL2Bridge.sol b/ethereum/contracts/bridge/interfaces/IL2Bridge.sol index 33975fe98c..6381430a10 100644 --- a/ethereum/contracts/bridge/interfaces/IL2Bridge.sol +++ b/ethereum/contracts/bridge/interfaces/IL2Bridge.sol @@ -12,7 +12,11 @@ interface IL2Bridge { bytes calldata _data ) external payable; - function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external; + function withdraw( + address _l1Receiver, + address _l2Token, + uint256 _amount + ) external; function l1TokenAddress(address _l2Token) external view returns (address); diff --git a/ethereum/contracts/bridge/interfaces/IL2ERC20Bridge.sol b/ethereum/contracts/bridge/interfaces/IL2ERC20Bridge.sol index 0e89f90654..01d32dae9c 100644 --- a/ethereum/contracts/bridge/interfaces/IL2ERC20Bridge.sol +++ b/ethereum/contracts/bridge/interfaces/IL2ERC20Bridge.sol @@ -4,5 +4,9 @@ pragma solidity ^0.8.13; /// @author Matter Labs interface IL2ERC20Bridge { - function initialize(address _l1Bridge, bytes32 _l2TokenProxyBytecodeHash, address _governor) external; + function initialize( + address _l1Bridge, + bytes32 _l2TokenProxyBytecodeHash, + address _governor + ) external; } diff --git a/ethereum/contracts/bridge/interfaces/IL2WethBridge.sol b/ethereum/contracts/bridge/interfaces/IL2WethBridge.sol index 94944a33cd..f4243d6f28 100644 --- a/ethereum/contracts/bridge/interfaces/IL2WethBridge.sol +++ b/ethereum/contracts/bridge/interfaces/IL2WethBridge.sol @@ -3,5 +3,9 @@ pragma solidity ^0.8.13; interface IL2WethBridge { - function initialize(address _l1Bridge, address _l1WethAddress, address _l2WethAddress) external; + function initialize( + address _l1Bridge, + address _l1WethAddress, + address _l2WethAddress + ) external; } diff --git a/ethereum/contracts/bridgehead/Bridgehead.sol b/ethereum/contracts/bridgehead/Bridgehead.sol index e553f0a99f..1ca60dc978 100644 --- a/ethereum/contracts/bridgehead/Bridgehead.sol +++ b/ethereum/contracts/bridgehead/Bridgehead.sol @@ -15,7 +15,7 @@ contract Bridgehead is BridgeheadGetters, BridgeheadMailbox, Registry { IAllowList _allowList, uint256 _priorityTxMaxGasLimit ) public { - require(bridgeheadStorage.chainImplementation == address(0), "r1"); + require(bridgeheadStorage.chainImplementation == address(0), "bridgehead1"); bridgeheadStorage.governor = _governor; bridgeheadStorage.chainImplementation = _chainImplementation; bridgeheadStorage.chainProxyAdmin = _chainProxyAdmin; diff --git a/ethereum/contracts/bridgehead/bridgehead-deps/BridgeheadMailbox.sol b/ethereum/contracts/bridgehead/bridgehead-deps/BridgeheadMailbox.sol index 9bbd6806b8..bdf970ef57 100644 --- a/ethereum/contracts/bridgehead/bridgehead-deps/BridgeheadMailbox.sol +++ b/ethereum/contracts/bridgehead/bridgehead-deps/BridgeheadMailbox.sol @@ -14,7 +14,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { uint256 _l2TxNumberInBlock ) external view override returns (bool) { address chainContract = bridgeheadStorage.chainContract[_chainId]; - require(chainContract != address(0), "r1"); return IBridgeheadChain(chainContract).isEthWithdrawalFinalized(_l2MessageIndex, _l2TxNumberInBlock); } @@ -26,7 +25,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { bytes32[] calldata _proof ) external view override returns (bool) { address chainContract = bridgeheadStorage.chainContract[_chainId]; - require(chainContract != address(0), "r1"); return IBridgeheadChain(chainContract).proveL2MessageInclusion(_blockNumber, _index, _message, _proof); } @@ -38,7 +36,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { bytes32[] calldata _proof ) external view override returns (bool) { address chainContract = bridgeheadStorage.chainContract[_chainId]; - require(chainContract != address(0), "r1"); return IBridgeheadChain(chainContract).proveL2LogInclusion(_blockNumber, _index, _log, _proof); } @@ -52,7 +49,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { TxStatus _status ) external view override returns (bool) { address chainContract = bridgeheadStorage.chainContract[_chainId]; - require(chainContract != address(0), "r1"); return IBridgeheadChain(chainContract).proveL1ToL2TransactionStatus( _l2TxHash, @@ -75,7 +71,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { address _refundRecipient ) public payable override returns (bytes32 canonicalTxHash) { address chainContract = bridgeheadStorage.chainContract[_chainId]; - canonicalTxHash = IBridgeheadChain(chainContract).requestL2TransactionBridgehead{value: msg.value}( msg.sender, _contractL2, @@ -97,7 +92,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { bytes32[] calldata _merkleProof ) external override { address chainContract = bridgeheadStorage.chainContract[_chainId]; - return IBridgeheadChain(chainContract).finalizeEthWithdrawalBridgehead( msg.sender, @@ -113,7 +107,11 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { /// @notice Transfer ether from the contract to the receiver /// @dev Reverts only if the transfer call failed - function withdrawFunds(uint256 _chainId, address _to, uint256 _amount) external onlyChainContract(_chainId) { + function withdrawFunds( + uint256 _chainId, + address _to, + uint256 _amount + ) external onlyChainContract(_chainId) { bool callSuccess; // Low-level assembly call, to avoid any memory copying (save gas) assembly { @@ -122,18 +120,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { require(callSuccess, "pz"); } - function requestL2TransactionProof( - uint256 _chainId, - WritePriorityOpParams memory _params, - bytes calldata _calldata, - bytes[] calldata _factoryDeps, - bool _isFree - ) external override returns (bytes32 canonicalTxHash) { - address chainContract = bridgeheadStorage.chainContract[_chainId]; - require(chainContract != address(0), "r1"); - return IBridgeheadChain(chainContract).requestL2TransactionProof(_params, _calldata, _factoryDeps, _isFree); - } - function l2TransactionBaseCost( uint256 _chainId, uint256 _gasPrice, @@ -141,7 +127,6 @@ contract BridgeheadMailbox is BridgeheadBase, IBridgeheadMailbox { uint256 _l2GasPerPubdataByteLimit ) external view returns (uint256) { address chainContract = bridgeheadStorage.chainContract[_chainId]; - require(chainContract != address(0), "r1"); return IBridgeheadChain(chainContract).l2TransactionBaseCost(_gasPrice, _l2GasLimit, _l2GasPerPubdataByteLimit); } } diff --git a/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadForProof.sol b/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadForProof.sol index 3374162b98..5c9972d8bc 100644 --- a/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadForProof.sol +++ b/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadForProof.sol @@ -13,7 +13,11 @@ interface IBridgeheadForProof is IBridgeheadBase { function collectOperationsFromPriorityQueue(uint256 _chainId, uint256 _index) external returns (bytes32 concatHash); /// @notice Adding txs to the priority queue - function addL2Logs(uint256 _chainId, uint256 _index, bytes32 _l2LogsRootHashes) external; + function addL2Logs( + uint256 _chainId, + uint256 _index, + bytes32 _l2LogsRootHashes + ) external; function requestL2TransactionProof( uint256 _chainId, diff --git a/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol b/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol index 36f493b344..faf8982abf 100644 --- a/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol +++ b/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol @@ -9,7 +9,11 @@ import "../chain-interfaces/IMailboxEvents.sol"; interface IBridgeheadMailbox is IMailboxEvents { function deposit(uint256 _chainId) external payable; - function withdrawFunds(uint256 _chainId, address _to, uint256 _amount) external; + function withdrawFunds( + uint256 _chainId, + address _to, + uint256 _amount + ) external; function isEthWithdrawalFinalized( uint256 _chainId, diff --git a/ethereum/contracts/bridgehead/chain-deps/ChainExecutor.sol b/ethereum/contracts/bridgehead/chain-deps/ChainExecutor.sol index 3bde79f8fb..ee4d9c21e3 100644 --- a/ethereum/contracts/bridgehead/chain-deps/ChainExecutor.sol +++ b/ethereum/contracts/bridgehead/chain-deps/ChainExecutor.sol @@ -21,9 +21,13 @@ contract ChainExecutor is IChainExecutor, ChainBase { function executeBlocks() external override nonReentrant {} /// @return concatHash , Returns the concatenated Hash of operations from the priority queue - function collectOperationsFromPriorityQueue( - uint256 _nPriorityOps - ) external override nonReentrant onlyProofChain returns (bytes32 concatHash) { + function collectOperationsFromPriorityQueue(uint256 _nPriorityOps) + external + override + nonReentrant + onlyProofChain + returns (bytes32 concatHash) + { concatHash = EMPTY_STRING_KECCAK; require(_nPriorityOps <= chainStorage.priorityQueue.getSize(), "g1"); diff --git a/ethereum/contracts/bridgehead/chain-deps/Mailbox.sol b/ethereum/contracts/bridgehead/chain-deps/Mailbox.sol index 385c4ef852..de04bbb3d9 100644 --- a/ethereum/contracts/bridgehead/chain-deps/Mailbox.sol +++ b/ethereum/contracts/bridgehead/chain-deps/Mailbox.sol @@ -29,16 +29,15 @@ contract Mailbox is IMailbox, ChainBase { uint16 _l2TxNumberInBlock, bytes calldata _message, bytes32[] calldata _merkleProof - ) external onlyBridgehead { - return - _finalizeEthWithdrawalSender( - _sender, - _l2BlockNumber, - _l2MessageIndex, - _l2TxNumberInBlock, - _message, - _merkleProof - ); + ) external onlyBridgehead knownSenderCanCallFunction(_sender, chainStorage.allowList) { + _finalizeEthWithdrawalSender( + _sender, + _l2BlockNumber, + _l2MessageIndex, + _l2TxNumberInBlock, + _message, + _merkleProof + ); } // this is implemented in the bridghead, does not go through the router. @@ -51,7 +50,13 @@ contract Mailbox is IMailbox, ChainBase { uint256 _l2GasPerPubdataByteLimit, bytes[] calldata _factoryDeps, address _refundRecipient - ) external payable onlyBridgehead returns (bytes32 canonicalTxHash) { + ) + external + payable + onlyBridgehead + knownSenderCanCallFunction(_sender, chainStorage.allowList) + returns (bytes32 canonicalTxHash) + { canonicalTxHash = _requestL2TransactionSender( _sender, _contractL2, @@ -143,7 +148,7 @@ contract Mailbox is IMailbox, ChainBase { ) internal view returns (bool) { // kl todo is this even needed? as we only add logs in executeblocks. // But if it is needed we need to update totalBlocksExecuted - // require(_blockNumber <= chainStorage.totalBlocksExecuted, "xx"); + require(_blockNumber <= chainStorage.totalBlocksExecuted, "xx"); bytes32 hashedLog = keccak256( abi.encodePacked(_log.l2ShardId, _log.isService, _log.txNumberInBlock, _log.sender, _log.key, _log.value) @@ -211,7 +216,7 @@ contract Mailbox is IMailbox, ChainBase { uint16 _l2TxNumberInBlock, bytes calldata _message, bytes32[] calldata _merkleProof - ) public override { + ) public override knownSenderCanCallFunction(msg.sender, chainStorage.allowList) { _finalizeEthWithdrawalSender( msg.sender, _l2BlockNumber, @@ -235,7 +240,7 @@ contract Mailbox is IMailbox, ChainBase { uint16 _l2TxNumberInBlock, bytes calldata _message, bytes32[] calldata _merkleProof - ) public nonReentrant knownSenderCanCallFunction(_sender, chainStorage.allowList) { + ) internal nonReentrant { require(!chainStorage.isEthWithdrawalFinalized[_l2BlockNumber][_l2MessageIndex], "jj"); L2Message memory l2ToL1Message = L2Message({ @@ -267,7 +272,7 @@ contract Mailbox is IMailbox, ChainBase { uint256 _l2GasPerPubdataByteLimit, bytes[] calldata _factoryDeps, address _refundRecipient - ) public payable returns (bytes32 canonicalTxHash) { + ) public payable knownSenderCanCallFunction(msg.sender, chainStorage.allowList) returns (bytes32 canonicalTxHash) { canonicalTxHash = _requestL2TransactionSender( msg.sender, _contractL2, @@ -307,12 +312,7 @@ contract Mailbox is IMailbox, ChainBase { uint256 _l2GasPerPubdataByteLimit, bytes[] calldata _factoryDeps, address _refundRecipient - ) - internal - nonReentrant - knownSenderCanCallFunction(_sender, chainStorage.allowList) - returns (bytes32 canonicalTxHash) - { + ) internal nonReentrant returns (bytes32 canonicalTxHash) { // Change the sender address if it is a smart contract to prevent address collision between L1 and L2. // Please note, currently zkSync address derivation is different from Ethereum one, but it may be changed in the future. address sender = _sender; @@ -457,9 +457,11 @@ contract Mailbox is IMailbox, ChainBase { } /// @notice Hashes the L2 bytecodes and returns them in the format in which they are processed by the bootloader - function _hashFactoryDeps( - bytes[] calldata _factoryDeps - ) internal pure returns (uint256[] memory hashedFactoryDeps) { + function _hashFactoryDeps(bytes[] calldata _factoryDeps) + internal + pure + returns (uint256[] memory hashedFactoryDeps) + { uint256 factoryDepsLen = _factoryDeps.length; hashedFactoryDeps = new uint256[](factoryDepsLen); for (uint256 i = 0; i < factoryDepsLen; i = i.uncheckedInc()) { @@ -473,9 +475,11 @@ contract Mailbox is IMailbox, ChainBase { } /// @dev Decode the withdraw message that came from L2 - function _parseL2WithdrawalMessage( - bytes memory _message - ) internal pure returns (address l1Receiver, uint256 amount) { + function _parseL2WithdrawalMessage(bytes memory _message) + internal + pure + returns (address l1Receiver, uint256 amount) + { // We check that the message is long enough to read the data. // Please note that there are two versions of the message: // 1. The message that is sent by `withdraw(address _l1Receiver)` diff --git a/ethereum/contracts/common/AllowListed.sol b/ethereum/contracts/common/AllowListed.sol index c0d0984ae2..b151fac668 100644 --- a/ethereum/contracts/common/AllowListed.sol +++ b/ethereum/contracts/common/AllowListed.sol @@ -17,7 +17,7 @@ abstract contract AllowListed { modifier knownSenderCanCallFunction(address _sender, IAllowList _allowList) { // Preventing the stack too deep error { - require(_allowList.canCall(_sender, address(this), msg.sig), "nr"); + require(_allowList.canCall(_sender, address(this), msg.sig), "nr2"); } _; } diff --git a/ethereum/contracts/common/interfaces/IAllowList.sol b/ethereum/contracts/common/interfaces/IAllowList.sol index bf58b9bb2c..77baff660e 100644 --- a/ethereum/contracts/common/interfaces/IAllowList.sol +++ b/ethereum/contracts/common/interfaces/IAllowList.sol @@ -37,9 +37,17 @@ interface IAllowList { function getAccessMode(address _target) external view returns (AccessMode); - function hasSpecialAccessToCall(address _caller, address _target, bytes4 _functionSig) external view returns (bool); - - function canCall(address _caller, address _target, bytes4 _functionSig) external view returns (bool); + function hasSpecialAccessToCall( + address _caller, + address _target, + bytes4 _functionSig + ) external view returns (bool); + + function canCall( + address _caller, + address _target, + bytes4 _functionSig + ) external view returns (bool); function getTokenDepositLimitData(address _l1Token) external view returns (Deposit memory); @@ -58,11 +66,20 @@ interface IAllowList { bool[] calldata _enables ) external; - function setPermissionToCall(address _caller, address _target, bytes4 _functionSig, bool _enable) external; + function setPermissionToCall( + address _caller, + address _target, + bytes4 _functionSig, + bool _enable + ) external; /*////////////////////////////////////////////////////////////// DEPOSIT LIMIT LOGIC //////////////////////////////////////////////////////////////*/ - function setDepositLimit(address _l1Token, bool _depositLimitation, uint256 _depositCap) external; + function setDepositLimit( + address _l1Token, + bool _depositLimitation, + uint256 _depositCap + ) external; } diff --git a/ethereum/contracts/common/interfaces/IL2ContractDeployer.sol b/ethereum/contracts/common/interfaces/IL2ContractDeployer.sol index 8222392c5a..1b48676d52 100644 --- a/ethereum/contracts/common/interfaces/IL2ContractDeployer.sol +++ b/ethereum/contracts/common/interfaces/IL2ContractDeployer.sol @@ -28,5 +28,9 @@ interface IL2ContractDeployer { /// @param _salt The create2 salt. /// @param _bytecodeHash The correctly formatted hash of the bytecode. /// @param _input The constructor calldata. - function create2(bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input) external; + function create2( + bytes32 _salt, + bytes32 _bytecodeHash, + bytes calldata _input + ) external; } diff --git a/ethereum/contracts/common/libraries/Diamond.sol b/ethereum/contracts/common/libraries/Diamond.sol index 34afac430b..01ed7da8d5 100644 --- a/ethereum/contracts/common/libraries/Diamond.sol +++ b/ethereum/contracts/common/libraries/Diamond.sol @@ -121,7 +121,11 @@ library Diamond { /// @dev Add new functions to the diamond proxy /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array - function _addFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private { + function _addFunctions( + address _facet, + bytes4[] memory _selectors, + bool _isFacetFreezable + ) private { DiamondStorage storage ds = getDiamondStorage(); require(_facet != address(0), "G"); // facet with zero address cannot be added @@ -141,7 +145,11 @@ library Diamond { /// @dev Change associated facets to already known function selectors /// NOTE: expect but NOT enforce that `_selectors` is NON-EMPTY array - function _replaceFunctions(address _facet, bytes4[] memory _selectors, bool _isFacetFreezable) private { + function _replaceFunctions( + address _facet, + bytes4[] memory _selectors, + bool _isFacetFreezable + ) private { DiamondStorage storage ds = getDiamondStorage(); require(_facet != address(0), "K"); // cannot replace facet with zero address @@ -194,7 +202,11 @@ library Diamond { /// - `_facet` is NON-ZERO address /// - `_facet` is already stored address in `DiamondStorage.facets` /// - `_selector` is NOT associated by another facet - function _addOneFunction(address _facet, bytes4 _selector, bool _isSelectorFreezable) private { + function _addOneFunction( + address _facet, + bytes4 _selector, + bool _isSelectorFreezable + ) private { DiamondStorage storage ds = getDiamondStorage(); uint16 selectorPosition = (ds.facetToSelectors[_facet].selectors.length).toUint16(); diff --git a/ethereum/contracts/common/libraries/L2ContractHelper.sol b/ethereum/contracts/common/libraries/L2ContractHelper.sol index 3605556b14..ad9e876080 100644 --- a/ethereum/contracts/common/libraries/L2ContractHelper.sol +++ b/ethereum/contracts/common/libraries/L2ContractHelper.sol @@ -22,7 +22,7 @@ library L2ContractHelper { require(_bytecode.length % 32 == 0, "bl"); uint256 bytecodeLenInWords = _bytecode.length / 32; - require(bytecodeLenInWords < 2 ** 16, "pp"); // bytecode length must be less than 2^16 words + require(bytecodeLenInWords < 2**16, "pp"); // bytecode length must be less than 2^16 words require(bytecodeLenInWords % 2 == 1, "pr"); // bytecode length in words must be odd hashedBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // Setting the version of the hash diff --git a/ethereum/contracts/dev-contracts/test/DummyExecutor.sol b/ethereum/contracts/dev-contracts/test/DummyExecutor.sol index ef997ebdae..6e7170f3a6 100644 --- a/ethereum/contracts/dev-contracts/test/DummyExecutor.sol +++ b/ethereum/contracts/dev-contracts/test/DummyExecutor.sol @@ -6,7 +6,7 @@ import "../../proof-system/chain-interfaces/IExecutor.sol"; /// @title DummyExecutor /// @notice A test smart contract implementing the IExecutor interface to simulate Executor behavior for testing purposes. -contract DummyExecutor is IProofExecutor { +contract DummyExecutor is IExecutor { address owner; // Flags to control if the contract should revert during commit, prove, and execute blocks operations @@ -52,10 +52,9 @@ contract DummyExecutor is IProofExecutor { shouldRevertOnExecuteBlocks = _shouldRevert; } - function commitBlocks( - StoredBlockInfo calldata _lastCommittedBlockData, - CommitBlockInfo[] calldata _newBlocksData - ) external { + function commitBlocks(StoredBlockInfo calldata _lastCommittedBlockData, CommitBlockInfo[] calldata _newBlocksData) + external + { require(!shouldRevertOnCommitBlocks, "DummyExecutor: shouldRevertOnCommitBlocks"); require( _lastCommittedBlockData.blockNumber == getTotalBlocksCommitted, @@ -81,7 +80,7 @@ contract DummyExecutor is IProofExecutor { require(_committedBlocks.length == 1, "DummyExecutor: Can prove only one block"); require( _committedBlocks[0].blockNumber == _prevBlock.blockNumber + 1, - "DummyExecutor: Can't prove block out of order" + "DummyExecutor 1: Can't prove block out of order" ); getTotalBlocksVerified += 1; @@ -100,7 +99,7 @@ contract DummyExecutor is IProofExecutor { getTotalBlocksExecuted += nBlocks; require( getTotalBlocksExecuted <= getTotalBlocksVerified, - "DummyExecutor: Can't execute blocks more than committed and proven currently" + "DummyExecutor 2: Can't execute blocks more than committed and proven currently" ); } diff --git a/ethereum/contracts/dev-contracts/test/GovernanceFacetTest.sol b/ethereum/contracts/dev-contracts/test/GovernanceFacetTest.sol index 2b65a166f2..3116692f67 100644 --- a/ethereum/contracts/dev-contracts/test/GovernanceFacetTest.sol +++ b/ethereum/contracts/dev-contracts/test/GovernanceFacetTest.sol @@ -9,6 +9,10 @@ contract GovernanceFacetTest is GovernanceFacet { chainStorage.governor = msg.sender; } + function isValidator(address _validator) external view returns (bool) { + return chainStorage.validators[_validator]; + } + function getPendingGovernor() external view returns (address) { return chainStorage.pendingGovernor; } diff --git a/ethereum/contracts/dev-contracts/test/TransactionValidatorTest.sol b/ethereum/contracts/dev-contracts/test/TransactionValidatorTest.sol index 24536f7fe1..2b27f0b44f 100644 --- a/ethereum/contracts/dev-contracts/test/TransactionValidatorTest.sol +++ b/ethereum/contracts/dev-contracts/test/TransactionValidatorTest.sol @@ -8,10 +8,10 @@ import "../../bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol"; import "../../common/Messaging.sol"; contract TransactionValidatorTest { - function validateL1ToL2Transaction( - L2CanonicalTransaction memory _transaction, - uint256 _priorityTxMaxGasLimit - ) external pure { + function validateL1ToL2Transaction(L2CanonicalTransaction memory _transaction, uint256 _priorityTxMaxGasLimit) + external + pure + { TransactionValidator.validateL1ToL2Transaction(_transaction, abi.encode(_transaction), _priorityTxMaxGasLimit); } diff --git a/ethereum/contracts/dev-contracts/test/UnsafeBytesTest.sol b/ethereum/contracts/dev-contracts/test/UnsafeBytesTest.sol index 838ba669f4..aa24afc44f 100644 --- a/ethereum/contracts/dev-contracts/test/UnsafeBytesTest.sol +++ b/ethereum/contracts/dev-contracts/test/UnsafeBytesTest.sol @@ -11,24 +11,27 @@ contract UnsafeBytesTest { return _bytes.readUint32(_start); } - function readAddress( - bytes memory _bytes, - uint256 _start - ) external pure returns (address readValue, uint256 offset) { + function readAddress(bytes memory _bytes, uint256 _start) + external + pure + returns (address readValue, uint256 offset) + { return _bytes.readAddress(_start); } - function readUint256( - bytes memory _bytes, - uint256 _start - ) external pure returns (uint256 readValue, uint256 offset) { + function readUint256(bytes memory _bytes, uint256 _start) + external + pure + returns (uint256 readValue, uint256 offset) + { return _bytes.readUint256(_start); } - function readBytes32( - bytes memory _bytes, - uint256 _start - ) external pure returns (bytes32 readValue, uint256 offset) { + function readBytes32(bytes memory _bytes, uint256 _start) + external + pure + returns (bytes32 readValue, uint256 offset) + { return _bytes.readBytes32(_start); } } diff --git a/ethereum/contracts/proof-system/ProofDiamondProxy.sol b/ethereum/contracts/proof-system/DiamondProxy.sol similarity index 98% rename from ethereum/contracts/proof-system/ProofDiamondProxy.sol rename to ethereum/contracts/proof-system/DiamondProxy.sol index 853e5917e8..78ce0c02c5 100644 --- a/ethereum/contracts/proof-system/ProofDiamondProxy.sol +++ b/ethereum/contracts/proof-system/DiamondProxy.sol @@ -6,7 +6,7 @@ import "../common/libraries/Diamond.sol"; /// @title Diamond Proxy Contract (EIP-2535) /// @author Matter Labs -contract ProofDiamondProxy { +contract DiamondProxy { constructor(uint256 _chainId, Diamond.DiamondCutData memory _diamondCut) { // Check that the contract is deployed on the expected chain. // Thus, the contract deployed by the same Create2 factory on the different chain will have different addresses! diff --git a/ethereum/contracts/proof-system/ProofSystem.sol b/ethereum/contracts/proof-system/ProofSystem.sol index 5496aba4b7..aa79792f17 100644 --- a/ethereum/contracts/proof-system/ProofSystem.sol +++ b/ethereum/contracts/proof-system/ProofSystem.sol @@ -41,7 +41,7 @@ contract ProofSystem is ProofGetters, ProofRegistry { proofStorage.governor = _governor; // We need to initialize the state hash because it is used in the commitment of the next block - IProofExecutor.StoredBlockInfo memory storedBlockZero = IProofExecutor.StoredBlockInfo( + IExecutor.StoredBlockInfo memory storedBlockZero = IExecutor.StoredBlockInfo( 0, _genesisBlockHash, _genesisIndexRepeatedStorageChanges, diff --git a/ethereum/contracts/proof-system/ValidatorTimelock.sol b/ethereum/contracts/proof-system/ValidatorTimelock.sol index 45404991cb..ca11b9c503 100644 --- a/ethereum/contracts/proof-system/ValidatorTimelock.sol +++ b/ethereum/contracts/proof-system/ValidatorTimelock.sol @@ -15,7 +15,7 @@ import "./chain-interfaces/IExecutor.sol"; /// @dev The contract overloads all of the 4 methods, that are used in state transition. When the block is committed, /// the timestamp is stored for it. Later, when the owner calls the block execution, the contract checks that block /// was committed not earlier than X time ago. -contract ValidatorTimelock is IProofExecutor, Ownable2Step { +contract ValidatorTimelock is IExecutor, Ownable2Step { /// @dev Part of the IBase interface. Not used in this contract. string public constant getName = "ValidatorTimelock"; @@ -26,7 +26,7 @@ contract ValidatorTimelock is IProofExecutor, Ownable2Step { event NewValidator(address _oldValidator, address _newValidator); /// @dev The main zkSync smart contract. - address public immutable proofSystemContract; + address public immutable diamondProxy; /// @dev The mapping of L2 block number => timestamp when it was commited. mapping(uint256 => uint256) public committedBlockTimestamp; @@ -37,9 +37,9 @@ contract ValidatorTimelock is IProofExecutor, Ownable2Step { /// @dev The delay between committing and executing blocks. uint256 public executionDelay; - constructor(address _initialOwner, address _proofSystemContract, uint256 _executionDelay, address _validator) { + constructor(address _initialOwner, address _diamondProxy, uint256 _executionDelay, address _validator) { _transferOwnership(_initialOwner); - proofSystemContract = _proofSystemContract; + diamondProxy = _diamondProxy; executionDelay = _executionDelay; validator = _validator; } @@ -111,7 +111,7 @@ contract ValidatorTimelock is IProofExecutor, Ownable2Step { /// @dev Call the zkSync contract with the same calldata as this contract was called. /// Note: it is called the zkSync contract, not delegatecalled! function _propagateToZkSync() internal { - address contractAddress = proofSystemContract; + address contractAddress = diamondProxy; assembly { // Copy function signature and arguments from calldata at zero position into memory at pointer position calldatacopy(0, 0, calldatasize()) diff --git a/ethereum/contracts/proof-system/chain-deps/facets/DiamondCut.sol b/ethereum/contracts/proof-system/chain-deps/facets/DiamondCut.sol index 42510e131c..15cf12d2f8 100644 --- a/ethereum/contracts/proof-system/chain-deps/facets/DiamondCut.sol +++ b/ethereum/contracts/proof-system/chain-deps/facets/DiamondCut.sol @@ -10,7 +10,7 @@ import "./Base.sol"; /// @title DiamondCutFacet - contract responsible for the management of upgrades. /// @author Matter Labs -contract DiamondCutFacet is ProofChainBase, IProofDiamondCut { +contract DiamondCutFacet is ProofChainBase, IDiamondCut { using UncheckedMath for uint256; string public constant getName = "DiamondCutFacet"; @@ -35,10 +35,11 @@ contract DiamondCutFacet is ProofChainBase, IProofDiamondCut { /// - With security council approvals instantly /// @dev Only the current governor can propose an upgrade /// @param _diamondCut The diamond cut parameters will be executed with the upgrade - function proposeTransparentUpgrade( - Diamond.DiamondCutData calldata _diamondCut, - uint40 _proposalId - ) external onlyGovernor noUpgradeProposed { + function proposeTransparentUpgrade(Diamond.DiamondCutData calldata _diamondCut, uint40 _proposalId) + external + onlyGovernor + noUpgradeProposed + { // Set the default value for proposal salt, since the proposal is fully transparent it doesn't change anything bytes32 proposalSalt; uint40 expectedProposalId = chainStorage.upgrades.currentProposalId + 1; diff --git a/ethereum/contracts/proof-system/chain-deps/facets/Executor.sol b/ethereum/contracts/proof-system/chain-deps/facets/Executor.sol index f64f7a9c73..d415fc29ee 100644 --- a/ethereum/contracts/proof-system/chain-deps/facets/Executor.sol +++ b/ethereum/contracts/proof-system/chain-deps/facets/Executor.sol @@ -12,7 +12,7 @@ import {L2_BOOTLOADER_ADDRESS, L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, L2_SYSTE /// @title zkSync Executor contract capable of processing events emitted in the zkSync protocol. /// @author Matter Labs -contract ExecutorFacet is ProofChainBase, IProofExecutor { +contract ExecutorFacet is ProofChainBase, IExecutor { using UncheckedMath for uint256; string public constant override getName = "ExecutorFacet"; @@ -101,10 +101,7 @@ contract ExecutorFacet is ProofChainBase, IProofExecutor { } /// @dev Check that L2 logs are proper and block contain all meta information for them - function _processL2Logs( - CommitBlockInfo calldata _newBlock, - bytes32 _expectedSystemContractUpgradeTxHash - ) + function _processL2Logs(CommitBlockInfo calldata _newBlock, bytes32 _expectedSystemContractUpgradeTxHash) internal pure returns ( @@ -177,10 +174,12 @@ contract ExecutorFacet is ProofChainBase, IProofExecutor { /// @notice 1. Checks timestamp. /// @notice 2. Process L2 logs. /// @notice 3. Store block commitments. - function commitBlocks( - StoredBlockInfo memory _lastCommittedBlockData, - CommitBlockInfo[] calldata _newBlocksData - ) external override nonReentrant onlyValidator { + function commitBlocks(StoredBlockInfo memory _lastCommittedBlockData, CommitBlockInfo[] calldata _newBlocksData) + external + override + nonReentrant + onlyValidator + { // Check that we commit blocks after last committed block require( chainStorage.storedBlockHashes[chainStorage.totalBlocksCommitted] == diff --git a/ethereum/contracts/proof-system/chain-deps/facets/Getters.sol b/ethereum/contracts/proof-system/chain-deps/facets/Getters.sol index 290e96161e..3c7f4c3cb9 100644 --- a/ethereum/contracts/proof-system/chain-deps/facets/Getters.sol +++ b/ethereum/contracts/proof-system/chain-deps/facets/Getters.sol @@ -10,7 +10,7 @@ import "../../chain-interfaces/IGetters.sol"; /// @title Getters Contract implements functions for getting contract state from outside the blockchain. /// @author Matter Labs -contract GettersFacet is ProofChainBase, IProofGetters { +contract GettersFacet is ProofChainBase, IGetters { using UncheckedMath for uint256; // using PriorityQueue for PriorityQueue.Queue; diff --git a/ethereum/contracts/proof-system/chain-deps/facets/Governance.sol b/ethereum/contracts/proof-system/chain-deps/facets/Governance.sol index 5ce4828b85..6609475488 100644 --- a/ethereum/contracts/proof-system/chain-deps/facets/Governance.sol +++ b/ethereum/contracts/proof-system/chain-deps/facets/Governance.sol @@ -7,7 +7,7 @@ import "./Base.sol"; /// @title Governance Contract controls access rights for contract management. /// @author Matter Labs -contract GovernanceFacet is ProofChainBase, IProofGovernance { +contract GovernanceFacet is ProofChainBase, IGovernance { string public constant override getName = "GovernanceFacet"; /// @notice Starts the transfer of governor rights. Only the current governor can propose a new pending one. diff --git a/ethereum/contracts/proof-system/chain-interfaces/IDiamondCut.sol b/ethereum/contracts/proof-system/chain-interfaces/IDiamondCut.sol index f92534feea..cb4fe51ae5 100644 --- a/ethereum/contracts/proof-system/chain-interfaces/IDiamondCut.sol +++ b/ethereum/contracts/proof-system/chain-interfaces/IDiamondCut.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.13; import "../../common/libraries/Diamond.sol"; import "./IBase.sol"; -interface IProofDiamondCut is IProofChainBase { +interface IDiamondCut is IProofChainBase { function proposeTransparentUpgrade(Diamond.DiamondCutData calldata _diamondCut, uint40 _proposalId) external; function proposeShadowUpgrade(bytes32 _proposalHash, uint40 _proposalId) external; diff --git a/ethereum/contracts/proof-system/chain-interfaces/IExecutor.sol b/ethereum/contracts/proof-system/chain-interfaces/IExecutor.sol index 3c0b7efe94..e2b0d17f55 100644 --- a/ethereum/contracts/proof-system/chain-interfaces/IExecutor.sol +++ b/ethereum/contracts/proof-system/chain-interfaces/IExecutor.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.13; import "./IBase.sol"; -interface IProofExecutor is IProofChainBase { +interface IExecutor is IProofChainBase { /// @notice Rollup block stored data /// @param blockNumber Rollup block number /// @param blockHash Hash of L2 block @@ -59,10 +59,8 @@ interface IProofExecutor is IProofChainBase { uint256[] serializedProof; } - function commitBlocks( - StoredBlockInfo calldata _lastCommittedBlockData, - CommitBlockInfo[] calldata _newBlocksData - ) external; + function commitBlocks(StoredBlockInfo calldata _lastCommittedBlockData, CommitBlockInfo[] calldata _newBlocksData) + external; function proveBlocks( StoredBlockInfo calldata _prevBlock, diff --git a/ethereum/contracts/proof-system/chain-interfaces/IGetters.sol b/ethereum/contracts/proof-system/chain-interfaces/IGetters.sol index 1a69c0a728..ba692ea9f2 100644 --- a/ethereum/contracts/proof-system/chain-interfaces/IGetters.sol +++ b/ethereum/contracts/proof-system/chain-interfaces/IGetters.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.13; import {VerifierParams, ProofUpgradeState} from "../chain-deps/ProofChainStorage.sol"; import "./IBase.sol"; -interface IProofGetters is IProofChainBase { +interface IGetters is IProofChainBase { /*////////////////////////////////////////////////////////////// CUSTOM GETTERS //////////////////////////////////////////////////////////////*/ diff --git a/ethereum/contracts/proof-system/chain-interfaces/IGovernance.sol b/ethereum/contracts/proof-system/chain-interfaces/IGovernance.sol index 6435a646fd..f23fd8b873 100644 --- a/ethereum/contracts/proof-system/chain-interfaces/IGovernance.sol +++ b/ethereum/contracts/proof-system/chain-interfaces/IGovernance.sol @@ -7,7 +7,7 @@ import "../Verifier.sol"; import "../chain-deps/ProofChainStorage.sol"; import "./IBase.sol"; -interface IProofGovernance is IProofChainBase { +interface IGovernance is IProofChainBase { function setPendingGovernor(address _newPendingGovernor) external; function acceptGovernor() external; diff --git a/ethereum/contracts/proof-system/chain-interfaces/IProofChain.sol b/ethereum/contracts/proof-system/chain-interfaces/IProofChain.sol index 80f0f0cf5f..ac095a4244 100644 --- a/ethereum/contracts/proof-system/chain-interfaces/IProofChain.sol +++ b/ethereum/contracts/proof-system/chain-interfaces/IProofChain.sol @@ -11,7 +11,7 @@ import "./IGetters.sol"; // kl to do remove this, needed for the server for now import "../../common/libraries/Diamond.sol"; -interface IProofChain is IProofGovernance, IProofExecutor, IProofGetters { +interface IProofChain is IGovernance, IExecutor, IGetters { function initialize( uint256 _chainId, address _bridgeheadChainContract, diff --git a/ethereum/contracts/proof-system/proof-system-deps/ProofRegistry.sol b/ethereum/contracts/proof-system/proof-system-deps/ProofRegistry.sol index 96b8105bae..ee6c0af5e2 100644 --- a/ethereum/contracts/proof-system/proof-system-deps/ProofRegistry.sol +++ b/ethereum/contracts/proof-system/proof-system-deps/ProofRegistry.sol @@ -17,7 +17,7 @@ import "../../bridgehead/chain-interfaces/IBridgeheadChain.sol"; // import "../chain-interfaces/IProofChain.sol"; -import "../ProofDiamondProxy.sol"; +import "../DiamondProxy.sol"; import "../chain-interfaces/IDiamondInit.sol"; /// @title Registry contract capable of handling new Hyperchains. @@ -65,7 +65,7 @@ contract ProofRegistry is ProofBase, IProofRegistry { Diamond.DiamondCutData memory cutData = _diamondCut; cutData.initCalldata = initData; - ProofDiamondProxy proofChainContract = new ProofDiamondProxy( + DiamondProxy proofChainContract = new DiamondProxy( block.chainid, cutData // _diamondCut diff --git a/ethereum/contracts/upgrades/DefaultUpgrade.sol b/ethereum/contracts/upgrades/DefaultUpgrade.sol index 160b2c1d49..395a85a195 100644 --- a/ethereum/contracts/upgrades/DefaultUpgrade.sol +++ b/ethereum/contracts/upgrades/DefaultUpgrade.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.13; import "../common/libraries/Diamond.sol"; import "./BaseZkSyncUpgrade.sol"; -contract ProofDefaultUpgrade is BaseZkSyncUpgrade { +contract DefaultUpgrade is BaseZkSyncUpgrade { /// @notice Placeholder function for custom logic for upgrading L1 contract. /// Typically this function will never be used. /// @param _customCallDataForUpgrade Custom data for an upgrade, which may be interpreted differently for each diff --git a/ethereum/src.ts/deploy-utils.ts b/ethereum/src.ts/deploy-utils.ts index 8cfdd5c67b..f50eed95bd 100644 --- a/ethereum/src.ts/deploy-utils.ts +++ b/ethereum/src.ts/deploy-utils.ts @@ -41,7 +41,7 @@ export async function deployViaCreate2( } const tx = await create2Factory.deploy(bytecode, create2Salt, ethTxOptions); - const receipt = await tx.wait(2); + const receipt = await tx.wait(1); const gasUsed = receipt.gasUsed; log(`${contractName} deployed, gasUsed: ${gasUsed.toString()}`); diff --git a/ethereum/src.ts/deploy.ts b/ethereum/src.ts/deploy.ts index 72390c9b1e..0b22879317 100644 --- a/ethereum/src.ts/deploy.ts +++ b/ethereum/src.ts/deploy.ts @@ -67,6 +67,7 @@ export interface DeployerConfig { deployWallet: Wallet; governorAddress?: string; verbose?: boolean; + addresses?: DeployedAddresses; } export function deployedAddressesFromEnv(): DeployedAddresses { @@ -110,11 +111,12 @@ export class Deployer { private deployWallet: Wallet; private verbose: boolean; private governorAddress: string; + public chainId: number; constructor(config: DeployerConfig) { this.deployWallet = config.deployWallet; this.verbose = config.verbose != null ? config.verbose : false; - this.addresses = deployedAddressesFromEnv(); + this.addresses = config.addresses ? config.addresses : deployedAddressesFromEnv(); this.governorAddress = config.governorAddress != null ? config.governorAddress : this.deployWallet.address; } @@ -128,9 +130,6 @@ export class Deployer { ) ); - // const genesisBlockHash = getHashFromEnv('CONTRACTS_GENESIS_ROOT'); // TODO: confusing name - // const genesisRollupLeafIndex = getNumberFromEnv('CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX'); - // const genesisBlockCommitment = getHashFromEnv('CONTRACTS_GENESIS_BLOCK_COMMITMENT'); const verifierParams = { recursionNodeLevelVkHash: getHashFromEnv('CONTRACTS_RECURSION_NODE_LEVEL_VK_HASH'), recursionLeafLevelVkHash: getHashFromEnv('CONTRACTS_RECURSION_LEAF_LEVEL_VK_HASH'), @@ -242,10 +241,13 @@ export class Deployer { console.log(`CONTRACTS_BRIDGEHEAD_CHAIN_PROXY_ADMIN_ADDR=${adminAddress}`); } - console.log( - `Bridgehead Chain Proxy deployed, gas used: ${(await instance.deployTransaction.wait()).gasUsed.toString()}` - ); - + if (this.verbose) { + console.log( + `Bridgehead Chain Proxy deployed, gas used: ${( + await instance.deployTransaction.wait() + ).gasUsed.toString()}` + ); + } this.addresses.Bridgehead.ChainProxyAdmin = adminAddress; } @@ -281,10 +283,11 @@ export class Deployer { console.log(`CONTRACTS_BRIDGEHEAD_PROXY_ADMIN_ADDR=${adminAddress}`); } - console.log( - `Bridgehead Proxy deployed, gas used: ${(await instance.deployTransaction.wait()).gasUsed.toString()}` - ); - + if (this.verbose) { + console.log( + `Bridgehead Proxy deployed, gas used: ${(await instance.deployTransaction.wait()).gasUsed.toString()}` + ); + } this.addresses.Bridgehead.BridgeheadProxyAdmin = adminAddress; } @@ -331,9 +334,11 @@ export class Deployer { console.log(`CONTRACTS_PROOF_SYSTEM_PROXY_ADMIN_ADDR=${adminAddress}`); } - console.log( - `ProofSystem Proxy deployed, gas used: ${(await instance.deployTransaction.wait()).gasUsed.toString()}` - ); + if (this.verbose) { + console.log( + `ProofSystem Proxy deployed, gas used: ${(await instance.deployTransaction.wait()).gasUsed.toString()}` + ); + } this.addresses.ProofSystem.ProofSystemProxyAdmin = adminAddress; } @@ -520,60 +525,38 @@ export class Deployer { public async deployBridgeheadContract(create2Salt: string, gasPrice?: BigNumberish, nonce?) { nonce = nonce ? parseInt(nonce) : await this.deployWallet.getTransactionCount(); - // deploy Bridgehead contract - // await this.deployChainImplementation(create2Salt, { gasPrice, nonce: nonce }); await this.deployBridgeheadChainProxy(create2Salt, { gasPrice, nonce: nonce + 0 }); - // await this.deployBridgeheadImplementation(create2Salt, { gasPrice, nonce: nonce + 2 }); - // await this.deployBridgeheadProxyAdmin(create2Salt, { gasPrice, nonce: nonce + 3 }); await this.deployBridgeheadProxy(create2Salt, { gasPrice, nonce: nonce + 1 }); } public async deployProofSystemContract(create2Salt: string, gasPrice?: BigNumberish, nonce?) { nonce = nonce ? parseInt(nonce) : await this.deployWallet.getTransactionCount(); - // deploy Bridgehead contract - // await this.deployVerifier(create2Salt, { gasPrice, nonce: nonce + 1 }); - // await this.deployChainImplementation(create2Salt, { gasPrice, nonce: nonce }); - await this.deployProofDiamond(create2Salt, gasPrice, nonce); - // await this.deployBridgeheadImplementation(create2Salt, { gasPrice, nonce: nonce + 2 }); - // await this.deployBridgeheadProxyAdmin(create2Salt, { gasPrice, nonce: nonce + 3 }); - await this.deployProofSystemProxy(create2Salt, { gasPrice, nonce: nonce + 1 }); + await this.deployProofDiamond(create2Salt, gasPrice); + await this.deployProofSystemProxy(create2Salt, { gasPrice }); await this.registerProofSystem(); } public async deployProofDiamond(create2Salt: string, gasPrice?: BigNumberish, nonce?) { nonce = nonce ? parseInt(nonce) : await this.deployWallet.getTransactionCount(); - // deploy Factory contract - const independentProofSystemDeployPromises = [ - this.deployProofExecutorFacet(create2Salt, { gasPrice, nonce: nonce }), - this.deployProofDiamondCutFacet(create2Salt, { gasPrice, nonce: nonce + 1 }), - this.deployProofGovernanceFacet(create2Salt, { gasPrice, nonce: nonce + 2 }), - this.deployProofGettersFacet(create2Salt, { gasPrice, nonce: nonce + 3 }), - this.deployVerifier(create2Salt, { gasPrice, nonce: nonce + 4 }), - this.deployProofDiamondInit(create2Salt, { gasPrice, nonce: nonce + 5 }) - ]; - await Promise.all(independentProofSystemDeployPromises); - nonce += 6; + await this.deployProofExecutorFacet(create2Salt, { gasPrice, nonce: nonce }); + await this.deployProofDiamondCutFacet(create2Salt, { gasPrice, nonce: nonce + 1 }); + await this.deployProofGovernanceFacet(create2Salt, { gasPrice, nonce: nonce + 2 }); + await this.deployProofGettersFacet(create2Salt, { gasPrice, nonce: nonce + 3 }); + await this.deployVerifier(create2Salt, { gasPrice, nonce: nonce + 4 }); + await this.deployProofDiamondInit(create2Salt, { gasPrice, nonce: nonce + 5 }); } public async registerProofSystem() { - // const gasLimit = 10_000_000; - - // nonce = nonce ? parseInt(nonce) : await this.deployWallet.getTransactionCount(); const bridgehead = this.bridgeheadContract(this.deployWallet); - const tx = await bridgehead.newProofSystem( - this.addresses.ProofSystem.ProofSystemProxy - // { - // gasPrice, - // nonce, - // gasLimit - // } - ); + const tx = await bridgehead.newProofSystem(this.addresses.ProofSystem.ProofSystemProxy); const receipt = await tx.wait(); - console.log(`Proof System registered, gas used: ${receipt.gasUsed.toString()}`); + if (this.verbose) { + console.log(`Proof System registered, gas used: ${receipt.gasUsed.toString()}`); + } // KL todo: ChainId is not a uint256 yet. } @@ -618,11 +601,14 @@ export class Deployer { this.addresses.Bridgehead.ChainProxy = contractAddress; this.addresses.ProofSystem.DiamondProxy = proofContractAddress; - console.log(`Hyperchain registered, gas used: ${receipt.gasUsed.toString()}`); - // KL todo: ChainId is not a uint256 yet. - console.log(`CHAIN_ETH_ZKSYNC_NETWORK_ID=${parseInt(chainId, 16)}`); - console.log(`CONTRACTS_BRIDGEHEAD_CHAIN_PROXY_ADDR=${contractAddress}`); - console.log(`CONTRACTS_DIAMOND_PROXY_ADDR=${proofContractAddress}`); + if (this.verbose) { + console.log(`Hyperchain registered, gas used: ${receipt.gasUsed.toString()}`); + // KL todo: ChainId is not a uint256 yet. + console.log(`CHAIN_ETH_ZKSYNC_NETWORK_ID=${parseInt(chainId, 16)}`); + console.log(`CONTRACTS_BRIDGEHEAD_CHAIN_PROXY_ADDR=${contractAddress}`); + console.log(`CONTRACTS_DIAMOND_PROXY_ADDR=${proofContractAddress}`); + } + this.chainId = parseInt(chainId, 16); } public async deployBridgeContracts(create2Salt: string, gasPrice?: BigNumberish, nonce?) { diff --git a/ethereum/src.ts/diamondCut.ts b/ethereum/src.ts/diamondCut.ts index ee4fd655c5..3929ab1bd1 100644 --- a/ethereum/src.ts/diamondCut.ts +++ b/ethereum/src.ts/diamondCut.ts @@ -2,8 +2,8 @@ import { Interface } from 'ethers/lib/utils'; import * as hardhat from 'hardhat'; import '@nomiclabs/hardhat-ethers'; import { ethers, Wallet } from 'ethers'; -import { IProofSystemFactory as IZkSyncFactory } from '../typechain/IProofSystemFactory'; -import { IProofChainBaseFactory as IBaseFactory } from '../typechain/IProofChainBaseFactory'; +import { IProofChainFactory } from '../typechain/IProofChainFactory'; +import { IProofChainBaseFactory } from '../typechain/IProofChainBaseFactory'; export enum Action { Add = 0, @@ -82,12 +82,12 @@ export async function getCurrentFacetCutsForAdd( } export async function getDeployedFacetCutsForRemove(wallet: Wallet, zkSyncAddress: string, updatedFaceNames: string[]) { - const mainContract = IZkSyncFactory.connect(zkSyncAddress, wallet); + const mainContract = IProofChainFactory.connect(zkSyncAddress, wallet); const diamondCutFacets = await mainContract.facets(); // We don't care about freezing, because we are removing the facets. const result = []; for (const { addr, selectors } of diamondCutFacets) { - const facet = IBaseFactory.connect(addr, wallet); + const facet = IProofChainBaseFactory.connect(addr, wallet); const facetName = await facet.getName(); if (updatedFaceNames.includes(facetName)) { result.push({ diff --git a/ethereum/test/unit_tests/diamond_cut_test.spec.ts b/ethereum/test/unit_tests/diamond_cut_test.spec.ts index 8fb5d7516b..f143056aec 100644 --- a/ethereum/test/unit_tests/diamond_cut_test.spec.ts +++ b/ethereum/test/unit_tests/diamond_cut_test.spec.ts @@ -2,8 +2,8 @@ import { expect } from 'chai'; import * as hardhat from 'hardhat'; import { Action, facetCut, diamondCut, getAllSelectors } from '../../src.ts/diamondCut'; import { - MailboxFacet, - MailboxFacetFactory, + Mailbox as MailboxFacet, + MailboxFactory as MailboxFacetFactory, DiamondCutTest, DiamondCutTestFactory, DiamondCutFacet, @@ -20,8 +20,9 @@ import { import { getCallRevertReason } from './utils'; import * as ethers from 'ethers'; -describe('Diamond proxy tests', function () { +describe('Diamond cut tests', function () { let diamondCutTest: DiamondCutTest; + let chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID || 270; before(async () => { const contractFactory = await hardhat.ethers.getContractFactory('DiamondCutTest'); @@ -36,7 +37,7 @@ describe('Diamond proxy tests', function () { let executorFacet2: ExecutorFacet; before(async () => { - const mailboxFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); + const mailboxFactory = await hardhat.ethers.getContractFactory('Mailbox'); const mailboxContract = await mailboxFactory.deploy(); mailboxFacet = MailboxFacetFactory.connect(mailboxContract.address, mailboxContract.signer); @@ -264,20 +265,20 @@ describe('Diamond proxy tests', function () { facetCut(diamondCutFacet.address, diamondCutFacet.interface, Action.Add, false), facetCut(gettersFacet.address, gettersFacet.interface, Action.Add, true) ]; - // const dummyVerifierParams = { - // recursionNodeLevelVkHash: ethers.constants.HashZero, - // recursionLeafLevelVkHash: ethers.constants.HashZero, - // recursionCircuitsSetVksHash: ethers.constants.HashZero - // }; + const dummyVerifierParams = { + recursionNodeLevelVkHash: ethers.constants.HashZero, + recursionLeafLevelVkHash: ethers.constants.HashZero, + recursionCircuitsSetVksHash: ethers.constants.HashZero + }; + const diamondInitCalldata = diamondInit.interface.encodeFunctionData('initialize', [ - // '0x03752D8252d67f99888E741E3fB642803B29B155', + chainId, + '0x0000000000000000000000000000000000000000', governorAddress, '0x02c775f0a90abf7a0e8043f2fdc38f0580ca9f9996a895d05a501bfeaa3b2e21', - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x70a0F165d6f8054d0d0CF8dFd4DD2005f0AF6B55', - // dummyVerifierParams, - false, + '0x0000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000', + dummyVerifierParams, '0x0100000000000000000000000000000000000000000000000000000000000000', '0x0100000000000000000000000000000000000000000000000000000000000000', 500000 // priority tx max L2 gas limit @@ -286,8 +287,8 @@ describe('Diamond proxy tests', function () { const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitCalldata); const proxyFactory = await hardhat.ethers.getContractFactory('DiamondProxy'); - const chainId = hardhat.network.config.chainId; - const proxyContract = await proxyFactory.deploy(chainId, diamondCutData); + const ethChainId = hardhat.network.config.chainId; + const proxyContract = await proxyFactory.deploy(ethChainId, diamondCutData); proxy = DiamondProxyFactory.connect(proxyContract.address, proxyContract.signer); proxyAsDiamondCut = DiamondCutFacetFactory.connect(proxy.address, governor); @@ -297,7 +298,7 @@ describe('Diamond proxy tests', function () { it('should revert emergency freeze when unauthorized governor', async () => { const proxyAsDiamondCutByRandomSigner = DiamondCutFacetFactory.connect(proxy.address, randomSigner); const revertReason = await getCallRevertReason(proxyAsDiamondCutByRandomSigner.freezeDiamond()); - expect(revertReason).equal('1g'); + expect(revertReason).equal('1g1'); }); it('should emergency freeze and unfreeze when authorized governor', async () => { diff --git a/ethereum/test/unit_tests/proxy_test.spec.ts b/ethereum/test/unit_tests/diamond_proxy_test.spec.ts similarity index 78% rename from ethereum/test/unit_tests/proxy_test.spec.ts rename to ethereum/test/unit_tests/diamond_proxy_test.spec.ts index 45deeb3c41..20e5be223a 100644 --- a/ethereum/test/unit_tests/proxy_test.spec.ts +++ b/ethereum/test/unit_tests/diamond_proxy_test.spec.ts @@ -3,16 +3,18 @@ import * as ethers from 'ethers'; import * as hardhat from 'hardhat'; import { Action, facetCut, diamondCut, getAllSelectors } from '../../src.ts/diamondCut'; import { - DiamondProxy, - DiamondProxyFactory, + DiamondProxy as DiamondProxy, + DiamondProxyFactory as DiamondProxyFactory, DiamondProxyTest, DiamondProxyTestFactory, DiamondCutFacet, DiamondCutFacetFactory, GettersFacet, GettersFacetFactory, - MailboxFacet, - MailboxFacetFactory, + Mailbox as MailboxFacet, + MailboxFactory as MailboxFacetFactory, + ExecutorFacet, + ExecutorFacetFactory, DiamondInit, DiamondInitFactory, TestnetERC20TokenFactory @@ -24,10 +26,11 @@ describe('Diamond proxy tests', function () { let diamondInit: DiamondInit; let diamondCutFacet: DiamondCutFacet; let gettersFacet: GettersFacet; - let mailboxFacet: MailboxFacet; + let executorFacet: ExecutorFacet; let diamondProxyTest: DiamondProxyTest; let governor: ethers.Signer; let governorAddress: string; + let chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID || 270; before(async () => { [governor] = await hardhat.ethers.getSigners(); @@ -45,12 +48,13 @@ describe('Diamond proxy tests', function () { const gettersFacetContract = await gettersFacetFactory.deploy(); gettersFacet = GettersFacetFactory.connect(gettersFacetContract.address, gettersFacetContract.signer); - const mailboxFacetFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); - const mailboxFacetContract = await mailboxFacetFactory.deploy(); - mailboxFacet = MailboxFacetFactory.connect(mailboxFacetContract.address, mailboxFacetContract.signer); + const executorFactory = await hardhat.ethers.getContractFactory(`ExecutorFacet`); + const executorContract = await executorFactory.deploy(); + executorFacet = ExecutorFacetFactory.connect(executorContract.address, executorContract.signer); const diamondProxyTestFactory = await hardhat.ethers.getContractFactory('DiamondProxyTest'); const diamondProxyTestContract = await diamondProxyTestFactory.deploy(); + diamondProxyTest = DiamondProxyTestFactory.connect( diamondProxyTestContract.address, diamondProxyTestContract.signer @@ -59,23 +63,24 @@ describe('Diamond proxy tests', function () { const facetCuts = [ facetCut(diamondCutFacet.address, diamondCutFacet.interface, Action.Add, false), facetCut(gettersFacet.address, gettersFacet.interface, Action.Add, false), - facetCut(mailboxFacet.address, mailboxFacet.interface, Action.Add, true) + facetCut(executorFacet.address, executorFacet.interface, Action.Add, true) + // facetCut(mailboxFacet.address, mailboxFacet.interface, Action.Add, true) ]; - // const dummyVerifierParams = { - // recursionNodeLevelVkHash: ethers.constants.HashZero, - // recursionLeafLevelVkHash: ethers.constants.HashZero, - // recursionCircuitsSetVksHash: ethers.constants.HashZero - // }; + const dummyVerifierParams = { + recursionNodeLevelVkHash: ethers.constants.HashZero, + recursionLeafLevelVkHash: ethers.constants.HashZero, + recursionCircuitsSetVksHash: ethers.constants.HashZero + }; + const diamondInitCalldata = diamondInit.interface.encodeFunctionData('initialize', [ - // '0x03752D8252d67f99888E741E3fB642803B29B155', + chainId, + '0x0000000000000000000000000000000000000000', governorAddress, '0x02c775f0a90abf7a0e8043f2fdc38f0580ca9f9996a895d05a501bfeaa3b2e21', - 0, - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x70a0F165d6f8054d0d0CF8dFd4DD2005f0AF6B55', - // dummyVerifierParams, - false, + '0x0000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000', + dummyVerifierParams, '0x0100000000000000000000000000000000000000000000000000000000000000', '0x0100000000000000000000000000000000000000000000000000000000000000', 500000 // priority tx max L2 gas limit @@ -84,8 +89,8 @@ describe('Diamond proxy tests', function () { const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitCalldata); const proxyFactory = await hardhat.ethers.getContractFactory('DiamondProxy'); - const chainId = hardhat.network.config.chainId; - const proxyContract = await proxyFactory.deploy(chainId, diamondCutData); + const ethChainId = hardhat.network.config.chainId; + const proxyContract = await proxyFactory.deploy(ethChainId, diamondCutData); proxy = DiamondProxyFactory.connect(proxyContract.address, proxyContract.signer); }); @@ -168,13 +173,17 @@ describe('Diamond proxy tests', function () { expect(revertReason).equal('f3'); }); - it('should revert on calling a freezable faucet when diamondStorage is frozen', async () => { - const mailboxFacetSelector0 = getAllSelectors(mailboxFacet.interface)[0]; - const revertReason = await getCallRevertReason(proxy.fallback({ data: mailboxFacetSelector0 })); + it('should revert on calling a freezable facet when diamondStorage is frozen', async () => { + const executorFacetSelector3 = getAllSelectors(executorFacet.interface)[3]; + const revertReason = await getCallRevertReason( + proxy.fallback({ + data: executorFacetSelector3 + '0000000000000000000000000000000000000000000000000000000000000000' + }) + ); expect(revertReason).equal('q1'); }); - it('should be able to call an unfreezable faucet when diamondStorage is frozen', async () => { + it('should be able to call an unfreezable facet when diamondStorage is frozen', async () => { const gettersFacetSelector1 = getAllSelectors(gettersFacet.interface)[1]; await proxy.fallback({ data: gettersFacetSelector1 }); }); diff --git a/ethereum/test/unit_tests/proof_executor_test.spec.ts b/ethereum/test/unit_tests/executor_test.spec.ts similarity index 68% rename from ethereum/test/unit_tests/proof_executor_test.spec.ts rename to ethereum/test/unit_tests/executor_test.spec.ts index e1f613cd2b..005576f1f8 100644 --- a/ethereum/test/unit_tests/proof_executor_test.spec.ts +++ b/ethereum/test/unit_tests/executor_test.spec.ts @@ -1,18 +1,26 @@ import { expect } from 'chai'; -import { BigNumber, ethers } from 'ethers'; +import { BigNumber, ethers, Wallet } from 'ethers'; import * as hardhat from 'hardhat'; +import '@openzeppelin/hardhat-upgrades'; + +import * as fs from 'fs'; +import * as path from 'path'; + import { Action, diamondCut, facetCut } from '../../src.ts/diamondCut'; import { AllowList, AllowListFactory, - ProofDiamondInitFactory, - ProofExecutorFacet, - ProofExecutorFacetFactory, - ProofGettersFacet, - ProofGettersFacetFactory, + DiamondInitFactory, + BridgeheadChainFactory, + Bridgehead, + BridgeheadFactory, + ExecutorFacet, + ExecutorFacetFactory, + GettersFacet, + GettersFacetFactory, // MailboxFacet, // MailboxFacetFactory, - ProofGovernanceFacetFactory + GovernanceFacetFactory } from '../../typechain'; import { AccessMode, @@ -23,23 +31,34 @@ import { L2_TO_L1_MESSENGER, genesisStoredBlockInfo, getCallRevertReason, - packBatchTimestampAndBlockTimestamp - // requestExecute + packBatchTimestampAndBlockTimestamp, + requestExecute } from './utils'; +import { Deployer } from '../../src.ts/deploy'; +import { hexlify, keccak256 } from 'ethers/lib/utils'; + +const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; + +const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); +const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); describe(`Executor tests`, function () { let owner: ethers.Signer; let validator: ethers.Signer; let randomSigner: ethers.Signer; let allowList: AllowList; - let executor: ProofExecutorFacet; - let getters: ProofGettersFacet; - // let mailbox: MailboxFacet; + let executor: ExecutorFacet; + let getters: GettersFacet; + let bridgeheadContract: Bridgehead; let newCommitedBlockBlockHash: any; let newCommitedBlockCommitment: any; let currentTimestamp: number; let newCommitBlockInfo: any; let newStoredBlockInfo: any; + let chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID || 270; + let genesisPriorityTxHash: string; + let genesisPriorityChainedHash: string; const proofInput = { recursiveAggregationInput: [], @@ -49,77 +68,108 @@ describe(`Executor tests`, function () { before(async () => { [owner, validator, randomSigner] = await hardhat.ethers.getSigners(); - const executorFactory = await hardhat.ethers.getContractFactory(`ProofExecutorFacet`); - const executorContract = await executorFactory.deploy(); - const executorFacet = ProofExecutorFacetFactory.connect(executorContract.address, executorContract.signer); + const deployWallet = Wallet.fromMnemonic(ethTestConfig.test_mnemonic2, "m/44'/60'/0'/0/1").connect( + owner.provider + ); + const governorAddress = await deployWallet.getAddress(); + + const gasPrice = await owner.provider.getGasPrice(); + + const tx = { + from: owner.getAddress(), + to: deployWallet.address, + value: ethers.utils.parseEther('1000'), + nonce: owner.getTransactionCount(), + gasLimit: 100000, + gasPrice: gasPrice + }; + + await owner.sendTransaction(tx); - const governanceFactory = await hardhat.ethers.getContractFactory(`ProofGovernanceFacet`); - const governanceContract = await governanceFactory.deploy(); - const governanceFacet = ProofGovernanceFacetFactory.connect( - governanceContract.address, - governanceContract.signer + const deployer = new Deployer({ + deployWallet, + governorAddress, + verbose: false, + addresses: addressConfig + }); + + const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + let nonce = await deployWallet.getTransactionCount(); + + await deployer.deployCreate2Factory({ gasPrice, nonce }); + nonce++; + + // await deployer.deployMulticall3(create2Salt, {gasPrice, nonce}); + // nonce++; + + process.env.CONTRACTS_GENESIS_ROOT = zeroHash; + process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = '0'; + process.env.CONTRACTS_GENESIS_BLOCK_COMMITMENT = zeroHash; + process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT = '72000000'; + process.env.CONTRACTS_RECURSION_NODE_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_LEAF_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_CIRCUITS_SET_VKS_HASH = zeroHash; + + await deployer.deployAllowList(create2Salt, { gasPrice, nonce }); + await deployer.deployBridgeheadContract(create2Salt, gasPrice); + await deployer.deployProofSystemContract(create2Salt, gasPrice); + + const verifierParams = { + recursionNodeLevelVkHash: zeroHash, + recursionLeafLevelVkHash: zeroHash, + recursionCircuitsSetVksHash: zeroHash + }; + const initialDiamondCut = await deployer.initialProofSystemProxyDiamondCut(); + + const proofSystem = deployer.proofSystemContract(deployWallet); + + await (await proofSystem.setParams(verifierParams, initialDiamondCut)).wait(); + + await deployer.registerHyperchain(create2Salt, gasPrice); + + chainId = deployer.chainId; + + const validatorTx = await deployer + .proofChainContract(deployWallet) + .setValidator(await validator.getAddress(), true); + await validatorTx.wait(); + + const allowListContract = deployer.l1AllowList(deployWallet); + const allowTx = await allowListContract.setBatchAccessMode( + [ + deployer.addresses.Bridgehead.BridgeheadProxy, + deployer.addresses.Bridgehead.ChainProxy, + deployer.addresses.ProofSystem.ProofSystemProxy, + deployer.addresses.ProofSystem.DiamondProxy, + deployer.addresses.Bridges.ERC20BridgeProxy, + deployer.addresses.Bridges.WethBridgeProxy + ], + [ + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public + ] ); + await allowTx.wait(); - const gettersFactory = await hardhat.ethers.getContractFactory(`ProofGettersFacet`); - const gettersContract = await gettersFactory.deploy(); - const gettersFacet = ProofGettersFacetFactory.connect(gettersContract.address, gettersContract.signer); - - // const mailboxFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); - // const mailboxContract = await mailboxFactory.deploy(); - // const mailboxFacet = MailboxFacetFactory.connect(mailboxContract.address, mailboxContract.signer); - - const allowListFactory = await hardhat.ethers.getContractFactory('AllowList'); - const allowListContract = await allowListFactory.deploy(await allowListFactory.signer.getAddress()); - allowList = AllowListFactory.connect(allowListContract.address, allowListContract.signer); - - const diamondInitFactory = await hardhat.ethers.getContractFactory('ProofDiamondInit'); - const diamondInitContract = await diamondInitFactory.deploy(); - const diamondInit = ProofDiamondInitFactory.connect(diamondInitContract.address, diamondInitContract.signer); - - const dummyHash = new Uint8Array(32); - dummyHash.set([1, 0, 0, 1]); - // const dummyAddress = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - const diamondInitData = diamondInit.interface.encodeFunctionData('initialize', [ - // KL todo: add factory proxy facet address here, - // factoryProxyFacet.address, - // dummyAddress, - await owner.getAddress(), - ethers.constants.HashZero, - 0, - ethers.constants.HashZero, - allowList.address, - // { - // recursionCircuitsSetVksHash: ethers.constants.HashZero, - // recursionLeafLevelVkHash: ethers.constants.HashZero, - // recursionNodeLevelVkHash: ethers.constants.HashZero - // }, - false, - dummyHash, - dummyHash, - 100000000000 - ]); - - const facetCuts = [ - facetCut(governanceFacet.address, governanceFacet.interface, Action.Add, true), - facetCut(executorFacet.address, executorFacet.interface, Action.Add, true), - facetCut(gettersFacet.address, gettersFacet.interface, Action.Add, false) - // facetCut(mailboxFacet.address, mailboxFacet.interface, Action.Add, true) - ]; - - const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitData); - - const diamondProxyFactory = await hardhat.ethers.getContractFactory('ProofDiamondProxy'); - const chainId = hardhat.network.config.chainId; - const diamondProxyContract = await diamondProxyFactory.deploy(chainId, diamondCutData); - - await (await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Public)).wait(); - - executor = ProofExecutorFacetFactory.connect(diamondProxyContract.address, executorContract.signer); - getters = ProofGettersFacetFactory.connect(diamondProxyContract.address, gettersContract.signer); - // mailbox = MailboxFacetFactory.connect(diamondProxyContract.address, mailboxContract.signer); - - const governance = ProofGovernanceFacetFactory.connect(diamondProxyContract.address, owner); - await governance.setValidator(await validator.getAddress(), true); + executor = ExecutorFacetFactory.connect(deployer.addresses.ProofSystem.DiamondProxy, deployWallet); + getters = GettersFacetFactory.connect(deployer.addresses.ProofSystem.DiamondProxy, deployWallet); + + let bridgeheadChainContract = BridgeheadChainFactory.connect( + deployer.addresses.Bridgehead.ChainProxy, + deployWallet + ); + bridgeheadContract = BridgeheadFactory.connect(deployer.addresses.Bridgehead.BridgeheadProxy, deployWallet); + + let priorityOp = await bridgeheadChainContract.priorityQueueFrontOperation(); + genesisPriorityTxHash = priorityOp[0]; + genesisPriorityChainedHash = keccak256( + ethers.utils.defaultAbiCoder.encode(['uint256', 'uint256'], [EMPTY_STRING_KECCAK, priorityOp[0]]) + ); }); describe(`Authorization check`, function () { @@ -152,21 +202,21 @@ describe(`Executor tests`, function () { const revertReason = await getCallRevertReason( executor.connect(randomSigner).commitBlocks(storedBlockInfo, [commitBlockInfo]) ); - expect(revertReason).equal(`1h`); + expect(revertReason).equal(`1h1`); }); it(`Should revert on committing by unauthorised address`, async () => { const revertReason = await getCallRevertReason( executor.connect(randomSigner).proveBlocks(storedBlockInfo, [storedBlockInfo], proofInput) ); - expect(revertReason).equal(`1h`); + expect(revertReason).equal(`1h1`); }); it(`Should revert on executing by unauthorised address`, async () => { const revertReason = await getCallRevertReason( executor.connect(randomSigner).executeBlocks([storedBlockInfo]) ); - expect(revertReason).equal(`1h`); + expect(revertReason).equal(`1h1`); }); }); @@ -754,148 +804,184 @@ describe(`Executor tests`, function () { expect(revertReason).equal(`n`); }); - // it(`Should revert on executing with unavailable prioirty operation hash`, async () => { - // const arbitraryCanonicalTxHash = ethers.utils.randomBytes(32); - // const chainedPriorityTxHash = ethers.utils.keccak256( - // ethers.utils.hexConcat([EMPTY_STRING_KECCAK, arbitraryCanonicalTxHash]) - // ); - - // const correctL2Logs = ethers.utils.hexConcat([ - // `0x00000002`, - // `0x00000000`, - // L2_SYSTEM_CONTEXT_ADDRESS, - // packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp), - // ethers.constants.HashZero, - // `0x00010000`, - // L2_BOOTLOADER_ADDRESS, - // arbitraryCanonicalTxHash, - // ethers.utils.hexZeroPad(`0x01`, 32) - // ]); - - // const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); - // correctNewCommitBlockInfo.l2Logs = correctL2Logs; - // correctNewCommitBlockInfo.priorityOperationsHash = chainedPriorityTxHash; - // correctNewCommitBlockInfo.numberOfLayer1Txs = 1; - - // const commitTx = await executor - // .connect(validator) - // .commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); - - // const result = await commitTx.wait(); - - // const correctNewStoredBlockInfo = Object.assign({}, newStoredBlockInfo); - // correctNewStoredBlockInfo.blockHash = result.events[0].args.blockHash; - // correctNewStoredBlockInfo.numberOfLayer1Txs = 1; - // correctNewStoredBlockInfo.priorityOperationsHash = chainedPriorityTxHash; - // correctNewStoredBlockInfo.commitment = result.events[0].args.commitment; - - // await executor - // .connect(validator) - // .proveBlocks(genesisStoredBlockInfo(), [correctNewStoredBlockInfo], proofInput); - - // const revertReason = await getCallRevertReason( - // executor.connect(validator).executeBlocks([correctNewStoredBlockInfo]) - // ); - // expect(revertReason).equal(`s`); - - // await executor.connect(validator).revertBlocks(0); - // }); - - // it(`Should revert on executing with unmatched priorty operation hash`, async () => { - // const arbitraryCanonicalTxHash = ethers.utils.randomBytes(32); - // const chainedPriorityTxHash = ethers.utils.keccak256( - // ethers.utils.hexConcat([EMPTY_STRING_KECCAK, arbitraryCanonicalTxHash]) - // ); - - // const correctL2Logs = ethers.utils.hexConcat([ - // `0x00000002`, - // `0x00000000`, - // L2_SYSTEM_CONTEXT_ADDRESS, - // packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp), - // ethers.constants.HashZero, - // `0x00010000`, - // L2_BOOTLOADER_ADDRESS, - // arbitraryCanonicalTxHash, - // ethers.utils.hexZeroPad(`0x01`, 32) - // ]); - - // const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); - // correctNewCommitBlockInfo.l2Logs = correctL2Logs; - // correctNewCommitBlockInfo.priorityOperationsHash = chainedPriorityTxHash; - // correctNewCommitBlockInfo.numberOfLayer1Txs = 1; - - // const commitTx = await executor - // .connect(validator) - // .commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); - - // const result = await commitTx.wait(); - - // const correctNewStoredBlockInfo = Object.assign({}, newStoredBlockInfo); - // correctNewStoredBlockInfo.blockHash = result.events[0].args.blockHash; - // correctNewStoredBlockInfo.numberOfLayer1Txs = 1; - // correctNewStoredBlockInfo.priorityOperationsHash = chainedPriorityTxHash; - // correctNewStoredBlockInfo.commitment = result.events[0].args.commitment; - - // await executor - // .connect(validator) - // .proveBlocks(genesisStoredBlockInfo(), [correctNewStoredBlockInfo], proofInput); - - // // await requestExecute( - // // mailbox, - // // ethers.constants.AddressZero, - // // ethers.utils.parseEther('10'), - // // '0x', - // // BigNumber.from(1000000), - // // [new Uint8Array(32)], - // // ethers.constants.AddressZero - // // ); - - // const revertReason = await getCallRevertReason( - // executor.connect(validator).executeBlocks([correctNewStoredBlockInfo]) - // ); - // expect(revertReason).equal(`x`); - - // await executor.connect(validator).revertBlocks(0); - // }); - - // it(`Should fail to commit block with wrong previous blockhash`, async () => { - // const correctL2Logs = ethers.utils.hexConcat([ - // `0x00000001`, - // `0x00000000`, - // L2_SYSTEM_CONTEXT_ADDRESS, - // ethers.utils.hexZeroPad(ethers.utils.hexlify(currentTimestamp), 32), - // ethers.constants.HashZero - // ]); - - // const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); - // correctNewCommitBlockInfo.l2Logs = correctL2Logs; - - // const block = genesisStoredBlockInfo(); - // block.blockHash = '0x' + '1'.repeat(64); - - // const revertReason = await getCallRevertReason( - // executor.connect(validator).commitBlocks(block, [correctNewCommitBlockInfo]) - // ); - // expect(revertReason).to.equal('i'); - // }); - - // it(`Should execute a block successfully`, async () => { - // const correctL2Logs = ethers.utils.hexConcat([ - // `0x00000001`, - // `0x00000000`, - // L2_SYSTEM_CONTEXT_ADDRESS, - // packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp), - // ethers.constants.HashZero - // ]); - - // const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); - // correctNewCommitBlockInfo.l2Logs = correctL2Logs; - - // await executor.connect(validator).commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); - // await executor.connect(validator).proveBlocks(genesisStoredBlockInfo(), [newStoredBlockInfo], proofInput); - // // await executor.connect(validator).executeBlocks([newStoredBlockInfo]); - - // expect(await getters.getTotalBlocksExecuted()).equal(1); - // }); + it(`Should revert on executing with unavailable prioirty operation hash`, async () => { + const arbitraryCanonicalTxHash = ethers.utils.randomBytes(32); + const chainedPriorityTxHash = ethers.utils.keccak256( + ethers.utils.hexConcat([ + ethers.utils.keccak256(ethers.utils.hexConcat([EMPTY_STRING_KECCAK, arbitraryCanonicalTxHash])), + ethers.utils.hexZeroPad(ethers.utils.hexlify(genesisPriorityTxHash), 32) + ]) + ); + + const correctL2Logs = ethers.utils.hexConcat([ + `0x00000002`, + `0x00000000`, + L2_SYSTEM_CONTEXT_ADDRESS, + packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp), + ethers.constants.HashZero, + `0x00010000`, + L2_BOOTLOADER_ADDRESS, + arbitraryCanonicalTxHash, + ethers.utils.hexZeroPad(`0x01`, 32), + `0x00000000`, + L2_BOOTLOADER_ADDRESS, + ethers.utils.hexZeroPad(ethers.utils.hexlify(genesisPriorityTxHash), 32), + ethers.utils.hexZeroPad(`0x01`, 32) + ]); + + const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); + correctNewCommitBlockInfo.l2Logs = correctL2Logs; + correctNewCommitBlockInfo.priorityOperationsHash = chainedPriorityTxHash; + correctNewCommitBlockInfo.numberOfLayer1Txs = 2; + + const commitTx = await executor + .connect(validator) + .commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); + + const result = await commitTx.wait(); + + const correctNewStoredBlockInfo = Object.assign({}, newStoredBlockInfo); + correctNewStoredBlockInfo.blockHash = result.events[0].args.blockHash; + correctNewStoredBlockInfo.numberOfLayer1Txs = 2; + correctNewStoredBlockInfo.priorityOperationsHash = chainedPriorityTxHash; + correctNewStoredBlockInfo.commitment = result.events[0].args.commitment; + + await executor + .connect(validator) + .proveBlocks(genesisStoredBlockInfo(), [correctNewStoredBlockInfo], proofInput); + + const revertReason = await getCallRevertReason( + executor.connect(validator).executeBlocks([correctNewStoredBlockInfo]) + ); + expect(revertReason).equal(`g1`); + + await executor.connect(validator).revertBlocks(0); + }); + + it(`Should revert on executing with unmatched priorty operation hash`, async () => { + const arbitraryCanonicalTxHash = ethers.utils.randomBytes(32); + const chainedPriorityTxHash = ethers.utils.keccak256( + ethers.utils.hexConcat([ + ethers.utils.keccak256(ethers.utils.hexConcat([EMPTY_STRING_KECCAK, arbitraryCanonicalTxHash])), + ethers.utils.hexZeroPad(ethers.utils.hexlify(genesisPriorityTxHash), 32) + ]) + ); + + const correctL2Logs = ethers.utils.hexConcat([ + `0x00000002`, + `0x00000000`, + L2_SYSTEM_CONTEXT_ADDRESS, + packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp), + ethers.constants.HashZero, + `0x00010000`, + L2_BOOTLOADER_ADDRESS, + arbitraryCanonicalTxHash, + ethers.utils.hexZeroPad(`0x01`, 32), + `0x00000000`, + L2_BOOTLOADER_ADDRESS, + ethers.utils.hexZeroPad(ethers.utils.hexlify(genesisPriorityTxHash), 32), + ethers.utils.hexZeroPad(`0x01`, 32) + ]); + + const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); + correctNewCommitBlockInfo.l2Logs = correctL2Logs; + correctNewCommitBlockInfo.priorityOperationsHash = chainedPriorityTxHash; + correctNewCommitBlockInfo.numberOfLayer1Txs = 2; + + const commitTx = await executor + .connect(validator) + .commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); + + const result = await commitTx.wait(); + + const correctNewStoredBlockInfo = Object.assign({}, newStoredBlockInfo); + correctNewStoredBlockInfo.blockHash = result.events[0].args.blockHash; + correctNewStoredBlockInfo.numberOfLayer1Txs = 2; + correctNewStoredBlockInfo.priorityOperationsHash = chainedPriorityTxHash; + correctNewStoredBlockInfo.commitment = result.events[0].args.commitment; + + await executor + .connect(validator) + .proveBlocks(genesisStoredBlockInfo(), [correctNewStoredBlockInfo], proofInput); + + await requestExecute( + chainId, + bridgeheadContract, + ethers.constants.AddressZero, + ethers.utils.parseEther('10'), + '0x', + BigNumber.from(1000000), + [new Uint8Array(32)], + ethers.constants.AddressZero + ); + + const revertReason = await getCallRevertReason( + executor.connect(validator).executeBlocks([correctNewStoredBlockInfo]) + ); + expect(revertReason).equal(`x`); + + await executor.connect(validator).revertBlocks(0); + }); + + it(`Should fail to commit block with wrong previous blockhash`, async () => { + const correctL2Logs = ethers.utils.hexConcat([ + `0x00000001`, + `0x00000000`, + L2_SYSTEM_CONTEXT_ADDRESS, + ethers.utils.hexZeroPad(ethers.utils.hexlify(currentTimestamp), 32), + ethers.constants.HashZero + ]); + + const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); + correctNewCommitBlockInfo.l2Logs = correctL2Logs; + + const block = genesisStoredBlockInfo(); + block.blockHash = '0x' + '1'.repeat(64); + + const revertReason = await getCallRevertReason( + executor.connect(validator).commitBlocks(block, [correctNewCommitBlockInfo]) + ); + expect(revertReason).to.equal('i'); + }); + + it(`Should execute a block successfully`, async () => { + const correctL2Logs = ethers.utils.hexConcat([ + `0x00000001`, + `0x00000000`, + L2_SYSTEM_CONTEXT_ADDRESS, + packBatchTimestampAndBlockTimestamp(currentTimestamp, currentTimestamp), + ethers.constants.HashZero, + `0x00000000`, + L2_BOOTLOADER_ADDRESS, + ethers.utils.hexlify(genesisPriorityTxHash), + ethers.utils.hexlify(BigNumber.from(1)) + ]); + + const correctNewCommitBlockInfo = Object.assign({}, newCommitBlockInfo); + correctNewCommitBlockInfo.l2Logs = correctL2Logs; + correctNewCommitBlockInfo.priorityOperationsHash = genesisPriorityChainedHash; + correctNewCommitBlockInfo.numberOfLayer1Txs = 1; + + // await executor.connect(validator).commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); + + const commitTx = await executor + .connect(validator) + .commitBlocks(genesisStoredBlockInfo(), [correctNewCommitBlockInfo]); + + const result = await commitTx.wait(); + + newCommitedBlockBlockHash = result.events[0].args.blockHash; + newCommitedBlockCommitment = result.events[0].args.commitment; + + newStoredBlockInfo.priorityOperationsHash = genesisPriorityChainedHash; + newStoredBlockInfo.numberOfLayer1Txs = 1; + newStoredBlockInfo.blockHash = newCommitedBlockBlockHash; + newStoredBlockInfo.commitment = newCommitedBlockCommitment; + + await executor.connect(validator).proveBlocks(genesisStoredBlockInfo(), [newStoredBlockInfo], proofInput); + await executor.connect(validator).executeBlocks([newStoredBlockInfo]); + + // expect(await getters.getTotalBlocksExecuted()).equal(1); + }); }); }); diff --git a/ethereum/test/unit_tests/governance_test.spec.ts b/ethereum/test/unit_tests/governance_test.spec.ts index 6dda562e64..0d44aa2c63 100644 --- a/ethereum/test/unit_tests/governance_test.spec.ts +++ b/ethereum/test/unit_tests/governance_test.spec.ts @@ -32,7 +32,7 @@ describe('Governance facet tests', function () { const revertReason = await getCallRevertReason( governanceTest.connect(randomSigner).setValidator(validatorAddress, true) ); - expect(revertReason).equal('1g'); + expect(revertReason).equal('1g1'); }); describe('change governor', function () { diff --git a/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts index 4e20d411e0..54956eb2d4 100644 --- a/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts +++ b/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts @@ -1,90 +1,149 @@ import { expect } from 'chai'; -import { ethers } from 'ethers'; +import { BigNumberish, ethers, Wallet } from 'ethers'; import * as hardhat from 'hardhat'; + +import * as fs from 'fs'; +import * as path from 'path'; + import { REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT } from 'zksync-web3/build/src/utils'; -import { IZkSync, IZkSyncFactory } from 'zksync-web3/build/typechain'; +// import { IZkSync as IBridgehead, IZkSyncFactory as IDiamondFactory } from 'zksync-web3/build/typechain'; import { Action, diamondCut, facetCut } from '../../src.ts/diamondCut'; import { AllowList, AllowListFactory, // BridgeheadFactory, TestnetERC20Token, - TestnetERC20TokenFactory - // IFactory as IZkSync, - // IFactoryFactory as IZkSyncFactory, + TestnetERC20TokenFactory, + GettersFacetFactory, + MailboxFactory as MailboxFacetFactory, + DiamondInitFactory, + BridgeheadFactory, + Bridgehead } from '../../typechain'; import { IL1Bridge } from '../../typechain/IL1Bridge'; import { IL1BridgeFactory } from '../../typechain/IL1BridgeFactory'; import { AccessMode, getCallRevertReason } from './utils'; +import { Deployer } from '../../src.ts/deploy'; + +const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; + +const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); +const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); + describe(`L1ERC20Bridge tests`, function () { let owner: ethers.Signer; let randomSigner: ethers.Signer; let allowList: AllowList; + let l1ERC20BridgeAddress: string; let l1ERC20Bridge: IL1Bridge; let erc20TestToken: TestnetERC20Token; let testnetERC20TokenContract: ethers.Contract; let l1Erc20BridgeContract: ethers.Contract; - let zksyncContract: IZkSync; - const zkChainId: string = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID; + let bridgeheadContract: Bridgehead; + let chainId = 0; before(async () => { [owner, randomSigner] = await hardhat.ethers.getSigners(); - const gettersFactory = await hardhat.ethers.getContractFactory(`GettersFacet`); - const gettersContract = await gettersFactory.deploy(); - const gettersFacet = GettersFacetFactory.connect(gettersContract.address, gettersContract.signer); - - const mailboxFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); - const mailboxContract = await mailboxFactory.deploy(); - const mailboxFacet = MailboxFacetFactory.connect(mailboxContract.address, mailboxContract.signer); - - const allowListFactory = await hardhat.ethers.getContractFactory('AllowList'); - const allowListContract = await allowListFactory.deploy(await allowListFactory.signer.getAddress()); - allowList = AllowListFactory.connect(allowListContract.address, allowListContract.signer); - - const diamondInitFactory = await hardhat.ethers.getContractFactory('DiamondInit'); - const diamondInitContract = await diamondInitFactory.deploy(); - const diamondInit = DiamondInitFactory.connect(diamondInitContract.address, diamondInitContract.signer); - - const dummyHash = new Uint8Array(32); - dummyHash.set([1, 0, 0, 1]); - // const dummyAddress = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - const diamondInitData = diamondInit.interface.encodeFunctionData('initialize', [ - // dummyAddress, - await owner.getAddress(), - ethers.constants.HashZero, - 0, - ethers.constants.HashZero, - allowList.address, - // { - // recursionCircuitsSetVksHash: ethers.constants.HashZero, - // recursionLeafLevelVkHash: ethers.constants.HashZero, - // recursionNodeLevelVkHash: ethers.constants.HashZero - // }, - false, - dummyHash, - dummyHash, - 100000000000 - ]); + const deployWallet = Wallet.fromMnemonic(ethTestConfig.test_mnemonic3, "m/44'/60'/0'/0/1").connect( + owner.provider + ); + const governorAddress = await deployWallet.getAddress(); + + const gasPrice = await owner.provider.getGasPrice(); + + const tx = { + from: owner.getAddress(), + to: deployWallet.address, + value: ethers.utils.parseEther('1000'), + nonce: owner.getTransactionCount(), + gasLimit: 100000, + gasPrice: gasPrice + }; + + await owner.sendTransaction(tx); + + const deployer = new Deployer({ + deployWallet, + governorAddress, + verbose: false, + addresses: addressConfig + }); + + const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + let nonce = await deployWallet.getTransactionCount(); - const facetCuts = [ - facetCut(gettersFacet.address, gettersFacet.interface, Action.Add, false), - facetCut(mailboxFacet.address, mailboxFacet.interface, Action.Add, true) - ]; + await deployer.deployCreate2Factory({ gasPrice, nonce }); + nonce++; - const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitData); + // await deployer.deployMulticall3(create2Salt, {gasPrice, nonce}); + // nonce++; - const diamondProxyFactory = await hardhat.ethers.getContractFactory('DiamondProxy'); - const chainId = hardhat.network.config.chainId; - const diamondProxyContract = await diamondProxyFactory.deploy(chainId, diamondCutData); + process.env.CONTRACTS_GENESIS_ROOT = zeroHash; + process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = '0'; + process.env.CONTRACTS_GENESIS_BLOCK_COMMITMENT = zeroHash; + process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT = '72000000'; + process.env.CONTRACTS_RECURSION_NODE_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_LEAF_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_CIRCUITS_SET_VKS_HASH = zeroHash; + + await deployer.deployAllowList(create2Salt, { gasPrice, nonce }); + await deployer.deployBridgeheadContract(create2Salt, gasPrice); + await deployer.deployProofSystemContract(create2Salt, gasPrice); + await deployer.deployBridgeContracts(create2Salt, gasPrice); + await deployer.deployWethBridgeContracts(create2Salt, gasPrice); + + const verifierParams = { + recursionNodeLevelVkHash: zeroHash, + recursionLeafLevelVkHash: zeroHash, + recursionCircuitsSetVksHash: zeroHash + }; + const initialDiamondCut = await deployer.initialProofSystemProxyDiamondCut(); + + const proofSystem = deployer.proofSystemContract(deployWallet); + + await (await proofSystem.setParams(verifierParams, initialDiamondCut)).wait(); + + await deployer.registerHyperchain(create2Salt, gasPrice); + chainId = deployer.chainId; + + // const validatorTx = await deployer.proofChainContract(deployWallet).setValidator(await validator.getAddress(), true); + // await validatorTx.wait(); + + allowList = deployer.l1AllowList(deployWallet); + + const allowTx = await allowList.setBatchAccessMode( + [ + deployer.addresses.Bridgehead.BridgeheadProxy, + deployer.addresses.Bridgehead.ChainProxy, + deployer.addresses.ProofSystem.ProofSystemProxy, + deployer.addresses.ProofSystem.DiamondProxy, + deployer.addresses.Bridges.ERC20BridgeProxy, + deployer.addresses.Bridges.WethBridgeProxy + ], + [ + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public + ] + ); + await allowTx.wait(); + + bridgeheadContract = BridgeheadFactory.connect(deployer.addresses.Bridgehead.BridgeheadProxy, deployWallet); const l1Erc20BridgeFactory = await hardhat.ethers.getContractFactory('L1ERC20Bridge'); l1Erc20BridgeContract = await l1Erc20BridgeFactory.deploy( - diamondProxyContract.address, - allowListContract.address + deployer.addresses.Bridgehead.BridgeheadProxy, + allowList.address ); - l1ERC20Bridge = IL1BridgeFactory.connect(l1Erc20BridgeContract.address, l1Erc20BridgeContract.signer); + l1ERC20BridgeAddress = l1Erc20BridgeContract.address; + l1ERC20Bridge = IL1BridgeFactory.connect(l1ERC20BridgeAddress, deployWallet); const testnetERC20TokenFactory = await hardhat.ethers.getContractFactory('TestnetERC20Token'); testnetERC20TokenContract = await testnetERC20TokenFactory.deploy('TestToken', 'TT', 18); @@ -94,14 +153,10 @@ describe(`L1ERC20Bridge tests`, function () { ); await erc20TestToken.mint(await randomSigner.getAddress(), ethers.utils.parseUnits('10000', 18)); - await erc20TestToken - .connect(randomSigner) - .approve(l1Erc20BridgeContract.address, ethers.utils.parseUnits('10000', 18)); + await erc20TestToken.connect(randomSigner).approve(l1ERC20BridgeAddress, ethers.utils.parseUnits('10000', 18)); - await (await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Public)).wait(); - - // Exposing the methods of IZkSync to the diamond proxy - zksyncContract = IZkSyncFactory.connect(diamondProxyContract.address, diamondProxyContract.provider); + // // Exposing the methods of IZkSync to the diamond proxy + // bridgeheadContract = BridgeheadFactory.connect(diamondProxyContract.address, diamondProxyContract.provider); }); it(`Should not allow an un-whitelisted address to deposit`, async () => { @@ -109,7 +164,7 @@ describe(`L1ERC20Bridge tests`, function () { l1ERC20Bridge .connect(randomSigner) .deposit( - zkChainId, + chainId, await randomSigner.getAddress(), testnetERC20TokenContract.address, 0, @@ -120,7 +175,7 @@ describe(`L1ERC20Bridge tests`, function () { ); expect(revertReason).equal(`nr`); - await (await allowList.setAccessMode(l1Erc20BridgeContract.address, AccessMode.Public)).wait(); + await (await allowList.setAccessMode(l1ERC20BridgeAddress, AccessMode.Public)).wait(); }); it(`Should not allow depositing zero amount`, async () => { @@ -128,7 +183,7 @@ describe(`L1ERC20Bridge tests`, function () { l1ERC20Bridge .connect(randomSigner) .deposit( - zkChainId, + chainId, await randomSigner.getAddress(), testnetERC20TokenContract.address, 0, @@ -144,8 +199,8 @@ describe(`L1ERC20Bridge tests`, function () { const depositorAddress = await randomSigner.getAddress(); await depositERC20( l1ERC20Bridge.connect(randomSigner), - zksyncContract, - zkChainId, + bridgeheadContract, + chainId, depositorAddress, testnetERC20TokenContract.address, ethers.utils.parseUnits('800', 18), @@ -155,20 +210,20 @@ describe(`L1ERC20Bridge tests`, function () { it(`Should revert on finalizing a withdrawal with wrong message length`, async () => { const revertReason = await getCallRevertReason( - l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(zkChainId, 0, 0, 0, '0x', []) + l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, '0x', []) ); - expect(revertReason).equal(`kk`); + expect(revertReason).equal(`rz`); }); it(`Should revert on finalizing a withdrawal with wrong function signature`, async () => { const revertReason = await getCallRevertReason( - l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(zkChainId, 0, 0, 0, ethers.utils.randomBytes(76), []) + l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, ethers.utils.randomBytes(76), []) ); - expect(revertReason).equal(`nt`); + expect(revertReason).equal(`rz`); }); it(`Should revert on finalizing a withdrawal with wrong block number`, async () => { - const functionSignature = `0x11a2ccc1`; + const functionSignature = `0xc87325f1`; const l1Receiver = await randomSigner.getAddress(); const l2ToL1message = ethers.utils.hexConcat([ functionSignature, @@ -177,13 +232,13 @@ describe(`L1ERC20Bridge tests`, function () { ethers.constants.HashZero ]); const revertReason = await getCallRevertReason( - l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(zkChainId, 10, 0, 0, l2ToL1message, []) + l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(chainId, 10, 0, 0, l2ToL1message, []) ); expect(revertReason).equal(`xx`); }); it(`Should revert on finalizing a withdrawal with wrong length of proof`, async () => { - const functionSignature = `0x11a2ccc1`; + const functionSignature = `0xc87325f1`; const l1Receiver = await randomSigner.getAddress(); const l2ToL1message = ethers.utils.hexConcat([ functionSignature, @@ -192,13 +247,13 @@ describe(`L1ERC20Bridge tests`, function () { ethers.constants.HashZero ]); const revertReason = await getCallRevertReason( - l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(zkChainId, 0, 0, 0, l2ToL1message, []) + l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, l2ToL1message, []) ); expect(revertReason).equal(`rz`); }); it(`Should revert on finalizing a withdrawal with wrong proof`, async () => { - const functionSignature = `0x11a2ccc1`; + const functionSignature = `0xc87325f1`; const l1Receiver = await randomSigner.getAddress(); const l2ToL1message = ethers.utils.hexConcat([ functionSignature, @@ -209,7 +264,7 @@ describe(`L1ERC20Bridge tests`, function () { const revertReason = await getCallRevertReason( l1ERC20Bridge .connect(randomSigner) - .finalizeWithdrawal(zkChainId, 0, 0, 0, l2ToL1message, Array(9).fill(ethers.constants.HashZero)) + .finalizeWithdrawal(chainId, 0, 0, 0, l2ToL1message, Array(9).fill(ethers.constants.HashZero)) ); expect(revertReason).equal(`nq`); }); @@ -217,8 +272,8 @@ describe(`L1ERC20Bridge tests`, function () { async function depositERC20( bridge: IL1Bridge, - zksyncContract: IZkSync, - zkChainId: string, + bridgeheadContract: Bridgehead, + chainId: BigNumberish, l2Receiver: string, l1Token: string, amount: ethers.BigNumber, @@ -227,10 +282,10 @@ async function depositERC20( ) { const gasPrice = await bridge.provider.getGasPrice(); const gasPerPubdata = REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT; - const neededValue = await zksyncContract.l2TransactionBaseCost(zkChainId, gasPrice, l2GasLimit, gasPerPubdata); + const neededValue = await bridgeheadContract.l2TransactionBaseCost(chainId, gasPrice, l2GasLimit, gasPerPubdata); await bridge.deposit( - zkChainId, + chainId, l2Receiver, l1Token, amount, diff --git a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts index 133d6e0b5e..5aefc260e2 100644 --- a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts +++ b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts @@ -1,14 +1,18 @@ import { expect } from 'chai'; -import { ethers } from 'ethers'; +import { ethers, Wallet } from 'ethers'; import * as hardhat from 'hardhat'; -import { IFactory as IZkSync } from '../../typechain/IFactory'; + +import * as fs from 'fs'; +import * as path from 'path'; + +import { IBridgehead } from '../../typechain/IBridgehead'; import { Action, diamondCut, facetCut } from '../../src.ts/diamondCut'; import { AllowList, AllowListFactory, DiamondInitFactory, GettersFacetFactory, - MailboxFacetFactory, + MailboxFactory, L1WethBridge, L1WethBridgeFactory, WETH9, @@ -20,11 +24,19 @@ import { hashL2Bytecode } from '../../scripts/utils'; import { Interface } from 'ethers/lib/utils'; import { Address } from 'zksync-web3/build/src/types'; +import { Deployer } from '../../src.ts/deploy'; + +const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; + +const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); +const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); + const DEPLOYER_SYSTEM_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000008006'; const REQUIRED_L2_GAS_PRICE_PER_PUBDATA = require('../../../SystemConfig.json').REQUIRED_L2_GAS_PRICE_PER_PUBDATA; export async function create2DeployFromL1( - zkSync: IZkSync, + bridgehead: IBridgehead, chainId: ethers.BigNumberish, walletAddress: Address, bytecode: ethers.BytesLike, @@ -35,10 +47,15 @@ export async function create2DeployFromL1( const deployerSystemContracts = new Interface(hardhat.artifacts.readArtifactSync('IContractDeployer').abi); const bytecodeHash = hashL2Bytecode(bytecode); const calldata = deployerSystemContracts.encodeFunctionData('create2', [create2Salt, bytecodeHash, constructor]); - const gasPrice = await zkSync.provider.getGasPrice(); - const expectedCost = await zkSync.l2TransactionBaseCost(gasPrice, l2GasLimit, REQUIRED_L2_GAS_PRICE_PER_PUBDATA); + const gasPrice = await bridgehead.provider.getGasPrice(); + const expectedCost = await bridgehead.l2TransactionBaseCost( + chainId, + gasPrice, + l2GasLimit, + REQUIRED_L2_GAS_PRICE_PER_PUBDATA + ); - await zkSync.requestL2Transaction( + await bridgehead.requestL2Transaction( chainId, DEPLOYER_SYSTEM_CONTRACT_ADDRESS, 0, @@ -57,62 +74,101 @@ describe('WETH Bridge tests', () => { let allowList: AllowList; let bridgeProxy: L1WethBridge; let l1Weth: WETH9; - let functionSignature = '0x6c0960f9'; + let functionSignature = '0x0fdef251'; + let chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID || 270; before(async () => { [owner, randomSigner] = await hardhat.ethers.getSigners(); - // prepare the diamond - - const gettersFactory = await hardhat.ethers.getContractFactory(`GettersFacet`); - const gettersContract = await gettersFactory.deploy(); - const gettersFacet = GettersFacetFactory.connect(gettersContract.address, gettersContract.signer); - - const mailboxFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); - const mailboxContract = await mailboxFactory.deploy(); - const mailboxFacet = MailboxFacetFactory.connect(mailboxContract.address, mailboxContract.signer); - - const allowListFactory = await hardhat.ethers.getContractFactory('AllowList'); - const allowListContract = await allowListFactory.deploy(await allowListFactory.signer.getAddress()); - allowList = AllowListFactory.connect(allowListContract.address, allowListContract.signer); - - const diamondInitFactory = await hardhat.ethers.getContractFactory('DiamondInit'); - const diamondInitContract = await diamondInitFactory.deploy(); - const diamondInit = DiamondInitFactory.connect(diamondInitContract.address, diamondInitContract.signer); - - const dummyHash = new Uint8Array(32); - dummyHash.set([1, 0, 0, 1]); - // const dummyAddress = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - const diamondInitData = diamondInit.interface.encodeFunctionData('initialize', [ - // dummyAddress, - await owner.getAddress(), - ethers.constants.HashZero, - 0, - ethers.constants.HashZero, - allowList.address, - // { - // recursionCircuitsSetVksHash: ethers.constants.HashZero, - // recursionLeafLevelVkHash: ethers.constants.HashZero, - // recursionNodeLevelVkHash: ethers.constants.HashZero - // }, - false, - dummyHash, - dummyHash, - 100000000000 - ]); - - const facetCuts = [ - facetCut(gettersFacet.address, gettersFacet.interface, Action.Add, false), - facetCut(mailboxFacet.address, mailboxFacet.interface, Action.Add, true) - ]; - - const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitData); - - const diamondProxyFactory = await hardhat.ethers.getContractFactory('DiamondProxy'); - const chainId = hardhat.network.config.chainId; - const diamondProxyContract = await diamondProxyFactory.deploy(chainId, diamondCutData); + const deployWallet = Wallet.fromMnemonic(ethTestConfig.test_mnemonic4, "m/44'/60'/0'/0/1").connect( + owner.provider + ); + const governorAddress = await deployWallet.getAddress(); + + const gasPrice = await owner.provider.getGasPrice(); + + const tx = { + from: owner.getAddress(), + to: deployWallet.address, + value: ethers.utils.parseEther('1000'), + nonce: owner.getTransactionCount(), + gasLimit: 100000, + gasPrice: gasPrice + }; + + await owner.sendTransaction(tx); + + const deployer = new Deployer({ + deployWallet, + governorAddress, + verbose: false, + addresses: addressConfig + }); + + const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + let nonce = await deployWallet.getTransactionCount(); + + await deployer.deployCreate2Factory({ gasPrice, nonce }); + nonce++; + + // await deployer.deployMulticall3(create2Salt, {gasPrice, nonce}); + // nonce++; + + process.env.CONTRACTS_GENESIS_ROOT = zeroHash; + process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = '0'; + process.env.CONTRACTS_GENESIS_BLOCK_COMMITMENT = zeroHash; + process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT = '72000000'; + process.env.CONTRACTS_RECURSION_NODE_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_LEAF_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_CIRCUITS_SET_VKS_HASH = zeroHash; + + await deployer.deployAllowList(create2Salt, { gasPrice, nonce }); + await deployer.deployBridgeheadContract(create2Salt, gasPrice); + await deployer.deployProofSystemContract(create2Salt, gasPrice); + await deployer.deployBridgeContracts(create2Salt, gasPrice); + await deployer.deployWethBridgeContracts(create2Salt, gasPrice); + + const verifierParams = { + recursionNodeLevelVkHash: zeroHash, + recursionLeafLevelVkHash: zeroHash, + recursionCircuitsSetVksHash: zeroHash + }; + const initialDiamondCut = await deployer.initialProofSystemProxyDiamondCut(); + + const proofSystem = deployer.proofSystemContract(deployWallet); + + await (await proofSystem.setParams(verifierParams, initialDiamondCut)).wait(); + + await deployer.registerHyperchain(create2Salt, gasPrice); + chainId = deployer.chainId; + + // const validatorTx = await deployer.proofChainContract(deployWallet).setValidator(await validator.getAddress(), true); + // await validatorTx.wait(); + + allowList = deployer.l1AllowList(deployWallet); + + const allowTx = await allowList.setBatchAccessMode( + [ + deployer.addresses.Bridgehead.BridgeheadProxy, + deployer.addresses.Bridgehead.ChainProxy, + deployer.addresses.ProofSystem.ProofSystemProxy, + deployer.addresses.ProofSystem.DiamondProxy, + deployer.addresses.Bridges.ERC20BridgeProxy, + deployer.addresses.Bridges.WethBridgeProxy + ], + [ + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public + ] + ); + await allowTx.wait(); - await (await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Public)).wait(); + // bridgeheadContract = BridgeheadFactory.connect(deployer.addresses.Bridgehead.BridgeheadProxy, deployWallet); l1Weth = WETH9Factory.connect( (await (await hardhat.ethers.getContractFactory('WETH9')).deploy()).address, @@ -123,13 +179,14 @@ describe('WETH Bridge tests', () => { const bridge = await ( await hardhat.ethers.getContractFactory('L1WethBridge') - ).deploy(l1Weth.address, diamondProxyContract.address, allowListContract.address); + ).deploy(l1Weth.address, deployer.addresses.Bridgehead.BridgeheadProxy, deployer.addresses.AllowList); // we don't test L2, so it is ok to give garbage factory deps and L2 address const garbageBytecode = '0x1111111111111111111111111111111111111111111111111111111111111111'; const garbageAddress = '0x71C7656EC7ab88b098defB751B7401B5f6d8976F'; const bridgeInitData = bridge.interface.encodeFunctionData('initialize', [ + chainId, [garbageBytecode, garbageBytecode], garbageAddress, await owner.getAddress(), @@ -203,14 +260,14 @@ describe('WETH Bridge tests', () => { const revertReason = await getCallRevertReason( bridgeProxy.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, '0x', []) ); - expect(revertReason).equal('Incorrect ETH message with additional data length'); + expect(revertReason).equal('pm'); }); it('Should revert on finalizing a withdrawal with wrong function selector', async () => { const revertReason = await getCallRevertReason( bridgeProxy.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, ethers.utils.randomBytes(96), []) ); - expect(revertReason).equal('Incorrect ETH message function selector'); + expect(revertReason).equal('is'); }); it('Should revert on finalizing a withdrawal with wrong receiver', async () => { @@ -226,7 +283,7 @@ describe('WETH Bridge tests', () => { [] ) ); - expect(revertReason).equal('Wrong L1 ETH withdraw receiver'); + expect(revertReason).equal('rz'); }); it('Should revert on finalizing a withdrawal with wrong L2 sender', async () => { @@ -247,6 +304,6 @@ describe('WETH Bridge tests', () => { [] ) ); - expect(revertReason).equal('The withdrawal was not initiated by L2 bridge'); + expect(revertReason).equal('rz'); }); }); diff --git a/ethereum/test/unit_tests/l2-upgrade.test.spec.ts b/ethereum/test/unit_tests/l2-upgrade.test.spec.ts index edae977d78..d18a4607b3 100644 --- a/ethereum/test/unit_tests/l2-upgrade.test.spec.ts +++ b/ethereum/test/unit_tests/l2-upgrade.test.spec.ts @@ -1,5 +1,7 @@ import { expect } from 'chai'; import * as hardhat from 'hardhat'; +import * as fs from 'fs'; +import * as path from 'path'; import { Action, facetCut, diamondCut } from '../../src.ts/diamondCut'; import { DiamondInitFactory, @@ -10,6 +12,9 @@ import { DiamondCutFacetFactory, GettersFacetFactory, GovernanceFacetFactory, + BridgeheadChainFactory, + BridgeheadChain, + DiamondFactory, GettersFacet, GovernanceFacet, DefaultUpgradeFactory, @@ -26,11 +31,24 @@ import { L2_BOOTLOADER_ADDRESS, packBatchTimestampAndBlockTimestamp } from './utils'; +import { readSystemContractsBytecode, hashL2Bytecode, readBlockBootloaderBytecode } from '../../scripts/utils'; +import { hexlify, keccak256 } from 'ethers/lib/utils'; import * as ethers from 'ethers'; -import { BigNumber, BigNumberish, BytesLike } from 'ethers'; +import { BigNumber, BigNumberish, Wallet, BytesLike } from 'ethers'; import { DiamondCutFacet } from '../../typechain'; import { REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT, hashBytecode } from 'zksync-web3/build/src/utils'; +import { Deployer } from '../../src.ts/deploy'; + +const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; + +const L2_BOOTLOADER_BYTECODE_HASH = hexlify(hashL2Bytecode(readBlockBootloaderBytecode())); +const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = hexlify(hashL2Bytecode(readSystemContractsBytecode('DefaultAccount'))); + +const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); +const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); + const SYSTEM_UPGRADE_TX_TYPE = 254; describe('L2 upgrade test', function () { @@ -49,90 +67,135 @@ describe('L2 upgrade test', function () { let verifier: string; let verifierParams: VerifierParams; const noopUpgradeTransaction = buildL2CanonicalTransaction({ txType: 0 }); + let chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID || 270; + let priorityOperationsHash: string; + let priorityOpTxHash: string; before(async () => { [owner] = await hardhat.ethers.getSigners(); - const executorFactory = await hardhat.ethers.getContractFactory('ExecutorFacet'); - const executorContract = await executorFactory.deploy(); - const executorFacet = ExecutorFacetFactory.connect(executorContract.address, executorContract.signer); - - const gettersFactory = await hardhat.ethers.getContractFactory('GettersFacet'); - const gettersContract = await gettersFactory.deploy(); - const gettersFacet = GettersFacetFactory.connect(gettersContract.address, gettersContract.signer); - - const diamondCutFacetFactory = await hardhat.ethers.getContractFactory('DiamondCutFacet'); - const diamondCutFacetContract = await diamondCutFacetFactory.deploy(); - const diamondCutFacet = DiamondCutFacetFactory.connect( - diamondCutFacetContract.address, - diamondCutFacetContract.signer + const deployWallet = Wallet.fromMnemonic(ethTestConfig.test_mnemonic3, "m/44'/60'/0'/0/1").connect( + owner.provider ); + const governorAddress = await deployWallet.getAddress(); + + const gasPrice = await owner.provider.getGasPrice(); - const governanceFactory = await hardhat.ethers.getContractFactory('GovernanceFacet'); - const governanceContract = await governanceFactory.deploy(); - const governanceFacet = GovernanceFacetFactory.connect(governanceContract.address, governanceContract.signer); - - const allowListFactory = await hardhat.ethers.getContractFactory('AllowList'); - const allowListContract = await allowListFactory.deploy(await allowListFactory.signer.getAddress()); - allowList = AllowListFactory.connect(allowListContract.address, allowListContract.signer); - - // Note, that while this testsuit is focused on testing MailboxFaucet only, - // we still need to initialize its storage via DiamondProxy - const diamondInitFactory = await hardhat.ethers.getContractFactory('DiamondInit'); - const diamondInitContract = await diamondInitFactory.deploy(); - const diamondInit = DiamondInitFactory.connect(diamondInitContract.address, diamondInitContract.signer); - - const dummyHash = new Uint8Array(32); - dummyHash.set([1, 0, 0, 1]); - verifier = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - verifierParams = { - recursionCircuitsSetVksHash: ethers.constants.HashZero, - recursionLeafLevelVkHash: ethers.constants.HashZero, - recursionNodeLevelVkHash: ethers.constants.HashZero + const tx = { + from: owner.getAddress(), + to: deployWallet.address, + value: ethers.utils.parseEther('1000'), + nonce: owner.getTransactionCount(), + gasLimit: 100000, + gasPrice: gasPrice }; - const diamondInitData = diamondInit.interface.encodeFunctionData('initialize', [ - verifier, - await owner.getAddress(), - ethers.constants.HashZero, - 0, - ethers.constants.HashZero, - allowList.address, - verifierParams, - false, - dummyHash, - dummyHash, - 100000000000 - ]); - const facetCuts = [ - // Should be unfreezable. The function to unfreeze contract is located on the diamond cut facet. - // That means if the diamond cut will be freezable, the proxy can NEVER be unfrozen. - facetCut(diamondCutFacet.address, diamondCutFacet.interface, Action.Add, false), - // Should be unfreezable. There are getters, that users can expect to be available. - facetCut(gettersFacet.address, gettersFacet.interface, Action.Add, false), - facetCut(executorFacet.address, executorFacet.interface, Action.Add, true), - facetCut(governanceFacet.address, governanceFacet.interface, Action.Add, true) - ]; + await owner.sendTransaction(tx); - const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitData); + const deployer = new Deployer({ + deployWallet, + governorAddress, + verbose: false, + addresses: addressConfig + }); + + const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + let nonce = await deployWallet.getTransactionCount(); + + await deployer.deployCreate2Factory({ gasPrice, nonce }); + nonce++; + + // await deployer.deployMulticall3(create2Salt, {gasPrice, nonce}); + // nonce++; - const diamondProxyFactory = await hardhat.ethers.getContractFactory('DiamondProxy'); - const chainId = hardhat.network.config.chainId; - diamondProxyContract = await diamondProxyFactory.deploy(chainId, diamondCutData); + process.env.CONTRACTS_GENESIS_ROOT = zeroHash; + process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = '0'; + process.env.CONTRACTS_GENESIS_BLOCK_COMMITMENT = zeroHash; + process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT = '72000000'; + process.env.CONTRACTS_RECURSION_NODE_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_LEAF_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_CIRCUITS_SET_VKS_HASH = zeroHash; + + await deployer.deployAllowList(create2Salt, { gasPrice, nonce }); + await deployer.deployBridgeheadContract(create2Salt, gasPrice); + await deployer.deployProofSystemContract(create2Salt, gasPrice); + await deployer.deployBridgeContracts(create2Salt, gasPrice); + await deployer.deployWethBridgeContracts(create2Salt, gasPrice); + + const verifierParams = { + recursionNodeLevelVkHash: zeroHash, + recursionLeafLevelVkHash: zeroHash, + recursionCircuitsSetVksHash: zeroHash + }; + verifier = deployer.addresses.ProofSystem.Verifier; + const initialDiamondCut = await deployer.initialProofSystemProxyDiamondCut(); + + const proofSystem = deployer.proofSystemContract(deployWallet); + + await (await proofSystem.setParams(verifierParams, initialDiamondCut)).wait(); + + await deployer.registerHyperchain(create2Salt, gasPrice); + chainId = deployer.chainId; + + // const validatorTx = await deployer.proofChainContract(deployWallet).setValidator(await validator.getAddress(), true); + // await validatorTx.wait(); + + allowList = deployer.l1AllowList(deployWallet); + + const allowTx = await allowList.setBatchAccessMode( + [ + deployer.addresses.Bridgehead.BridgeheadProxy, + deployer.addresses.Bridgehead.ChainProxy, + deployer.addresses.ProofSystem.ProofSystemProxy, + deployer.addresses.ProofSystem.DiamondProxy, + deployer.addresses.Bridges.ERC20BridgeProxy, + deployer.addresses.Bridges.WethBridgeProxy + ], + [ + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public + ] + ); + await allowTx.wait(); - await (await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Public)).wait(); + proxyExecutor = ExecutorFacetFactory.connect(deployer.addresses.ProofSystem.DiamondProxy, deployWallet); + proxyGetters = GettersFacetFactory.connect(deployer.addresses.ProofSystem.DiamondProxy, deployWallet); + proxyDiamondCut = DiamondCutFacetFactory.connect(deployer.addresses.ProofSystem.DiamondProxy, deployWallet); + proxyGovernance = GovernanceFacetFactory.connect(deployer.addresses.ProofSystem.DiamondProxy, deployWallet); - proxyExecutor = ExecutorFacetFactory.connect(diamondProxyContract.address, owner); - proxyGetters = GettersFacetFactory.connect(diamondProxyContract.address, owner); - proxyDiamondCut = DiamondCutFacetFactory.connect(diamondProxyContract.address, owner); - proxyGovernance = GovernanceFacetFactory.connect(diamondProxyContract.address, owner); + await (await proxyGovernance.setValidator(await deployWallet.getAddress(), true)).wait(); - await (await proxyGovernance.setValidator(await owner.getAddress(), true)).wait(); + // bridgeheadContract = BridgeheadFactory.connect(deployer.addresses.Bridgehead.BridgeheadProxy, deployWallet); + let bridgeheadChainContract = BridgeheadChainFactory.connect( + deployer.addresses.Bridgehead.ChainProxy, + deployWallet + ); + + let priorityOp = await bridgeheadChainContract.priorityQueueFrontOperation(); + priorityOpTxHash = priorityOp[0]; + priorityOperationsHash = keccak256( + ethers.utils.defaultAbiCoder.encode(['uint256', 'uint256'], [EMPTY_STRING_KECCAK, priorityOp[0]]) + ); }); it('Upgrade should work even if not all blocks are processed', async () => { + const timestamp = (await hardhat.ethers.provider.getBlock('latest')).timestamp; + const l2Logs = encodeLogs([ + contextLog(timestamp, ethers.constants.HashZero), + // bootloaderLog(l2UpgradeTxHash), + // bootloaderLog(l2UpgradeTxHash) + chainIdLog(priorityOpTxHash) + ]); block1Info = await buildCommitBlockInfo(genesisStoredBlockInfo(), { - blockNumber: 1 + blockNumber: 1, + priorityOperationsHash: priorityOperationsHash, + numberOfLayer1Txs: 1, + l2Logs }); const commitReceipt = await (await proxyExecutor.commitBlocks(genesisStoredBlockInfo(), [block1Info])).wait(); @@ -142,7 +205,7 @@ describe('L2 upgrade test', function () { expect(await proxyGetters.getL2SystemContractsUpgradeTxHash()).to.equal(ethers.constants.HashZero); await ( - await executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + await executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { newProtocolVersion: 1, l2ProtocolUpgradeTx: noopUpgradeTransaction }) @@ -158,14 +221,14 @@ describe('L2 upgrade test', function () { it('Timestamp should behave correctly', async () => { // Upgrade was scheduled for now should work fine const timeNow = (await hardhat.ethers.provider.getBlock('latest')).timestamp; - await executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + await executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { upgradeTimestamp: ethers.BigNumber.from(timeNow), l2ProtocolUpgradeTx: noopUpgradeTransaction }); // Upgrade that was scheduled for the future should not work now const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { upgradeTimestamp: ethers.BigNumber.from(timeNow).mul(2), l2ProtocolUpgradeTx: noopUpgradeTransaction }) @@ -180,7 +243,7 @@ describe('L2 upgrade test', function () { txType: 255 }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx }) ); @@ -197,7 +260,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, newProtocolVersion: 3 }) @@ -215,7 +278,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, newProtocolVersion: 0 }) @@ -233,7 +296,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, newProtocolVersion: 3 }) @@ -251,7 +314,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, newProtocolVersion: 3 }) @@ -270,7 +333,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, newProtocolVersion: 3 }) @@ -290,7 +353,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, factoryDeps: [myFactoryDep], newProtocolVersion: 3 @@ -310,7 +373,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, factoryDeps: [myFactoryDep], newProtocolVersion: 3 @@ -332,7 +395,7 @@ describe('L2 upgrade test', function () { }); const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { l2ProtocolUpgradeTx: wrongTx, factoryDeps: Array(33).fill(myFactoryDep), newProtocolVersion: 3 @@ -373,7 +436,9 @@ describe('L2 upgrade test', function () { newProtocolVersion: 4 }; - const upgradeReceipt = await (await executeTransparentUpgrade(proxyGetters, proxyDiamondCut, upgrade)).wait(); + const upgradeReceipt = await ( + await executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, upgrade) + ).wait(); const defaultUpgradeFactory = await hardhat.ethers.getContractFactory('DefaultUpgrade'); const upgradeEvents = upgradeReceipt.logs.map((log) => { @@ -417,15 +482,11 @@ describe('L2 upgrade test', function () { expect(upgradeEvents[2].args.newVerifierParams[2]).to.eq(newerVerifierParams.recursionCircuitsSetVksHash); expect(upgradeEvents[3].name).to.eq('NewL2BootloaderBytecodeHash'); - expect(upgradeEvents[3].args.previousBytecodeHash).to.eq( - '0x0100000100000000000000000000000000000000000000000000000000000000' - ); + expect(upgradeEvents[3].args.previousBytecodeHash).to.eq(L2_BOOTLOADER_BYTECODE_HASH); expect(upgradeEvents[3].args.newBytecodeHash).to.eq(bootloaderHash); expect(upgradeEvents[4].name).to.eq('NewL2DefaultAccountBytecodeHash'); - expect(upgradeEvents[4].args.previousBytecodeHash).to.eq( - '0x0100000100000000000000000000000000000000000000000000000000000000' - ); + expect(upgradeEvents[4].args.previousBytecodeHash).to.eq(L2_DEFAULT_ACCOUNT_BYTECODE_HASH); expect(upgradeEvents[4].args.newBytecodeHash).to.eq(defaultAccountHash); }); @@ -457,7 +518,7 @@ describe('L2 upgrade test', function () { newProtocolVersion: 5 }; const revertReason = await getCallRevertReason( - executeTransparentUpgrade(proxyGetters, proxyDiamondCut, upgrade) + executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, upgrade) ); await proxyDiamondCut.cancelUpgradeProposal(await proxyGetters.getProposedUpgradeHash()); @@ -561,7 +622,7 @@ describe('L2 upgrade test', function () { it('Should successfully commit a sequential upgrade', async () => { expect(await proxyGetters.getL2SystemContractsUpgradeBlockNumber()).to.equal(0); await ( - await executeTransparentUpgrade(proxyGetters, proxyDiamondCut, { + await executeTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { newProtocolVersion: 5, l2ProtocolUpgradeTx: noopUpgradeTransaction }) @@ -590,7 +651,7 @@ describe('L2 upgrade test', function () { it('Should successfully commit custom upgrade', async () => { const upgradeReceipt = await ( - await executeCustomTransparentUpgrade(proxyGetters, proxyDiamondCut, { + await executeCustomTransparentUpgrade(chainId, proxyGetters, proxyDiamondCut, { newProtocolVersion: 6, l2ProtocolUpgradeTx: noopUpgradeTransaction }) @@ -639,6 +700,8 @@ interface L2ToL1Log { sender: string; key: string; value: string; + shardId?: number; + isService?: boolean; } function contextLog(timestamp: number, prevBlockHash: BytesLike): L2ToL1Log { @@ -657,6 +720,16 @@ function bootloaderLog(txHash: BytesLike): L2ToL1Log { }; } +function chainIdLog(txHash: BytesLike): L2ToL1Log { + return { + sender: L2_BOOTLOADER_ADDRESS, + key: ethers.utils.hexlify(txHash), + value: ethers.utils.hexlify(BigNumber.from(1)), + isService: true, + shardId: 0 + }; +} + function encodeLog(log: L2ToL1Log): string { return ethers.utils.hexConcat([ `0x00000000`, @@ -809,6 +882,7 @@ function buildProposeUpgrade(proposedUpgrade: PartialProposedUpgrade): ProposedU } async function executeTransparentUpgrade( + chainId: BigNumberish, proxyGetters: GettersFacet, proxyDiamondCut: DiamondCutFacet, partialUpgrade: Partial, @@ -828,7 +902,7 @@ async function executeTransparentUpgrade( const defaultUpgrade = await defaultUpgradeFactory.deploy(); const diamondUpgradeInit = DefaultUpgradeFactory.connect(defaultUpgrade.address, defaultUpgrade.signer); - const upgradeCalldata = diamondUpgradeInit.interface.encodeFunctionData('upgrade', [upgrade]); + const upgradeCalldata = diamondUpgradeInit.interface.encodeFunctionData('upgrade', [chainId, upgrade]); const diamondCutData = diamondCut([], diamondUpgradeInit.address, upgradeCalldata); @@ -839,6 +913,7 @@ async function executeTransparentUpgrade( } async function executeCustomTransparentUpgrade( + chainId: BigNumberish, proxyGetters: GettersFacet, proxyDiamondCut: DiamondCutFacet, partialUpgrade: Partial, @@ -858,7 +933,7 @@ async function executeCustomTransparentUpgrade( const customUpgrade = await upgradeFactory.deploy(); const diamondUpgradeInit = CustomUpgradeTestFactory.connect(customUpgrade.address, customUpgrade.signer); - const upgradeCalldata = diamondUpgradeInit.interface.encodeFunctionData('upgrade', [upgrade]); + const upgradeCalldata = diamondUpgradeInit.interface.encodeFunctionData('upgrade', [chainId, upgrade]); const diamondCutData = diamondCut([], diamondUpgradeInit.address, upgradeCalldata); diff --git a/ethereum/test/unit_tests/mailbox_test.spec.ts b/ethereum/test/unit_tests/mailbox_test.spec.ts index e620098edf..be5c270b7f 100644 --- a/ethereum/test/unit_tests/mailbox_test.spec.ts +++ b/ethereum/test/unit_tests/mailbox_test.spec.ts @@ -2,82 +2,151 @@ import { expect } from 'chai'; import * as hardhat from 'hardhat'; import { Action, facetCut, diamondCut } from '../../src.ts/diamondCut'; import { - MailboxFacet, - MailboxFacetFactory, + BridgeheadMailbox, + BridgeheadMailboxFactory, + BridgeheadFactory, + BridgeheadChainFactory, DiamondInitFactory, AllowListFactory, AllowList, Forwarder, - ForwarderFactory + ForwarderFactory, + DiamondCutTestFactory, + DiamondFactory } from '../../typechain'; + +import * as fs from 'fs'; +import * as path from 'path'; + import { DEFAULT_REVERT_REASON, getCallRevertReason, AccessMode, REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - requestExecute + requestExecute, + requestExecuteDirect } from './utils'; +import { Wallet, BigNumberish, BytesLike } from 'ethers'; +import { Address } from 'zksync-web3/build/src/types'; + import * as ethers from 'ethers'; +import { Deployer } from '../../src.ts/deploy'; + +const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; + +const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); +const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); + describe('Mailbox tests', function () { - const chainId = ethers.BigNumber.from(9); - let mailbox: MailboxFacet; let allowList: AllowList; + let bridgeheadContract: ethers.Contract; + let bridgeheadChainContract: ethers.Contract; let diamondProxyContract: ethers.Contract; let owner: ethers.Signer; let randomSigner: ethers.Signer; const MAX_CODE_LEN_WORDS = (1 << 16) - 1; const MAX_CODE_LEN_BYTES = MAX_CODE_LEN_WORDS * 32; let forwarder: Forwarder; + let chainId = process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID || 270; before(async () => { [owner, randomSigner] = await hardhat.ethers.getSigners(); - const mailboxFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); - const mailboxContract = await mailboxFactory.deploy(); - const mailboxFacet = MailboxFacetFactory.connect(mailboxContract.address, mailboxContract.signer); - - const allowListFactory = await hardhat.ethers.getContractFactory('AllowList'); - const allowListContract = await allowListFactory.deploy(await allowListFactory.signer.getAddress()); - allowList = AllowListFactory.connect(allowListContract.address, allowListContract.signer); - - // Note, that while this testsuit is focused on testing MailboxFaucet only, - // we still need to initialize its storage via DiamondProxy - const diamondInitFactory = await hardhat.ethers.getContractFactory('DiamondInit'); - const diamondInitContract = await diamondInitFactory.deploy(); - const diamondInit = DiamondInitFactory.connect(diamondInitContract.address, diamondInitContract.signer); - - const dummyHash = new Uint8Array(32); - dummyHash.set([1, 0, 0, 1]); - const dummyAddress = ethers.utils.hexlify(ethers.utils.randomBytes(20)); - const diamondInitData = diamondInit.interface.encodeFunctionData('initialize', [ - // dummyAddress, - dummyAddress, - ethers.constants.HashZero, - 0, - ethers.constants.HashZero, - allowList.address, - // { - // recursionCircuitsSetVksHash: ethers.constants.HashZero, - // recursionLeafLevelVkHash: ethers.constants.HashZero, - // recursionNodeLevelVkHash: ethers.constants.HashZero - // }, - false, - dummyHash, - dummyHash, - 100000000000 - ]); - - const facetCuts = [facetCut(mailboxFacet.address, mailboxFacet.interface, Action.Add, false)]; - const diamondCutData = diamondCut(facetCuts, diamondInit.address, diamondInitData); - - const diamondProxyFactory = await hardhat.ethers.getContractFactory('DiamondProxy'); - const chainId = hardhat.network.config.chainId; - diamondProxyContract = await diamondProxyFactory.deploy(chainId, diamondCutData); - - await (await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Public)).wait(); - - mailbox = MailboxFacetFactory.connect(diamondProxyContract.address, mailboxContract.signer); + const deployWallet = Wallet.fromMnemonic(ethTestConfig.test_mnemonic3, "m/44'/60'/0'/0/1").connect( + owner.provider + ); + const governorAddress = await deployWallet.getAddress(); + + const gasPrice = await owner.provider.getGasPrice(); + + const tx = { + from: owner.getAddress(), + to: deployWallet.address, + value: ethers.utils.parseEther('1000'), + nonce: owner.getTransactionCount(), + gasLimit: 100000, + gasPrice: gasPrice + }; + + await owner.sendTransaction(tx); + + const deployer = new Deployer({ + deployWallet, + governorAddress, + verbose: false, + addresses: addressConfig + }); + + const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + let nonce = await deployWallet.getTransactionCount(); + + await deployer.deployCreate2Factory({ gasPrice, nonce }); + nonce++; + + // await deployer.deployMulticall3(create2Salt, {gasPrice, nonce}); + // nonce++; + + process.env.CONTRACTS_GENESIS_ROOT = zeroHash; + process.env.CONTRACTS_GENESIS_ROLLUP_LEAF_INDEX = '0'; + process.env.CONTRACTS_GENESIS_BLOCK_COMMITMENT = zeroHash; + process.env.CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT = '72000000'; + process.env.CONTRACTS_RECURSION_NODE_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_LEAF_LEVEL_VK_HASH = zeroHash; + process.env.CONTRACTS_RECURSION_CIRCUITS_SET_VKS_HASH = zeroHash; + + await deployer.deployAllowList(create2Salt, { gasPrice, nonce }); + await deployer.deployBridgeheadContract(create2Salt, gasPrice); + await deployer.deployProofSystemContract(create2Salt, gasPrice); + await deployer.deployBridgeContracts(create2Salt, gasPrice); + await deployer.deployWethBridgeContracts(create2Salt, gasPrice); + + const verifierParams = { + recursionNodeLevelVkHash: zeroHash, + recursionLeafLevelVkHash: zeroHash, + recursionCircuitsSetVksHash: zeroHash + }; + const initialDiamondCut = await deployer.initialProofSystemProxyDiamondCut(); + + const proofSystem = deployer.proofSystemContract(deployWallet); + + await (await proofSystem.setParams(verifierParams, initialDiamondCut)).wait(); + + await deployer.registerHyperchain(create2Salt, gasPrice); + chainId = deployer.chainId; + + // const validatorTx = await deployer.proofChainContract(deployWallet).setValidator(await validator.getAddress(), true); + // await validatorTx.wait(); + + allowList = deployer.l1AllowList(deployWallet); + + const allowTx = await allowList.setBatchAccessMode( + [ + deployer.addresses.Bridgehead.BridgeheadProxy, + deployer.addresses.Bridgehead.ChainProxy, + deployer.addresses.ProofSystem.ProofSystemProxy, + deployer.addresses.ProofSystem.DiamondProxy, + deployer.addresses.Bridges.ERC20BridgeProxy, + deployer.addresses.Bridges.WethBridgeProxy + ], + [ + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public, + AccessMode.Public + ] + ); + await allowTx.wait(); + + bridgeheadContract = BridgeheadFactory.connect(deployer.addresses.Bridgehead.BridgeheadProxy, deployWallet); + bridgeheadChainContract = BridgeheadChainFactory.connect( + deployer.addresses.Bridgehead.ChainProxy, + deployWallet + ); const forwarderFactory = await hardhat.ethers.getContractFactory('Forwarder'); const forwarderContract = await forwarderFactory.deploy(); @@ -88,7 +157,7 @@ describe('Mailbox tests', function () { const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox, + bridgeheadContract, ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -105,7 +174,7 @@ describe('Mailbox tests', function () { const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox, + bridgeheadContract, ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -122,7 +191,7 @@ describe('Mailbox tests', function () { const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox, + bridgeheadContract, ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -137,9 +206,8 @@ describe('Mailbox tests', function () { it('Should not accept bytecode that is too long', async () => { const revertReason = await getCallRevertReason( - requestExecute( - chainId, - mailbox, + requestExecuteDirect( + bridgeheadChainContract, ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -166,7 +234,7 @@ describe('Mailbox tests', function () { const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox, + bridgeheadContract, ethers.constants.AddressZero, ethers.utils.parseEther('12'), '0x', @@ -180,14 +248,19 @@ describe('Mailbox tests', function () { }); it('Should accept depositing less than or equal to the deposit limit', async () => { - const gasPrice = await mailbox.provider.getGasPrice(); + const gasPrice = await bridgeheadContract.provider.getGasPrice(); const l2GasLimit = ethers.BigNumber.from(1000000); - const l2Cost = await mailbox.l2TransactionBaseCost(gasPrice, l2GasLimit, REQUIRED_L2_GAS_PRICE_PER_PUBDATA); + const l2Cost = await bridgeheadContract.l2TransactionBaseCost( + chainId, + gasPrice, + l2GasLimit, + REQUIRED_L2_GAS_PRICE_PER_PUBDATA + ); const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox, + bridgeheadContract, ethers.constants.AddressZero, DEPOSIT_LIMIT.sub(l2Cost), '0x', @@ -205,7 +278,7 @@ describe('Mailbox tests', function () { const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox, + bridgeheadContract, ethers.constants.AddressZero, ethers.BigNumber.from(1), '0x', @@ -226,12 +299,12 @@ describe('Mailbox tests', function () { }); it(`Should not allow an un-whitelisted address to call`, async () => { - await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Closed); + await allowList.setAccessMode(bridgeheadChainContract.address, AccessMode.Closed); const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox.connect(randomSigner), + bridgeheadContract.connect(randomSigner), ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -240,22 +313,22 @@ describe('Mailbox tests', function () { ethers.constants.AddressZero ) ); - expect(revertReason).equal(`nr`); + expect(revertReason).equal(`nr2`); }); it(`Should allow the whitelisted address to call`, async () => { - await allowList.setAccessMode(diamondProxyContract.address, AccessMode.SpecialAccessOnly); + await allowList.setAccessMode(bridgeheadChainContract.address, AccessMode.SpecialAccessOnly); await allowList.setPermissionToCall( await owner.getAddress(), - diamondProxyContract.address, - `0xeb672419`, + bridgeheadChainContract.address, + `0xca0fbd7c`, true ); const revertReason = await getCallRevertReason( requestExecute( chainId, - mailbox.connect(owner), + bridgeheadContract.connect(owner), ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -277,7 +350,7 @@ describe('Mailbox tests', function () { return { transaction: await requestExecute( chainId, - mailbox.connect(owner), + bridgeheadContract.connect(owner), ethers.constants.AddressZero, ethers.BigNumber.from(0), '0x', @@ -290,7 +363,7 @@ describe('Mailbox tests', function () { }; const encodeRequest = (refundRecipient) => - mailbox.interface.encodeFunctionData('requestL2Transaction', [ + bridgeheadContract.interface.encodeFunctionData('requestL2Transaction', [ chainId, ethers.constants.AddressZero, 0, @@ -302,8 +375,9 @@ describe('Mailbox tests', function () { ]); let overrides: ethers.PayableOverrides = {}; - overrides.gasPrice = await mailbox.provider.getGasPrice(); - overrides.value = await mailbox.l2TransactionBaseCost( + overrides.gasPrice = await bridgeheadContract.provider.getGasPrice(); + overrides.value = await bridgeheadContract.l2TransactionBaseCost( + chainId, overrides.gasPrice, l2GasLimit, REQUIRED_L2_GAS_PRICE_PER_PUBDATA @@ -312,7 +386,11 @@ describe('Mailbox tests', function () { callViaForwarder = async (refundRecipient) => { return { - transaction: await forwarder.forward(mailbox.address, encodeRequest(refundRecipient), overrides), + transaction: await forwarder.forward( + bridgeheadContract.address, + encodeRequest(refundRecipient), + overrides + ), expectedSender: aliasAddress(forwarder.address) }; }; @@ -320,7 +398,7 @@ describe('Mailbox tests', function () { callViaConstructorForwarder = async (refundRecipient) => { const constructorForwarder = await ( await hardhat.ethers.getContractFactory('ConstructorForwarder') - ).deploy(mailbox.address, encodeRequest(refundRecipient), overrides); + ).deploy(bridgeheadContract.address, encodeRequest(refundRecipient), overrides); return { transaction: constructorForwarder.deployTransaction, @@ -332,8 +410,8 @@ describe('Mailbox tests', function () { it('Should only alias externally-owned addresses', async () => { const indirections = [callDirectly, callViaForwarder, callViaConstructorForwarder]; const refundRecipients = [ - [mailbox.address, false], - [await mailbox.signer.getAddress(), true] + [bridgeheadContract.address, false], + [await bridgeheadContract.signer.getAddress(), true] ]; for (const sendTransaction of indirections) { @@ -341,7 +419,7 @@ describe('Mailbox tests', function () { const result = await sendTransaction(refundRecipient); const [event] = (await result.transaction.wait()).logs; - const parsedEvent = mailbox.interface.parseLog(event); + const parsedEvent = bridgeheadContract.interface.parseLog(event); expect(parsedEvent.name).to.equal('NewPriorityRequest'); const canonicalTransaction = parsedEvent.args.transaction; diff --git a/ethereum/test/unit_tests/utils.ts b/ethereum/test/unit_tests/utils.ts index 68f799884b..675ae64968 100644 --- a/ethereum/test/unit_tests/utils.ts +++ b/ethereum/test/unit_tests/utils.ts @@ -31,10 +31,32 @@ export async function getCallRevertReason(promise) { try { await promise; } catch (e) { + // KL todo. The error messages are messed up. So we need all these cases. try { - revertReason = e.reason.match(/reverted with reason string '(.*)'/)?.[1] || e.reason; + revertReason = e.reason.match(/reverted with reason string '([^']*)'/)?.[1] || e.reason; + if ( + revertReason === 'cannot estimate gas; transaction may fail or may require manual gas limit' || + revertReason === DEFAULT_REVERT_REASON + ) { + revertReason = e.error.toString().match(/revert with reason \"([^']*)\"/)[1] || 'PLACEHOLDER_STRING'; + } } catch (_) { - throw e; + try { + if ( + revertReason === 'cannot estimate gas; transaction may fail or may require manual gas limit' || + revertReason === DEFAULT_REVERT_REASON + ) { + if (e.error) { + revertReason = + e.error.toString().match(/reverted with reason string '([^']*)'/)[1] || 'PLACEHOLDER_STRING'; + } else { + revertReason = + e.toString().match(/reverted with reason string '([^']*)'/)[1] || 'PLACEHOLDER_STRING'; + } + } + } catch (_) { + throw e.error.toString().slice(0, 5000) + e.error.toString().slice(-6000); + } } } return revertReason; @@ -77,6 +99,39 @@ export async function requestExecute( ); } +// due to gas reasons we call tha Chais's contract directly, instead of the bridgehead. +export async function requestExecuteDirect( + mailbox: ethers.Contract, + to: Address, + l2Value: ethers.BigNumber, + calldata: ethers.BytesLike, + l2GasLimit: ethers.BigNumber, + factoryDeps: BytesLike[], + refundRecipient: string +) { + let overrides = { gasPrice: 0 as BigNumberish, value: 0 as BigNumberish, gasLimit: 29000000 as BigNumberish }; + overrides.gasPrice = await mailbox.provider.getGasPrice(); + + // we call bridgeheadChain direcetly to avoid running out of gas. + const baseCost = await mailbox.l2TransactionBaseCost( + overrides.gasPrice, + ethers.BigNumber.from(100000), + REQUIRED_L2_GAS_PRICE_PER_PUBDATA + ); + overrides.value = baseCost.add(ethers.BigNumber.from(0)); + + return await mailbox.requestL2Transaction( + to, + l2Value, + calldata, + l2GasLimit, + REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + factoryDeps, + refundRecipient, + overrides + ); +} + export function genesisStoredBlockInfo(): StoredBlockInfo { return { blockNumber: 0, diff --git a/ethereum/test/unit_tests/validator_timelock_test.spec.ts b/ethereum/test/unit_tests/validator_timelock_test.spec.ts index fe2b4dae65..becf5e45b6 100644 --- a/ethereum/test/unit_tests/validator_timelock_test.spec.ts +++ b/ethereum/test/unit_tests/validator_timelock_test.spec.ts @@ -200,7 +200,7 @@ describe(`ValidatorTimelock tests`, function () { validatorTimelock.connect(validator).executeBlocks([getMockStoredBlockInfo(2)]) ); - expect(revertReason).equal("DummyExecutor: Can't execute blocks more than committed and proven currently"); + expect(revertReason).equal('DummyExecutor 2: Can'); }); // These tests primarily needed to make gas statistics be more accurate. diff --git a/ethereum/test/unit_tests/zksync-upgrade.fork.ts b/ethereum/test/unit_tests/zksync-upgrade.fork.ts index 5761c345b0..984aa2c43f 100644 --- a/ethereum/test/unit_tests/zksync-upgrade.fork.ts +++ b/ethereum/test/unit_tests/zksync-upgrade.fork.ts @@ -12,8 +12,8 @@ import { IGovernanceFactory } from '../../typechain/IGovernanceFactory'; import { IGovernance } from '../../typechain/IGovernance'; import { IMailboxFactory } from '../../typechain/IMailboxFactory'; import { IMailbox } from '../../typechain/IMailbox'; -import { IFactoryFactory } from '../../typechain/IFactoryFactory'; -import { IFactory } from '../../typechain/IFactory'; +import { IBridgeheadFactory } from '../../typechain/IBridgeheadFactory'; +import { IBridgehead } from '../../typechain/IBridgehead'; import { ethers } from 'ethers'; // TODO: change to the mainet config @@ -21,7 +21,7 @@ const DIAMOND_PROXY_ADDRESS = '0x1908e2BF4a88F91E4eF0DC72f02b8Ea36BEa2319'; describe('Diamond proxy upgrade fork test', function () { let governor: ethers.Signer; - let diamondProxy: IFactory; + let diamondProxy: IBridgehead; let newDiamondCutFacet: IDiamondCut; let newExecutorFacet: IExecutor; @@ -33,7 +33,7 @@ describe('Diamond proxy upgrade fork test', function () { before(async () => { const signers = await hardhat.ethers.getSigners(); - diamondProxy = IFactoryFactory.connect(DIAMOND_PROXY_ADDRESS, signers[0]); + diamondProxy = IBridgeheadFactory.connect(DIAMOND_PROXY_ADDRESS, signers[0]); const governorAddress = await diamondProxy.getGovernor(); await hardhat.network.provider.request({ method: 'hardhat_impersonateAccount', params: [governorAddress] }); @@ -57,7 +57,7 @@ describe('Diamond proxy upgrade fork test', function () { const governanceFacet = await governanceFacetFactory.deploy(); newGovernanceFacet = IGovernanceFactory.connect(governanceFacet.address, governanceFacet.signer); - const mailboxFacetFactory = await hardhat.ethers.getContractFactory('MailboxFacet'); + const mailboxFacetFactory = await hardhat.ethers.getContractFactory('Mailbox'); const mailboxFacet = await mailboxFacetFactory.deploy(); newMailboxFacet = IMailboxFactory.connect(mailboxFacet.address, mailboxFacet.signer); @@ -75,7 +75,7 @@ describe('Diamond proxy upgrade fork test', function () { const diamondCutFacet = await hardhat.ethers.getContractAt('DiamondCutFacet', newDiamondCutFacet.address); const executor = await hardhat.ethers.getContractAt('ExecutorFacet', newExecutorFacet.address); const governance = await hardhat.ethers.getContractAt('GovernanceFacet', newGovernanceFacet.address); - const mailbox = await hardhat.ethers.getContractAt('MailboxFacet', newMailboxFacet.address); + const mailbox = await hardhat.ethers.getContractAt('Mailbox', newMailboxFacet.address); const oldFacets = await diamondProxy.facets(); let selectorsToRemove = []; @@ -159,7 +159,7 @@ describe('Diamond proxy upgrade fork test', function () { const diamondCutFacet = await hardhat.ethers.getContractAt('DiamondCutFacet', newDiamondCutFacet.address); const executor = await hardhat.ethers.getContractAt('ExecutorFacet', newExecutorFacet.address); const governance = await hardhat.ethers.getContractAt('GovernanceFacet', newGovernanceFacet.address); - const mailbox = await hardhat.ethers.getContractAt('MailboxFacet', newMailboxFacet.address); + const mailbox = await hardhat.ethers.getContractAt('Mailbox', newMailboxFacet.address); const facets = [...(await await diamondProxy.facets())].sort(); const expectedFacets = [ diff --git a/zksync/contracts/L2ContractHelper.sol b/zksync/contracts/L2ContractHelper.sol index 5f443daac5..1203524a09 100644 --- a/zksync/contracts/L2ContractHelper.sol +++ b/zksync/contracts/L2ContractHelper.sol @@ -44,7 +44,11 @@ interface IContractDeployer { /// @param _salt a unique value to create the deterministic address of the new contract /// @param _bytecodeHash the bytecodehash of the new contract to be deployed /// @param _input the calldata to be sent to the constructor of the new contract - function create2(bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input) external; + function create2( + bytes32 _salt, + bytes32 _bytecodeHash, + bytes calldata _input + ) external; } interface IEthToken { diff --git a/zksync/contracts/SystemContractsCaller.sol b/zksync/contracts/SystemContractsCaller.sol index 7b4812ce71..1c6ce2936f 100644 --- a/zksync/contracts/SystemContractsCaller.sol +++ b/zksync/contracts/SystemContractsCaller.sol @@ -34,7 +34,12 @@ library Utils { /// @notice The library contains the functions to make system calls. /// @dev A more detailed description of the library and its methods can be found in the `system-contracts` repo. library SystemContractsCaller { - function systemCall(uint32 gasLimit, address to, uint256 value, bytes memory data) internal returns (bool success) { + function systemCall( + uint32 gasLimit, + address to, + uint256 value, + bytes memory data + ) internal returns (bool success) { address callAddr = SYSTEM_CALL_CALL_ADDRESS; uint32 dataStart; diff --git a/zksync/contracts/bridge/L2ERC20Bridge.sol b/zksync/contracts/bridge/L2ERC20Bridge.sol index d687e2fcb1..ec571f7a9e 100644 --- a/zksync/contracts/bridge/L2ERC20Bridge.sol +++ b/zksync/contracts/bridge/L2ERC20Bridge.sol @@ -36,7 +36,11 @@ contract L2ERC20Bridge is IL2Bridge, Initializable { _disableInitializers(); } - function initialize(address _l1Bridge, bytes32 _l2TokenProxyBytecodeHash, address _governor) external initializer { + function initialize( + address _l1Bridge, + bytes32 _l2TokenProxyBytecodeHash, + address _governor + ) external initializer { require(_l1Bridge != address(0), "bf"); require(_l2TokenProxyBytecodeHash != bytes32(0), "df"); require(_governor != address(0), "sf"); @@ -97,7 +101,11 @@ contract L2ERC20Bridge is IL2Bridge, Initializable { /// @param _l1Receiver The account address that should receive funds on L1 /// @param _l2Token The L2 token address which is withdrawn /// @param _amount The total amount of tokens to be withdrawn - function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external override { + function withdraw( + address _l1Receiver, + address _l2Token, + uint256 _amount + ) external override { IL2StandardToken(_l2Token).bridgeBurn(msg.sender, _amount); address l1Token = l1TokenAddress[_l2Token]; diff --git a/zksync/contracts/bridge/L2WethBridge.sol b/zksync/contracts/bridge/L2WethBridge.sol index 9cd12cadf7..dd23748a56 100644 --- a/zksync/contracts/bridge/L2WethBridge.sol +++ b/zksync/contracts/bridge/L2WethBridge.sol @@ -41,7 +41,11 @@ contract L2WethBridge is IL2Bridge, Initializable { /// @param _l1WethAddress The address of the L1 WETH token. /// @param _l2WethAddress The address of the L2 WETH token. /// @dev The function can only be called once during contract deployment due to the 'initializer' modifier. - function initialize(address _l1Bridge, address _l1WethAddress, address _l2WethAddress) external initializer { + function initialize( + address _l1Bridge, + address _l1WethAddress, + address _l2WethAddress + ) external initializer { require(_l1Bridge != address(0), "L1 WETH bridge address cannot be zero"); require(_l1WethAddress != address(0), "L1 WETH token address cannot be zero"); require(_l2WethAddress != address(0), "L2 WETH token address cannot be zero"); @@ -55,7 +59,11 @@ contract L2WethBridge is IL2Bridge, Initializable { /// @param _l1Receiver The account address that would receive the WETH on L1 /// @param _l2Token Address of the L2 WETH token /// @param _amount Total amount of WETH to withdraw - function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external override { + function withdraw( + address _l1Receiver, + address _l2Token, + uint256 _amount + ) external override { require(_l2Token == l2WethAddress, "Only WETH can be withdrawn"); require(_amount > 0, "Amount cannot be zero"); diff --git a/zksync/contracts/bridge/interfaces/IL2Bridge.sol b/zksync/contracts/bridge/interfaces/IL2Bridge.sol index e67fbbb722..8116e79dc6 100644 --- a/zksync/contracts/bridge/interfaces/IL2Bridge.sol +++ b/zksync/contracts/bridge/interfaces/IL2Bridge.sol @@ -26,7 +26,11 @@ interface IL2Bridge { bytes calldata _data ) external payable; - function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external; + function withdraw( + address _l1Receiver, + address _l2Token, + uint256 _amount + ) external; function l1TokenAddress(address _l2Token) external view returns (address); diff --git a/zksync/contracts/interfaces/IPaymasterFlow.sol b/zksync/contracts/interfaces/IPaymasterFlow.sol index dc1b849f40..c2df9d166a 100644 --- a/zksync/contracts/interfaces/IPaymasterFlow.sol +++ b/zksync/contracts/interfaces/IPaymasterFlow.sol @@ -12,5 +12,9 @@ pragma solidity ^0.8.0; interface IPaymasterFlow { function general(bytes calldata input) external; - function approvalBased(address _token, uint256 _minAllowance, bytes calldata _innerInput) external; + function approvalBased( + address _token, + uint256 _minAllowance, + bytes calldata _innerInput + ) external; } From f0f46dd4e504b98672d3d3dd2ce233dc94dd9f9d Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 4 Oct 2023 09:15:04 +0100 Subject: [PATCH 3/7] removed extra function --- .../bridgehead-interfaces/IBridgeheadMailbox.sol | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol b/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol index faf8982abf..58af7f2744 100644 --- a/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol +++ b/ethereum/contracts/bridgehead/bridgehead-interfaces/IBridgeheadMailbox.sol @@ -67,14 +67,6 @@ interface IBridgeheadMailbox is IMailboxEvents { address _refundRecipient ) external payable returns (bytes32 canonicalTxHash); - function requestL2TransactionProof( - uint256 _chainId, - WritePriorityOpParams memory _params, - bytes calldata _calldata, - bytes[] calldata _factoryDeps, - bool _isFree - ) external returns (bytes32 canonicalTxHash); - function l2TransactionBaseCost( uint256 _chainId, uint256 _gasPrice, From 7965b062055795464e5aa4e6995bf586bf598c2f Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 4 Oct 2023 09:39:54 +0100 Subject: [PATCH 4/7] replaced readBlockBootloaderBytecode in tests --- ethereum/src.ts/deploy.ts | 8 ++++++-- ethereum/test/unit_tests/executor_test.spec.ts | 7 ++++++- ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts | 7 ++++++- ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts | 7 ++++++- ethereum/test/unit_tests/l2-upgrade.test.spec.ts | 9 +++++---- ethereum/test/unit_tests/mailbox_test.spec.ts | 7 ++++++- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/ethereum/src.ts/deploy.ts b/ethereum/src.ts/deploy.ts index 0b22879317..8e63a41a0d 100644 --- a/ethereum/src.ts/deploy.ts +++ b/ethereum/src.ts/deploy.ts @@ -26,8 +26,8 @@ import { } from '../scripts/utils'; import { deployViaCreate2 } from './deploy-utils'; -const L2_BOOTLOADER_BYTECODE_HASH = hexlify(hashL2Bytecode(readBlockBootloaderBytecode())); -const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = hexlify(hashL2Bytecode(readSystemContractsBytecode('DefaultAccount'))); +let L2_BOOTLOADER_BYTECODE_HASH = hexlify(hashL2Bytecode(readBlockBootloaderBytecode())); +let L2_DEFAULT_ACCOUNT_BYTECODE_HASH = hexlify(hashL2Bytecode(readSystemContractsBytecode('DefaultAccount'))); export interface DeployedAddresses { Bridgehead: { @@ -68,6 +68,8 @@ export interface DeployerConfig { governorAddress?: string; verbose?: boolean; addresses?: DeployedAddresses; + bootloaderBytecodeHash?: string; + defaultAccountBytecodeHash?: string; } export function deployedAddressesFromEnv(): DeployedAddresses { @@ -118,6 +120,8 @@ export class Deployer { this.verbose = config.verbose != null ? config.verbose : false; this.addresses = config.addresses ? config.addresses : deployedAddressesFromEnv(); this.governorAddress = config.governorAddress != null ? config.governorAddress : this.deployWallet.address; + L2_BOOTLOADER_BYTECODE_HASH = config.bootloaderBytecodeHash ? config.bootloaderBytecodeHash : L2_BOOTLOADER_BYTECODE_HASH; + L2_DEFAULT_ACCOUNT_BYTECODE_HASH = config.defaultAccountBytecodeHash ? config.defaultAccountBytecodeHash : L2_DEFAULT_ACCOUNT_BYTECODE_HASH; } public async initialProofSystemProxyDiamondCut() { diff --git a/ethereum/test/unit_tests/executor_test.spec.ts b/ethereum/test/unit_tests/executor_test.spec.ts index 005576f1f8..a6a3baaa0f 100644 --- a/ethereum/test/unit_tests/executor_test.spec.ts +++ b/ethereum/test/unit_tests/executor_test.spec.ts @@ -39,6 +39,9 @@ import { hexlify, keccak256 } from 'ethers/lib/utils'; const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; +const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; +const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; + const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); @@ -90,7 +93,9 @@ describe(`Executor tests`, function () { deployWallet, governorAddress, verbose: false, - addresses: addressConfig + addresses: addressConfig, + bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, + defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH }); const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); diff --git a/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts index 54956eb2d4..6b062154e8 100644 --- a/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts +++ b/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts @@ -28,6 +28,9 @@ import { Deployer } from '../../src.ts/deploy'; const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; +const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; +const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; + const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); @@ -69,7 +72,9 @@ describe(`L1ERC20Bridge tests`, function () { deployWallet, governorAddress, verbose: false, - addresses: addressConfig + addresses: addressConfig, + bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, + defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH }); const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); diff --git a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts index 5aefc260e2..4de3738d88 100644 --- a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts +++ b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts @@ -28,6 +28,9 @@ import { Deployer } from '../../src.ts/deploy'; const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; +const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; +const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; + const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); @@ -102,7 +105,9 @@ describe('WETH Bridge tests', () => { deployWallet, governorAddress, verbose: false, - addresses: addressConfig + addresses: addressConfig, + bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, + defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH }); const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); diff --git a/ethereum/test/unit_tests/l2-upgrade.test.spec.ts b/ethereum/test/unit_tests/l2-upgrade.test.spec.ts index d18a4607b3..2e364418e0 100644 --- a/ethereum/test/unit_tests/l2-upgrade.test.spec.ts +++ b/ethereum/test/unit_tests/l2-upgrade.test.spec.ts @@ -31,7 +31,6 @@ import { L2_BOOTLOADER_ADDRESS, packBatchTimestampAndBlockTimestamp } from './utils'; -import { readSystemContractsBytecode, hashL2Bytecode, readBlockBootloaderBytecode } from '../../scripts/utils'; import { hexlify, keccak256 } from 'ethers/lib/utils'; import * as ethers from 'ethers'; import { BigNumber, BigNumberish, Wallet, BytesLike } from 'ethers'; @@ -42,8 +41,8 @@ import { Deployer } from '../../src.ts/deploy'; const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; -const L2_BOOTLOADER_BYTECODE_HASH = hexlify(hashL2Bytecode(readBlockBootloaderBytecode())); -const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = hexlify(hashL2Bytecode(readSystemContractsBytecode('DefaultAccount'))); +const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; +const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); @@ -96,7 +95,9 @@ describe('L2 upgrade test', function () { deployWallet, governorAddress, verbose: false, - addresses: addressConfig + addresses: addressConfig, + bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, + defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH }); const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); diff --git a/ethereum/test/unit_tests/mailbox_test.spec.ts b/ethereum/test/unit_tests/mailbox_test.spec.ts index be5c270b7f..34b2d51785 100644 --- a/ethereum/test/unit_tests/mailbox_test.spec.ts +++ b/ethereum/test/unit_tests/mailbox_test.spec.ts @@ -35,6 +35,9 @@ import { Deployer } from '../../src.ts/deploy'; const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; +const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; +const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; + const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); @@ -76,7 +79,9 @@ describe('Mailbox tests', function () { deployWallet, governorAddress, verbose: false, - addresses: addressConfig + addresses: addressConfig, + bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, + defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH }); const create2Salt = ethers.utils.hexlify(ethers.utils.randomBytes(32)); From 76016d0f9fd81c27d332c24aa0ca02a65f9bb661 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 4 Oct 2023 09:47:31 +0100 Subject: [PATCH 5/7] fixing readBlockBootloaderBytecode error --- ethereum/src.ts/deploy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethereum/src.ts/deploy.ts b/ethereum/src.ts/deploy.ts index 8e63a41a0d..9159c2a279 100644 --- a/ethereum/src.ts/deploy.ts +++ b/ethereum/src.ts/deploy.ts @@ -26,8 +26,8 @@ import { } from '../scripts/utils'; import { deployViaCreate2 } from './deploy-utils'; -let L2_BOOTLOADER_BYTECODE_HASH = hexlify(hashL2Bytecode(readBlockBootloaderBytecode())); -let L2_DEFAULT_ACCOUNT_BYTECODE_HASH = hexlify(hashL2Bytecode(readSystemContractsBytecode('DefaultAccount'))); +let L2_BOOTLOADER_BYTECODE_HASH : string; +let L2_DEFAULT_ACCOUNT_BYTECODE_HASH : string; export interface DeployedAddresses { Bridgehead: { @@ -120,8 +120,8 @@ export class Deployer { this.verbose = config.verbose != null ? config.verbose : false; this.addresses = config.addresses ? config.addresses : deployedAddressesFromEnv(); this.governorAddress = config.governorAddress != null ? config.governorAddress : this.deployWallet.address; - L2_BOOTLOADER_BYTECODE_HASH = config.bootloaderBytecodeHash ? config.bootloaderBytecodeHash : L2_BOOTLOADER_BYTECODE_HASH; - L2_DEFAULT_ACCOUNT_BYTECODE_HASH = config.defaultAccountBytecodeHash ? config.defaultAccountBytecodeHash : L2_DEFAULT_ACCOUNT_BYTECODE_HASH; + L2_BOOTLOADER_BYTECODE_HASH = config.bootloaderBytecodeHash ? config.bootloaderBytecodeHash : hexlify(hashL2Bytecode(readBlockBootloaderBytecode())); + L2_DEFAULT_ACCOUNT_BYTECODE_HASH = config.defaultAccountBytecodeHash ? config.defaultAccountBytecodeHash : hexlify(hashL2Bytecode(readSystemContractsBytecode('DefaultAccount'))); } public async initialProofSystemProxyDiamondCut() { From 08e664aef22b07ce8f36621d9b6892a69ad34a7e Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 4 Oct 2023 10:04:03 +0100 Subject: [PATCH 6/7] added constants for testing --- .../test/test_config/constant/addresses.json | 33 +++++++++++++++++++ ethereum/test/test_config/constant/eth.json | 14 ++++++++ .../test/unit_tests/executor_test.spec.ts | 2 +- .../unit_tests/l1_erc20_bridge_test.spec.ts | 2 +- .../unit_tests/l1_weth_bridge_test.spec.ts | 2 +- .../test/unit_tests/l2-upgrade.test.spec.ts | 2 +- ethereum/test/unit_tests/mailbox_test.spec.ts | 2 +- 7 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 ethereum/test/test_config/constant/addresses.json create mode 100644 ethereum/test/test_config/constant/eth.json diff --git a/ethereum/test/test_config/constant/addresses.json b/ethereum/test/test_config/constant/addresses.json new file mode 100644 index 0000000000..2adfc8b483 --- /dev/null +++ b/ethereum/test/test_config/constant/addresses.json @@ -0,0 +1,33 @@ +{ + "Bridgehead": { + "BridgeheadProxy": "0x0000000000000000000000000000000000000000", + "BridgeheadImplementation": "0x0000000000000000000000000000000000000000", + "BridgeheadProxyAdmin": "0x0000000000000000000000000000000000000000", + "ChainImplementation": "0x0000000000000000000000000000000000000000", + "ChainProxy": "0x0000000000000000000000000000000000000000", + "ChainProxyAdmin": "0x0000000000000000000000000000000000000000" + }, + "ProofSystem": { + "ProofSystemProxy": "0x0000000000000000000000000000000000000000", + "ProofSystemImplementation": "0x0000000000000000000000000000000000000000", + "ProofSystemProxyAdmin": "0x0000000000000000000000000000000000000000", + "Verifier": "0x0000000000000000000000000000000000000000", + "GovernanceFacet": "0x0000000000000000000000000000000000000000", + "DiamondCutFacet": "0x0000000000000000000000000000000000000000", + "ExecutorFacet": "0x0000000000000000000000000000000000000000", + "GettersFacet": "0x0000000000000000000000000000000000000000", + "DiamondInit": "0x0000000000000000000000000000000000000000", + "DiamondUpgradeInit": "0x0000000000000000000000000000000000000000", + "DefaultUpgrade": "0x0000000000000000000000000000000000000000", + "DiamondProxy": "0x0000000000000000000000000000000000000000" + }, + "Bridges": { + "ERC20BridgeImplementation": "0x0000000000000000000000000000000000000000", + "ERC20BridgeProxy": "0x0000000000000000000000000000000000000000", + "WethBridgeImplementation": "0x0000000000000000000000000000000000000000", + "WethBridgeProxy": "0x0000000000000000000000000000000000000000" + }, + "AllowList": "0x0000000000000000000000000000000000000000", + "Create2Factory": "0x0000000000000000000000000000000000000000", + "ValidatorTimeLock": "0x0000000000000000000000000000000000000000" +} diff --git a/ethereum/test/test_config/constant/eth.json b/ethereum/test/test_config/constant/eth.json new file mode 100644 index 0000000000..f6e6003a50 --- /dev/null +++ b/ethereum/test/test_config/constant/eth.json @@ -0,0 +1,14 @@ +{ + "web3_url": "http://127.0.0.1:8545", + "test_mnemonic": "stuff slice staff easily soup parent arm payment cotton trade scatter struggle", + "test_mnemonic2": "pair glimpse monkey crisp eternal often favorite amused valley year prize inspire", + "test_mnemonic3": "jar coyote segment sign gate host device wonder mention hybrid spawn rifle", + "test_mnemonic4": "science rally wrestle destroy fly album manual virus cloud tortoise core adapt", + "test_mnemonic5": "process supply swift attack build mobile laundry keep regret just arrive pepper", + "test_mnemonic6": "age second sugar novel round mechanic settle garage peasant spell bus surprise", + "test_mnemonic7": "embody number total rice word lunch reject jungle merge siren elegant finger", + "test_mnemonic8": "race bring office flip tired subject region public about target effort aisle", + "test_mnemonic9": "regret bench until lesson fever two license garlic series rice odor tourist", + "test_mnemonic10": "misery lizard beach magic blue one genre damage excess police image become", + "mnemonic": "fine music test violin matrix prize squirrel panther purchase material script deal" +} diff --git a/ethereum/test/unit_tests/executor_test.spec.ts b/ethereum/test/unit_tests/executor_test.spec.ts index a6a3baaa0f..58289426bf 100644 --- a/ethereum/test/unit_tests/executor_test.spec.ts +++ b/ethereum/test/unit_tests/executor_test.spec.ts @@ -42,7 +42,7 @@ const zeroHash = '0x000000000000000000000000000000000000000000000000000000000000 const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const testConfigPath ='./test/test_config/constant'; const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); diff --git a/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts index 6b062154e8..83dc09e7f1 100644 --- a/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts +++ b/ethereum/test/unit_tests/l1_erc20_bridge_test.spec.ts @@ -31,7 +31,7 @@ const zeroHash = '0x000000000000000000000000000000000000000000000000000000000000 const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const testConfigPath ='./test/test_config/constant'; const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); diff --git a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts index 4de3738d88..cc3ae593f8 100644 --- a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts +++ b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts @@ -31,7 +31,7 @@ const zeroHash = '0x000000000000000000000000000000000000000000000000000000000000 const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const testConfigPath ='./test/test_config/constant'; const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); diff --git a/ethereum/test/unit_tests/l2-upgrade.test.spec.ts b/ethereum/test/unit_tests/l2-upgrade.test.spec.ts index 2e364418e0..bd138228e3 100644 --- a/ethereum/test/unit_tests/l2-upgrade.test.spec.ts +++ b/ethereum/test/unit_tests/l2-upgrade.test.spec.ts @@ -44,7 +44,7 @@ const zeroHash = '0x000000000000000000000000000000000000000000000000000000000000 const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const testConfigPath ='./test/test_config/constant'; const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); diff --git a/ethereum/test/unit_tests/mailbox_test.spec.ts b/ethereum/test/unit_tests/mailbox_test.spec.ts index 34b2d51785..ec747fcede 100644 --- a/ethereum/test/unit_tests/mailbox_test.spec.ts +++ b/ethereum/test/unit_tests/mailbox_test.spec.ts @@ -38,7 +38,7 @@ const zeroHash = '0x000000000000000000000000000000000000000000000000000000000000 const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000" ; const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); +const testConfigPath ='./test/test_config/constant'; const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); const addressConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/addresses.json`, { encoding: 'utf-8' })); From d79960a53556b6d4c8fa07033cc7dd759e230a38 Mon Sep 17 00:00:00 2001 From: kelemeno Date: Wed, 4 Oct 2023 10:20:27 +0100 Subject: [PATCH 7/7] added token config --- ethereum/scripts/utils.ts | 2 +- .../test/test_config/constant/localhost.json | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 ethereum/test/test_config/constant/localhost.json diff --git a/ethereum/scripts/utils.ts b/ethereum/scripts/utils.ts index 27634376e2..2867087744 100644 --- a/ethereum/scripts/utils.ts +++ b/ethereum/scripts/utils.ts @@ -149,7 +149,7 @@ export type L1Token = { }; export function getTokens(network: string): L1Token[] { - const configPath = `${process.env.ZKSYNC_HOME}/etc/tokens/${network}.json`; + const configPath = process.env.ZKSYNC_HOME ? `${process.env.ZKSYNC_HOME}/etc/tokens/${network}.json` : `./test/test_config/constant/${network}.json`; return JSON.parse( fs.readFileSync(configPath, { encoding: 'utf-8' diff --git a/ethereum/test/test_config/constant/localhost.json b/ethereum/test/test_config/constant/localhost.json new file mode 100644 index 0000000000..e3b6aa5366 --- /dev/null +++ b/ethereum/test/test_config/constant/localhost.json @@ -0,0 +1,98 @@ +[ + { + "name": "DAI", + "symbol": "DAI", + "decimals": 18, + "address": "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" + }, + { + "name": "wBTC", + "symbol": "wBTC", + "decimals": 8, + "address": "0x3fad2B2E21eA1c96618Cc76a42Fb5a77c3f71c6F" + }, + { + "name": "BAT", + "symbol": "BAT", + "decimals": 18, + "address": "0x2c7E84980191210883d2dF3167A3AB6A2cc15E01" + }, + { + "name": "GNT", + "symbol": "GNT", + "decimals": 18, + "address": "0x5C55e2cf0a4243b9C7676e0aD8687C308959A153" + }, + { + "name": "MLTT", + "symbol": "MLTT", + "decimals": 18, + "address": "0xa1453A97EF37FD456c0698e9aF0b745c669Ad8Ee" + }, + { + "name": "DAIK", + "symbol": "DAIK", + "decimals": 18, + "address": "0x66F85dC64Ead7f86fb3288489E48Ae520eDaa774" + }, + { + "name": "wBTCK", + "symbol": "wBTCK", + "decimals": 8, + "address": "0x23AB565D319E9A82ba5F05b783ACe9E6960516be" + }, + { + "name": "BATK", + "symbol": "BATS", + "decimals": 18, + "address": "0xEAF2734b6c1DF7AD8F45569e50dc70179727D604" + }, + { + "name": "GNTK", + "symbol": "GNTS", + "decimals": 18, + "address": "0x2FDfd23587B1b60FB9b427bd47b34427ca33210F" + }, + { + "name": "MLTTK", + "symbol": "MLTTS", + "decimals": 18, + "address": "0x1f54bd31077A42f00f5530A012b8eDE0992F7cdD" + }, + { + "name": "DAIL", + "symbol": "DAIL", + "decimals": 18, + "address": "0x6Cec063Ec6099C3B7428F031f9B4d206E1eC0a4b" + }, + { + "name": "wBTCL", + "symbol": "wBTCP", + "decimals": 8, + "address": "0x20902cA38AD7Ab02e4423B7c5A251AEBBa966e6b" + }, + { + "name": "BATL", + "symbol": "BATW", + "decimals": 18, + "address": "0xaB27993C34F0053852dafF017cFb7bF977509D38" + }, + { + "name": "GNTL", + "symbol": "GNTW", + "decimals": 18, + "address": "0x6e77E09aa1d75ad2D00196452E66d19A972aC462" + }, + { + "name": "MLTTL", + "symbol": "MLTTW", + "decimals": 18, + "address": "0xFFe5ef7d6da85DF52EA904876552792bed79adcB" + }, + { + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "address": "0x2F85d7963Bb149Df2097C500CE8Cc7b417F95926" + } +]