From bfcea79f2107bf27d9b6f199a2907d61b67bd70a Mon Sep 17 00:00:00 2001 From: kelemeno <34402761+kelemeno@users.noreply.github.com> Date: Mon, 10 Jun 2024 23:59:31 +0100 Subject: [PATCH] chore: cleanup (#519) --- .../contracts/upgrades/UpgradeHyperchains.sol | 44 --- .../contracts/upgrades/Upgrade_v1_4_1.sol | 54 --- l1-contracts/package.json | 6 +- .../scripts/governance-accept-ownership.ts | 141 ------- l1-contracts/scripts/hyperchain-upgrade-1.ts | 71 ---- l1-contracts/scripts/hyperchain-upgrade-2.ts | 68 ---- l1-contracts/scripts/hyperchain-upgrade-3.ts | 68 ---- l1-contracts/scripts/token-migration.ts | 47 ++- .../scripts/upgrade-consistency-checker.ts | 83 ++--- l1-contracts/scripts/verify.ts | 39 +- l1-contracts/src.ts/hyperchain-upgrade.ts | 348 ------------------ l2-contracts/package.json | 4 - .../src/deploy-force-deploy-upgrader.ts | 60 --- ...loy-shared-bridge-implementation-legacy.ts | 206 ----------- .../src/deploy-shared-bridge-on-l2.ts | 55 --- 15 files changed, 116 insertions(+), 1178 deletions(-) delete mode 100644 l1-contracts/contracts/upgrades/UpgradeHyperchains.sol delete mode 100644 l1-contracts/contracts/upgrades/Upgrade_v1_4_1.sol delete mode 100644 l1-contracts/scripts/governance-accept-ownership.ts delete mode 100644 l1-contracts/scripts/hyperchain-upgrade-1.ts delete mode 100644 l1-contracts/scripts/hyperchain-upgrade-2.ts delete mode 100644 l1-contracts/scripts/hyperchain-upgrade-3.ts delete mode 100644 l1-contracts/src.ts/hyperchain-upgrade.ts delete mode 100644 l2-contracts/src/deploy-force-deploy-upgrader.ts delete mode 100644 l2-contracts/src/deploy-shared-bridge-implementation-legacy.ts delete mode 100644 l2-contracts/src/deploy-shared-bridge-on-l2.ts diff --git a/l1-contracts/contracts/upgrades/UpgradeHyperchains.sol b/l1-contracts/contracts/upgrades/UpgradeHyperchains.sol deleted file mode 100644 index 16ce5f1ca..000000000 --- a/l1-contracts/contracts/upgrades/UpgradeHyperchains.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {Diamond} from "../state-transition/libraries/Diamond.sol"; -import {BaseZkSyncUpgrade, ProposedUpgrade} from "./BaseZkSyncUpgrade.sol"; -import {ETH_TOKEN_ADDRESS} from "../common/Config.sol"; - -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -/// @notice This upgrade will be used to migrate Era to be part of the hyperchain ecosystem contracts. -contract UpgradeHyperchains is BaseZkSyncUpgrade { - /// @notice The main function that will be called by the upgrade proxy. - /// @param _proposedUpgrade The upgrade to be executed. - function upgrade(ProposedUpgrade calldata _proposedUpgrade) public override returns (bytes32) { - ( - uint256 chainId, - address bridgehubAddress, - address stateTransitionManager, - address sharedBridgeAddress, - address chainAdmin, - address validatorTimelock - ) = abi.decode(_proposedUpgrade.postUpgradeCalldata, (uint256, address, address, address, address, address)); - require(chainId != 0, "UpgradeHyperchain: 1"); - require(bridgehubAddress != address(0), "UpgradeHyperchain: 2"); - require(stateTransitionManager != address(0), "UpgradeHyperchain: 3"); - require(sharedBridgeAddress != address(0), "UpgradeHyperchain: 4"); - require(chainAdmin != address(0), "UpgradeHyperchains: 5"); - require(validatorTimelock != address(0), "UpgradeHyperchains: 6"); - - s.chainId = chainId; - s.bridgehub = bridgehubAddress; - s.stateTransitionManager = stateTransitionManager; - s.baseTokenBridge = sharedBridgeAddress; - s.baseToken = ETH_TOKEN_ADDRESS; - s.baseTokenGasPriceMultiplierNominator = 1; - s.baseTokenGasPriceMultiplierDenominator = 1; - s.admin = chainAdmin; - s.validators[validatorTimelock] = true; - - super.upgrade(_proposedUpgrade); - return Diamond.DIAMOND_INIT_SUCCESS_RETURN_VALUE; - } -} diff --git a/l1-contracts/contracts/upgrades/Upgrade_v1_4_1.sol b/l1-contracts/contracts/upgrades/Upgrade_v1_4_1.sol deleted file mode 100644 index baca21ab6..000000000 --- a/l1-contracts/contracts/upgrades/Upgrade_v1_4_1.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {Diamond} from "../state-transition/libraries/Diamond.sol"; -import {BaseZkSyncUpgrade, ProposedUpgrade} from "./BaseZkSyncUpgrade.sol"; -import {PubdataPricingMode, FeeParams} from "../state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; - -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -contract Upgrade_v1_4_1 is BaseZkSyncUpgrade { - uint32 constant PRIORITY_TX_BATCH_OVERHEAD_L1_GAS = 1_000_000; - uint32 constant PRIORITY_TX_PUBDATA_PER_BATCH = 120_000; - uint32 constant PRIORITY_TX_MAX_GAS_PER_BATCH = 80_000_000; - uint32 constant PRIORITY_TX_MAX_PUBDATA = 99_000; - uint64 constant PRIORITY_TX_MINIMAL_GAS_PRICE = 250_000_000; - - /// This event is an exact copy of the "IAdmin.NewFeeParams" event. Since they have the same name and parameters, - /// these will be tracked by indexers in the same manner. - event NewFeeParams(FeeParams oldFeeParams, FeeParams newFeeParams); - - /// This function is a copy of the "Admin.changeFeeParams" function. - /// It is to be used once to set the new fee params for the first time as they needed for the correct functioning of the upgrade. - function changeFeeParams(FeeParams memory _newFeeParams) private { - // Double checking that the new fee params are valid, i.e. - // the maximal pubdata per batch is not less than the maximal pubdata per priority transaction. - require(_newFeeParams.maxPubdataPerBatch >= _newFeeParams.priorityTxMaxPubdata, "n6"); - - FeeParams memory oldFeeParams = s.feeParams; - s.feeParams = _newFeeParams; - - emit NewFeeParams(oldFeeParams, _newFeeParams); - } - - /// @notice The main function that will be called by the upgrade proxy. - /// @param _proposedUpgrade The upgrade to be executed. - function upgrade(ProposedUpgrade calldata _proposedUpgrade) public override returns (bytes32) { - // The execution of the next parts of the upgrade does depend on these fee params being already set correctly - changeFeeParams( - FeeParams({ - pubdataPricingMode: PubdataPricingMode.Rollup, - batchOverheadL1Gas: PRIORITY_TX_BATCH_OVERHEAD_L1_GAS, - maxPubdataPerBatch: PRIORITY_TX_PUBDATA_PER_BATCH, - maxL2GasPerBatch: PRIORITY_TX_MAX_GAS_PER_BATCH, - priorityTxMaxPubdata: PRIORITY_TX_MAX_PUBDATA, - minimalL2GasPrice: PRIORITY_TX_MINIMAL_GAS_PRICE - }) - ); - - super.upgrade(_proposedUpgrade); - - return Diamond.DIAMOND_INIT_SUCCESS_RETURN_VALUE; - } -} diff --git a/l1-contracts/package.json b/l1-contracts/package.json index c265b26ea..d30c93950 100644 --- a/l1-contracts/package.json +++ b/l1-contracts/package.json @@ -75,13 +75,9 @@ "migrate-governance": "ts-node scripts/migrate-governance.ts", "display-governance": "ts-node scripts/display-governance.ts", "upgrade-system": "ts-node upgrade-system/index.ts", - "hyperchain-upgrade-1": "ts-node scripts/hyperchain-upgrade-1.ts", - "hyperchain-upgrade-2": "ts-node scripts/hyperchain-upgrade-2.ts", - "hyperchain-upgrade-3": "ts-node scripts/hyperchain-upgrade-3.ts", "token-migration": "ts-node scripts/token-migration.ts", "setup-legacy-bridge-era": "ts-node scripts/setup-legacy-bridge-era.ts", - "upgrade-consistency-checker": "ts-node scripts/upgrade-consistency-checker.ts", - "governance-accept-ownership": "ts-node scripts/governance-accept-ownership.ts" + "upgrade-consistency-checker": "ts-node scripts/upgrade-consistency-checker.ts" }, "dependencies": { "dotenv": "^16.0.3", diff --git a/l1-contracts/scripts/governance-accept-ownership.ts b/l1-contracts/scripts/governance-accept-ownership.ts deleted file mode 100644 index 1c366f684..000000000 --- a/l1-contracts/scripts/governance-accept-ownership.ts +++ /dev/null @@ -1,141 +0,0 @@ -/// This script is needed to migrate the ownership for key contracts to the governance multisig - -// hardhat import should be the first import in the file -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as hardhat from "hardhat"; -import { Command } from "commander"; -import { Wallet, ethers } from "ethers"; -import { formatUnits, parseUnits, Interface } from "ethers/lib/utils"; -import { web3Provider, GAS_MULTIPLIER } from "./utils"; -import { ethTestConfig } from "../src.ts/utils"; - -const ownable2StepInterface = new Interface(hardhat.artifacts.readArtifactSync("ValidatorTimelock").abi); -const governanceInterface = new Interface(hardhat.artifacts.readArtifactSync("Governance").abi); - -const provider = web3Provider(); - -async function main() { - const program = new Command(); - - program.version("0.1.0").name("upgrade-shared-bridge-era").description("upgrade shared bridge for era diamond proxy"); - - program - .command("transfer-ownership") - .option("--private-key ") - .option("--gas-price ") - .option("--nonce ") - .option("--owner-address ") - .option("--validator-timelock-addr ") - .option("--stm-addr ") - .option("--l1-shared-bridge-addr ") - .option("--bridgehub-addr ") - .option("--proxy-admin-addr ") - .option("--only-verifier") - .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 ownerAddress = ethers.utils.getAddress(cmd.ownerAddress); - console.log(`Using owner address: ${ownerAddress}`); - - const gasPrice = cmd.gasPrice - ? parseUnits(cmd.gasPrice, "gwei") - : (await provider.getGasPrice()).mul(GAS_MULTIPLIER); - console.log(`Using gas price: ${formatUnits(gasPrice, "gwei")} gwei`); - - const nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployWallet.getTransactionCount(); - console.log(`Using nonce: ${nonce}`); - - // Moving ownership for ValidatorTimelock - const validatorTimelockAddr = ethers.utils.getAddress(cmd.validatorTimelockAddr); - console.log(`Using ValidatorTimelock address: ${validatorTimelockAddr}`); - const stmAddr = ethers.utils.getAddress(cmd.stmAddr); - console.log("Using STM address: ", stmAddr); - const l1SharedBridgeAddr = ethers.utils.getAddress(cmd.l1SharedBridgeAddr); - console.log("Using L1 Shared Bridge address: ", l1SharedBridgeAddr); - const bridgehubAddr = ethers.utils.getAddress(cmd.bridgehubAddr); - console.log("Using Bridgehub address: ", bridgehubAddr); - const proxyAdminAddr = ethers.utils.getAddress(cmd.proxyAdminAddr); - console.log("Using Proxy Admin address: ", proxyAdminAddr); - - await transferOwnership1StepTo(deployWallet, validatorTimelockAddr, ownerAddress, true); - await transferOwnership1StepTo(deployWallet, stmAddr, ownerAddress, true); - await transferOwnership1StepTo(deployWallet, l1SharedBridgeAddr, ownerAddress, true); - await transferOwnership1StepTo(deployWallet, bridgehubAddr, ownerAddress, true); - await transferOwnership1StepTo(deployWallet, proxyAdminAddr, ownerAddress, false); - }); - - program - .command("accept-ownership") - .option("--validator-timelock-addr ") - .option("--stm-addr ") - .option("--l1-shared-bridge-addr ") - .option("--bridgehub-addr ") - .action(async (cmd) => { - // Moving ownership for ValidatorTimelock - const validatorTimelockAddr = ethers.utils.getAddress(cmd.validatorTimelockAddr); - console.log(`Using ValidatorTimelock address: ${validatorTimelockAddr}`); - const stmAddr = ethers.utils.getAddress(cmd.stmAddr); - console.log("Using STM address: ", stmAddr); - const l1SharedBridgeAddr = ethers.utils.getAddress(cmd.l1SharedBridgeAddr); - console.log("Using L1 Shared Bridge address: ", l1SharedBridgeAddr); - const bridgehubAddr = ethers.utils.getAddress(cmd.bridgehubAddr); - console.log("Using Bridgehub address: ", bridgehubAddr); - - const addresses = [validatorTimelockAddr, stmAddr, l1SharedBridgeAddr, bridgehubAddr]; - - const govCalls = addresses.map(acceptOwnershipCall); - - const govOperation = { - calls: govCalls, - predecessor: ethers.constants.HashZero, - salt: ethers.constants.HashZero, - }; - - const scheduleData = governanceInterface.encodeFunctionData("scheduleTransparent", [govOperation, 0]); - const executeData = governanceInterface.encodeFunctionData("execute", [govOperation]); - - console.log("Calldata for scheduling: ", scheduleData); - console.log("Calldata for execution: ", executeData); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - }); - -async function transferOwnership1StepTo( - wallet: ethers.Wallet, - contractAddress: string, - newOwner: string, - printPendingOwner: boolean = true -) { - const contract = new ethers.Contract(contractAddress, ownable2StepInterface, wallet); - console.log("Transferring ownership of contract: ", contractAddress, " to: ", newOwner); - const tx = await contract.transferOwnership(newOwner); - console.log("Tx hash", tx.hash); - await tx.wait(); - if (printPendingOwner) { - const newPendingOwner = await contract.pendingOwner(); - console.log("New pending owner: ", newPendingOwner); - } -} - -function acceptOwnershipCall(target: string) { - const data = ownable2StepInterface.encodeFunctionData("acceptOwnership", []); - return { - target, - value: 0, - data, - }; -} diff --git a/l1-contracts/scripts/hyperchain-upgrade-1.ts b/l1-contracts/scripts/hyperchain-upgrade-1.ts deleted file mode 100644 index 90a398ee3..000000000 --- a/l1-contracts/scripts/hyperchain-upgrade-1.ts +++ /dev/null @@ -1,71 +0,0 @@ -// hardhat import should be the first import in the file -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as hardhat from "hardhat"; -import { Command } from "commander"; -import { Wallet } from "ethers"; -import { Deployer } from "../src.ts/deploy"; -import { formatUnits, parseUnits } from "ethers/lib/utils"; -import { web3Provider, GAS_MULTIPLIER } from "./utils"; -import { deployedAddressesFromEnv } from "../src.ts/deploy-utils"; -import { ethTestConfig } from "../src.ts/utils"; -import { upgradeToHyperchains1 } from "../src.ts/hyperchain-upgrade"; - -const provider = web3Provider(); - -async function main() { - const program = new Command(); - - program.version("0.1.0").name("deploy").description("deploy L1 contracts"); - - program - .option("--private-key ") - .option("--chain-id ") - .option("--gas-price ") - .option("--nonce ") - .option("--owner-address ") - .option("--create2-salt ") - .option("--diamond-upgrade-init ") - .option("--only-verifier") - .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 ownerAddress = cmd.ownerAddress ? cmd.ownerAddress : deployWallet.address; - console.log(`Using owner address: ${ownerAddress}`); - - const gasPrice = cmd.gasPrice - ? parseUnits(cmd.gasPrice, "gwei") - : (await provider.getGasPrice()).mul(GAS_MULTIPLIER); - 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 create2Salt = cmd.create2Salt - ? cmd.create2Salt - : "0x0000000000000000000000000000000000000000000000000000000000000000"; - - const deployer = new Deployer({ - deployWallet, - addresses: deployedAddressesFromEnv(), - ownerAddress, - verbose: true, - }); - - await upgradeToHyperchains1(deployer, gasPrice, create2Salt, nonce); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - }); diff --git a/l1-contracts/scripts/hyperchain-upgrade-2.ts b/l1-contracts/scripts/hyperchain-upgrade-2.ts deleted file mode 100644 index ae8fd93ad..000000000 --- a/l1-contracts/scripts/hyperchain-upgrade-2.ts +++ /dev/null @@ -1,68 +0,0 @@ -// hardhat import should be the first import in the file -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as hardhat from "hardhat"; -import { Command } from "commander"; -import { Wallet } from "ethers"; -import { Deployer } from "../src.ts/deploy"; -import { formatUnits, parseUnits } from "ethers/lib/utils"; -import { web3Provider, GAS_MULTIPLIER } from "./utils"; -import { deployedAddressesFromEnv } from "../src.ts/deploy-utils"; -import { ethTestConfig } from "../src.ts/utils"; -import { upgradeToHyperchains2 } from "../src.ts/hyperchain-upgrade"; - -const provider = web3Provider(); - -async function main() { - const program = new Command(); - - program.version("0.1.0").name("deploy").description("deploy L1 contracts"); - - program - .option("--private-key ") - .option("--chain-id ") - .option("--gas-price ") - .option("--nonce ") - .option("--owner-address ") - .option("--create2-salt ") - .option("--print-file-path ") - .option("--diamond-upgrade-init ") - .option("--only-verifier") - .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 ownerAddress = cmd.ownerAddress ? cmd.ownerAddress : deployWallet.address; - console.log(`Using owner address: ${ownerAddress}`); - - const gasPrice = cmd.gasPrice - ? parseUnits(cmd.gasPrice, "gwei") - : (await provider.getGasPrice()).mul(GAS_MULTIPLIER); - 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, - addresses: deployedAddressesFromEnv(), - ownerAddress, - verbose: true, - }); - - await upgradeToHyperchains2(deployer, gasPrice, cmd.printFilePath); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - }); diff --git a/l1-contracts/scripts/hyperchain-upgrade-3.ts b/l1-contracts/scripts/hyperchain-upgrade-3.ts deleted file mode 100644 index e66065d94..000000000 --- a/l1-contracts/scripts/hyperchain-upgrade-3.ts +++ /dev/null @@ -1,68 +0,0 @@ -// hardhat import should be the first import in the file -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as hardhat from "hardhat"; -import { Command } from "commander"; -import { Wallet } from "ethers"; -import { Deployer } from "../src.ts/deploy"; -import { formatUnits, parseUnits } from "ethers/lib/utils"; -import { web3Provider, GAS_MULTIPLIER } from "./utils"; -import { deployedAddressesFromEnv } from "../src.ts/deploy-utils"; -import { ethTestConfig } from "../src.ts/utils"; -import { upgradeToHyperchains3 } from "../src.ts/hyperchain-upgrade"; - -const provider = web3Provider(); - -async function main() { - const program = new Command(); - - program.version("0.1.0").name("deploy").description("deploy L1 contracts"); - - program - .option("--private-key ") - .option("--chain-id ") - .option("--gas-price ") - .option("--nonce ") - .option("--owner-address ") - .option("--create2-salt ") - .option("--print-file-path ") - .option("--diamond-upgrade-init ") - .option("--only-verifier") - .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 ownerAddress = cmd.ownerAddress ? cmd.ownerAddress : deployWallet.address; - console.log(`Using owner address: ${ownerAddress}`); - - const gasPrice = cmd.gasPrice - ? parseUnits(cmd.gasPrice, "gwei") - : (await provider.getGasPrice()).mul(GAS_MULTIPLIER); - 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, - addresses: deployedAddressesFromEnv(), - ownerAddress, - verbose: true, - }); - - await upgradeToHyperchains3(deployer, cmd.printFilePath); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - }); diff --git a/l1-contracts/scripts/token-migration.ts b/l1-contracts/scripts/token-migration.ts index d9ec8757a..b18260ca3 100644 --- a/l1-contracts/scripts/token-migration.ts +++ b/l1-contracts/scripts/token-migration.ts @@ -2,10 +2,13 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars import * as hardhat from "hardhat"; import { Command } from "commander"; -import { web3Url } from "./utils"; +import { web3Url, web3Provider } from "./utils"; import { ethers } from "ethers"; import { Provider, utils } from "zksync-ethers"; +import type { Deployer } from "../src.ts/deploy"; +import { IERC20Factory } from "../typechain/IERC20Factory"; + async function main() { const program = new Command(); @@ -218,3 +221,45 @@ async function prepareGovernanceTokenMigrationCall( executeCalldata, }; } + +const provider = web3Provider(); + +/// used together with anvil for local fork tests. Not used at the moment, will be used for next token migration. +// https://www.notion.so/matterlabs/Mainnet-shared-bridge-token-fork-test-aac05561dda64fb4ad38c40d2f479378?pvs=4 +export async function transferTokensOnForkedNetwork(deployer: Deployer) { + // the list of tokens that need to be migrated, use output from `get-confirmed-tokens` command + const tokenList = ["0x5A520e593F89c908cd2bc27D928bc75913C55C42"]; + for (const tokenAddress of tokenList) { + const erc20contract = IERC20Factory.connect(tokenAddress, provider); + console.log(`Migrating token ${tokenAddress}`); + console.log( + `Balance before: ${await erc20contract.balanceOf(deployer.addresses.Bridges.ERC20BridgeProxy)}, ${await erc20contract.balanceOf(deployer.addresses.Bridges.SharedBridgeProxy)}` + ); + await transferTokens(deployer, tokenAddress); + console.log( + `Balance after: ${await erc20contract.balanceOf(deployer.addresses.Bridges.ERC20BridgeProxy)}, ${await erc20contract.balanceOf(deployer.addresses.Bridges.SharedBridgeProxy)}` + ); + } + for (const tokenAddress of tokenList) { + const erc20contract = IERC20Factory.connect(tokenAddress, provider); + if (!(await erc20contract.balanceOf(deployer.addresses.Bridges.ERC20BridgeProxy)).eq(0)) { + console.log(`Failed to transfer all tokens ${tokenAddress}`); + } + } +} + +/// This is used to transfer tokens from the sharedBridge. +/// We're keeping this as we will have another migration of tokens, but it is not used atm. +export async function transferTokens(deployer: Deployer, token: string) { + const eraChainId = "324"; + const sharedBridge = deployer.defaultSharedBridge(deployer.deployWallet); + const tx = await sharedBridge.safeTransferFundsFromLegacy( + token, + deployer.addresses.Bridges.ERC20BridgeProxy, + eraChainId, + "1000000", + { gasLimit: 25_000_000 } + ); + await tx.wait(); + console.log("Receipt", tx.hash); +} diff --git a/l1-contracts/scripts/upgrade-consistency-checker.ts b/l1-contracts/scripts/upgrade-consistency-checker.ts index 3972c8695..5da064a04 100644 --- a/l1-contracts/scripts/upgrade-consistency-checker.ts +++ b/l1-contracts/scripts/upgrade-consistency-checker.ts @@ -16,43 +16,43 @@ import { getCurrentFacetCutsForAdd } from "../src.ts/diamondCut"; // 2. Getter methods in STM. // List the contracts that should become the upgrade targets -const genesisUpgrade = "0xc6aB8b3b93f3E47fb4163eB9Dc7A61E1a5D86369"; -const validatorTimelockDeployTx = "0x420e0dddae4a1565fee430ecafa8f5ddbc3eebee2666d0c91f97a47bf054eeb4"; -const validatorTimelock = "0xc2d7a7Bd59a548249e64C1a587220c0E4F6F439E"; -const upgradeHyperchains = "0xb2963DDc6694a989B527AED0B1E19f9F0675AE4d"; +const genesisUpgrade = process.env.CONTRACTS_GENESIS_UPGRADE_ADDR!; +const validatorTimelockDeployTx = "0xde4ef2b77241b605acaa1658ff8815df0911bf81555a80c9cbdde42fbcaaea30"; +const validatorTimelock = process.env.CONTRACTS_VALIDATOR_TIMELOCK_ADDR!; +const upgradeHyperchains = process.env.CONTRACTS_HYPERCHAIN_UPGRADE_ADDR!; -const verifier = "0x9D6c59D9A234F585B367b4ba3C62e5Ec7A6179FD"; -const proxyAdmin = "0xf2c1d17441074FFb18E9A918db81A17dB1752146"; +const verifier = process.env.CONTRACTS_VERIFIER_ADDR!; +const proxyAdmin = process.env.CONTRACTS_TRANSPARENT_PROXY_ADMIN_ADDR!; -const bridgeHubImpl = "0xF9D2E98Ed518eC6Daac0579a9707d83da55D5f89"; -const bridgeHub = "0x5B5c82f4Da996e118B127880492a23391376F65c"; +const bridgeHubImpl = process.env.CONTRACTS_BRIDGEHUB_IMPL_ADDR!; +const bridgeHub = process.env.CONTRACTS_BRIDGEHUB_PROXY_ADDR!; -const executorFacet = "0x1a451d9bFBd176321966e9bc540596Ca9d39B4B1"; -const adminFacet = "0x342a09385E9BAD4AD32a6220765A6c333552e565"; -const mailboxFacetDeployTx = "0x2fa6af6e9317089be2734ffae73771c8099382d390d4edbb6c35e2db7f73b152"; -const mailboxFacet = "0x7814399116C17F2750Ca99cBFD2b75bA9a0793d7"; -const gettersFacet = "0x345c6ca2F3E08445614f4299001418F125AD330a"; +const executorFacet = process.env.CONTRACTS_EXECUTOR_FACET_ADDR!; +const adminFacet = process.env.CONTRACTS_ADMIN_FACET_ADDR!; +const mailboxFacetDeployTx = "0x995b23564b30f1551a9705313128e282591b38a1fc9c981d3251a929b190780d"; +const mailboxFacet = process.env.CONTRACTS_MAILBOX_FACET_ADDR!; +const gettersFacet = process.env.CONTRACTS_GETTERS_FACET_ADDR!; -const diamondInit = "0x05D865AE297d236Bc5C7988328d02A00b3D38a4F"; +const diamondInit = process.env.CONTRACTS_DIAMOND_INIT_ADDR!; -const stmImplDeployTx = "0x7a077accd4ee39d14b6c23ef31ece4a84c87aff41cd64fd4d2ac23a3885dd4f8"; -const stmImpl = "0x3060D61538fC91B6580e34C5b5D09651CBB9c609"; -const stmDeployTx = "0x30138b826e8f8f855e7fe9e6153d49376b53bce71c34cb2a78e186b12156c966"; -const stm = "0x280372beAAf440C52a2ed893daa14CDACc0422b8"; +const stmImplDeployTx = "0xe01c0bb497017a25c92bfc712e370e8f900554b107fe0b6022976d05c349f2b6"; +const stmImpl = process.env.CONTRACTS_STATE_TRANSITION_IMPL_ADDR!; +const stmDeployTx = "0x514bbf46d227eee8567825bf5c8ee1855aa8a1916f7fee7b191e2e3d5ecba849"; +const stm = process.env.CONTRACTS_STATE_TRANSITION_PROXY_ADDR!; -const sharedBridgeImplDeployTx = "0xd24d38cab0beb62f6de9a83cd0a5d7e339e985ba84ac6ef07a336efd79ae333a"; -const sharedBridgeImpl = "0x3819200C978d8A589a1e28A2e8fEb9a0CAD700F7"; -const sharedBridgeProxy = "0x241F19eA8CcD04515b309f1C9953A322F51891FC"; +const sharedBridgeImplDeployTx = "0x074204db79298c2f6beccae881c2ad7321c331e97fb4bd93adce2eb23bf17a17"; +const sharedBridgeImpl = process.env.CONTRACTS_L1_SHARED_BRIDGE_IMPL_ADDR!; +const sharedBridgeProxy = process.env.CONTRACTS_L1_SHARED_BRIDGE_PROXY_ADDR!; -const legacyBridgeImplDeployTx = "0xd8cca5843318ca176afd1075ca6fbb941837a641324300d3719f9189e49fd62c"; -const legacyBridgeImpl = "0xbf3d4109D65A66c629D1999fb630bE2eE16d7038"; +const legacyBridgeImplDeployTx = "0x234da786f098fa2e44b9abaf41b7045b4a25570e1a34fd01a101d23570e84d61"; +const legacyBridgeImpl = process.env.CONTRACTS_L1_ERC20_BRIDGE_IMPL_ADDR!; const expectedL1WethAddress = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"; const initialOwner = "0x71d84c3404a6ae258E6471d4934B96a2033F9438"; -const expectedOwner = "0x71d84c3404a6ae258E6471d4934B96a2033F9438"; -const expectedDelay = 0; -const eraChainId = 324; -const expectedSalt = "0x0000000000000000000000000000000000000000000000000000000000000000"; +const expectedOwner = "0x71d84c3404a6ae258E6471d4934B96a2033F9438"; //process.env.CONTRACTS_GOVERNANCE_ADDR!; +const expectedDelay = "75600"; +const eraChainId = process.env.CONTRACTS_ERA_CHAIN_ID!; +const expectedSalt = "0x0000000000000000000000000000000000000000000000000000000000000001"; const expectedHyperchainAddr = "0x32400084c286cf3e17e7b677ea9583e60a000324"; const maxNumberOfHyperchains = 100; const expectedStoredBatchHashZero = "0x1574fa776dec8da2071e5f20d71840bfcbd82c2bca9ad68680edfedde1710bc4"; @@ -60,16 +60,17 @@ const expectedL2BridgeAddress = "0x11f943b2c77b743AB90f4A0Ae7d5A4e7FCA3E102"; const expectedL1LegacyBridge = "0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063"; const expectedGenesisBatchCommitment = "0x2d00e5f8d77afcebf58a6b82ae56ba967566fe7dfbcb6760319fb0d215d18ffd"; const expectedIndexRepeatedStorageChanges = BigNumber.from(54); -const expectedProtocolVersion = 24; +const expectedProtocolVersion = BigNumber.from(2).pow(32).mul(24); + const expectedGenesisRoot = "0xabdb766b18a479a5c783a4b80e12686bc8ea3cc2d8a3050491b701d72370ebb5"; const expectedRecursionNodeLevelVkHash = "0xf520cd5b37e74e19fdb369c8d676a04dce8a19457497ac6686d2bb95d94109c8"; -const expectedRecursionLeafLevelVkHash = "0x435202d277dd06ef3c64ddd99fda043fc27c2bd8b7c66882966840202c27f4f6"; +const expectedRecursionLeafLevelVkHash = "0xf9664f4324c1400fa5c3822d667f30e873f53f1b8033180cd15fe41c1e2355c6"; const expectedRecursionCircuitsSetVksHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; const expectedBootloaderHash = "0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e"; const expectedDefaultAccountHash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32"; -const validatorOne = "0x0D3250c3D5FAcb74Ac15834096397a3Ef790ec99"; -const validatorTwo = "0x3527439923a63F8C13CF72b8Fe80a77f6e572092"; +const validatorOne = process.env.ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR!; +const validatorTwo = process.env.ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR!; const l1Provider = new ethers.providers.JsonRpcProvider(web3Url()); @@ -102,7 +103,7 @@ async function extractInitCode(data: string) { const initCode = iface.parseTransaction({ data }).args._initCode; const salt = iface.parseTransaction({ data }).args._salt; if (salt !== expectedSalt) { - throw new Error("Salt is not correct"); + throw new Error(`Salt is not correct ${salt}`); } return initCode; @@ -135,30 +136,30 @@ async function extractProxyInitializationData(contract: ethers.Contract, data: s if (usedValidatorTimelock.toLowerCase() !== validatorTimelock.toLowerCase()) { throw new Error("Validator timelock is not correct"); } - const usedGenesisUpgrade = initializeData.genesisUpgrade; + const usedGenesisUpgrade = initializeData.chainCreationParams.genesisUpgrade; if (usedGenesisUpgrade.toLowerCase() !== genesisUpgrade.toLowerCase()) { throw new Error("Genesis upgrade is not correct"); } - const usedGenesisBatchHash = initializeData.genesisBatchHash; + const usedGenesisBatchHash = initializeData.chainCreationParams.genesisBatchHash; if (usedGenesisBatchHash.toLowerCase() !== expectedGenesisRoot.toLowerCase()) { throw new Error("Genesis batch hash is not correct"); } - const usedGenesisIndexRepeatedStorageChanges = initializeData.genesisIndexRepeatedStorageChanges; + const usedGenesisIndexRepeatedStorageChanges = initializeData.chainCreationParams.genesisIndexRepeatedStorageChanges; if (!usedGenesisIndexRepeatedStorageChanges.eq(expectedIndexRepeatedStorageChanges)) { throw new Error("Genesis index repeated storage changes is not correct"); } - const usedGenesisBatchCommitment = initializeData.genesisBatchCommitment; + const usedGenesisBatchCommitment = initializeData.chainCreationParams.genesisBatchCommitment; if (usedGenesisBatchCommitment.toLowerCase() !== expectedGenesisBatchCommitment.toLowerCase()) { throw new Error("Genesis batch commitment is not correct"); } const usedProtocolVersion = initializeData.protocolVersion; if (!usedProtocolVersion.eq(expectedProtocolVersion)) { - throw new Error("Protocol version is not correct"); + throw new Error(`Protocol version is not correct ${usedProtocolVersion}`); } - const diamondCut = initializeData.diamondCut; + const diamondCut = initializeData.chainCreationParams.diamondCut; if (diamondCut.initAddress.toLowerCase() !== diamondInit.toLowerCase()) { throw new Error("Diamond init address is not correct"); @@ -315,7 +316,7 @@ async function checkBridgehub() { const owner = await contract.owner(); if (owner.toLowerCase() != expectedOwner.toLowerCase()) { - throw new Error("ValidatorTimelock owner is not correct"); + throw new Error("Bridgehub owner is not correct"); } const baseToken = await contract.baseToken(eraChainId); @@ -444,7 +445,7 @@ async function checkLegacyBridge() { await checkCorrectInitCode(legacyBridgeImplDeployTx, contract, artifact.bytecode, [sharedBridgeProxy]); - console.log("L1 shared bridge impl correct!"); + console.log("L1 legacy bridge impl correct!"); } async function checkProxyAdmin() { @@ -476,7 +477,7 @@ async function main() { await checkIdenticalBytecode(gettersFacet, "GettersFacet"); await checkIdenticalBytecode(adminFacet, "AdminFacet"); await checkIdenticalBytecode(bridgeHubImpl, "Bridgehub"); - await checkIdenticalBytecode(verifier, eraChainId == 324 ? "Verifier" : "TestnetVerifier"); + await checkIdenticalBytecode(verifier, eraChainId == "324" ? "Verifier" : "TestnetVerifier"); await checkIdenticalBytecode(diamondInit, "DiamondInit"); await checkMailbox(); diff --git a/l1-contracts/scripts/verify.ts b/l1-contracts/scripts/verify.ts index 82e17283b..e1726a5d6 100644 --- a/l1-contracts/scripts/verify.ts +++ b/l1-contracts/scripts/verify.ts @@ -1,7 +1,7 @@ // hardhat import should be the first import in the file import * as hardhat from "hardhat"; import { deployedAddressesFromEnv } from "../src.ts/deploy-utils"; -import { getNumberFromEnv, getHashFromEnv, getAddressFromEnv, ethTestConfig } from "../src.ts/utils"; +import { ethTestConfig, getNumberFromEnv, getHashFromEnv, getAddressFromEnv } from "../src.ts/utils"; import { Interface } from "ethers/lib/utils"; import { Deployer } from "../src.ts/deploy"; @@ -11,14 +11,21 @@ import { getTokens } from "../src.ts/deploy-token"; const provider = web3Provider(); -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function verifyPromise(address: string, constructorArguments?: Array, libraries?: object): Promise { +function verifyPromise( + address: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + constructorArguments?: Array, + libraries?: object, + contract?: string + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): Promise { return new Promise((resolve, reject) => { hardhat .run("verify:verify", { address, constructorArguments, libraries, + contract, }) .then(() => resolve(`Successfully verified ${address}`)) .catch((e) => reject(`Failed to verify ${address}\nError: ${e.message}`)); @@ -72,10 +79,12 @@ async function main() { const promise2 = verifyPromise(addresses.ValidatorTimeLock, [deployWalletAddress, executionDelay, eraChainId]); promises.push(promise2); - console.log("CONTRACTS_HYPERCHAIN_UPGRADE_ADDR", process.env.CONTRACTS_HYPERCHAIN_UPGRADE_ADDR); - const promise3 = verifyPromise(process.env.CONTRACTS_HYPERCHAIN_UPGRADE_ADDR); + const promise3 = verifyPromise(process.env.CONTRACTS_DEFAULT_UPGRADE_ADDR); promises.push(promise3); + const promise4 = verifyPromise(process.env.CONTRACTS_HYPERCHAIN_UPGRADE_ADDR); + promises.push(promise4); + const promise5 = verifyPromise(addresses.TransparentProxyAdmin); promises.push(promise5); @@ -127,11 +136,13 @@ async function main() { { owner: addresses.Governance, validatorTimelock: addresses.ValidatorTimeLock, - genesisUpgrade: addresses.StateTransition.GenesisUpgrade, - genesisBatchHash, - genesisIndexRepeatedStorageChanges: genesisRollupLeafIndex, - genesisBatchCommitment, - diamondCut, + chainCreationParams: { + genesisUpgrade: addresses.StateTransition.GenesisUpgrade, + genesisBatchHash, + genesisIndexRepeatedStorageChanges: genesisRollupLeafIndex, + genesisBatchCommitment, + diamondCut, + }, protocolVersion, }, ]); @@ -144,8 +155,12 @@ async function main() { promises.push(promise9); // bridges - // Note: do this manually and pass in to verify:verify the following: contract:"contracts/bridge/L1ERC20Bridge.sol:L1ERC20Bridge" - const promise10 = verifyPromise(addresses.Bridges.ERC20BridgeImplementation, [addresses.Bridges.SharedBridgeProxy]); + const promise10 = verifyPromise( + addresses.Bridges.ERC20BridgeImplementation, + [addresses.Bridges.SharedBridgeProxy], + undefined, + "contracts/bridge/L1ERC20Bridge.sol:L1ERC20Bridge" + ); promises.push(promise10); const eraDiamondProxy = getAddressFromEnv("CONTRACTS_ERA_DIAMOND_PROXY_ADDR"); diff --git a/l1-contracts/src.ts/hyperchain-upgrade.ts b/l1-contracts/src.ts/hyperchain-upgrade.ts deleted file mode 100644 index 56e8573a9..000000000 --- a/l1-contracts/src.ts/hyperchain-upgrade.ts +++ /dev/null @@ -1,348 +0,0 @@ -// hardhat import should be the first import in the file -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import * as hardhat from "hardhat"; -import * as path from "path"; - -import "@nomiclabs/hardhat-ethers"; - -import type { BigNumberish } from "ethers"; -import { ethers } from "ethers"; - -import type { Deployer } from "./deploy"; - -import type { ITransparentUpgradeableProxy } from "../typechain/ITransparentUpgradeableProxy"; -import { ITransparentUpgradeableProxyFactory } from "../typechain/ITransparentUpgradeableProxyFactory"; -import { StateTransitionManagerFactory, L1SharedBridgeFactory, ValidatorTimelockFactory } from "../typechain"; - -import { Interface } from "ethers/lib/utils"; -import { ADDRESS_ONE, getAddressFromEnv, readBytecode } from "./utils"; - -import { - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - priorityTxMaxGasLimit, - applyL1ToL2Alias, - hashL2Bytecode, -} from "../../l2-contracts/src/utils"; -import { ETH_ADDRESS_IN_CONTRACTS } from "zksync-ethers/build/src/utils"; - -const contractArtifactsPath = path.join(process.env.ZKSYNC_HOME as string, "contracts/l2-contracts/artifacts-zk/"); -const openzeppelinBeaconProxyArtifactsPath = path.join(contractArtifactsPath, "@openzeppelin/contracts/proxy/beacon"); -export const BEACON_PROXY_BYTECODE = readBytecode(openzeppelinBeaconProxyArtifactsPath, "BeaconProxy"); - -/// In the hardhat tests we do the upgrade all at once. -/// On localhost/stage/.. we will call the components and send the calldata to Governance manually -export async function upgradeToHyperchains( - deployer: Deployer, - gasPrice: BigNumberish, - printFileName?: string, - create2Salt?: string, - nonce?: number -) { - await upgradeToHyperchains1(deployer, gasPrice, create2Salt, nonce); - await upgradeToHyperchains2(deployer, gasPrice, printFileName); - await upgradeToHyperchains3(deployer, printFileName); -} - -/// this just deploys the contract ( we do it here instead of using the protocol-upgrade tool, since we are deploying more than just facets, the Bridgehub, STM, etc.) -export async function upgradeToHyperchains1( - deployer: Deployer, - gasPrice: BigNumberish, - create2Salt?: string, - nonce?: number -) { - /// we manually override the governance address so that we can set the variables - deployer.addresses.Governance = deployer.deployWallet.address; - // does not interfere with existing system - // note other contract were already deployed - if (deployer.verbose) { - console.log("Deploying new contracts"); - } - await deployNewContracts(deployer, gasPrice, create2Salt, nonce); - - // register Era in Bridgehub, STM - const stateTransitionManager = deployer.stateTransitionManagerContract(deployer.deployWallet); - - if (deployer.verbose) { - console.log("Registering Era in stateTransitionManager"); - } - const txRegister = await stateTransitionManager.registerAlreadyDeployedHyperchain( - deployer.chainId, - deployer.addresses.StateTransition.DiamondProxy - ); - - await txRegister.wait(); - - const bridgehub = deployer.bridgehubContract(deployer.deployWallet); - if (deployer.verbose) { - console.log("Registering Era in Bridgehub"); - } - - const tx = await bridgehub.createNewChain( - deployer.chainId, - deployer.addresses.StateTransition.StateTransitionProxy, - ETH_ADDRESS_IN_CONTRACTS, - ethers.constants.HashZero, - deployer.addresses.Governance, - ethers.constants.HashZero, - { gasPrice } - ); - await tx.wait(); - - if (deployer.verbose) { - console.log("Setting L1Erc20Bridge data in shared bridge"); - } - const sharedBridge = L1SharedBridgeFactory.connect( - deployer.addresses.Bridges.SharedBridgeProxy, - deployer.deployWallet - ); - const tx1 = await sharedBridge.setL1Erc20Bridge(deployer.addresses.Bridges.ERC20BridgeProxy); - await tx1.wait(); - - if (deployer.verbose) { - console.log("Initializing l2 bridge in shared bridge", deployer.addresses.Bridges.L2SharedBridgeProxy); - } - const tx2 = await sharedBridge.initializeChainGovernance( - deployer.chainId, - deployer.addresses.Bridges.L2SharedBridgeProxy - ); - await tx2.wait(); - - if (deployer.verbose) { - console.log("Setting Validator timelock in STM"); - } - const stm = StateTransitionManagerFactory.connect( - deployer.addresses.StateTransition.StateTransitionProxy, - deployer.deployWallet - ); - const tx3 = await stm.setValidatorTimelock(deployer.addresses.ValidatorTimeLock); - await tx3.wait(); - - if (deployer.verbose) { - console.log("Setting dummy STM in Validator timelock"); - } - - const ethTxOptions: ethers.providers.TransactionRequest = {}; - ethTxOptions.gasLimit ??= 10_000_000; - const migrationSTMAddress = await deployer.deployViaCreate2( - "MigrationSTM", - [deployer.deployWallet.address], - create2Salt, - ethTxOptions - ); - console.log("Migration STM address", migrationSTMAddress); - - const validatorTimelock = ValidatorTimelockFactory.connect( - deployer.addresses.ValidatorTimeLock, - deployer.deployWallet - ); - const tx4 = await validatorTimelock.setStateTransitionManager(migrationSTMAddress); - await tx4.wait(); - - const validatorOneAddress = getAddressFromEnv("ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR"); - const validatorTwoAddress = getAddressFromEnv("ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR"); - const tx5 = await validatorTimelock.addValidator(deployer.chainId, validatorOneAddress, { gasPrice }); - const receipt5 = await tx5.wait(); - const tx6 = await validatorTimelock.addValidator(deployer.chainId, validatorTwoAddress, { gasPrice }); - const receipt6 = await tx6.wait(); - - const tx7 = await validatorTimelock.setStateTransitionManager( - deployer.addresses.StateTransition.StateTransitionProxy - ); - const receipt7 = await tx7.wait(); - if (deployer.verbose) { - console.log( - "Validators added, stm transferred back", - receipt5.transactionHash, - receipt6.transactionHash, - receipt7.transactionHash - ); - } -} - -// this should be called after the diamond cut has been proposed and executed -// this simulates the main part of the upgrade, registration into the Bridgehub and STM, and the bridge upgrade -export async function upgradeToHyperchains2(deployer: Deployer, gasPrice: BigNumberish, printFileName?: string) { - // upgrading system contracts on Era only adds setChainId in systemContext, does not interfere with anything - // we first upgrade the DiamondProxy. the Mailbox is backwards compatible, so the L1ERC20 and other bridges should still work. - // this requires the sharedBridge to be deployed. - // In theory, the L1SharedBridge deposits should be disabled until the L2Bridge is upgraded. - // However, without the Portal, UI being upgraded it does not matter (nobody will call it, they will call the legacy bridge) - - // the L2Bridge and L1ERC20Bridge should be updated relatively in sync, as new messages might not be parsed correctly by the old bridge. - // however new bridges can parse old messages. L1->L2 messages are faster, so L2 side is upgraded first. - if (deployer.verbose) { - console.log("Upgrading L2 bridge"); - } - await upgradeL2Bridge(deployer, gasPrice, printFileName); - - if (deployer.verbose) { - console.log("Transferring L1 ERC20 bridge to proxy admin"); - } - await transferERC20BridgeToProxyAdmin(deployer, gasPrice, printFileName); - - if (process.env.CHAIN_ETH_NETWORK != "hardhat") { - if (deployer.verbose) { - console.log("Upgrading L1 ERC20 bridge"); - } - await upgradeL1ERC20Bridge(deployer, gasPrice, printFileName); - } -} - -// This sets the Shared Bridge parameters. We need to do this separately, as these params will be known after the upgrade -export async function upgradeToHyperchains3(deployer: Deployer, printFileName?: string) { - const sharedBridge = L1SharedBridgeFactory.connect( - deployer.addresses.Bridges.SharedBridgeProxy, - deployer.deployWallet - ); - const data2 = sharedBridge.interface.encodeFunctionData("setEraPostDiamondUpgradeFirstBatch", [ - process.env.CONTRACTS_ERA_POST_DIAMOND_UPGRADE_FIRST_BATCH, - ]); - const data3 = sharedBridge.interface.encodeFunctionData("setEraPostLegacyBridgeUpgradeFirstBatch", [ - process.env.CONTRACTS_ERA_POST_LEGACY_BRIDGE_UPGRADE_FIRST_BATCH, - ]); - const data4 = sharedBridge.interface.encodeFunctionData("setEraLegacyBridgeLastDepositTime", [ - process.env.CONTRACTS_ERA_LEGACY_UPGRADE_LAST_DEPOSIT_BATCH, - process.env.CONTRACTS_ERA_LEGACY_UPGRADE_LAST_DEPOSIT_TX_NUMBER, - ]); - await deployer.executeUpgrade(deployer.addresses.Bridges.SharedBridgeProxy, 0, data2, printFileName); - await deployer.executeUpgrade(deployer.addresses.Bridges.SharedBridgeProxy, 0, data3, printFileName); - await deployer.executeUpgrade(deployer.addresses.Bridges.SharedBridgeProxy, 0, data4, printFileName); -} - -async function deployNewContracts(deployer: Deployer, gasPrice: BigNumberish, create2Salt?: string, nonce?: number) { - nonce = nonce || (await deployer.deployWallet.getTransactionCount()); - create2Salt = create2Salt || ethers.utils.hexlify(ethers.utils.randomBytes(32)); - - // Create2 factory already deployed - - await deployer.deployGenesisUpgrade(create2Salt, { - gasPrice, - nonce, - }); - - await deployer.deployValidatorTimelock(create2Salt, { gasPrice }); - - await deployer.deployHyperchainsUpgrade(create2Salt, { - gasPrice, - }); - await deployer.deployVerifier(create2Salt, { gasPrice }); - - if (process.env.CHAIN_ETH_NETWORK != "hardhat") { - await deployer.deployTransparentProxyAdmin(create2Salt, { gasPrice }); - } - // console.log("Proxy admin is already deployed (not via Create2)", deployer.addresses.TransparentProxyAdmin); - // console.log("CONTRACTS_TRANSPARENT_PROXY_ADMIN_ADDR=0xf2c1d17441074FFb18E9A918db81A17dB1752146"); - await deployer.deployBridgehubContract(create2Salt, gasPrice); - - await deployer.deployStateTransitionManagerContract(create2Salt, [], gasPrice); - await deployer.setStateTransitionManagerInValidatorTimelock({ gasPrice }); - - await deployer.deploySharedBridgeContracts(create2Salt, gasPrice); - await deployer.deployERC20BridgeImplementation(create2Salt, { gasPrice }); -} - -async function upgradeL2Bridge(deployer: Deployer, gasPrice: BigNumberish, printFileName?: string) { - const l2BridgeImplementationAddress = process.env.CONTRACTS_L2_SHARED_BRIDGE_IMPL_ADDR!; - - // upgrade from L1 governance. This has to come from governacne on L1. - const l2BridgeAbi = ["function initialize(address, address, bytes32, address)"]; - const l2BridgeContract = new ethers.Contract(ADDRESS_ONE, l2BridgeAbi, deployer.deployWallet); - const l2Bridge = l2BridgeContract.interface; //L2_SHARED_BRIDGE_INTERFACE; - - const l2BridgeCalldata = l2Bridge.encodeFunctionData("initialize", [ - deployer.addresses.Bridges.SharedBridgeProxy, - deployer.addresses.Bridges.ERC20BridgeProxy, - hashL2Bytecode(BEACON_PROXY_BYTECODE), - applyL1ToL2Alias(deployer.addresses.Governance), - ]); - - const bridgeProxy: ITransparentUpgradeableProxy = ITransparentUpgradeableProxyFactory.connect( - ADDRESS_ONE, - deployer.deployWallet - ); // we just need the interface, so wrong address - - const l2ProxyCalldata = bridgeProxy.interface.encodeFunctionData("upgradeToAndCall", [ - l2BridgeImplementationAddress, - l2BridgeCalldata, - ]); - // console.log("kl todo", l2BridgeImplementationAddress, l2BridgeCalldata) - const factoryDeps = []; - const requiredValueForL2Tx = await deployer - .bridgehubContract(deployer.deployWallet) - .l2TransactionBaseCost(deployer.chainId, gasPrice, priorityTxMaxGasLimit, REQUIRED_L2_GAS_PRICE_PER_PUBDATA); //"1000000000000000000"; - - const mailboxFacet = new Interface(hardhat.artifacts.readArtifactSync("MailboxFacet").abi); - const mailboxCalldata = mailboxFacet.encodeFunctionData("requestL2Transaction", [ - process.env.CONTRACTS_L2_ERC20_BRIDGE_ADDR, - 0, - l2ProxyCalldata, - priorityTxMaxGasLimit, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - factoryDeps, - deployer.deployWallet.address, - ]); - - await deployer.executeUpgrade( - deployer.addresses.StateTransition.DiamondProxy, - requiredValueForL2Tx, - mailboxCalldata, - printFileName - ); -} - -async function upgradeL1ERC20Bridge(deployer: Deployer, gasPrice: BigNumberish, printFileName?: string) { - if (process.env.CHAIN_ETH_NETWORK != "hardhat") { - // we need to wait here for a new block - await new Promise((resolve) => setTimeout(resolve, 5000)); - // upgrade ERC20. - const proxyAdminAbi = ["function upgrade(address, address)"]; - const proxyAdmin = new ethers.Contract( - deployer.addresses.TransparentProxyAdmin, - proxyAdminAbi, - deployer.deployWallet - ); - const data1 = await proxyAdmin.interface.encodeFunctionData("upgrade", [ - deployer.addresses.Bridges.ERC20BridgeProxy, - deployer.addresses.Bridges.ERC20BridgeImplementation, - ]); - - await deployer.executeUpgrade(deployer.addresses.TransparentProxyAdmin, 0, data1, printFileName); - - if (deployer.verbose) { - console.log("L1ERC20Bridge upgrade sent"); - } - } -} - -export async function transferERC20BridgeToProxyAdmin( - deployer: Deployer, - gasPrice: BigNumberish, - printFileName?: string -) { - const bridgeProxy: ITransparentUpgradeableProxy = ITransparentUpgradeableProxyFactory.connect( - deployer.addresses.Bridges.ERC20BridgeProxy, - deployer.deployWallet - ); - const data1 = await bridgeProxy.interface.encodeFunctionData("changeAdmin", [ - deployer.addresses.TransparentProxyAdmin, - ]); - - await deployer.executeUpgrade(deployer.addresses.Bridges.ERC20BridgeProxy, 0, data1, printFileName); - - if (deployer.verbose) { - console.log("ERC20Bridge ownership transfer sent"); - } -} - -export async function transferTokens(deployer: Deployer, token: string) { - const sharedBridge = deployer.defaultSharedBridge(deployer.deployWallet); - const tx = await sharedBridge.safeTransferFundsFromLegacy( - token, - deployer.addresses.Bridges.ERC20BridgeProxy, - "324", - "300000", - { gasLimit: 25_000_000 } - ); - await tx.wait(); - console.log("Receipt", tx.hash); -} diff --git a/l2-contracts/package.json b/l2-contracts/package.json index 6f0375390..2f5907461 100644 --- a/l2-contracts/package.json +++ b/l2-contracts/package.json @@ -35,13 +35,9 @@ "clean": "hardhat clean", "test": "hardhat test", "verify": "hardhat run src/verify.ts", - "deploy-testnet-paymaster": "ts-node src/deploy-testnet-paymaster.ts", "deploy-testnet-paymaster-through-l1": "ts-node src/deploy-testnet-paymaster-through-l1.ts", - "deploy-force-deploy-upgrader": "ts-node src/deploy-force-deploy-upgrader.ts", "deploy-force-deploy-upgrader-through-l1": "ts-node src/deploy-force-deploy-upgrader-through-l1.ts", - "deploy-shared-bridge-on-l2": "ts-node scripts/deploy-shared-bridge-on-l2.ts", "deploy-shared-bridge-on-l2-through-l1": "ts-node src/deploy-shared-bridge-on-l2-through-l1.ts", - "deploy-shared-bridge-l2-implementation": "ts-node src/deploy-shared-bridge-implementation-legacy.ts", "publish-bridge-preimages": "ts-node src/publish-bridge-preimages.ts", "deploy-l2-weth": "ts-node src/deploy-l2-weth.ts", "upgrade-bridge-contracts": "ts-node src/upgrade-bridge-impl.ts", diff --git a/l2-contracts/src/deploy-force-deploy-upgrader.ts b/l2-contracts/src/deploy-force-deploy-upgrader.ts deleted file mode 100644 index 8545dc44d..000000000 --- a/l2-contracts/src/deploy-force-deploy-upgrader.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Command } from "commander"; -import { ethers, Wallet } from "ethers"; -import { computeL2Create2Address, create2DeployFromL1, provider, priorityTxMaxGasLimit } from "./utils"; -import { ethTestConfig } from "./deploy-utils"; - -import * as hre from "hardhat"; - -// Script to deploy the force deploy upgrader contract and output its address. -// Note, that this script expects that the L2 contracts have been compiled PRIOR -// to running this script. -async function main() { - const program = new Command(); - - program - .version("0.1.0") - .name("deploy-force-deploy-upgrader") - .option("--chain-id ") - .description("Deploys the force deploy upgrader contract to L2"); - - program.option("--private-key ").action(async (cmd) => { - const chainId: string = cmd.chainId ? cmd.chainId : process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID; - 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 forceDeployUpgraderBytecode = hre.artifacts.readArtifactSync("ForceDeployUpgrader").bytecode; - const create2Salt = ethers.constants.HashZero; - const forceDeployUpgraderAddress = computeL2Create2Address( - deployWallet, - forceDeployUpgraderBytecode, - "0x", - create2Salt - ); - - // TODO: request from API how many L2 gas needs for the transaction. - await create2DeployFromL1( - chainId, - deployWallet, - forceDeployUpgraderBytecode, - "0x", - create2Salt, - priorityTxMaxGasLimit - ); - - console.log(`CONTRACTS_L2_DEFAULT_UPGRADE_ADDR=${forceDeployUpgraderAddress}`); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - }); diff --git a/l2-contracts/src/deploy-shared-bridge-implementation-legacy.ts b/l2-contracts/src/deploy-shared-bridge-implementation-legacy.ts deleted file mode 100644 index 84a7df17a..000000000 --- a/l2-contracts/src/deploy-shared-bridge-implementation-legacy.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { Command } from "commander"; -import { artifacts } from "hardhat"; -import type { BigNumberish } from "ethers"; -import { ethers, Wallet } from "ethers"; -import { formatUnits, Interface, parseUnits, defaultAbiCoder } from "ethers/lib/utils"; -import { - computeL2Create2Address, - provider, - priorityTxMaxGasLimit, - hashL2Bytecode, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, -} from "./utils"; - -import { ethTestConfig } from "./deploy-utils"; - -import { Deployer } from "../../l1-contracts/src.ts/deploy"; -import { GAS_MULTIPLIER } from "../../l1-contracts/scripts/utils"; -import { deployedAddressesFromEnv } from "../../l1-contracts/src.ts/deploy-utils"; - -import * as hre from "hardhat"; -import { IZkSyncHyperchainFactory } from "../../l1-contracts/typechain/IZkSyncHyperchainFactory"; - -const DEPLOYER_SYSTEM_CONTRACT_ADDRESS = "0x0000000000000000000000000000000000008006"; - -const L2_SHARED_BRIDGE_IMPLEMENTATION_BYTECODE = hre.artifacts.readArtifactSync("L2SharedBridge").bytecode; - -async function create2DeployFromL1( - chainId: ethers.BigNumberish, - wallet: ethers.Wallet, - bytecode: ethers.BytesLike, - constructor: ethers.BytesLike, - create2Salt: ethers.BytesLike, - l2GasLimit: ethers.BigNumberish, - gasPrice?: ethers.BigNumberish, - extraFactoryDeps?: ethers.BytesLike[] -) { - const hyperchainAddress = deployedAddressesFromEnv().StateTransition.DiamondProxy; - const hyperchain = IZkSyncHyperchainFactory.connect(hyperchainAddress, wallet); - - const deployerSystemContracts = new Interface(artifacts.readArtifactSync("IContractDeployer").abi); - const bytecodeHash = hashL2Bytecode(bytecode); - const calldata = deployerSystemContracts.encodeFunctionData("create2", [create2Salt, bytecodeHash, constructor]); - gasPrice ??= await wallet.provider.getGasPrice(); - const expectedCost = await hyperchain.l2TransactionBaseCost(gasPrice, l2GasLimit, REQUIRED_L2_GAS_PRICE_PER_PUBDATA); - - const factoryDeps = extraFactoryDeps ? [bytecode, ...extraFactoryDeps] : [bytecode]; - return await hyperchain.requestL2Transaction( - DEPLOYER_SYSTEM_CONTRACT_ADDRESS, - 0, - calldata, - l2GasLimit, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - factoryDeps, - wallet.address, - { value: expectedCost.mul(5), gasPrice } - ); -} - -export async function publishBytecodeFromL1( - wallet: ethers.Wallet, - factoryDeps: ethers.BytesLike[], - gasPrice?: ethers.BigNumberish -) { - const hyperchainAddress = deployedAddressesFromEnv().StateTransition.DiamondProxy; - const hyperchain = IZkSyncHyperchainFactory.connect(hyperchainAddress, wallet); - - const requiredValueToPublishBytecodes = await hyperchain.l2TransactionBaseCost( - gasPrice, - priorityTxMaxGasLimit, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA - ); - - const nonce = await wallet.getTransactionCount(); - const tx1 = await hyperchain.requestL2Transaction( - ethers.constants.AddressZero, - 0, - "0x", - priorityTxMaxGasLimit, - REQUIRED_L2_GAS_PRICE_PER_PUBDATA, - factoryDeps, - wallet.address, - { gasPrice, nonce, value: requiredValueToPublishBytecodes } - ); - await tx1.wait(); -} - -export async function publishL2SharedBridgeDependencyBytecodesOnL2( - deployer: Deployer, - chainId: string, - gasPrice: BigNumberish -) { - /// #################################################################################################################### - - if (deployer.verbose) { - console.log("Providing necessary L2 bytecodes"); - } - - const L2_STANDARD_ERC20_PROXY_FACTORY_BYTECODE = hre.artifacts.readArtifactSync("UpgradeableBeacon").bytecode; - const L2_STANDARD_ERC20_IMPLEMENTATION_BYTECODE = hre.artifacts.readArtifactSync("L2StandardERC20").bytecode; - - await publishBytecodeFromL1( - deployer.deployWallet, - [L2_STANDARD_ERC20_PROXY_FACTORY_BYTECODE, L2_STANDARD_ERC20_IMPLEMENTATION_BYTECODE], - gasPrice - ); - - if (deployer.verbose) { - console.log("Bytecodes published on L2"); - } -} - -export async function deploySharedBridgeImplOnL2ThroughL1(deployer: Deployer, chainId: string, gasPrice: BigNumberish) { - if (deployer.verbose) { - console.log("Deploying L2SharedBridge Implementation"); - } - - if (!L2_SHARED_BRIDGE_IMPLEMENTATION_BYTECODE) { - throw new Error("L2_SHARED_BRIDGE_IMPLEMENTATION_BYTECODE not found"); - } - if (deployer.verbose) { - console.log("L2_SHARED_BRIDGE_IMPLEMENTATION_BYTECODE loaded"); - - console.log("Computing L2SharedBridge Implementation Address"); - } - const l2SharedBridgeImplAddress = computeL2Create2Address( - deployer.deployWallet, - L2_SHARED_BRIDGE_IMPLEMENTATION_BYTECODE, - defaultAbiCoder.encode(["uint256"], [deployer.chainId]), - ethers.constants.HashZero - ); - deployer.addresses.Bridges.L2SharedBridgeImplementation = l2SharedBridgeImplAddress; - if (deployer.verbose) { - console.log(`L2SharedBridge Implementation Address: ${l2SharedBridgeImplAddress}`); - - console.log("Deploying L2SharedBridge Implementation"); - } - - /// L2StandardTokenProxy bytecode. We need this bytecode to be accessible on the L2, it is enough to add to factoryDeps - const L2_STANDARD_TOKEN_PROXY_BYTECODE = hre.artifacts.readArtifactSync("BeaconProxy").bytecode; - - // TODO: request from API how many L2 gas needs for the transaction. - const tx2 = await create2DeployFromL1( - chainId, - deployer.deployWallet, - L2_SHARED_BRIDGE_IMPLEMENTATION_BYTECODE, - defaultAbiCoder.encode(["uint256"], [deployer.chainId]), - ethers.constants.HashZero, - priorityTxMaxGasLimit, - gasPrice, - [L2_STANDARD_TOKEN_PROXY_BYTECODE] - ); - - await tx2.wait(); - if (deployer.verbose) { - console.log("Deployed L2SharedBridge Implementation"); - console.log(`CONTRACTS_L2_SHARED_BRIDGE_IMPL_ADDR=${l2SharedBridgeImplAddress}`); - } -} - -async function main() { - const program = new Command(); - - program.version("0.1.0").name("deploy-shared-bridge-on-l2-through-l1"); - - program - .option("--private-key ") - .option("--chain-id ") - .option("--gas-price ") - .option("--nonce ") - .option("--erc20-bridge ") - .action(async (cmd) => { - const chainId: string = cmd.chainId ? cmd.chainId : process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID; - 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 deployer = new Deployer({ - deployWallet, - ownerAddress: deployWallet.address, - verbose: true, - }); - - const nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployer.deployWallet.getTransactionCount(); - console.log(`Using nonce: ${nonce}`); - - const gasPrice = cmd.gasPrice - ? parseUnits(cmd.gasPrice, "gwei") - : (await provider.getGasPrice()).mul(GAS_MULTIPLIER); - console.log(`Using gas price: ${formatUnits(gasPrice, "gwei")} gwei`); - await publishL2SharedBridgeDependencyBytecodesOnL2(deployer, chainId, gasPrice); - await deploySharedBridgeImplOnL2ThroughL1(deployer, chainId, gasPrice); - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - }); diff --git a/l2-contracts/src/deploy-shared-bridge-on-l2.ts b/l2-contracts/src/deploy-shared-bridge-on-l2.ts deleted file mode 100644 index e1fed93d8..000000000 --- a/l2-contracts/src/deploy-shared-bridge-on-l2.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Command } from "commander"; -import { Wallet } from "ethers"; -import { formatUnits, parseUnits } from "ethers/lib/utils"; -import { Deployer } from "../../l1-contracts/src.ts/deploy"; -import { GAS_MULTIPLIER } from "../../l1-contracts/scripts/utils"; -import { provider } from "./utils"; -import { ethTestConfig } from "./deploy-utils"; - -async function main() { - const program = new Command(); - - program.version("0.1.0").name("initialize-erc20-bridge-chain"); - - program - .option("--private-key ") - .option("--chain-id ") - .option("--gas-price ") - .option("--nonce ") - .option("--erc20-bridge ") - .action(async (cmd) => { - // const chainId: string = cmd.chainId ? cmd.chainId : process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID; - 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()).mul(GAS_MULTIPLIER); - 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, - ownerAddress: deployWallet.address, - verbose: true, - }); - - deployer; - }); - - await program.parseAsync(process.argv); -} - -main() - .then(() => process.exit(0)) - .catch((err) => { - console.error("Error:", err); - process.exit(1); - });