diff --git a/AllContractsHashes.json b/AllContractsHashes.json index 7822b668e..de28a3705 100644 --- a/AllContractsHashes.json +++ b/AllContractsHashes.json @@ -1712,10 +1712,10 @@ "zkBytecodePath": null }, { - "contractName": "l1-contracts/CreateAndTransfer", - "evmBytecodeHash": "0x3ef11e5b831a5114a37d3daa2265740bd39b5302b11d972a872462c747f991ed", - "evmBytecodePath": "/l1-contracts/out/CreateAndTransfer.sol/CreateAndTransfer.json", - "evmDeployedBytecodeHash": "0xae6d5f0e37eb646c6f61340d8ba97f1c23f3b022500f99c089e5ef95a6332c87", + "contractName": "l1-contracts/Create2AndTransfer", + "evmBytecodeHash": "0x95d7ded2a7e878aa82674a330a2b3638b0efa6168a4e0af9b30afdf68384cabb", + "evmBytecodePath": "/l1-contracts/out/Create2AndTransfer.sol/Create2AndTransfer.json", + "evmDeployedBytecodeHash": "0xdfaa9e7594513b81050146de2564399318a7f5be75c6b55bda5309368de2d6c1", "zkBytecodeHash": null, "zkBytecodePath": null }, diff --git a/l1-contracts/.env b/l1-contracts/.env index 4f40c9e49..e74827f78 100644 --- a/l1-contracts/.env +++ b/l1-contracts/.env @@ -49,3 +49,5 @@ ZK_CHAIN_CONFIG=/script-config/register-zk-chain.toml ZK_CHAIN_OUTPUT=/script-out/output-deploy-zk-chain-era.toml FORCE_DEPLOYMENTS_CONFIG=/script-config/generate-force-deployments-data.toml GATEWAY_PREPARATION_L1_CONFIG=/script-config/gateway-preparation-l1.toml +GATEWAY_UPGRADE_ECOSYSTEM_INPUT=/script-config/gateway-upgrade-ecosystem.toml +GATEWAY_UPGRADE_ECOSYSTEM_OUTPUT=/script-out/gateway-upgrade-ecosystem.toml \ No newline at end of file diff --git a/l1-contracts/deploy-scripts/AcceptAdmin.s.sol b/l1-contracts/deploy-scripts/AcceptAdmin.s.sol index 9fc2601cd..548506336 100644 --- a/l1-contracts/deploy-scripts/AcceptAdmin.s.sol +++ b/l1-contracts/deploy-scripts/AcceptAdmin.s.sol @@ -16,6 +16,7 @@ import {IGovernance} from "contracts/governance/IGovernance.sol"; import {stdToml} from "forge-std/StdToml.sol"; import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; +import {L2WrappedBaseTokenStore} from "contracts/bridge/L2WrappedBaseTokenStore.sol"; bytes32 constant SET_TOKEN_MULTIPLIER_SETTER_ROLE = keccak256("SET_TOKEN_MULTIPLIER_SETTER_ROLE"); @@ -226,4 +227,29 @@ contract AcceptAdmin is Script { Utils.adminExecute(adminAddr, accessControlRestriction, validatorTimelock, data, 0); } + + /// @notice Adds L2WrappedBaseToken of a chain to the store. + /// @param storeAddress THe address of the `L2WrappedBaseTokenStore`. + /// @param ecosystemAdmin The address of the ecosystem admin contract. + /// @param chainId The chain id of the chain. + /// @param l2WBaseToken The address of the L2WrappedBaseToken. + function addL2WethToStore( + address storeAddress, + ChainAdmin ecosystemAdmin, + uint256 chainId, + address l2WBaseToken + ) public { + L2WrappedBaseTokenStore l2WrappedBaseTokenStore = L2WrappedBaseTokenStore(storeAddress); + + Call[] memory calls = new Call[](1); + calls[0] = Call({ + target: storeAddress, + value: 0, + data: abi.encodeCall(l2WrappedBaseTokenStore.initializeChain, (chainId, l2WBaseToken)) + }); + + vm.startBroadcast(); + ecosystemAdmin.multicall(calls, true); + vm.stopBroadcast(); + } } diff --git a/l1-contracts/deploy-scripts/Create2AndTransfer.sol b/l1-contracts/deploy-scripts/Create2AndTransfer.sol new file mode 100644 index 000000000..b2961a962 --- /dev/null +++ b/l1-contracts/deploy-scripts/Create2AndTransfer.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; + +pragma solidity 0.8.24; + +/// @title Create2AndTransfer +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +/// @dev Allows to deterministically create a contract with a fixed owner. +contract Create2AndTransfer { + /// @notice The address of the contract deployed during inside the constructor. + address public immutable deployedAddress; + + constructor(bytes memory bytecode, bytes32 salt, address owner) { + address addr; + assembly { + addr := create2(0x0, add(bytecode, 0x20), mload(bytecode), salt) + } + + require(addr != address(0), "Create2: Failed on deploy"); + Ownable(addr).transferOwnership(owner); + + deployedAddress = addr; + } +} diff --git a/l1-contracts/deploy-scripts/CreateAndTransfer.sol b/l1-contracts/deploy-scripts/CreateAndTransfer.sol deleted file mode 100644 index a429d354f..000000000 --- a/l1-contracts/deploy-scripts/CreateAndTransfer.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -import {ProxyAdmin} from "@openzeppelin/contracts-v4/proxy/transparent/ProxyAdmin.sol"; - -pragma solidity 0.8.24; - -contract CreateAndTransfer { - constructor(bytes memory bytecode, bytes32 salt, address owner) { - address addr; - assembly { - addr := create2(0x0, add(bytecode, 0x20), mload(bytecode), salt) - } - - require(addr != address(0), "Create2: Failed on deploy"); - ProxyAdmin proxy = ProxyAdmin(addr); - proxy.transferOwnership(owner); - } -} diff --git a/l1-contracts/deploy-scripts/RegisterZKChain.s.sol b/l1-contracts/deploy-scripts/RegisterZKChain.s.sol index e427b86b3..19ea9cba8 100644 --- a/l1-contracts/deploy-scripts/RegisterZKChain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterZKChain.s.sol @@ -31,7 +31,7 @@ import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; import {Call} from "contracts/governance/Common.sol"; import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; -import {CreateAndTransfer} from "./CreateAndTransfer.sol"; +import {Create2AndTransfer} from "./Create2AndTransfer.sol"; import {ChainAdminOwnable} from "contracts/governance/ChainAdminOwnable.sol"; // solhint-disable-next-line gas-struct-packing @@ -460,10 +460,10 @@ contract RegisterZKChainScript is Script { function deployChainProxyAddress() internal { bytes memory input = abi.encode(type(ProxyAdmin).creationCode, config.create2Salt, output.chainAdmin); - bytes memory encoded = abi.encodePacked(type(CreateAndTransfer).creationCode, input); - address createAndTransfer = Utils.deployViaCreate2(encoded, config.create2Salt, config.create2FactoryAddress); + bytes memory encoded = abi.encodePacked(type(Create2AndTransfer).creationCode, input); + address create2AndTransfer = Utils.deployViaCreate2(encoded, config.create2Salt, config.create2FactoryAddress); - address proxyAdmin = vm.computeCreate2Address(config.create2Salt, keccak256(encoded), createAndTransfer); + address proxyAdmin = vm.computeCreate2Address(config.create2Salt, keccak256(encoded), create2AndTransfer); console.log("Transparent Proxy Admin deployed at:", address(proxyAdmin)); output.chainProxyAdmin = address(proxyAdmin); diff --git a/l1-contracts/deploy-scripts/upgrade/BytecodePublisher.s.sol b/l1-contracts/deploy-scripts/upgrade/BytecodePublisher.s.sol index 3981da95a..dbfb351ca 100644 --- a/l1-contracts/deploy-scripts/upgrade/BytecodePublisher.s.sol +++ b/l1-contracts/deploy-scripts/upgrade/BytecodePublisher.s.sol @@ -26,6 +26,9 @@ library BytecodePublisher { uint256 currentBatchSize = 0; uint256 batchStartIndex = 0; + bytes[] memory toPublish = new bytes[](bytecodes.length); + uint256 toPublishPtr = 0; + for (uint256 i = 0; i < totalBytecodes; i++) { bytes32 hash = L2ContractHelper.hashL2Bytecode(bytecodes[i]); if (bytecodesSupplier.publishingBlock(hash) != 0) { @@ -49,20 +52,22 @@ library BytecodePublisher { // Check if adding this bytecode exceeds the MAX_BATCH_SIZE if (currentBatchSize + bytecodeSize > MAX_BATCH_SIZE) { // Publish the current batch - bytes[] memory currentBatch = slice(bytecodes, batchStartIndex, i); + bytes[] memory currentBatch = slice(toPublish, 0, toPublishPtr); _publishBatch(bytecodesSupplier, currentBatch); // Reset for the next batch batchStartIndex = i; - currentBatchSize = bytecodeSize; - } else { - currentBatchSize += bytecodeSize; + toPublishPtr = 0; + currentBatchSize = 0; } + + currentBatchSize += bytecodeSize; + toPublish[toPublishPtr++] = bytecodes[i]; } // Publish the last batch if any - if (batchStartIndex < totalBytecodes) { - bytes[] memory lastBatch = slice(bytecodes, batchStartIndex, totalBytecodes); + if (toPublishPtr != 0) { + bytes[] memory lastBatch = slice(toPublish, 0, toPublishPtr); _publishBatch(bytecodesSupplier, lastBatch); } } diff --git a/l1-contracts/deploy-scripts/upgrade/ChainUpgrade.s.sol b/l1-contracts/deploy-scripts/upgrade/ChainUpgrade.s.sol index 103258d88..b32c5d61a 100644 --- a/l1-contracts/deploy-scripts/upgrade/ChainUpgrade.s.sol +++ b/l1-contracts/deploy-scripts/upgrade/ChainUpgrade.s.sol @@ -13,33 +13,22 @@ import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; import {Call} from "contracts/governance/Common.sol"; +import {ChainTypeManager} from "contracts/state-transition/ChainTypeManager.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; -interface LegacyChainAdmin { - function owner() external view returns (address); -} - contract ChainUpgrade is Script { using stdToml for string; struct ChainConfig { address deployerAddress; - address ownerAddress; uint256 chainChainId; address chainDiamondProxyAddress; - bool permanentRollup; address bridgehubProxyAddress; - address oldSharedBridgeProxyAddress; - } - - struct Output { - address accessControlRestriction; - address chainAdmin; } address currentChainAdmin; ChainConfig config; - Output output; function prepareChain( string memory ecosystemInputPath, @@ -55,14 +44,8 @@ contract ChainUpgrade is Script { initializeConfig(configPath, ecosystemInputPath, ecosystemOutputPath); - checkCorrectOwnerAddress(); - - governanceMoveToNewChainAdmin(); - // This script does nothing, it only checks that the provided inputs are correct. // It is just a wrapper to easily call `upgradeChain` - - saveOutput(outputPath); } function run() public { @@ -79,8 +62,8 @@ contract ChainUpgrade is Script { function upgradeChain(uint256 oldProtocolVersion, Diamond.DiamondCutData memory upgradeCutData) public { Utils.adminExecute( - output.chainAdmin, - output.accessControlRestriction, + IZKChain(config.chainDiamondProxyAddress).getAdmin(), + address(0), config.chainDiamondProxyAddress, abi.encodeCall(IAdmin.upgradeChainFromVersion, (oldProtocolVersion, upgradeCutData)), 0 @@ -101,70 +84,11 @@ contract ChainUpgrade is Script { // are parsed alfabetically and not by key. // https://book.getfoundry.sh/cheatcodes/parse-toml - config.ownerAddress = toml.readAddress("$.owner_address"); config.chainChainId = toml.readUint("$.chain.chain_id"); - config.chainDiamondProxyAddress = toml.readAddress("$.chain.diamond_proxy_address"); - config.permanentRollup = toml.readBool("$.chain.permanent_rollup"); toml = vm.readFile(ecosystemInputPath); - config.bridgehubProxyAddress = toml.readAddress("$.contracts.bridgehub_proxy_address"); - config.oldSharedBridgeProxyAddress = toml.readAddress("$.contracts.old_shared_bridge_proxy_address"); - } - - function checkCorrectOwnerAddress() internal { - currentChainAdmin = address(IZKChain(config.chainDiamondProxyAddress).getAdmin()); - address currentAdminOwner = LegacyChainAdmin(currentChainAdmin).owner(); - require(currentAdminOwner == config.ownerAddress, "Only the owner of the chain admin can call this function"); - } - - // TODO(EVM-924): this function is not used. - function deployNewChainAdmin() internal { - vm.broadcast(config.ownerAddress); - AccessControlRestriction accessControlRestriction = new AccessControlRestriction(0, config.ownerAddress); - - address[] memory restrictions; - restrictions = new address[](1); - restrictions[0] = address(accessControlRestriction); - - vm.broadcast(config.ownerAddress); - ChainAdmin newChainAdmin = new ChainAdmin(restrictions); - output.chainAdmin = address(newChainAdmin); - output.accessControlRestriction = address(accessControlRestriction); - } - - /// @dev The caller of this function needs to be the owner of the chain admin - /// of the - function governanceMoveToNewChainAdmin() internal { - // Firstly, we need to call the legacy chain admin to transfer the ownership to the new chain admin - Call[] memory calls = new Call[](1); - calls[0] = Call({ - target: config.chainDiamondProxyAddress, - value: 0, - data: abi.encodeCall(IAdmin.setPendingAdmin, (output.chainAdmin)) - }); - - vm.startBroadcast(config.ownerAddress); - ChainAdmin(payable(currentChainAdmin)).multicall(calls, true); - vm.stopBroadcast(); - - // Now we need to accept the adminship - Utils.adminExecute({ - _admin: output.chainAdmin, - _accessControlRestriction: output.accessControlRestriction, - _target: config.chainDiamondProxyAddress, - _data: abi.encodeCall(IAdmin.acceptAdmin, ()), - _value: 0 - }); - } - - function saveOutput(string memory outputPath) internal { - vm.serializeAddress("root", "chain_admin_addr", output.chainAdmin); - - string memory toml = vm.serializeAddress("root", "access_control_restriction", output.accessControlRestriction); - string memory root = vm.projectRoot(); - vm.writeToml(toml, outputPath); - console.log("Output saved at:", outputPath); + config.chainDiamondProxyAddress = Bridgehub(config.bridgehubProxyAddress).getHyperchain(config.chainChainId); } } diff --git a/l1-contracts/deploy-scripts/upgrade/EcosystemUpgrade.s.sol b/l1-contracts/deploy-scripts/upgrade/EcosystemUpgrade.s.sol index 211a17212..083ee64c7 100644 --- a/l1-contracts/deploy-scripts/upgrade/EcosystemUpgrade.s.sol +++ b/l1-contracts/deploy-scripts/upgrade/EcosystemUpgrade.s.sol @@ -73,6 +73,11 @@ import {BytecodesSupplier} from "contracts/upgrades/BytecodesSupplier.sol"; import {GovernanceUpgradeTimer} from "contracts/upgrades/GovernanceUpgradeTimer.sol"; import {L2WrappedBaseTokenStore} from "contracts/bridge/L2WrappedBaseTokenStore.sol"; import {RollupDAManager} from "contracts/state-transition/data-availability/RollupDAManager.sol"; +import {Create2AndTransfer} from "../Create2AndTransfer.sol"; + +interface IBridgehubLegacy { + function stateTransitionManager(uint256 chainId) external returns (address); +} struct FixedForceDeploymentsData { uint256 l1ChainId; @@ -221,6 +226,9 @@ contract EcosystemUpgrade is Script { address stateTransitionManagerAddress; address transparentProxyAdmin; address eraDiamondProxy; + uint256 newProtocolVersion; + uint256 oldProtocolVersion; + address l1LegacySharedBridge; } struct TokensConfig { @@ -250,6 +258,8 @@ contract EcosystemUpgrade is Script { initializeConfig(configPath); + initializeOldData(); + instantiateCreate2Factory(); deployBytecodesSupplier(); @@ -295,9 +305,26 @@ contract EcosystemUpgrade is Script { function run() public { prepareEcosystemContracts( - "/script-config/gateway-upgrade-ecosystem.toml", - "/script-out/gateway-upgrade-ecosystem.toml" + vm.envString("GATEWAY_UPGRADE_ECOSYSTEM_INPUT"), + vm.envString("GATEWAY_UPGRADE_ECOSYSTEM_OUTPUT") + ); + } + + function initializeOldData() internal { + config.contracts.newProtocolVersion = getNewProtocolVersion(); + config.contracts.oldProtocolVersion = getOldProtocolVersion(); + + uint256 ctmProtocolVersion = ChainTypeManager(config.contracts.stateTransitionManagerAddress).protocolVersion(); + require( + ctmProtocolVersion != getNewProtocolVersion(), + "The new protocol version is already present on the ChainTypeManager" ); + + config.contracts.oldValidatorTimelock = ChainTypeManager(config.contracts.stateTransitionManagerAddress) + .validatorTimelock(); + + // In the future this value will be populated with the new shared bridge, but since the version on the CTM is the old one, the old bridge is stored here as well. + config.contracts.l1LegacySharedBridge = Bridgehub(config.contracts.bridgehubProxyAddress).sharedBridge(); } function provideAcceptOwnershipCalls() public returns (Call[] memory calls) { @@ -409,6 +436,13 @@ contract EcosystemUpgrade is Script { ), value: 0 }); + // Note, that the server requires that the validator timelock is updated together with the protocol version + // as it relies on it to dynamically fetch the validator timelock address. + Call memory setValidatorTimelockCall = Call({ + target: config.contracts.stateTransitionManagerAddress, + data: abi.encodeCall(ChainTypeManager.setValidatorTimelock, (addresses.validatorTimelock)), + value: 0 + }); // The call that will start the timer till the end of the upgrade. Call memory timerCall = Call({ @@ -417,9 +451,10 @@ contract EcosystemUpgrade is Script { value: 0 }); - calls = new Call[](2); + calls = new Call[](3); calls[0] = ctmCall; - calls[1] = timerCall; + calls[1] = setValidatorTimelockCall; + calls[2] = timerCall; } function getChainUpgradeInfo() public returns (Diamond.DiamondCutData memory upgradeCutData) { @@ -621,14 +656,9 @@ contract EcosystemUpgrade is Script { data: abi.encodeCall(ChainTypeManager.setChainCreationParams, (prepareNewChainCreationParams())), value: 0 }); - calls[5] = Call({ - target: config.contracts.stateTransitionManagerAddress, - data: abi.encodeCall(ChainTypeManager.setValidatorTimelock, (addresses.validatorTimelock)), - value: 0 - }); // Now, we need to update the bridgehub - calls[6] = Call({ + calls[5] = Call({ target: config.contracts.bridgehubProxyAddress, data: abi.encodeCall( Bridgehub.setAddresses, @@ -642,7 +672,7 @@ contract EcosystemUpgrade is Script { }); // Setting the necessary params for the L1Nullifier contract - calls[7] = Call({ + calls[6] = Call({ target: config.contracts.oldSharedBridgeProxyAddress, data: abi.encodeCall( L1Nullifier.setL1NativeTokenVault, @@ -650,18 +680,18 @@ contract EcosystemUpgrade is Script { ), value: 0 }); - calls[8] = Call({ + calls[7] = Call({ target: config.contracts.oldSharedBridgeProxyAddress, data: abi.encodeCall(L1Nullifier.setL1AssetRouter, (addresses.bridges.sharedBridgeProxy)), value: 0 }); - calls[9] = Call({ + calls[8] = Call({ target: config.contracts.stateTransitionManagerAddress, // Making the old protocol version no longer invalid data: abi.encodeCall(ChainTypeManager.setProtocolVersionDeadline, (getOldProtocolVersion(), 0)), value: 0 }); - calls[10] = Call({ + calls[9] = Call({ target: addresses.upgradeTimer, // Double checking that the deadline has passed. data: abi.encodeCall(GovernanceUpgradeTimer.checkDeadline, ()), @@ -679,7 +709,6 @@ contract EcosystemUpgrade is Script { // are parsed alfabetically and not by key. // https://book.getfoundry.sh/cheatcodes/parse-toml config.eraChainId = toml.readUint("$.era_chain_id"); - config.ownerAddress = toml.readAddress("$.owner_address"); config.testnetVerifier = toml.readBool("$.testnet_verifier"); config.contracts.maxNumberOfChains = toml.readUint("$.contracts.max_number_of_chains"); @@ -714,15 +743,21 @@ contract EcosystemUpgrade is Script { config.contracts.defaultAAHash = toml.readBytes32("$.contracts.default_aa_hash"); config.contracts.bootloaderHash = toml.readBytes32("$.contracts.bootloader_hash"); - config.contracts.stateTransitionManagerAddress = toml.readAddress( - "$.contracts.state_transition_manager_address" - ); config.contracts.bridgehubProxyAddress = toml.readAddress("$.contracts.bridgehub_proxy_address"); - config.contracts.oldSharedBridgeProxyAddress = toml.readAddress("$.contracts.old_shared_bridge_proxy_address"); + + config.ownerAddress = Bridgehub(config.contracts.bridgehubProxyAddress).owner(); + config.contracts.stateTransitionManagerAddress = IBridgehubLegacy(config.contracts.bridgehubProxyAddress) + .stateTransitionManager(config.eraChainId); + config.contracts.oldSharedBridgeProxyAddress = Bridgehub(config.contracts.bridgehubProxyAddress).sharedBridge(); + config.contracts.eraDiamondProxy = ChainTypeManager(config.contracts.stateTransitionManagerAddress) + .getHyperchain(config.eraChainId); + config.contracts.legacyErc20BridgeAddress = address( + L1AssetRouter(config.contracts.oldSharedBridgeProxyAddress).legacyBridge() + ); + config.contracts.oldValidatorTimelock = ChainTypeManager(config.contracts.stateTransitionManagerAddress) + .validatorTimelock(); + config.contracts.transparentProxyAdmin = toml.readAddress("$.contracts.transparent_proxy_admin"); - config.contracts.eraDiamondProxy = toml.readAddress("$.contracts.era_diamond_proxy"); - config.contracts.legacyErc20BridgeAddress = toml.readAddress("$.contracts.legacy_erc20_bridge_address"); - config.contracts.oldValidatorTimelock = toml.readAddress("$.contracts.old_validator_timelock"); config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); config.governanceUpgradeTimerInitialDelay = toml.readUint("$.governance_upgrade_timer_initial_delay"); @@ -794,6 +829,7 @@ contract EcosystemUpgrade is Script { function deployBytecodesSupplier() internal { address contractAddress = deployViaCreate2(type(BytecodesSupplier).creationCode); console.log("BytecodesSupplier deployed at:", contractAddress); + notifyAboutDeployment(contractAddress, "BytecodesSupplier", hex""); addresses.bytecodesSupplier = contractAddress; } @@ -857,47 +893,65 @@ contract EcosystemUpgrade is Script { function deployVerifier() internal { bytes memory code; + string memory contractName; if (config.testnetVerifier) { code = type(TestnetVerifier).creationCode; + contractName = "TestnetVerifier"; } else { code = type(Verifier).creationCode; + contractName = "Verifier"; } address contractAddress = deployViaCreate2(code); - console.log("Verifier deployed at:", contractAddress); + notifyAboutDeployment(contractAddress, contractName, hex""); addresses.stateTransition.verifier = contractAddress; } function deployDefaultUpgrade() internal { address contractAddress = deployViaCreate2(type(DefaultUpgrade).creationCode); - console.log("DefaultUpgrade deployed at:", contractAddress); + notifyAboutDeployment(contractAddress, "DefaultUpgrade", hex""); addresses.stateTransition.defaultUpgrade = contractAddress; } function deployGenesisUpgrade() internal { bytes memory bytecode = abi.encodePacked(type(L1GenesisUpgrade).creationCode); address contractAddress = deployViaCreate2(bytecode); - console.log("GenesisUpgrade deployed at:", contractAddress); + notifyAboutDeployment(contractAddress, "L1GenesisUpgrade", hex""); addresses.stateTransition.genesisUpgrade = contractAddress; } function deployGatewayUpgrade() internal { bytes memory bytecode = abi.encodePacked(type(GatewayUpgrade).creationCode); address contractAddress = deployViaCreate2(bytecode); - console.log("GatewayUpgrade deployed at:", contractAddress); + notifyAboutDeployment(contractAddress, "GatewayUpgrade", hex""); + addresses.gatewayUpgrade = contractAddress; } function deployDAValidators() internal { - vm.broadcast(msg.sender); - address rollupDAManager = address(new RollupDAManager()); + // Note, that here we use the `msg.sender` address, while the final owner should be the decentralized governance. + // The ownership will be transferred later during the `updateOwners` step. + address rollupDAManager = address( + create2WithDeterministicOwner(type(RollupDAManager).creationCode, msg.sender) + ); addresses.daAddresses.rollupDAManager = rollupDAManager; + notifyAboutDeployment(rollupDAManager, "RollupDAManager", hex""); + + if (RollupDAManager(rollupDAManager).owner() != address(msg.sender)) { + require( + RollupDAManager(rollupDAManager).pendingOwner() == address(msg.sender), + "Ownership was not set correctly" + ); + vm.broadcast(msg.sender); + RollupDAManager(rollupDAManager).acceptOwnership(); + } + // This contract is located in the `da-contracts` folder, we output it the same way for consistency/ease of use. address rollupDAValidator = deployViaCreate2(Utils.readRollupDAValidatorBytecode()); - console.log("L1RollupDAValidator deployed at:", rollupDAValidator); + notifyAboutDeployment(rollupDAValidator, "RollupL1DAValidator", hex""); addresses.daAddresses.l1RollupDAValidator = rollupDAValidator; address validiumDAValidator = deployViaCreate2(type(ValidiumL1DAValidator).creationCode); - console.log("L1ValidiumDAValidator deployed at:", validiumDAValidator); + notifyAboutDeployment(validiumDAValidator, "ValidiumL1DAValidator", hex""); addresses.daAddresses.l1ValidiumDAValidator = validiumDAValidator; vm.broadcast(msg.sender); @@ -915,17 +969,26 @@ contract EcosystemUpgrade is Script { abi.encode(config.deployerAddress, executionDelay, config.eraChainId) ); address contractAddress = deployViaCreate2(bytecode); - console.log("ValidatorTimelock deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "ValidatorTimelock", + abi.encode(config.deployerAddress, executionDelay, config.eraChainId) + ); addresses.validatorTimelock = contractAddress; } function deployBridgehubImplementation() internal { bytes memory bridgeHubBytecode = abi.encodePacked( type(Bridgehub).creationCode, - abi.encode(config.l1ChainId, config.ownerAddress, (config.contracts.maxNumberOfChains)) + abi.encode(config.l1ChainId, config.ownerAddress, config.contracts.maxNumberOfChains) ); address bridgehubImplementation = deployViaCreate2(bridgeHubBytecode); - console.log("Bridgehub Implementation deployed at:", bridgehubImplementation); + notifyAboutDeployment( + bridgehubImplementation, + "Bridgehub", + abi.encode(config.l1ChainId, config.ownerAddress, config.contracts.maxNumberOfChains), + "Bridgehub Implementation" + ); addresses.bridgehub.bridgehubImplementation = bridgehubImplementation; } @@ -935,7 +998,12 @@ contract EcosystemUpgrade is Script { abi.encode(config.contracts.bridgehubProxyAddress) ); address messageRootImplementation = deployViaCreate2(messageRootBytecode); - console.log("MessageRoot Implementation deployed at:", messageRootImplementation); + notifyAboutDeployment( + messageRootImplementation, + "MessageRoot", + abi.encode(config.contracts.bridgehubProxyAddress), + "Message Root Implementation" + ); addresses.bridgehub.messageRootImplementation = messageRootImplementation; bytes memory bytecode = abi.encodePacked( @@ -947,7 +1015,16 @@ contract EcosystemUpgrade is Script { ) ); address messageRootProxy = deployViaCreate2(bytecode); - console.log("Message Root Proxy deployed at:", messageRootProxy); + notifyAboutDeployment( + messageRootProxy, + "TransparentUpgradeableProxy", + abi.encode( + messageRootImplementation, + config.contracts.transparentProxyAdmin, + abi.encodeCall(MessageRoot.initialize, ()) + ), + "Message Root Proxy" + ); addresses.bridgehub.messageRootProxy = messageRootProxy; } @@ -957,7 +1034,12 @@ contract EcosystemUpgrade is Script { abi.encode(config.contracts.bridgehubProxyAddress, addresses.bridges.sharedBridgeProxy) ); address ctmDTImplementation = deployViaCreate2(ctmDTBytecode); - console.log("CTM Deployment Tracker Implementation deployed at:", ctmDTImplementation); + notifyAboutDeployment( + ctmDTImplementation, + "CTMDeploymentTracker", + abi.encode(config.contracts.bridgehubProxyAddress, addresses.bridges.sharedBridgeProxy), + "CTM Deployment Tracker Implementation" + ); addresses.bridgehub.ctmDeploymentTrackerImplementation = ctmDTImplementation; bytes memory bytecode = abi.encodePacked( @@ -969,7 +1051,16 @@ contract EcosystemUpgrade is Script { ) ); address ctmDTProxy = deployViaCreate2(bytecode); - console.log("CTM Deployment Tracker Proxy deployed at:", ctmDTProxy); + notifyAboutDeployment( + ctmDTProxy, + "TransparentUpgradeableProxy", + abi.encode( + ctmDTImplementation, + config.contracts.transparentProxyAdmin, + abi.encodeCall(CTMDeploymentTracker.initialize, (config.deployerAddress)) + ), + "CTM Deployment Tracker Proxy deployed at:" + ); addresses.bridgehub.ctmDeploymentTrackerProxy = ctmDTProxy; } @@ -982,7 +1073,7 @@ contract EcosystemUpgrade is Script { address executorFacet = deployViaCreate2( abi.encodePacked(type(ExecutorFacet).creationCode, abi.encode(config.l1ChainId)) ); - console.log("ExecutorFacet deployed at:", executorFacet); + notifyAboutDeployment(executorFacet, "ExecutorFacet", hex""); addresses.stateTransition.executorFacet = executorFacet; address adminFacet = deployViaCreate2( @@ -991,21 +1082,25 @@ contract EcosystemUpgrade is Script { abi.encode(config.l1ChainId, addresses.daAddresses.rollupDAManager) ) ); - console.log("AdminFacet deployed at:", adminFacet); + notifyAboutDeployment( + adminFacet, + "AdminFacet", + abi.encode(config.l1ChainId, addresses.daAddresses.rollupDAManager) + ); addresses.stateTransition.adminFacet = adminFacet; address mailboxFacet = deployViaCreate2( abi.encodePacked(type(MailboxFacet).creationCode, abi.encode(config.eraChainId, config.l1ChainId)) ); - console.log("MailboxFacet deployed at:", mailboxFacet); + notifyAboutDeployment(mailboxFacet, "MailboxFacet", abi.encode(config.eraChainId, config.l1ChainId)); addresses.stateTransition.mailboxFacet = mailboxFacet; address gettersFacet = deployViaCreate2(type(GettersFacet).creationCode); - console.log("GettersFacet deployed at:", gettersFacet); + notifyAboutDeployment(gettersFacet, "GettersFacet", hex""); addresses.stateTransition.gettersFacet = gettersFacet; address diamondInit = deployViaCreate2(type(DiamondInit).creationCode); - console.log("DiamondInit deployed at:", diamondInit); + notifyAboutDeployment(diamondInit, "DiamondInit", hex""); addresses.stateTransition.diamondInit = diamondInit; } @@ -1015,7 +1110,12 @@ contract EcosystemUpgrade is Script { abi.encode(config.contracts.bridgehubProxyAddress) ); address contractAddress = deployViaCreate2(bytecode); - console.log("ChainTypeManagerImplementation deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "ChainTypeManager", + abi.encode(config.contracts.bridgehubProxyAddress), + "ChainTypeManagerImplementation" + ); addresses.stateTransition.chainTypeManagerImplementation = contractAddress; } @@ -1043,7 +1143,12 @@ contract EcosystemUpgrade is Script { abi.encode(config.contracts.bridgehubProxyAddress, config.eraChainId, config.contracts.eraDiamondProxy) ); address contractAddress = deployViaCreate2(bytecode); - console.log("L1NullifierImplementation deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "L1Nullifier", + abi.encode(config.contracts.bridgehubProxyAddress, config.eraChainId, config.contracts.eraDiamondProxy), + "L1NullifierImplementation" + ); addresses.bridges.l1NullifierImplementation = contractAddress; } @@ -1060,7 +1165,19 @@ contract EcosystemUpgrade is Script { ) ); address contractAddress = deployViaCreate2(bytecode); - console.log("SharedBridgeImplementation deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "L1AssetRouter", + // solhint-disable-next-line func-named-parameters + abi.encode( + config.tokens.tokenWethAddress, + config.contracts.bridgehubProxyAddress, + config.contracts.oldSharedBridgeProxyAddress, + config.eraChainId, + config.contracts.eraDiamondProxy + ), + "SharedBridgeImplementation" + ); addresses.bridges.sharedBridgeImplementation = contractAddress; } @@ -1075,7 +1192,16 @@ contract EcosystemUpgrade is Script { ) ); address contractAddress = deployViaCreate2(bytecode); - console.log("SharedBridgeProxy deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "TransparentUpgradeableProxy", + abi.encode( + addresses.bridges.sharedBridgeImplementation, + config.contracts.transparentProxyAdmin, + initCalldata + ), + "SharedBridgeProxy deployed at:" + ); addresses.bridges.sharedBridgeProxy = contractAddress; } @@ -1098,7 +1224,17 @@ contract EcosystemUpgrade is Script { ) ); address contractAddress = deployViaCreate2(bytecode); - console.log("Erc20BridgeImplementation deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "L1ERC20Bridge", + abi.encode( + config.contracts.oldSharedBridgeProxyAddress, + addresses.bridges.sharedBridgeProxy, + addresses.vaults.l1NativeTokenVaultProxy, + config.eraChainId + ), + "Erc20BridgeImplementation" + ); addresses.bridges.erc20BridgeImplementation = contractAddress; } @@ -1109,21 +1245,19 @@ contract EcosystemUpgrade is Script { abi.encode() ); address contractAddress = deployViaCreate2(bytecode); - console.log("BridgedStandardERC20Implementation deployed at:", contractAddress); + notifyAboutDeployment(contractAddress, "BridgedStandardERC20", hex""); addresses.bridges.bridgedStandardERC20Implementation = contractAddress; } function deployBridgedTokenBeacon() internal { - // Note, that the `msg.sender` will be set as the owner. - // This means that we can not use a naive create2factory. It may be replaced - // with a more advanced one, but CREATE from a hot wallet is fine too. - vm.startBroadcast(msg.sender); - UpgradeableBeacon beacon = new UpgradeableBeacon(addresses.bridges.bridgedStandardERC20Implementation); - beacon.transferOwnership(config.ownerAddress); - vm.stopBroadcast(); - address contractAddress = address(beacon); - console.log("BridgedTokenBeacon deployed at:", contractAddress); - addresses.bridges.bridgedTokenBeacon = contractAddress; + bytes memory initCode = abi.encodePacked( + type(UpgradeableBeacon).creationCode, + abi.encode(addresses.bridges.bridgedStandardERC20Implementation) + ); + + address beacon = create2WithDeterministicOwner(initCode, config.ownerAddress); + notifyAboutDeployment(beacon, "UpgradeableBeacon", hex""); + addresses.bridges.bridgedTokenBeacon = beacon; } function deployL1NativeTokenVaultImplementation() internal { @@ -1137,7 +1271,16 @@ contract EcosystemUpgrade is Script { ) ); address contractAddress = deployViaCreate2(bytecode); - console.log("L1NativeTokenVaultImplementation deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "L1NativeTokenVault", + abi.encode( + config.tokens.tokenWethAddress, + addresses.bridges.sharedBridgeProxy, + config.contracts.oldSharedBridgeProxyAddress + ), + "L1NativeTokenVaultImplementation" + ); addresses.vaults.l1NativeTokenVaultImplementation = contractAddress; } @@ -1155,7 +1298,16 @@ contract EcosystemUpgrade is Script { ) ); address contractAddress = deployViaCreate2(bytecode); - console.log("L1NativeTokenVaultProxy deployed at:", contractAddress); + notifyAboutDeployment( + contractAddress, + "TransparentUpgradeableProxy", + abi.encode( + addresses.vaults.l1NativeTokenVaultImplementation, + config.contracts.transparentProxyAdmin, + initCalldata + ), + "L1NativeTokenVaultProxy:" + ); addresses.vaults.l1NativeTokenVaultProxy = contractAddress; IL1AssetRouter sharedBridge = IL1AssetRouter(addresses.bridges.sharedBridgeProxy); @@ -1174,6 +1326,12 @@ contract EcosystemUpgrade is Script { ); addresses.transitionaryOwner = deployViaCreate2(bytecode); + + notifyAboutDeployment(addresses.transitionaryOwner, "TransitionaryOwner", abi.encode(config.ownerAddress)); + } + + function getInitialDelay() external view returns (uint256) { + return config.governanceUpgradeTimerInitialDelay; } function deployGovernanceUpgradeTimer() internal { @@ -1191,6 +1349,11 @@ contract EcosystemUpgrade is Script { ); addresses.upgradeTimer = deployViaCreate2(bytecode); + notifyAboutDeployment( + addresses.upgradeTimer, + "GovernanceUpgradeTimer", + abi.encode(INITIAL_DELAY, MAX_ADDITIONAL_DELAY, config.ownerAddress, config.ecosystemAdminAddress) + ); } function deployL2WrappedBaseTokenStore() internal { @@ -1200,6 +1363,22 @@ contract EcosystemUpgrade is Script { ); addresses.l2WrappedBaseTokenStore = deployViaCreate2(bytecode); + notifyAboutDeployment( + addresses.l2WrappedBaseTokenStore, + "L2WrappedBaseTokenStore", + abi.encode(config.ownerAddress, config.ecosystemAdminAddress) + ); + } + + function create2WithDeterministicOwner(bytes memory initCode, address owner) internal returns (address) { + bytes memory creatorInitCode = abi.encodePacked( + type(Create2AndTransfer).creationCode, + abi.encode(initCode, config.contracts.create2FactorySalt, owner) + ); + + address deployerAddr = deployViaCreate2(creatorInitCode); + + return Create2AndTransfer(deployerAddr).deployedAddress(); } function _moveGovernanceToOwner(address target) internal { @@ -1296,6 +1475,40 @@ contract EcosystemUpgrade is Script { }); } + function notifyAboutDeployment( + address contractAddr, + string memory contractName, + bytes memory constructorParams + ) internal { + notifyAboutDeployment(contractAddr, contractName, constructorParams, contractName); + } + + function notifyAboutDeployment( + address contractAddr, + string memory contractName, + bytes memory constructorParams, + string memory displayName + ) internal { + string memory basicMessage = string.concat(displayName, " has been deployed at ", vm.toString(contractAddr)); + console.log(basicMessage); + + string memory forgeMessage; + if (constructorParams.length == 0) { + forgeMessage = string.concat("forge verify-contract ", vm.toString(contractAddr), " ", contractName); + } else { + forgeMessage = string.concat( + "forge verify-contract ", + vm.toString(contractAddr), + " ", + contractName, + " --constructor-args ", + vm.toString(constructorParams) + ); + } + + console.log(forgeMessage); + } + function saveOutput(string memory outputPath) internal { prepareNewChainCreationParams(); @@ -1408,10 +1621,18 @@ contract EcosystemUpgrade is Script { ); vm.serializeBytes("contracts_config", "diamond_cut_data", generatedData.diamondCutData); - string memory contractsConfig = vm.serializeBytes( + vm.serializeBytes("contracts_config", "force_deployments_data", generatedData.forceDeploymentsData); + + vm.serializeUint("contracts_config", "new_protocol_version", config.contracts.newProtocolVersion); + + vm.serializeUint("contracts_config", "old_protocol_version", config.contracts.oldProtocolVersion); + + vm.serializeAddress("contracts_config", "old_validator_timelock", config.contracts.oldValidatorTimelock); + + string memory contractsConfig = vm.serializeAddress( "contracts_config", - "force_deployments_data", - generatedData.forceDeploymentsData + "l1_legacy_shared_bridge", + config.contracts.l1LegacySharedBridge ); vm.serializeAddress("deployed_addresses", "validator_timelock_addr", addresses.validatorTimelock); @@ -1509,24 +1730,4 @@ contract EcosystemUpgrade is Script { // add this to be excluded from coverage report function test() internal {} - - function addL2WethToStore( - address storeAddress, - ChainAdmin chainAdmin, - uint256 chainId, - address l2WBaseToken - ) public { - L2WrappedBaseTokenStore l2WrappedBaseTokenStore = L2WrappedBaseTokenStore(storeAddress); - - Call[] memory calls = new Call[](1); - calls[0] = Call({ - target: storeAddress, - value: 0, - data: abi.encodeCall(l2WrappedBaseTokenStore.initializeChain, (chainId, l2WBaseToken)) - }); - - vm.startBroadcast(); - chainAdmin.multicall(calls, true); - vm.stopBroadcast(); - } } diff --git a/l1-contracts/deploy-scripts/upgrade/README.md b/l1-contracts/deploy-scripts/upgrade/README.md new file mode 100644 index 000000000..0d8f2c0eb --- /dev/null +++ b/l1-contracts/deploy-scripts/upgrade/README.md @@ -0,0 +1,10 @@ +# Gateway upgrade related scripts + +## Example of usage + +1. Create a file similar to one of those in the `/l1-contracts/upgrade-envs/` for our environment. +2. Run the following to prepare the ecosystem: + +```sh +GATEWAY_UPGRADE_ECOSYSTEM_INPUT=/upgrade-envs/ forge script --sig "run()" EcosystemUpgrade --ffi --rpc-url --gas-limit 20000000000 --broadcast --slow +``` diff --git a/l1-contracts/foundry.toml b/l1-contracts/foundry.toml index 84614c12c..c3b4a43fa 100644 --- a/l1-contracts/foundry.toml +++ b/l1-contracts/foundry.toml @@ -20,6 +20,7 @@ fs_permissions = [ { access = "read", path = "../system-contracts/zkout/" }, { access = "read", path = "./script-config" }, { access = "read-write", path = "./script-out" }, + { access = "read", path = "./upgrade-envs" }, { access = "read", path = "./out" }, { access = "read-write", path = "./test/foundry/l1/integration/deploy-scripts/script-config/" }, { access = "read-write", path = "./test/foundry/l1/integration/deploy-scripts/script-out/" }, diff --git a/l1-contracts/package.json b/l1-contracts/package.json index 813790bdc..63f4cfc1c 100644 --- a/l1-contracts/package.json +++ b/l1-contracts/package.json @@ -61,7 +61,7 @@ "test": "yarn workspace da-contracts build && hardhat test test/unit_tests/*.spec.ts --network hardhat", "test:foundry": "forge test --ffi --match-path 'test/foundry/l1/*' --no-match-test 'test_MainnetFork'", "test:zkfoundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --zksync --match-path 'test/foundry/l2/*'", - "test:mainnet-upgrade-fork": "forge test --match-test test_MainnetFork --ffi --rpc-url $INFURA_MAINNET --gas-limit 2000000000", + "test:mainnet-upgrade-fork": "forge test --match-test test_MainnetFork --ffi --rpc-url $INFURA_MAINNET --gas-limit 20000000000", "test:fork": "TEST_CONTRACTS_FORK=1 yarn run hardhat test test/unit_tests/*.fork.ts --network hardhat", "coverage:foundry": "forge coverage --ffi --match-path 'test/foundry/l1/*' --no-match-coverage 'contracts/(bridge/.*L2.*\\.sol|governance/L2AdminFactory\\.sol)' --no-match-test test_MainnetFork", "deploy-no-build": "ts-node scripts/deploy.ts", diff --git a/l1-contracts/scripts/display-governance.ts b/l1-contracts/scripts/display-governance.ts index 4b6741386..010295c26 100644 --- a/l1-contracts/scripts/display-governance.ts +++ b/l1-contracts/scripts/display-governance.ts @@ -1,4 +1,4 @@ -/// Temporary script that generated the needed calldata for the migration of the governance. +/// Temporary script that helps to generate the needed calldata for the migration of the governance. // hardhat import should be the first import in the file // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/l1-contracts/scripts/upgrade-env-generator.ts b/l1-contracts/scripts/upgrade-env-generator.ts new file mode 100644 index 000000000..43359e6bb --- /dev/null +++ b/l1-contracts/scripts/upgrade-env-generator.ts @@ -0,0 +1,47 @@ +/// Temporary script that helps to generate the calldata to the gateway upgrade. + +// 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 { Provider } from "zksync-ethers"; +import { ethers } from "ethers"; + +async function main() { + const program = new Command(); + + program.version("0.1.0").name("upgrade-new-generator"); + + program + .option("--l2-rpc-url ") + .option("--l1-rpc-url ") + .action(async (cmd) => { + const l1Provider = new ethers.providers.JsonRpcProvider(cmd.l1RpcUrl); + const l2Provider = new Provider(cmd.l2RpcUrl); + + const bridgehubAddr = await l2Provider.getBridgehubContractAddress(); + const proxyAdmin = await l1Provider.getStorageAt( + bridgehubAddr, + // This is the storage slot where TransparentUpgradeableProxy stores + // its admin + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + ); + + if (!proxyAdmin.startsWith("0x" + "0".repeat(24)) || proxyAdmin == ethers.constants.HashZero) { + throw new Error(`Invalid ProxyAdmin: ${proxyAdmin}`); + } + + console.log(`bridgehub_proxy_address = "${bridgehubAddr}"`); + console.log(`transparent_proxy_admin = "0x${proxyAdmin.substring(26)}"`); + }); + + await program.parseAsync(process.argv); +} + +main() + .then(() => process.exit(0)) + .catch((err) => { + console.error("Error:", err); + process.exit(1); + }); diff --git a/l1-contracts/test/foundry/l1/integration/UpgradeTest.t.sol b/l1-contracts/test/foundry/l1/integration/UpgradeTest.t.sol index 6434ce976..d9aacc5f5 100644 --- a/l1-contracts/test/foundry/l1/integration/UpgradeTest.t.sol +++ b/l1-contracts/test/foundry/l1/integration/UpgradeTest.t.sol @@ -11,9 +11,9 @@ import {ChainUpgrade} from "deploy-scripts/upgrade/ChainUpgrade.s.sol"; import {Call} from "contracts/governance/Common.sol"; import {Test} from "forge-std/Test.sol"; -string constant ECOSYSTEM_INPUT = "/test/foundry/l1/integration/upgrade-envs/script-config/mainnet.toml"; +string constant ECOSYSTEM_INPUT = "/upgrade-envs/mainnet.toml"; string constant ECOSYSTEM_OUTPUT = "/test/foundry/l1/integration/upgrade-envs/script-out/mainnet.toml"; -string constant CHAIN_INPUT = "/test/foundry/l1/integration/upgrade-envs/script-config/mainnet-era.toml"; +string constant CHAIN_INPUT = "/upgrade-envs/mainnet-era.toml"; string constant CHAIN_OUTPUT = "/test/foundry/l1/integration/upgrade-envs/script-out/mainnet-era.toml"; contract UpgradeTest is Test { @@ -59,6 +59,8 @@ contract UpgradeTest is Test { // We also may need to test that normal flow of block commit / verify / execute works (but it is hard) // so it was tested in e2e local environment. + vm.warp(block.timestamp + generateUpgradeData.getInitialDelay()); + console.log("Starting stage2 of the upgrade!"); governanceMulticall(generateUpgradeData.getOwnerAddress(), generateUpgradeData.getStage2UpgradeCalls()); diff --git a/l1-contracts/upgrade-envs/devnet.toml b/l1-contracts/upgrade-envs/devnet.toml new file mode 100644 index 000000000..8acbc9ff8 --- /dev/null +++ b/l1-contracts/upgrade-envs/devnet.toml @@ -0,0 +1,28 @@ +era_chain_id = 13377331 +testnet_verifier = true +governance_upgrade_timer_initial_delay = 120 + +[contracts] +max_number_of_chains = 100 +create2_factory_salt = "0x0000000000000000000000000000000000000000000000000000000000000001" +validator_timelock_execution_delay = 0 +genesis_root = "0xf9030b78c5bf5ac997a76962aa32c90a6d8e8ebce9838c8eeb388d73e1f7659a" +genesis_rollup_leaf_index = 64 +genesis_batch_commitment = "0x34c1b220363e0cde7eaf10fe95754d61de097e0f9d9a1dc56c8026562e395259" +recursion_node_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +recursion_leaf_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +recursion_circuits_set_vks_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +priority_tx_max_gas_limit = 72000000 +diamond_init_pubdata_pricing_mode = 0 +diamond_init_batch_overhead_l1_gas = 1000000 +diamond_init_max_pubdata_per_batch = 120000 +diamond_init_max_l2_gas_per_batch = 80000000 +diamond_init_priority_tx_max_pubdata = 99000 +diamond_init_minimal_l2_gas_price = 250000000 +bootloader_hash = "0x010008e5b883de8897598e83d383e332b87d09164363816c15f22353c3cd910d" +default_aa_hash = "0x0100052307b3b66ef67935255483d39b3c8dcdb47fdf94dddca11ebe8271afe6" +bridgehub_proxy_address = "0xbcb012c6a973f971c987a3be4ff3a75fe9510bcb" +transparent_proxy_admin = "0x8b7e5ca7dd323657a1a276ef5aa3ab6454c90c53" + +[tokens] +token_weth_address = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" diff --git a/l1-contracts/upgrade-envs/mainnet-era.toml b/l1-contracts/upgrade-envs/mainnet-era.toml new file mode 100644 index 000000000..42a835dbd --- /dev/null +++ b/l1-contracts/upgrade-envs/mainnet-era.toml @@ -0,0 +1,2 @@ +[chain] +chain_id = 324 diff --git a/l1-contracts/upgrade-envs/mainnet.toml b/l1-contracts/upgrade-envs/mainnet.toml new file mode 100644 index 000000000..a9577d3d7 --- /dev/null +++ b/l1-contracts/upgrade-envs/mainnet.toml @@ -0,0 +1,28 @@ +era_chain_id = 324 +testnet_verifier = false +governance_upgrade_timer_initial_delay = 1058400 + +[contracts] +max_number_of_chains = 100 +create2_factory_salt = "0xde6b9c610417de5c775c1601c947f482e4f4e30c0f7b848c6d2b0554d76f607e" +validator_timelock_execution_delay = 0 +genesis_root = "0xf9030b78c5bf5ac997a76962aa32c90a6d8e8ebce9838c8eeb388d73e1f7659a" +genesis_rollup_leaf_index = 64 +genesis_batch_commitment = "0x34c1b220363e0cde7eaf10fe95754d61de097e0f9d9a1dc56c8026562e395259" +recursion_node_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +recursion_leaf_level_vk_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +recursion_circuits_set_vks_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +priority_tx_max_gas_limit = 72000000 +diamond_init_pubdata_pricing_mode = 0 +diamond_init_batch_overhead_l1_gas = 1000000 +diamond_init_max_pubdata_per_batch = 120000 +diamond_init_max_l2_gas_per_batch = 80000000 +diamond_init_priority_tx_max_pubdata = 99000 +diamond_init_minimal_l2_gas_price = 250000000 +bootloader_hash = "0x010008e5b883de8897598e83d383e332b87d09164363816c15f22353c3cd910d" +default_aa_hash = "0x0100052307b3b66ef67935255483d39b3c8dcdb47fdf94dddca11ebe8271afe6" +bridgehub_proxy_address = "0x303a465B659cBB0ab36eE643eA362c509EEb5213" +transparent_proxy_admin = "0xC2a36181fB524a6bEfE639aFEd37A67e77d62cf1" + +[tokens] +token_weth_address = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"