From a036012ad95e52a97200303b4b1e413b13eea83a Mon Sep 17 00:00:00 2001 From: jayt106 Date: Tue, 1 Aug 2023 16:51:04 -0400 Subject: [PATCH] remove weth bridge deploy --- docs/Overview.md | 4 +- ethereum/contracts/zksync/DiamondInit.sol | 4 +- ethereum/package.json | 6 +- ethereum/scripts/deploy-weth-bridges.ts | 60 ----- ethereum/scripts/deploy.ts | 4 +- ethereum/scripts/initialize-bridges.ts | 45 ---- ethereum/scripts/initialize-l1-allow-list.ts | 3 +- ethereum/scripts/initialize-l2-weth-token.ts | 183 ------------- ethereum/scripts/initialize-weth-bridges.ts | 106 -------- ethereum/scripts/upgrades/upgrade-6.ts | 194 -------------- ethereum/scripts/verify.ts | 26 +- ethereum/src.ts/deploy.ts | 69 +---- .../unit_tests/l1_weth_bridge_test.spec.ts | 245 ------------------ zksync/package.json | 1 - zksync/src/deployL2Weth.ts | 125 --------- zksync/src/upgradeL2BridgeImpl.ts | 4 +- 16 files changed, 17 insertions(+), 1062 deletions(-) delete mode 100644 ethereum/scripts/deploy-weth-bridges.ts delete mode 100644 ethereum/scripts/initialize-l2-weth-token.ts delete mode 100644 ethereum/scripts/initialize-weth-bridges.ts delete mode 100644 ethereum/scripts/upgrades/upgrade-6.ts delete mode 100644 ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts delete mode 100644 zksync/src/deployL2Weth.ts diff --git a/docs/Overview.md b/docs/Overview.md index 1a8bddfe..97219020 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -209,7 +209,7 @@ The L2 counterpart of the L1 ERC20 bridge. - `withdraw` - initiate a withdrawal by burning funds on the contract and sending a corresponding message to L1. - `finalizeDeposit` - finalize the deposit and mint funds on L2. -##### L1WethBridge +##### L1WethBridge (Removed) The custom bridge exclusively handles transfers of WETH tokens between the two domains. It is designed to streamline and enhance the user experience for bridging WETH tokens by minimizing the number of transactions required and reducing @@ -220,7 +220,7 @@ it is wrapped back into WETH and delivered to the L2 recipient. Thus, the deposit is made in one transaction, and the user receives L2 WETH that can be unwrapped to ETH. -##### L2WethBridge +##### L2WethBridge (Removed) The L2 counterpart of the L1 WETH bridge. diff --git a/ethereum/contracts/zksync/DiamondInit.sol b/ethereum/contracts/zksync/DiamondInit.sol index 0c19c3cd..d9fb9021 100644 --- a/ethereum/contracts/zksync/DiamondInit.sol +++ b/ethereum/contracts/zksync/DiamondInit.sol @@ -39,15 +39,13 @@ contract DiamondInit is Base { bool _zkPorterIsAvailable, bytes32 _l2BootloaderBytecodeHash, bytes32 _l2DefaultAccountBytecodeHash, - uint256 _priorityTxMaxGasLimit, - address _gasTokenAddress + uint256 _priorityTxMaxGasLimit ) external reentrancyGuardInitializer returns (bytes32) { require(address(_verifier) != address(0), "vt"); require(_governor != address(0), "vy"); s.verifier = _verifier; s.governor = _governor; - s.gasTokenAddress = _gasTokenAddress; // We need to initialize the state hash because it is used in the commitment of the next block IExecutor.StoredBlockInfo memory storedBlockZero = IExecutor.StoredBlockInfo( diff --git a/ethereum/package.json b/ethereum/package.json index a7ea833e..92b6d1bb 100644 --- a/ethereum/package.json +++ b/ethereum/package.json @@ -51,9 +51,6 @@ "test": "CONTRACT_TESTS=1 yarn hardhat test test/unit_tests/*.spec.ts --network hardhat", "test:fork": "CONTRACT_TESTS=1 TEST_CONTRACTS_FORK=1 yarn run hardhat test test/unit_tests/*.fork.ts --network hardhat", "deploy-no-build": "ts-node scripts/deploy.ts", - "deploy-weth-bridges": "ts-node scripts/deploy-weth-bridges.ts", - "initialize-weth-bridges": "ts-node scripts/initialize-weth-bridges.ts", - "initialize-l2-weth-token": "ts-node scripts/initialize-l2-weth-token.ts", "allow-list-manager": "ts-node scripts/allow-list-manager.ts", "deploy-erc20": "ts-node scripts/deploy-erc20.ts", "token-info": "ts-node scripts/token-info.ts", @@ -69,8 +66,7 @@ "upgrade-2": "ts-node scripts/upgrades/upgrade-2.ts", "upgrade-3": "ts-node scripts/upgrades/upgrade-3.ts", "upgrade-4": "ts-node scripts/upgrades/upgrade-4.ts", - "upgrade-5": "ts-node scripts/upgrades/upgrade-5.ts", - "upgrade-6": "ts-node scripts/upgrades/upgrade-6.ts" + "upgrade-5": "ts-node scripts/upgrades/upgrade-5.ts" }, "dependencies": { "dotenv": "^16.0.3" diff --git a/ethereum/scripts/deploy-weth-bridges.ts b/ethereum/scripts/deploy-weth-bridges.ts deleted file mode 100644 index 6e0d7ec8..00000000 --- a/ethereum/scripts/deploy-weth-bridges.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Command } from 'commander'; -import { Wallet, ethers } from 'ethers'; -import { Deployer } from '../src.ts/deploy'; -import { formatUnits, parseUnits } from 'ethers/lib/utils'; -import * as fs from 'fs'; -import * as path from 'path'; -import { web3Provider } from './utils'; - -const provider = web3Provider(); -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' })); - -async function main() { - const program = new Command(); - - program.version('0.1.0').name('deploy').description('deploy weth bridges'); - - program - .option('--private-key ') - .option('--gas-price ') - .option('--nonce ') - .option('--governor-address ') - .option('--create2-salt ') - .action(async (cmd) => { - const deployWallet = cmd.privateKey - ? new Wallet(cmd.privateKey, provider) - : Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/0" - ).connect(provider); - console.log(`Using deployer wallet: ${deployWallet.address}`); - - const governorAddress = cmd.governorAddress ? cmd.governorAddress : deployWallet.address; - console.log(`Using governor address: ${governorAddress}`); - - const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); - console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); - - let nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployWallet.getTransactionCount(); - console.log(`Using nonce: ${nonce}`); - - const create2Salt = cmd.create2Salt ? cmd.create2Salt : ethers.utils.hexlify(ethers.utils.randomBytes(32)); - - const deployer = new Deployer({ - deployWallet, - governorAddress, - verbose: true - }); - - await deployer.deployWethBridgeContracts(create2Salt, gasPrice); - }); - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error('Error:', err); - process.exit(1); - }); diff --git a/ethereum/scripts/deploy.ts b/ethereum/scripts/deploy.ts index 6cc59770..d3f0c87f 100644 --- a/ethereum/scripts/deploy.ts +++ b/ethereum/scripts/deploy.ts @@ -64,10 +64,8 @@ async function main() { nonce++; } await deployer.deployAllowList(create2Salt, { gasPrice, nonce }); - await deployer.deployWethToken(create2Salt, { gasPrice, nonce: nonce + 1 }); - await deployer.deployZkSyncContract(create2Salt, gasPrice, nonce + 2); + await deployer.deployZkSyncContract(create2Salt, gasPrice, nonce + 1); await deployer.deployBridgeContracts(create2Salt, gasPrice); // Do not pass nonce, since it was increment after deploying zkSync contracts - await deployer.deployWethBridgeContracts(create2Salt, gasPrice); await deployer.deployValidatorTimelock(create2Salt, { gasPrice }); }); diff --git a/ethereum/scripts/initialize-bridges.ts b/ethereum/scripts/initialize-bridges.ts index 18366e47..ff1de593 100644 --- a/ethereum/scripts/initialize-bridges.ts +++ b/ethereum/scripts/initialize-bridges.ts @@ -13,7 +13,6 @@ import { import * as fs from 'fs'; import * as path from 'path'; -import { WETH9, WETH9Factory } from '../typechain'; const provider = web3Provider(); const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); @@ -52,16 +51,6 @@ const L2_STANDARD_ERC20_PROXY_FACTORY_BYTECODE = readBytecode( const L2_ERC20_BRIDGE_INTERFACE = readInterface(l2BridgeArtifactsPath, 'L2ERC20Bridge'); const DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = getNumberFromEnv('CONTRACTS_DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT'); -async function approveSpendingGasToken(weth9: WETH9, wallet: Wallet, spender: string, amount: ethers.BigNumber) { - weth9 = weth9.connect(wallet); - const approveTx = await weth9.approve(spender, amount, { - gasLimit: 210000, - }); - await approveTx.wait() - let allowance = await weth9.allowance(wallet.address, spender); - console.log(`Wallet ${wallet.address} allowance for spender ${spender}: ${ethers.utils.formatEther(allowance)}`); -} - async function main() { const program = new Command(); @@ -87,41 +76,7 @@ async function main() { verbose: true }); - // mint weth token, with weth admin wallet - const deploy2Wallet = cmd.privateKey - ? new Wallet(cmd.privateKey, provider) - : Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/1" - ).connect(provider); - const zkSync = deployer.zkSyncContract(deployWallet); - - const wethTokenAddress = deployer.addresses.WethToken; - console.log(wethTokenAddress); - - let weth9 = WETH9Factory.connect(wethTokenAddress, deploy2Wallet) - // mint for deployer wallet - const tx = await weth9.mint(deployWallet.address, ethers.utils.parseEther('10000000000'), { - gasLimit: 210000, - }); - await tx.wait() - const weth9Balance = await weth9.balanceOf(deployWallet.address); - console.log(`[deployer]weth9 Balance: ${ethers.utils.formatEther(weth9Balance)}`) - - // mint for deployer2 wallet - const tx2 = await weth9.mint(deploy2Wallet.address, ethers.utils.parseEther('10000000000'), { - gasLimit: 210000, - }); - await tx2.wait() - const weth9Balance2 = await weth9.balanceOf(deploy2Wallet.address); - console.log(`[deployer2]weth9 Balance: ${ethers.utils.formatEther(weth9Balance2)}`) - - // approve bridge for spending with the deployer wallet - await approveSpendingGasToken(weth9, deployWallet, zkSync.address, ethers.constants.MaxUint256); - await approveSpendingGasToken(weth9, deploy2Wallet, zkSync.address, ethers.constants.MaxUint256); - - const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); diff --git a/ethereum/scripts/initialize-l1-allow-list.ts b/ethereum/scripts/initialize-l1-allow-list.ts index 9d8c933a..c7c614ab 100644 --- a/ethereum/scripts/initialize-l1-allow-list.ts +++ b/ethereum/scripts/initialize-l1-allow-list.ts @@ -41,8 +41,7 @@ async function main() { await allowListContract.setBatchAccessMode( [ deployer.addresses.ZkSync.DiamondProxy, - deployer.addresses.Bridges.ERC20BridgeProxy, - deployer.addresses.Bridges.WethBridgeProxy + deployer.addresses.Bridges.ERC20BridgeProxy ], [AccessMode.Public, AccessMode.Public, AccessMode.Public], { nonce } diff --git a/ethereum/scripts/initialize-l2-weth-token.ts b/ethereum/scripts/initialize-l2-weth-token.ts deleted file mode 100644 index 598489ca..00000000 --- a/ethereum/scripts/initialize-l2-weth-token.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { Command } from 'commander'; -import { ethers, Wallet } from 'ethers'; -import { Deployer } from '../src.ts/deploy'; -import { formatUnits, parseUnits } from 'ethers/lib/utils'; -import { web3Provider, getNumberFromEnv, REQUIRED_L2_GAS_PRICE_PER_PUBDATA } from './utils'; -import { getTokens } from 'reading-tool'; - -import * as fs from 'fs'; -import * as path from 'path'; - -const provider = web3Provider(); -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 contractArtifactsPath = path.join(process.env.ZKSYNC_HOME as string, 'contracts/zksync/artifacts-zk/'); -const l2BridgeArtifactsPath = path.join(contractArtifactsPath, 'cache-zk/solpp-generated-contracts/bridge/'); -const openzeppelinTransparentProxyArtifactsPath = path.join( - contractArtifactsPath, - '@openzeppelin/contracts/proxy/transparent/' -); - -function readInterface(path: string, fileName: string) { - const abi = JSON.parse(fs.readFileSync(`${path}/${fileName}.sol/${fileName}.json`, { encoding: 'utf-8' })).abi; - return new ethers.utils.Interface(abi); -} - -const DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = getNumberFromEnv('CONTRACTS_DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT'); -const L2_WETH_INTERFACE = readInterface(l2BridgeArtifactsPath, 'L2Weth'); -const TRANSPARENT_UPGRADEABLE_PROXY = readInterface( - openzeppelinTransparentProxyArtifactsPath, - 'TransparentUpgradeableProxy' -); - -function getL2Calldata(l2WethBridgeAddress: string, l1WethTokenAddress: string, l2WethTokenImplAddress: string) { - const upgradeData = L2_WETH_INTERFACE.encodeFunctionData('initializeV2', [l2WethBridgeAddress, l1WethTokenAddress]); - return TRANSPARENT_UPGRADEABLE_PROXY.encodeFunctionData('upgradeToAndCall', [l2WethTokenImplAddress, upgradeData]); -} - -async function getL1TxInfo( - deployer: Deployer, - to: string, - l2Calldata: string, - refundRecipient: string, - gasPrice: ethers.BigNumber -) { - const zksync = deployer.zkSyncContract(ethers.Wallet.createRandom().connect(provider)); - const l1Calldata = zksync.interface.encodeFunctionData('requestL2Transaction', [ - 0, - { - l2Contract: to, - l2Value: 0, - gasAmount: 0, - l2GasLimit: DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT, - l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - }, - l2Calldata, - [], // It is assumed that the target has already been deployed - refundRecipient - ]); - - const neededValue = await zksync.l2TransactionBaseCost( - gasPrice, - DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA - ); - - return { - to: zksync.address, - data: l1Calldata, - value: neededValue.toString(), - gasPrice: gasPrice.toString() - }; -} - -async function main() { - const program = new Command(); - - program.version('0.1.0').name('initialize-l2-weth-token'); - - const l2WethBridgeAddress = process.env.CONTRACTS_L2_WETH_BRIDGE_ADDR; - const l2WethTokenProxyAddress = process.env.CONTRACTS_L2_WETH_TOKEN_PROXY_ADDR; - const l2WethTokenImplAddress = process.env.CONTRACTS_L2_WETH_TOKEN_IMPL_ADDR; - const tokens = getTokens(process.env.CHAIN_ETH_NETWORK || 'localhost'); - const l1WethTokenAddress = process.env.CONTRACTS_L1_WETH_TOKEN_ADDR; - - program - .command('prepare-calldata') - .option('--private-key ') - .option('--gas-price ') - .action(async (cmd) => { - const deployWallet = cmd.privateKey - ? new Wallet(cmd.privateKey, provider) - : Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/1" - ).connect(provider); - console.log(`Using deployer wallet: ${deployWallet.address}`); - - const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); - console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); - - const deployer = new Deployer({ - deployWallet, - governorAddress: deployWallet.address, - verbose: true - }); - - const l2Calldata = getL2Calldata(l2WethBridgeAddress, l1WethTokenAddress, l2WethTokenImplAddress); - const l1TxInfo = await getL1TxInfo( - deployer, - l2WethTokenProxyAddress, - l2Calldata, - ethers.constants.AddressZero, - gasPrice - ); - console.log(JSON.stringify(l1TxInfo, null, 4)); - console.log('IMPORTANT: gasPrice that you provide in the transaction should <= to the one provided above.'); - }); - - program - .command('instant-call') - .option('--private-key ') - .option('--gas-price ') - .option('--nonce ') - .action(async (cmd) => { - const deployWallet = cmd.privateKey - ? new Wallet(cmd.privateKey, provider) - : Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/1" - ).connect(provider); - console.log(`Using deployer wallet: ${deployWallet.address}`); - - const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); - console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); - - const nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployWallet.getTransactionCount(); - console.log(`Using deployer nonce: ${nonce}`); - - const deployer = new Deployer({ - deployWallet, - governorAddress: deployWallet.address, - verbose: true - }); - - const zkSync = deployer.zkSyncContract(deployWallet); - const requiredValueToInitializeBridge = await zkSync.l2TransactionBaseCost( - gasPrice, - DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA - ); - const calldata = getL2Calldata(l2WethBridgeAddress, l1WethTokenAddress, l2WethTokenImplAddress); - - const tx = await zkSync.requestL2Transaction( - requiredValueToInitializeBridge.mul(2), - { - l2Contract: l2WethTokenProxyAddress, - l2Value: 0, - gasAmount: requiredValueToInitializeBridge, - l2GasLimit: DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT, - l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - }, - calldata, - [], - deployWallet.address, - { - gasPrice, - } - ); - const receipt = await tx.wait(); - - console.log(`L2 WETH token initialized, gasUsed: ${receipt.gasUsed.toString()}`); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error('Error:', err); - process.exit(1); - }); diff --git a/ethereum/scripts/initialize-weth-bridges.ts b/ethereum/scripts/initialize-weth-bridges.ts deleted file mode 100644 index 0401d47f..00000000 --- a/ethereum/scripts/initialize-weth-bridges.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Command } from 'commander'; -import { ethers, Wallet } from 'ethers'; -import { Deployer } from '../src.ts/deploy'; -import { formatUnits, parseUnits } from 'ethers/lib/utils'; -import { web3Provider, applyL1ToL2Alias, getNumberFromEnv, REQUIRED_L2_GAS_PRICE_PER_PUBDATA } from './utils'; - -import * as fs from 'fs'; -import * as path from 'path'; - -const provider = web3Provider(); -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 contractArtifactsPath = path.join(process.env.ZKSYNC_HOME as string, 'contracts/zksync/artifacts-zk/'); -const l2BridgeArtifactsPath = path.join(contractArtifactsPath, 'cache-zk/solpp-generated-contracts/bridge/'); - -const openzeppelinTransparentProxyArtifactsPath = path.join( - contractArtifactsPath, - '@openzeppelin/contracts/proxy/transparent/' -); - -function readBytecode(path: string, fileName: string) { - return JSON.parse(fs.readFileSync(`${path}/${fileName}.sol/${fileName}.json`, { encoding: 'utf-8' })).bytecode; -} - -const L2_WETH_BRIDGE_PROXY_BYTECODE = readBytecode( - openzeppelinTransparentProxyArtifactsPath, - 'TransparentUpgradeableProxy' -); -const L2_WETH_BRIDGE_IMPLEMENTATION_BYTECODE = readBytecode(l2BridgeArtifactsPath, 'L2WethBridge'); -const DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = getNumberFromEnv('CONTRACTS_DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT'); - -async function main() { - const program = new Command(); - - program.version('0.1.0').name('initialize-weth-bridges'); - - program - .option('--private-key ') - .option('--gas-price ') - .option('--nonce ') - .action(async (cmd) => { - const deployWallet = cmd.privateKey - ? new Wallet(cmd.privateKey, provider) - : Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/0" - ).connect(provider); - console.log(`Using deployer wallet: ${deployWallet.address}`); - - const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); - console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); - - const nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployWallet.getTransactionCount(); - console.log(`Using deployer nonce: ${nonce}`); - - const l2WethAddress = process.env.CONTRACTS_L2_WETH_TOKEN_PROXY_ADDR; - - const deployer = new Deployer({ - deployWallet, - governorAddress: deployWallet.address, - verbose: true - }); - - const zkSync = deployer.zkSyncContract(deployWallet); - const l1WethBridge = deployer.defaultWethBridge(deployWallet); - - const l1GovernorAddress = await zkSync.getGovernor(); - // Check whether governor is a smart contract on L1 to apply alias if needed. - const l1GovernorCodeSize = ethers.utils.hexDataLength( - await deployWallet.provider.getCode(l1GovernorAddress) - ); - const l2GovernorAddress = l1GovernorCodeSize == 0 ? l1GovernorAddress : applyL1ToL2Alias(l1GovernorAddress); - - // There will be two deployments done during the initial initialization - const requiredValueToInitializeBridge = await zkSync.l2TransactionBaseCost( - gasPrice, - DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA - ); - - const tx = await l1WethBridge.initialize( - [L2_WETH_BRIDGE_IMPLEMENTATION_BYTECODE, L2_WETH_BRIDGE_PROXY_BYTECODE], - l2WethAddress, - l2GovernorAddress, - requiredValueToInitializeBridge, - requiredValueToInitializeBridge, - { - gasPrice - } - ); - const receipt = await tx.wait(); - - console.log(`WETH bridge initialized, gasUsed: ${receipt.gasUsed.toString()}`); - console.log(`CONTRACTS_L2_WETH_BRIDGE_ADDR=${await l1WethBridge.l2Bridge()}`); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error('Error:', err); - process.exit(1); - }); diff --git a/ethereum/scripts/upgrades/upgrade-6.ts b/ethereum/scripts/upgrades/upgrade-6.ts deleted file mode 100644 index cf887ce5..00000000 --- a/ethereum/scripts/upgrades/upgrade-6.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { Command } from 'commander'; -import { diamondCut } from '../../src.ts/diamondCut'; -import { BigNumberish } from 'ethers'; -import { ethers } from 'hardhat'; -import { Provider, Wallet } from 'zksync-web3'; -import '@nomiclabs/hardhat-ethers'; -import { web3Provider } from '../utils'; -import { Deployer } from '../../src.ts/deploy'; -import * as fs from 'fs'; -import * as path from 'path'; -import { applyL1ToL2Alias, hashBytecode } from 'zksync-web3/build/src/utils'; - -type ForceDeployment = { - bytecodeHash: string; - newAddress: string; - callConstructor: boolean; - value: BigNumberish; - input: string; -}; - -function sleep(millis: number) { - return new Promise((resolve) => setTimeout(resolve, millis)); -} - -async function prepareCalldata( - diamondUpgradeAddress: string, - l2WethTokenDeployment: ForceDeployment, - otherDeployments: Array -) { - const diamondUpgradeInit6 = await ethers.getContractAt('DiamondUpgradeInit6', ZERO_ADDRESS); - const newDeployerSystemContract = await ethers.getContractAt('IL2ContractDeployer', ZERO_ADDRESS); - - const upgradeL2WethTokenCalldata = await newDeployerSystemContract.interface.encodeFunctionData( - 'forceDeployOnAddresses', - [[l2WethTokenDeployment]] - ); - - const upgradeSystemContractsCalldata = await newDeployerSystemContract.interface.encodeFunctionData( - 'forceDeployOnAddresses', - [otherDeployments] - ); - - // Prepare the diamond cut data - const upgradeInitData = await diamondUpgradeInit6.interface.encodeFunctionData('forceDeploy', [ - upgradeL2WethTokenCalldata, - upgradeSystemContractsCalldata, - [] // Empty factory deps - ]); - - return diamondCut([], diamondUpgradeAddress, upgradeInitData); -} - -const provider = web3Provider(); -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 zksProvider = new Provider(process.env.API_WEB3_JSON_RPC_HTTP_URL); - -const ZERO_ADDRESS = ethers.constants.AddressZero; - -async function getCalldata( - diamondUpgradeAddress: string, - params: ForceDeployment[], - l2WethTokenProxyAddress: string, - l2WethTokenImplAddress: string -) { - // Generate wallet with random private key to load main contract governor. - const randomWallet = new Wallet(ethers.utils.randomBytes(32), zksProvider, provider); - let governor = await (await randomWallet.getMainContract()).getGovernor(); - // Apply L1 to L2 mask if needed. - if (ethers.utils.hexDataLength(await zksProvider.getCode(governor)) != 0) { - governor = applyL1ToL2Alias(governor); - } - - // This is TransparentUpgradeable proxy - const constructorInput = ethers.utils.defaultAbiCoder.encode( - ['address', 'address', 'bytes'], - [l2WethTokenImplAddress, governor, '0x'] - ); - const bytecodeHash = ethers.utils.hexlify(hashBytecode(await zksProvider.getCode(l2WethTokenProxyAddress))); - - const l2WethUpgrade: ForceDeployment = { - newAddress: l2WethTokenProxyAddress, - bytecodeHash, - callConstructor: true, - value: 0, - input: constructorInput - }; - // Get diamond cut data - return await prepareCalldata(diamondUpgradeAddress, l2WethUpgrade, params); -} - -async function main() { - const program = new Command(); - - program.version('0.1.0').name('force-deploy-upgrade-6'); - - program - .command('prepare-calldata') - .requiredOption('--diamond-upgrade-address ') - .requiredOption('--deployment-params ') - .requiredOption('--l2WethTokenProxyAddress ') - .requiredOption('--l2WethTokenImplAddress ') - .action(async (cmd) => { - // Get address of the diamond init contract - const diamondUpgradeAddress = cmd.diamondUpgradeAddress; - // Get L2 WETH token proxy address - const l2WethTokenProxyAddress = cmd.l2WethTokenProxyAddress; - // Get L2 WETH token implementation address - const l2WethTokenImplAddress = cmd.l2WethTokenImplAddress; - // Encode data for the upgrade call - const params: Array = JSON.parse(cmd.deploymentParams); - - // Get diamond cut data - const calldata = await getCalldata( - diamondUpgradeAddress, - params, - l2WethTokenProxyAddress, - l2WethTokenImplAddress - ); - console.log(calldata); - }); - - program - .command('force-upgrade') - .option('--private-key ') - .option('--proposal-id ') - .requiredOption('--diamond-upgrade-address ') - .requiredOption('--deployment-params ') - .requiredOption('--l2WethTokenProxyAddress ') - .requiredOption('--l2WethTokenImplAddress ') - .action(async (cmd) => { - const deployWallet = cmd.privateKey - ? new ethers.Wallet(cmd.privateKey, provider) - : ethers.Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/1" - ).connect(provider); - - const deployer = new Deployer({ - deployWallet, - governorAddress: ZERO_ADDRESS, - verbose: true - }); - const zkSyncContract = deployer.zkSyncContract(deployWallet); - - // Get address of the diamond init contract - const diamondUpgradeAddress = cmd.diamondUpgradeAddress; - // Encode data for the upgrade call - const params: Array = JSON.parse(cmd.deploymentParams); - // Get L2 WETH token proxy address - const l2WethTokenProxyAddress = cmd.l2WethTokenProxyAddress; - // Get L2 WETH token implementation address - const l2WethTokenImplAddress = cmd.l2WethTokenImplAddress; - - // Get diamond cut data - const upgradeParam = await getCalldata( - diamondUpgradeAddress, - params, - l2WethTokenProxyAddress, - l2WethTokenImplAddress - ); - - const proposalId = cmd.proposalId ? cmd.proposalId : (await zkSyncContract.getCurrentProposalId()).add(1); - const proposeUpgradeTx = await zkSyncContract.proposeTransparentUpgrade(upgradeParam, proposalId); - await proposeUpgradeTx.wait(); - - const executeUpgradeTx = await zkSyncContract.executeUpgrade(upgradeParam, ethers.constants.HashZero); - const executeUpgradeRec = await executeUpgradeTx.wait(); - const deployL2TxHashes = executeUpgradeRec.events - .filter((event) => event.event === 'NewPriorityRequest') - .map((event) => event.args[1]); - for (const txHash of deployL2TxHashes) { - console.log(txHash); - let receipt = null; - while (receipt == null) { - receipt = await zksProvider.getTransactionReceipt(txHash); - await sleep(100); - } - - if (receipt.status != 1) { - throw new Error('Failed to process L2 tx'); - } - } - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error('Error:', err); - process.exit(1); - }); diff --git a/ethereum/scripts/verify.ts b/ethereum/scripts/verify.ts index 76eabd3d..8bdae372 100644 --- a/ethereum/scripts/verify.ts +++ b/ethereum/scripts/verify.ts @@ -1,9 +1,8 @@ import { deployedAddressesFromEnv } from '../src.ts/deploy'; import * as hardhat from 'hardhat'; -import {Wallet} from "ethers"; -import {web3Provider} from "./utils"; -import path from "path"; -import fs from "fs"; +import { web3Provider } from './utils'; +import path from 'path'; +import fs from 'fs'; const provider = web3Provider(); const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); @@ -40,14 +39,10 @@ async function main() { promises.push(promise); } - const deployWallet = Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/1" - ).connect(provider); - const weth = verifyPromise(addresses.WethToken, [ - deployWallet.address - ]); - promises.push(weth); + // const deployWallet = Wallet.fromMnemonic( + // process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, + // "m/44'/60'/0'/0/1" + // ).connect(provider); // TODO: Restore after switching to hardhat tasks (SMA-1711). // promises.push(verifyPromise(addresses.AllowList, [governor])); @@ -73,13 +68,6 @@ async function main() { ]); promises.push(promise); - const promise2 = verifyPromise(addresses.Bridges.WethBridgeImplementation, [ - addresses.WethToken, - addresses.ZkSync.DiamondProxy, - addresses.AllowList - ]); - promises.push(promise2); - const messages = await Promise.allSettled(promises); for (const message of messages) { console.log(message.status == 'fulfilled' ? message.value : message.reason); diff --git a/ethereum/src.ts/deploy.ts b/ethereum/src.ts/deploy.ts index 54016927..5cf42c21 100644 --- a/ethereum/src.ts/deploy.ts +++ b/ethereum/src.ts/deploy.ts @@ -6,12 +6,10 @@ import { Interface } from 'ethers/lib/utils'; import { Action, facetCut, diamondCut } from './diamondCut'; import { IZkSyncFactory } from '../typechain/IZkSyncFactory'; import { L1ERC20BridgeFactory } from '../typechain/L1ERC20BridgeFactory'; -import { L1WethBridgeFactory } from '../typechain/L1WethBridgeFactory'; import { ValidatorTimelockFactory } from '../typechain/ValidatorTimelockFactory'; import { SingletonFactoryFactory } from '../typechain/SingletonFactoryFactory'; import { AllowListFactory } from '../typechain'; import { hexlify } from 'ethers/lib/utils'; -import { getTokens } from 'reading-tool'; import { readSystemContractsBytecode, hashL2Bytecode, @@ -39,13 +37,10 @@ export interface DeployedAddresses { Bridges: { ERC20BridgeImplementation: string; ERC20BridgeProxy: string; - WethBridgeImplementation: string; - WethBridgeProxy: string; }; AllowList: string; ValidatorTimeLock: string; Create2Factory: string; - WethToken: string; } export interface DeployerConfig { @@ -69,13 +64,10 @@ export function deployedAddressesFromEnv(): DeployedAddresses { }, Bridges: { ERC20BridgeImplementation: getAddressFromEnv('CONTRACTS_L1_ERC20_BRIDGE_IMPL_ADDR'), - ERC20BridgeProxy: getAddressFromEnv('CONTRACTS_L1_ERC20_BRIDGE_PROXY_ADDR'), - WethBridgeImplementation: getAddressFromEnv('CONTRACTS_L1_WETH_BRIDGE_IMPL_ADDR'), - WethBridgeProxy: getAddressFromEnv('CONTRACTS_L1_WETH_BRIDGE_PROXY_ADDR') + ERC20BridgeProxy: getAddressFromEnv('CONTRACTS_L1_ERC20_BRIDGE_PROXY_ADDR') }, AllowList: getAddressFromEnv('CONTRACTS_L1_ALLOW_LIST_ADDR'), Create2Factory: getAddressFromEnv('CONTRACTS_CREATE2_FACTORY_ADDR'), - WethToken: getAddressFromEnv('CONTRACTS_L1_WETH_TOKEN_ADDR'), ValidatorTimeLock: getAddressFromEnv('CONTRACTS_VALIDATOR_TIMELOCK_ADDR') }; } @@ -142,8 +134,7 @@ export class Deployer { false, // isPorterAvailable L2_BOOTLOADER_BYTECODE_HASH, L2_DEFAULT_ACCOUNT_BYTECODE_HASH, - priorityTxMaxGasLimit, - this.addresses.WethToken, + priorityTxMaxGasLimit ]); return diamondCut(facetCuts, this.addresses.ZkSync.DiamondInit, diamondInitCalldata); @@ -334,52 +325,6 @@ export class Deployer { this.addresses.Bridges.ERC20BridgeProxy = contractAddress; } - public async deployWethToken(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { - ethTxOptions.gasLimit ??= 10_000_000; - const contractAddress = await this.deployViaCreate2('WETH9', [this.governorAddress], create2Salt, ethTxOptions); - - if (this.verbose) { - console.log(`CONTRACTS_L1_WETH_TOKEN_ADDR=${contractAddress}`); - } - - this.addresses.WethToken = contractAddress; - } - - public async deployWethBridgeImplementation( - create2Salt: string, - ethTxOptions: ethers.providers.TransactionRequest - ) { - ethTxOptions.gasLimit ??= 10_000_000; - const contractAddress = await this.deployViaCreate2( - 'L1WethBridge', - [this.addresses.WethToken, this.addresses.ZkSync.DiamondProxy, this.addresses.AllowList], - create2Salt, - ethTxOptions - ); - - if (this.verbose) { - console.log(`CONTRACTS_L1_WETH_BRIDGE_IMPL_ADDR=${contractAddress}`); - } - - this.addresses.Bridges.WethBridgeImplementation = contractAddress; - } - - public async deployWethBridgeProxy(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { - ethTxOptions.gasLimit ??= 10_000_000; - const contractAddress = await this.deployViaCreate2( - 'TransparentUpgradeableProxy', - [this.addresses.Bridges.WethBridgeImplementation, this.governorAddress, '0x'], - create2Salt, - ethTxOptions - ); - - if (this.verbose) { - console.log(`CONTRACTS_L1_WETH_BRIDGE_PROXY_ADDR=${contractAddress}`); - } - - this.addresses.Bridges.WethBridgeProxy = contractAddress; - } - public async deployDiamondInit(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { ethTxOptions.gasLimit ??= 10_000_000; const contractAddress = await this.deployViaCreate2('DiamondInit', [], create2Salt, ethTxOptions); @@ -456,12 +401,6 @@ export class Deployer { await this.deployERC20BridgeProxy(create2Salt, { gasPrice, nonce: nonce + 1 }); } - public async deployWethBridgeContracts(create2Salt: string, gasPrice?: BigNumberish, nonce?) { - nonce = nonce ? parseInt(nonce) : await this.deployWallet.getTransactionCount(); - await this.deployWethBridgeImplementation(create2Salt, { gasPrice, nonce: nonce++ }); - await this.deployWethBridgeProxy(create2Salt, { gasPrice, nonce: nonce++ }); - } - public async deployValidatorTimelock(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { ethTxOptions.gasLimit ??= 10_000_000; const executionDelay = getNumberFromEnv('CONTRACTS_VALIDATOR_TIMELOCK_EXECUTION_DELAY'); @@ -499,8 +438,4 @@ export class Deployer { public defaultERC20Bridge(signerOrProvider: Signer | providers.Provider) { return L1ERC20BridgeFactory.connect(this.addresses.Bridges.ERC20BridgeProxy, signerOrProvider); } - - public defaultWethBridge(signerOrProvider: Signer | providers.Provider) { - return L1WethBridgeFactory.connect(this.addresses.Bridges.WethBridgeProxy, signerOrProvider); - } } diff --git a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts b/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts deleted file mode 100644 index 98ebab09..00000000 --- a/ethereum/test/unit_tests/l1_weth_bridge_test.spec.ts +++ /dev/null @@ -1,245 +0,0 @@ -import { expect } from 'chai'; -import { ethers } from 'ethers'; -import * as hardhat from 'hardhat'; -import { IZkSync } from '../../typechain/IZkSync'; -import { Action, diamondCut, facetCut } from '../../src.ts/diamondCut'; -import { - AllowList, - AllowListFactory, - DiamondInitFactory, - GettersFacetFactory, - MailboxFacetFactory, - L1WethBridge, - L1WethBridgeFactory, - WETH9, - WETH9Factory -} from '../../typechain'; -import { AccessMode, getCallRevertReason } from './utils'; -import { hashL2Bytecode } from '../../scripts/utils'; - -import { Interface } from 'ethers/lib/utils'; -import { Address } from 'zksync-web3/build/src/types'; - -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, - walletAddress: Address, - bytecode: ethers.BytesLike, - constructor: ethers.BytesLike, - create2Salt: ethers.BytesLike, - l2GasLimit: ethers.BigNumberish -) { - 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); - - await zkSync.requestL2Transaction( - DEPLOYER_SYSTEM_CONTRACT_ADDRESS, - 0, - calldata, - l2GasLimit, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - [bytecode], - walletAddress, - { value: expectedCost, gasPrice } - ); -} - -describe('WETH Bridge tests', () => { - let owner: ethers.Signer; - let randomSigner: ethers.Signer; - let allowList: AllowList; - let bridgeProxy: L1WethBridge; - let l1Weth: WETH9; - let functionSignature = '0x6c0960f9'; - - 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); - - await (await allowList.setAccessMode(diamondProxyContract.address, AccessMode.Public)).wait(); - - l1Weth = WETH9Factory.connect( - (await (await hardhat.ethers.getContractFactory('WETH9')).deploy()).address, - owner - ); - - // prepare the bridge - - const bridge = await ( - await hardhat.ethers.getContractFactory('L1WethBridge') - ).deploy(l1Weth.address, diamondProxyContract.address, allowListContract.address); - - // 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', [ - [garbageBytecode, garbageBytecode], - garbageAddress, - await owner.getAddress(), - ethers.constants.WeiPerEther, - ethers.constants.WeiPerEther - ]); - const _bridgeProxy = await ( - await hardhat.ethers.getContractFactory('ERC1967Proxy') - ).deploy(bridge.address, bridgeInitData, { value: ethers.constants.WeiPerEther.mul(2) }); - - bridgeProxy = L1WethBridgeFactory.connect(_bridgeProxy.address, _bridgeProxy.signer); - }); - - it('Should not allow an un-whitelisted address to deposit', async () => { - const revertReason = await getCallRevertReason( - bridgeProxy - .connect(randomSigner) - .deposit( - await randomSigner.getAddress(), - ethers.constants.AddressZero, - 0, - 0, - 0, - ethers.constants.AddressZero - ) - ); - - expect(revertReason).equal('nr'); - - // This is only so the following tests don't need whitelisting - await (await allowList.setAccessMode(bridgeProxy.address, AccessMode.Public)).wait(); - }); - - it('Should not allow depositing zero WETH', async () => { - const revertReason = await getCallRevertReason( - bridgeProxy - .connect(randomSigner) - .deposit( - await randomSigner.getAddress(), - await bridgeProxy.l1WethAddress(), - 0, - 0, - 0, - ethers.constants.AddressZero - ) - ); - - expect(revertReason).equal('Amount cannot be zero'); - }); - - it(`Should deposit successfully`, async () => { - await l1Weth.connect(randomSigner).deposit({ value: 100 }); - await (await l1Weth.connect(randomSigner).approve(bridgeProxy.address, 100)).wait(); - await bridgeProxy - .connect(randomSigner) - .deposit( - await randomSigner.getAddress(), - l1Weth.address, - 100, - 1000000, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - await randomSigner.getAddress(), - { value: ethers.constants.WeiPerEther } - ); - }); - - it('Should revert on finalizing a withdrawal with wrong message length', async () => { - const revertReason = await getCallRevertReason( - bridgeProxy.connect(randomSigner).finalizeWithdrawal(0, 0, 0, '0x', []) - ); - expect(revertReason).equal('Incorrect ETH message with additional data length'); - }); - - it('Should revert on finalizing a withdrawal with wrong function selector', async () => { - const revertReason = await getCallRevertReason( - bridgeProxy.connect(randomSigner).finalizeWithdrawal(0, 0, 0, ethers.utils.randomBytes(96), []) - ); - expect(revertReason).equal('Incorrect ETH message function selector'); - }); - - it('Should revert on finalizing a withdrawal with wrong receiver', async () => { - const revertReason = await getCallRevertReason( - bridgeProxy - .connect(randomSigner) - .finalizeWithdrawal( - 0, - 0, - 0, - ethers.utils.hexConcat([functionSignature, ethers.utils.randomBytes(92)]), - [] - ) - ); - expect(revertReason).equal('Wrong L1 ETH withdraw receiver'); - }); - - it('Should revert on finalizing a withdrawal with wrong L2 sender', async () => { - const revertReason = await getCallRevertReason( - bridgeProxy - .connect(randomSigner) - .finalizeWithdrawal( - 0, - 0, - 0, - ethers.utils.hexConcat([ - functionSignature, - bridgeProxy.address, - ethers.utils.randomBytes(32), - ethers.utils.randomBytes(40) - ]), - [] - ) - ); - expect(revertReason).equal('The withdrawal was not initiated by L2 bridge'); - }); -}); diff --git a/zksync/package.json b/zksync/package.json index 0c427ebe..58f4dda5 100644 --- a/zksync/package.json +++ b/zksync/package.json @@ -31,7 +31,6 @@ "clean": "hardhat clean", "deploy-testnet-paymaster": "hardhat run src/deployTestnetPaymaster.ts", "publish-bridge-preimages": "hardhat run src/publish-bridge-preimages.ts", - "deploy-l2-weth": "ts-node src/deployL2Weth.ts", "upgrade-l2-erc20-contract": "ts-node src/upgradeL2BridgeImpl.ts" }, "dependencies": { diff --git a/zksync/src/deployL2Weth.ts b/zksync/src/deployL2Weth.ts deleted file mode 100644 index 18f19fd6..00000000 --- a/zksync/src/deployL2Weth.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { Command } from 'commander'; -import { ethers, Wallet } from 'ethers'; -import { Deployer } from '../../ethereum/src.ts/deploy'; -import { formatUnits, parseUnits } from 'ethers/lib/utils'; -import { web3Provider } from '../../ethereum/scripts/utils'; - -import { getNumberFromEnv, create2DeployFromL1, computeL2Create2Address } from './utils'; - -import * as fs from 'fs'; -import * as path from 'path'; - -const provider = web3Provider(); -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 contractArtifactsPath = path.join(process.env.ZKSYNC_HOME as string, 'contracts/zksync/artifacts-zk/'); -const l2BridgeArtifactsPath = path.join(contractArtifactsPath, 'cache-zk/solpp-generated-contracts/bridge/'); - -const openzeppelinTransparentProxyArtifactsPath = path.join( - contractArtifactsPath, - '@openzeppelin/contracts/proxy/transparent/' -); - -function readBytecode(path: string, fileName: string) { - return JSON.parse(fs.readFileSync(`${path}/${fileName}.sol/${fileName}.json`, { encoding: 'utf-8' })).bytecode; -} - -function readInterface(path: string, fileName: string) { - const abi = JSON.parse(fs.readFileSync(`${path}/${fileName}.sol/${fileName}.json`, { encoding: 'utf-8' })).abi; - return new ethers.utils.Interface(abi); -} - -const L2_WETH_INTERFACE = readInterface(l2BridgeArtifactsPath, 'L2Weth'); -const L2_WETH_IMPLEMENTATION_BYTECODE = readBytecode(l2BridgeArtifactsPath, 'L2Weth'); -const L2_WETH_PROXY_BYTECODE = readBytecode(openzeppelinTransparentProxyArtifactsPath, 'TransparentUpgradeableProxy'); - -async function main() { - const program = new Command(); - - program.version('0.1.0').name('deploy-l2-weth'); - - program - .option('--private-key ') - .option('--gas-price ') - .option('--nonce ') - .action(async (cmd) => { - const deployWallet = cmd.privateKey - ? new Wallet(cmd.privateKey, provider) - : Wallet.fromMnemonic( - process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, - "m/44'/60'/0'/0/0" - ).connect(provider); - console.log(`Using deployer wallet: ${deployWallet.address}`); - - const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); - console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); - - const nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployWallet.getTransactionCount(); - console.log(`Using nonce: ${nonce}`); - - const deployer = new Deployer({ - deployWallet, - governorAddress: deployWallet.address, - verbose: true - }); - - const zkSync = deployer.zkSyncContract(deployWallet); - - const priorityTxMaxGasLimit = getNumberFromEnv('CONTRACTS_PRIORITY_TX_MAX_GAS_LIMIT'); - const governorAddress = await zkSync.getGovernor(); - const abiCoder = new ethers.utils.AbiCoder(); - - const l2WethImplAddr = computeL2Create2Address( - deployWallet, - L2_WETH_IMPLEMENTATION_BYTECODE, - '0x', - ethers.constants.HashZero - ); - - const proxyInitializationParams = L2_WETH_INTERFACE.encodeFunctionData('initialize', [ - 'Wrapped Ether', - 'WETH' - ]); - const l2ERC20BridgeProxyConstructor = ethers.utils.arrayify( - abiCoder.encode( - ['address', 'address', 'bytes'], - [l2WethImplAddr, governorAddress, proxyInitializationParams] - ) - ); - const l2WethProxyAddr = computeL2Create2Address( - deployWallet, - L2_WETH_PROXY_BYTECODE, - l2ERC20BridgeProxyConstructor, - ethers.constants.HashZero - ); - - await create2DeployFromL1( - deployWallet, - L2_WETH_IMPLEMENTATION_BYTECODE, - '0x', - ethers.constants.HashZero, - priorityTxMaxGasLimit - ); - - await create2DeployFromL1( - deployWallet, - L2_WETH_PROXY_BYTECODE, - l2ERC20BridgeProxyConstructor, - ethers.constants.HashZero, - priorityTxMaxGasLimit - ); - - console.log(`CONTRACTS_L2_WETH_TOKEN_IMPL_ADDR=${l2WethImplAddr}`); - console.log(`CONTRACTS_L2_WETH_TOKEN_PROXY_ADDR=${l2WethProxyAddr}`); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error('Error:', err); - process.exit(1); - }); diff --git a/zksync/src/upgradeL2BridgeImpl.ts b/zksync/src/upgradeL2BridgeImpl.ts index 5e718af2..9841dce3 100644 --- a/zksync/src/upgradeL2BridgeImpl.ts +++ b/zksync/src/upgradeL2BridgeImpl.ts @@ -20,9 +20,9 @@ export function getContractBytecode(contractName: string) { return hre.artifacts.readArtifactSync(contractName).bytecode; } -type SupportedContracts = 'L2ERC20Bridge' | 'L2StandardERC20' | 'L2WethBridge' | 'L2Weth'; +type SupportedContracts = 'L2ERC20Bridge' | 'L2StandardERC20'; function checkSupportedContract(contract: any): contract is SupportedContracts { - if (!['L2ERC20Bridge', 'L2StandardERC20', 'L2WethBridge', 'L2Weth'].includes(contract)) { + if (!['L2ERC20Bridge', 'L2StandardERC20'].includes(contract)) { throw new Error(`Unsupported contract: ${contract}`); }