From febc8a7a3809ab3c3583aac8b9f1172038d3231e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Thu, 25 Apr 2024 15:39:15 +0800 Subject: [PATCH 01/38] feat: add deterministic, multi-layer deployment script --- contracts/lib/forge-std | 2 +- contracts/scripts/foundry/DeployScroll.s.sol | 1148 ++++++++++++++++++ 2 files changed, 1149 insertions(+), 1 deletion(-) create mode 100644 contracts/scripts/foundry/DeployScroll.s.sol diff --git a/contracts/lib/forge-std b/contracts/lib/forge-std index 662ae0d693..bb4ceea94d 160000 --- a/contracts/lib/forge-std +++ b/contracts/lib/forge-std @@ -1 +1 @@ -Subproject commit 662ae0d6936654c5d1fb79fc15f521de28edb60e +Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol new file mode 100644 index 0000000000..e888112731 --- /dev/null +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -0,0 +1,1148 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.24; + +import {Script, console} from "forge-std/Script.sol"; +import {VmSafe} from "forge-std/Vm.sol"; + +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +import {EmptyContract} from "../../src/misc/EmptyContract.sol"; + +import {EnforcedTxGateway} from "../../src/L1/gateways/EnforcedTxGateway.sol"; +import {L1CustomERC20Gateway} from "../../src/L1/gateways/L1CustomERC20Gateway.sol"; +import {L1ERC1155Gateway} from "../../src/L1/gateways/L1ERC1155Gateway.sol"; +import {L1ERC721Gateway} from "../../src/L1/gateways/L1ERC721Gateway.sol"; +import {L1ETHGateway} from "../../src/L1/gateways/L1ETHGateway.sol"; +import {L1GatewayRouter} from "../../src/L1/gateways/L1GatewayRouter.sol"; +import {L1MessageQueueWithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueWithGasPriceOracle.sol"; +import {L1ScrollMessenger} from "../../src/L1/L1ScrollMessenger.sol"; +import {L1StandardERC20Gateway} from "../../src/L1/gateways/L1StandardERC20Gateway.sol"; +import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol"; +import {L2GasPriceOracle} from "../../src/L1/rollup/L2GasPriceOracle.sol"; +import {MultipleVersionRollupVerifier} from "../../src/L1/rollup/MultipleVersionRollupVerifier.sol"; +import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol"; +import {ZkEvmVerifierV1} from "../../src/libraries/verifier/ZkEvmVerifierV1.sol"; + +import {L2CustomERC20Gateway} from "../../src/L2/gateways/L2CustomERC20Gateway.sol"; +import {L2ERC1155Gateway} from "../../src/L2/gateways/L2ERC1155Gateway.sol"; +import {L2ERC721Gateway} from "../../src/L2/gateways/L2ERC721Gateway.sol"; +import {L2ETHGateway} from "../../src/L2/gateways/L2ETHGateway.sol"; +import {L2GatewayRouter} from "../../src/L2/gateways/L2GatewayRouter.sol"; +import {L2ScrollMessenger} from "../../src/L2/L2ScrollMessenger.sol"; +import {L2StandardERC20Gateway} from "../../src/L2/gateways/L2StandardERC20Gateway.sol"; +import {L2WETHGateway} from "../../src/L2/gateways/L2WETHGateway.sol"; +import {L1GasPriceOracle} from "../../src/L2/predeploys/L1GasPriceOracle.sol"; +import {L2MessageQueue} from "../../src/L2/predeploys/L2MessageQueue.sol"; +import {L2TxFeeVault} from "../../src/L2/predeploys/L2TxFeeVault.sol"; +import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol"; +import {WrappedEther} from "../../src/L2/predeploys/WrappedEther.sol"; +import {ScrollStandardERC20} from "../../src/libraries/token/ScrollStandardERC20.sol"; +import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol"; + +/// @dev The address of DeterministicDeploymentProxy. +/// See https://github.com/Arachnid/deterministic-deployment-proxy. +address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + +/// @dev The default salt prefix used for deriving deterministic deployment addresses. +string constant DEFAULT_SALT_PREFIX = "ScrollStack"; + +contract ProxyAdminSetOwner is ProxyAdmin { + /// @dev allow setting the owner in the constructor, otherwise + /// DeterministicDeploymentProxy would become the owner. + constructor(address owner) { + _transferOwnership(owner); + } +} + +contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory { + /// @dev allow setting the owner in the constructor, otherwise + /// DeterministicDeploymentProxy would become the owner. + constructor(address owner, address _implementation) ScrollStandardERC20Factory(_implementation) { + _transferOwnership(owner); + } +} + +contract DeterminsticDeploymentScript is Script { + string internal saltPrefix; + + constructor(string memory _saltPrefix) { + saltPrefix = _saltPrefix; + } + + function deploy(string memory name, bytes memory code) internal returns (address) { + return _deploy(name, code); + } + + function deploy( + string memory name, + bytes memory code, + bytes memory args + ) internal returns (address) { + return _deploy(name, abi.encodePacked(code, args)); + } + + function _deploy(string memory name, bytes memory codeWithArgs) private returns (address) { + // check override (mainly used with predeploys) + address addr = vm.envOr(string(abi.encodePacked(name, "_OVERRIDE")), address(0)); + + if (addr != address(0)) { + if (addr.code.length == 0) { + (VmSafe.CallerMode mode, , ) = vm.readCallers(); + + // if we're ready to start broadcasting transactions, then we + // must ensure that the override contract has been deployed. + if (mode == VmSafe.CallerMode.Broadcast || mode == VmSafe.CallerMode.RecurrentBroadcast) { + console.log(string(abi.encodePacked("[ERROR] ", name, "_OVERRIDE=", vm.toString(addr), " not deployed in broadcast mode"))); + revert(); + } + } + + logAddress(name, addr); + return addr; + } + + // predict determinstic deployment address + addr = _predict(name, codeWithArgs); + logAddress(name, addr); + + // return if the contract is already deployed, + // in this case the subsequent initialization steps will probably break + if (addr.code.length > 0) { + console.log(string(abi.encodePacked("[WARN] contract ", name, " is already deployed"))); + return addr; + } + + // deploy contract + bytes32 salt = _getSalt(name); + bytes memory data = abi.encodePacked(salt, codeWithArgs); + (bool success, ) = DETERMINISTIC_DEPLOYMENT_PROXY_ADDR.call(data); + require(success, "call failed"); + require(addr.code.length != 0, "deployment address mismatch"); + + return addr; + } + + function _getSalt(string memory name) internal view returns (bytes32) { + return keccak256(abi.encodePacked(saltPrefix, name)); + } + + function _predict(string memory name, bytes memory codeWithArgs) private view returns (address) { + bytes32 salt = _getSalt(name); + + return address(uint160(uint256(keccak256(abi.encodePacked( + bytes1(0xff), + DETERMINISTIC_DEPLOYMENT_PROXY_ADDR, + salt, + keccak256(codeWithArgs) + ))))); + } + + function logAddress(string memory name, address addr) internal view { + console.log(string(abi.encodePacked(name, "_ADDR=", vm.toString(address(addr))))); + } +} + +contract DeployScroll is DeterminsticDeploymentScript { + /********************** + * Contracts to deploy * + **********************/ + + // L1 addresses + address L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR; + address L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR; + address L1_ENFORCED_TX_GATEWAY_PROXY_ADDR; + address L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR; + address L1_ERC1155_GATEWAY_PROXY_ADDR; + address L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR; + address L1_ERC721_GATEWAY_PROXY_ADDR; + address L1_ETH_GATEWAY_IMPLEMENTATION_ADDR; + address L1_ETH_GATEWAY_PROXY_ADDR; + address L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR; + address L1_GATEWAY_ROUTER_PROXY_ADDR; + address L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR; + address L1_MESSAGE_QUEUE_PROXY_ADDR; + address L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR; + address L1_PROXY_ADMIN_ADDR; + address L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR; + address L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR; + address L1_SCROLL_CHAIN_PROXY_ADDR; + address L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR; + address L1_SCROLL_MESSENGER_PROXY_ADDR; + address L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR; + address L1_WETH_ADDR; + address L1_WETH_GATEWAY_IMPLEMENTATION_ADDR; + address L1_WETH_GATEWAY_PROXY_ADDR; + address L1_WHITELIST_ADDR; + address L1_ZKEVM_VERIFIER_V1_ADDR; + address L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR; + address L2_GAS_PRICE_ORACLE_PROXY_ADDR; + + // L2 addresses + address L1_GAS_PRICE_ORACLE_ADDR; + address L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR; + address L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR; + address L2_ERC1155_GATEWAY_PROXY_ADDR; + address L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR; + address L2_ERC721_GATEWAY_PROXY_ADDR; + address L2_ETH_GATEWAY_IMPLEMENTATION_ADDR; + address L2_ETH_GATEWAY_PROXY_ADDR; + address L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR; + address L2_GATEWAY_ROUTER_PROXY_ADDR; + address L2_MESSAGE_QUEUE_ADDR; + address L2_PROXY_ADMIN_ADDR; + address L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR; + address L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR; + address L2_SCROLL_MESSENGER_PROXY_ADDR; + address L2_SCROLL_STANDARD_ERC20_ADDR; + address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR; + address L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR; + address L2_TX_FEE_VAULT_ADDR; + address L2_WETH_ADDR; + address L2_WETH_GATEWAY_IMPLEMENTATION_ADDR; + address L2_WETH_GATEWAY_PROXY_ADDR; + address L2_WHITELIST_ADDR; + + /*************************** + * Configuration parameters * + ***************************/ + + // general configurations + uint64 CHAIN_ID_L2 = uint64(vm.envUint("CHAIN_ID_L2")); + uint256 MAX_TX_IN_CHUNK = vm.envUint("MAX_TX_IN_CHUNK"); + uint256 MAX_L1_MESSAGE_GAS_LIMIT = vm.envUint("MAX_L1_MESSAGE_GAS_LIMIT"); + + string SALT_PREFIX = vm.envOr("SALT_PREFIX", DEFAULT_SALT_PREFIX); + string BROADCAST_LAYER = vm.envOr("BROADCAST_LAYER", string("")); + + // accounts + address L1_COMMIT_SENDER_ADDR = vm.envAddress("L1_COMMIT_SENDER_ADDR"); + address L1_FINALIZE_SENDER_ADDR = vm.envAddress("L1_FINALIZE_SENDER_ADDR"); + address L1_GAS_PRICE_ORACLE_SENDER_ADDR = vm.envAddress("L1_GAS_PRICE_ORACLE_SENDER_ADDR"); + address L2_GAS_PRICE_ORACLE_SENDER_ADDR = vm.envAddress("L2_GAS_PRICE_ORACLE_SENDER_ADDR"); + + address DEPLOYER_ADDR; // implicit, derived from private key / wallet + + // contracts deployed outside this script + address L1_FEE_VAULT_ADDR = vm.envAddress("L1_FEE_VAULT_ADDR"); + address L1_PLONK_VERIFIER_ADDR = vm.envAddress("L1_PLONK_VERIFIER_ADDR"); + + /************** + * Constructor * + **************/ + + constructor() DeterminsticDeploymentScript(SALT_PREFIX) { + // empty + } + + /************ + * Utilities * + ************/ + + /// @dev Ensure that `addr` is not the zero address. + /// This helps catch bugs arising from incorrect deployment order. + function notnull(address addr) internal returns (address) { + require(addr != address(0), "null address"); + return addr; + } + + /// @dev Only broadcast code block if we run the script on the specified layer. + modifier broadcast(string memory layer) { + if (keccak256(bytes(BROADCAST_LAYER)) == keccak256(bytes(layer))) { + vm.startBroadcast(); + } else { + // make sure we use the correct sender in simulation + vm.startPrank(DEPLOYER_ADDR); + } + + _; + + if (keccak256(bytes(BROADCAST_LAYER)) == keccak256(bytes(layer))) { + vm.stopBroadcast(); + } else { + vm.stopPrank(); + } + } + + /// @dev Only execute block if we run the script on the specified layer. + modifier only(string memory layer) { + if (keccak256(bytes(BROADCAST_LAYER)) != keccak256(bytes(layer))) { + return; + } + _; + } + + /************************* + * Deployment entry point * + *************************/ + + function run() public { + DEPLOYER_ADDR = msg.sender; + logAddress("DEPLOYER", DEPLOYER_ADDR); + + if (DETERMINISTIC_DEPLOYMENT_PROXY_ADDR.code.length == 0) { + console.log(string(abi.encodePacked("[ERROR] DeterministicDeploymentProxy (", vm.toString(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR), ") is not available"))); + revert(); + } + + deployL1Contracts1stPass(); + deployL2Contracts1stPass(); + deployL1Contracts2ndPass(); + deployL2Contracts2ndPass(); + initializeL1Contracts(); + initializeL2Contracts(); + } + + // @notice deployL1Contracts1stPass deploys L1 contracts whose initialization does not depend on any L2 addresses. + function deployL1Contracts1stPass() internal broadcast("L1") { + deployL1Weth(); + deployL1ProxyAdmin(); + deployL1PlaceHolder(); + deployL1Whitelist(); + deployL2GasPriceOracle(); + deployL1ScrollChainProxy(); + deployL1ScrollMessengerProxy(); + deployL1EnforcedTxGateway(); + deployL1ZkEvmVerifierV1(); + deployL1MultipleVersionRollupVerifier(); + deployL1MessageQueue(); + deployL1ScrollChain(); + deployL1GatewayRouter(); + deployL1ETHGatewayProxy(); + deployL1WETHGatewayProxy(); + deployL1StandardERC20GatewayProxy(); + deployL1CustomERC20GatewayProxy(); + deployL1ERC721GatewayProxy(); + deployL1ERC1155GatewayProxy(); + } + + // @notice deployL2Contracts1stPass deploys L2 contracts whose initialization does not depend on any L1 addresses. + function deployL2Contracts1stPass() internal broadcast("L2") { + deployL2MessageQueue(); + deployL1GasPriceOracle(); + deployL2Whitelist(); + deployL2Weth(); + deployTxFeeVault(); + deployL2ProxyAdmin(); + deployL2PlaceHolder(); + deployL2ScrollMessengerProxy(); + deployL2ETHGatewayProxy(); + deployL2WETHGatewayProxy(); + deployL2StandardERC20GatewayProxy(); + deployL2CustomERC20GatewayProxy(); + deployL2ERC721GatewayProxy(); + deployL2ERC1155GatewayProxy(); + deployScrollStandardERC20Factory(); + } + + // @notice deployL1Contracts2ndPass deploys L1 contracts whose initialization depends on some L2 addresses. + function deployL1Contracts2ndPass() internal broadcast("L1") { + deployL1ScrollMessenger(); + deployL1StandardERC20Gateway(); + deployL1ETHGateway(); + deployL1WETHGateway(); + deployL1CustomERC20Gateway(); + deployL1ERC721Gateway(); + deployL1ERC1155Gateway(); + } + + // @notice deployL2Contracts2ndPass deploys L2 contracts whose initialization depends on some L1 addresses. + function deployL2Contracts2ndPass() internal broadcast("L2") { + // upgradable + deployL2ScrollMessenger(); + deployL2GatewayRouter(); + deployL2StandardERC20Gateway(); + deployL2ETHGateway(); + deployL2WETHGateway(); + deployL2CustomERC20Gateway(); + deployL2ERC721Gateway(); + deployL2ERC1155Gateway(); + } + + // @notice initializeL1Contracts initializes contracts deployed on L1. + function initializeL1Contracts() internal broadcast("L1") only("L1") { + initializeScrollChain(); + initializeL2GasPriceOracle(); + initializeL1MessageQueue(); + initializeL1ScrollMessenger(); + initializeEnforcedTxGateway(); + initializeL1GatewayRouter(); + initializeL1CustomERC20Gateway(); + initializeL1ERC1155Gateway(); + initializeL1ERC721Gateway(); + initializeL1ETHGateway(); + initializeL1StandardERC20Gateway(); + initializeL1WETHGateway(); + initializeL1Whitelist(); + } + + // @notice initializeL2Contracts initializes contracts deployed on L2. + function initializeL2Contracts() internal broadcast("L2") only("L2") { + initializeL2MessageQueue(); + initializeL2TxFeeVault(); + initializeL1GasPriceOracle(); + initializeL2ScrollMessenger(); + initializeL2GatewayRouter(); + initializeL2CustomERC20Gateway(); + initializeL2ERC1155Gateway(); + initializeL2ERC721Gateway(); + initializeL2ETHGateway(); + initializeL2StandardERC20Gateway(); + initializeL2WETHGateway(); + initializeScrollStandardERC20Factory(); + initializeL2Whitelist(); + } + + /*************************** + * L1: 1st pass deployment * + **************************/ + + function deployL1Weth() internal { + L1_WETH_ADDR = deploy("L1_WETH", type(WrappedEther).creationCode); + } + + function deployL1ProxyAdmin() internal { + bytes memory args = abi.encode(DEPLOYER_ADDR); + L1_PROXY_ADMIN_ADDR = deploy("L1_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + } + + function deployL1PlaceHolder() internal { + L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy("L1_PROXY_IMPLEMENTATION_PLACEHOLDER", type(EmptyContract).creationCode); + } + + function deployL1Whitelist() internal { + bytes memory args = abi.encode(DEPLOYER_ADDR); + L1_WHITELIST_ADDR = deploy("L1_WHITELIST", type(Whitelist).creationCode, args); + } + + function deployL2GasPriceOracle() internal { + L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR = deploy("L2_GAS_PRICE_ORACLE_IMPLEMENTATION", type(L2GasPriceOracle).creationCode); + + bytes memory args = abi.encode( + notnull(L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_GAS_PRICE_ORACLE_PROXY_ADDR = deploy("L2_GAS_PRICE_ORACLE_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1ScrollChainProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_SCROLL_CHAIN_PROXY_ADDR = deploy("L1_SCROLL_CHAIN_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1ScrollMessengerProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_SCROLL_MESSENGER_PROXY_ADDR = deploy("L1_SCROLL_MESSENGER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1EnforcedTxGateway() internal { + L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION", type(EnforcedTxGateway).creationCode); + + bytes memory args = abi.encode( + notnull(L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = deploy("L1_ENFORCED_TX_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1ZkEvmVerifierV1() internal { + logAddress("L1_PLONK_VERIFIER", L1_PLONK_VERIFIER_ADDR); + bytes memory args = abi.encode(notnull(L1_PLONK_VERIFIER_ADDR)); + L1_ZKEVM_VERIFIER_V1_ADDR = deploy("L1_ZKEVM_VERIFIER_V1", type(ZkEvmVerifierV1).creationCode, args); + } + + function deployL1MultipleVersionRollupVerifier() internal { + uint256[] memory _versions = new uint256[](1); + address[] memory _verifiers = new address[](1); + _versions[0] = 1; + _verifiers[0] = notnull(L1_ZKEVM_VERIFIER_V1_ADDR); + + bytes memory args = abi.encode(notnull(L1_SCROLL_CHAIN_PROXY_ADDR), _versions, _verifiers); + L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR = deploy("L1_MULTIPLE_VERSION_ROLLUP_VERIFIER", type(MultipleVersionRollupVerifier).creationCode, args); + } + + function deployL1MessageQueue() internal { + bytes memory args = abi.encode( + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L1_SCROLL_CHAIN_PROXY_ADDR), + notnull(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR) + ); + + L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = deploy("L1_MESSAGE_QUEUE_IMPLEMENTATION", type(L1MessageQueueWithGasPriceOracle).creationCode, args); + + bytes memory args2 = abi.encode( + notnull(L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_MESSAGE_QUEUE_PROXY_ADDR = deploy("L1_MESSAGE_QUEUE_PROXY", type(TransparentUpgradeableProxy).creationCode, args2); + } + + function deployL1ScrollChain() internal { + bytes memory args = abi.encode( + CHAIN_ID_L2, + notnull(L1_MESSAGE_QUEUE_PROXY_ADDR), + notnull(L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR) + ); + + L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = deploy("L1_SCROLL_CHAIN_IMPLEMENTATION", type(ScrollChain).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_SCROLL_CHAIN_PROXY_ADDR)), + notnull(L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR) + ); + } + + function deployL1GatewayRouter() internal { + L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy("L1_GATEWAY_ROUTER_IMPLEMENTATION", type(L1GatewayRouter).creationCode); + + bytes memory args = abi.encode( + notnull(L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_GATEWAY_ROUTER_PROXY_ADDR = deploy("L1_GATEWAY_ROUTER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1ETHGatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_ETH_GATEWAY_PROXY_ADDR = deploy("L1_ETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1WETHGatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_WETH_GATEWAY_PROXY_ADDR = deploy("L1_WETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1StandardERC20GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = deploy("L1_STANDARD_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1CustomERC20GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = deploy("L1_CUSTOM_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1ERC721GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_ERC721_GATEWAY_PROXY_ADDR = deploy("L1_ERC721_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL1ERC1155GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L1_ERC1155_GATEWAY_PROXY_ADDR = deploy("L1_ERC1155_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + /*************************** + * L2: 1st pass deployment * + **************************/ + + function deployL2MessageQueue() internal { + bytes memory args = abi.encode(DEPLOYER_ADDR); + L2_MESSAGE_QUEUE_ADDR = deploy("L2_MESSAGE_QUEUE", type(L2MessageQueue).creationCode, args); + } + + function deployL1GasPriceOracle() internal { + bytes memory args = abi.encode(DEPLOYER_ADDR); + L1_GAS_PRICE_ORACLE_ADDR = deploy("L1_GAS_PRICE_ORACLE", type(L1GasPriceOracle).creationCode, args); + } + + function deployL2Whitelist() internal { + bytes memory args = abi.encode(DEPLOYER_ADDR); + L2_WHITELIST_ADDR = deploy("L2_WHITELIST", type(Whitelist).creationCode, args); + } + + function deployL2Weth() internal { + L2_WETH_ADDR = deploy("L2_WETH", type(WrappedEther).creationCode); + } + + function deployTxFeeVault() internal { + bytes memory args = abi.encode( + DEPLOYER_ADDR, + L1_FEE_VAULT_ADDR, + 10 ether + ); + + L2_TX_FEE_VAULT_ADDR = deploy("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); + } + + function deployL2ProxyAdmin() internal { + bytes memory args = abi.encode(DEPLOYER_ADDR); + L2_PROXY_ADMIN_ADDR = deploy("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + } + + function deployL2PlaceHolder() internal { + L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy("L2_PROXY_IMPLEMENTATION_PLACEHOLDER", type(EmptyContract).creationCode); + } + + function deployL2ScrollMessengerProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_SCROLL_MESSENGER_PROXY_ADDR = deploy("L2_SCROLL_MESSENGER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2StandardERC20GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = deploy("L2_STANDARD_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2ETHGatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_ETH_GATEWAY_PROXY_ADDR = deploy("L2_ETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2WETHGatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_WETH_GATEWAY_PROXY_ADDR = deploy("L2_WETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2CustomERC20GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = deploy("L2_CUSTOM_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2ERC721GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_ERC721_GATEWAY_PROXY_ADDR = deploy("L2_ERC721_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2ERC1155GatewayProxy() internal { + bytes memory args = abi.encode( + notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_ERC1155_GATEWAY_PROXY_ADDR = deploy("L2_ERC1155_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployScrollStandardERC20Factory() internal { + L2_SCROLL_STANDARD_ERC20_ADDR = deploy("L2_SCROLL_STANDARD_ERC20", type(ScrollStandardERC20).creationCode); + + bytes memory args = abi.encode( + DEPLOYER_ADDR, + notnull(L2_SCROLL_STANDARD_ERC20_ADDR) + ); + + L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = deploy("L2_SCROLL_STANDARD_ERC20_FACTORY", type(ScrollStandardERC20FactorySetOwner).creationCode, args); + } + + /*************************** + * L1: 2nd pass deployment * + **************************/ + + function deployL1ScrollMessenger() internal { + bytes memory args = abi.encode( + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L1_SCROLL_CHAIN_PROXY_ADDR), + notnull(L1_MESSAGE_QUEUE_PROXY_ADDR) + ); + + L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy("L1_SCROLL_MESSENGER_IMPLEMENTATION", type(L1ScrollMessenger).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)), + notnull(L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) + ); + } + + function deployL1ETHGateway() internal { + bytes memory args = abi.encode( + notnull(L2_ETH_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + + L1_ETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ETH_GATEWAY_IMPLEMENTATION", type(L1ETHGateway).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_ETH_GATEWAY_PROXY_ADDR)), + notnull(L1_ETH_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL1WETHGateway() internal { + bytes memory args = abi.encode( + notnull(L1_WETH_ADDR), + notnull(L2_WETH_ADDR), + notnull(L2_WETH_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + + L1_WETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_WETH_GATEWAY_IMPLEMENTATION", type(L1WETHGateway).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_WETH_GATEWAY_PROXY_ADDR)), + notnull(L1_WETH_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL1StandardERC20Gateway() internal { + bytes memory args = abi.encode( + notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L2_SCROLL_STANDARD_ERC20_ADDR), + notnull(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) + ); + + L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION", type(L1StandardERC20Gateway).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR)), + notnull(L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL1CustomERC20Gateway() internal { + bytes memory args = abi.encode( + notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + + L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION", type(L1CustomERC20Gateway).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR)), + notnull(L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL1ERC721Gateway() internal { + bytes memory args = abi.encode(notnull(L2_ERC721_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); + + L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ERC721_GATEWAY_IMPLEMENTATION", type(L1ERC721Gateway).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_ERC721_GATEWAY_PROXY_ADDR)), + notnull(L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL1ERC1155Gateway() internal { + bytes memory args = abi.encode(notnull(L2_ERC1155_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); + + L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ERC1155_GATEWAY_IMPLEMENTATION", type(L1ERC1155Gateway).creationCode, args); + + ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L1_ERC1155_GATEWAY_PROXY_ADDR)), + notnull(L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + /*************************** + * L2: 2nd pass deployment * + **************************/ + + function deployL2ScrollMessenger() internal { + bytes memory args = abi.encode(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), notnull(L2_MESSAGE_QUEUE_ADDR)); + + L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy("L2_SCROLL_MESSENGER_IMPLEMENTATION", type(L2ScrollMessenger).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)), + notnull(L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) + ); + } + + function deployL2GatewayRouter() internal { + L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy("L2_GATEWAY_ROUTER_IMPLEMENTATION", type(L2GatewayRouter).creationCode); + + bytes memory args = abi.encode( + notnull(L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR), + notnull(L2_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + L2_GATEWAY_ROUTER_PROXY_ADDR = deploy("L2_GATEWAY_ROUTER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployL2StandardERC20Gateway() internal { + bytes memory args = abi.encode( + notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) + ); + + L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION", type(L2StandardERC20Gateway).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR)), + notnull(L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL2ETHGateway() internal { + bytes memory args = abi.encode( + notnull(L1_ETH_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + + L2_ETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_ETH_GATEWAY_IMPLEMENTATION", type(L2ETHGateway).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_ETH_GATEWAY_PROXY_ADDR)), + notnull(L2_ETH_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL2WETHGateway() internal { + bytes memory args = abi.encode( + notnull(L2_WETH_ADDR), + notnull(L1_WETH_ADDR), + notnull(L1_WETH_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + + L2_WETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_WETH_GATEWAY_IMPLEMENTATION", type(L2WETHGateway).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_WETH_GATEWAY_PROXY_ADDR)), + notnull(L2_WETH_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL2CustomERC20Gateway() internal { + bytes memory args = abi.encode( + notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + + L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION", type(L2CustomERC20Gateway).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR)), + notnull(L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL2ERC721Gateway() internal { + bytes memory args = abi.encode(notnull(L1_ERC721_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); + + L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_ERC721_GATEWAY_IMPLEMENTATION", type(L2ERC721Gateway).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_ERC721_GATEWAY_PROXY_ADDR)), + notnull(L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + function deployL2ERC1155Gateway() internal { + bytes memory args = abi.encode(notnull(L1_ERC1155_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); + + L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_ERC1155_GATEWAY_IMPLEMENTATION", type(L2ERC1155Gateway).creationCode, args); + + ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( + ITransparentUpgradeableProxy(notnull(L2_ERC1155_GATEWAY_PROXY_ADDR)), + notnull(L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR) + ); + } + + /********************** + * L1: initialization * + *********************/ + + function initializeScrollChain() internal { + ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).initialize( + notnull(L1_MESSAGE_QUEUE_PROXY_ADDR), + notnull(L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR), + MAX_TX_IN_CHUNK + ); + + ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addSequencer(L1_COMMIT_SENDER_ADDR); + ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addProver(L1_FINALIZE_SENDER_ADDR); + } + + function initializeL2GasPriceOracle() internal { + L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).initialize( + 21000, // _txGas + 53000, // _txGasContractCreation + 4, // _zeroGas + 16 // _nonZeroGas + ); + + L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).updateWhitelist(L1_WHITELIST_ADDR); + } + + function initializeL1MessageQueue() internal { + L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initialize( + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L1_SCROLL_CHAIN_PROXY_ADDR), + notnull(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR), + notnull(L2_GAS_PRICE_ORACLE_PROXY_ADDR), + MAX_L1_MESSAGE_GAS_LIMIT + ); + + L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initializeV2(); + } + + function initializeL1ScrollMessenger() internal { + L1ScrollMessenger(payable(L1_SCROLL_MESSENGER_PROXY_ADDR)).initialize( + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L1_FEE_VAULT_ADDR), + notnull(L1_SCROLL_CHAIN_PROXY_ADDR), + notnull(L1_MESSAGE_QUEUE_PROXY_ADDR) + ); + } + + function initializeEnforcedTxGateway() internal { + EnforcedTxGateway(payable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR)).initialize( + notnull(L1_MESSAGE_QUEUE_PROXY_ADDR), + notnull(L1_FEE_VAULT_ADDR) + ); + + // disable gateway + EnforcedTxGateway(payable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR)).setPause(true); + } + + function initializeL1GatewayRouter() internal { + L1GatewayRouter(L1_GATEWAY_ROUTER_PROXY_ADDR).initialize( + notnull(L1_ETH_GATEWAY_PROXY_ADDR), + notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR) + ); + } + + function initializeL1CustomERC20Gateway() internal { + L1CustomERC20Gateway(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize( + notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL1ERC1155Gateway() internal { + L1ERC1155Gateway(L1_ERC1155_GATEWAY_PROXY_ADDR).initialize( + notnull(L2_ERC1155_GATEWAY_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL1ERC721Gateway() internal { + L1ERC721Gateway(L1_ERC721_GATEWAY_PROXY_ADDR).initialize( + notnull(L2_ERC721_GATEWAY_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL1ETHGateway() internal { + L1ETHGateway(L1_ETH_GATEWAY_PROXY_ADDR).initialize( + notnull(L2_ETH_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL1StandardERC20Gateway() internal { + L1StandardERC20Gateway(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize( + notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L2_SCROLL_STANDARD_ERC20_ADDR), + notnull(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) + ); + } + + function initializeL1WETHGateway() internal { + L1WETHGateway(payable(L1_WETH_GATEWAY_PROXY_ADDR)).initialize( + notnull(L2_WETH_GATEWAY_PROXY_ADDR), + notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) + ); + + // set WETH gateway in router + { + address[] memory _tokens = new address[](1); + _tokens[0] = notnull(L1_WETH_ADDR); + address[] memory _gateways = new address[](1); + _gateways[0] = notnull(L1_WETH_GATEWAY_PROXY_ADDR); + L1GatewayRouter(L1_GATEWAY_ROUTER_PROXY_ADDR).setERC20Gateway(_tokens, _gateways); + } + } + + function initializeL1Whitelist() internal { + address[] memory accounts = new address[](1); + accounts[0] = L1_GAS_PRICE_ORACLE_SENDER_ADDR; + Whitelist(L1_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); + } + + /********************** + * L2: initialization * + *********************/ + + function initializeL2MessageQueue() internal { + L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).initialize(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); + } + + function initializeL2TxFeeVault() internal { + L2TxFeeVault(payable(L2_TX_FEE_VAULT_ADDR)).updateMessenger(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); + } + + function initializeL1GasPriceOracle() internal { + L1GasPriceOracle(L1_GAS_PRICE_ORACLE_ADDR).updateWhitelist(notnull(L2_WHITELIST_ADDR)); + } + + function initializeL2ScrollMessenger() internal { + L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).initialize(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); + } + + function initializeL2GatewayRouter() internal { + L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).initialize( + notnull(L2_ETH_GATEWAY_PROXY_ADDR), + notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR) + ); + } + + function initializeL2CustomERC20Gateway() internal { + L2CustomERC20Gateway(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize( + notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL2ERC1155Gateway() internal { + L2ERC1155Gateway(L2_ERC1155_GATEWAY_PROXY_ADDR).initialize( + notnull(L1_ERC1155_GATEWAY_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL2ERC721Gateway() internal { + L2ERC721Gateway(L2_ERC721_GATEWAY_PROXY_ADDR).initialize( + notnull(L1_ERC721_GATEWAY_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL2ETHGateway() internal { + L2ETHGateway(L2_ETH_GATEWAY_PROXY_ADDR).initialize( + notnull(L1_ETH_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + } + + function initializeL2StandardERC20Gateway() internal { + L2StandardERC20Gateway(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize( + notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) + ); + } + + function initializeL2WETHGateway() internal { + L2WETHGateway(payable(L2_WETH_GATEWAY_PROXY_ADDR)).initialize( + notnull(L1_WETH_GATEWAY_PROXY_ADDR), + notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), + notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) + ); + + // set WETH gateway in router + { + address[] memory _tokens = new address[](1); + _tokens[0] = notnull(L2_WETH_ADDR); + address[] memory _gateways = new address[](1); + _gateways[0] = notnull(L2_WETH_GATEWAY_PROXY_ADDR); + L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).setERC20Gateway(_tokens, _gateways); + } + } + + function initializeScrollStandardERC20Factory() internal { + ScrollStandardERC20Factory(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR).transferOwnership( + notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR) + ); + } + + function initializeL2Whitelist() internal { + address[] memory accounts = new address[](1); + accounts[0] = L2_GAS_PRICE_ORACLE_SENDER_ADDR; + Whitelist(L2_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); + } +} From 5c42eb381bd4c5783a1504e8dcce55857ffb7cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Thu, 25 Apr 2024 18:12:42 +0800 Subject: [PATCH 02/38] disable bytecode_hash --- contracts/foundry.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 3ea34d7a48..bbf66c3b37 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -27,4 +27,7 @@ block_coinbase = '0x0000000000000000000000000000000000000000' # the address of ` block_timestamp = 0 # the value of `block.timestamp` in tests block_difficulty = 0 # the value of `block.difficulty` in tests +# remove bytecode hash for reliable deterministic addresses +bytecode_hash = "none" + gas_reports = ["L2GasPriceOracle"] From 6eb58c10975d6375be708370d0e9487feccd0a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Thu, 25 Apr 2024 18:14:14 +0800 Subject: [PATCH 03/38] rename param --- contracts/scripts/foundry/DeployScroll.s.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index e888112731..3db6121a30 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -222,8 +222,8 @@ contract DeployScroll is DeterminsticDeploymentScript { // accounts address L1_COMMIT_SENDER_ADDR = vm.envAddress("L1_COMMIT_SENDER_ADDR"); address L1_FINALIZE_SENDER_ADDR = vm.envAddress("L1_FINALIZE_SENDER_ADDR"); - address L1_GAS_PRICE_ORACLE_SENDER_ADDR = vm.envAddress("L1_GAS_PRICE_ORACLE_SENDER_ADDR"); - address L2_GAS_PRICE_ORACLE_SENDER_ADDR = vm.envAddress("L2_GAS_PRICE_ORACLE_SENDER_ADDR"); + address L1_GAS_ORACLE_SENDER_ADDR = vm.envAddress("L1_GAS_ORACLE_SENDER_ADDR"); + address L2_GAS_ORACLE_SENDER_ADDR = vm.envAddress("L2_GAS_ORACLE_SENDER_ADDR"); address DEPLOYER_ADDR; // implicit, derived from private key / wallet @@ -1047,7 +1047,7 @@ contract DeployScroll is DeterminsticDeploymentScript { function initializeL1Whitelist() internal { address[] memory accounts = new address[](1); - accounts[0] = L1_GAS_PRICE_ORACLE_SENDER_ADDR; + accounts[0] = L1_GAS_ORACLE_SENDER_ADDR; Whitelist(L1_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); } @@ -1142,7 +1142,7 @@ contract DeployScroll is DeterminsticDeploymentScript { function initializeL2Whitelist() internal { address[] memory accounts = new address[](1); - accounts[0] = L2_GAS_PRICE_ORACLE_SENDER_ADDR; + accounts[0] = L2_GAS_ORACLE_SENDER_ADDR; Whitelist(L2_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); } } From 491aa9136966a02105e23849d693100480e0abf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 15:30:30 +0800 Subject: [PATCH 04/38] use toml config file --- contracts/configuration/config-contracts.toml | 55 ++ contracts/configuration/config.toml | 41 ++ contracts/foundry.toml | 11 +- contracts/scripts/foundry/DeployScroll.s.sol | 643 ++++++++++++++---- 4 files changed, 612 insertions(+), 138 deletions(-) create mode 100644 contracts/configuration/config-contracts.toml create mode 100644 contracts/configuration/config.toml diff --git a/contracts/configuration/config-contracts.toml b/contracts/configuration/config-contracts.toml new file mode 100644 index 0000000000..b0681a0ec7 --- /dev/null +++ b/contracts/configuration/config-contracts.toml @@ -0,0 +1,55 @@ +L1_WETH_ADDR = "" +L1_PROXY_ADMIN_ADDR = "" +L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = "" +L1_WHITELIST_ADDR = "" +L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR = "" +L2_GAS_PRICE_ORACLE_PROXY_ADDR = "" +L1_SCROLL_CHAIN_PROXY_ADDR = "" +L1_SCROLL_MESSENGER_PROXY_ADDR = "" +L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = "" +L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = "" +L1_ZKEVM_VERIFIER_V1_ADDR = "" +L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR = "" +L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = "" +L1_MESSAGE_QUEUE_PROXY_ADDR = "" +L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = "" +L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = "" +L1_GATEWAY_ROUTER_PROXY_ADDR = "" +L1_ETH_GATEWAY_PROXY_ADDR = "" +L1_WETH_GATEWAY_PROXY_ADDR = "" +L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = "" +L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = "" +L1_ERC721_GATEWAY_PROXY_ADDR = "" +L1_ERC1155_GATEWAY_PROXY_ADDR = "" +L2_MESSAGE_QUEUE_ADDR = "" +L1_GAS_PRICE_ORACLE_ADDR = "" +L2_WHITELIST_ADDR = "" +L2_WETH_ADDR = "" +L2_TX_FEE_VAULT_ADDR = "" +L2_PROXY_ADMIN_ADDR = "" +L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = "" +L2_SCROLL_MESSENGER_PROXY_ADDR = "" +L2_ETH_GATEWAY_PROXY_ADDR = "" +L2_WETH_GATEWAY_PROXY_ADDR = "" +L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = "" +L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = "" +L2_ERC721_GATEWAY_PROXY_ADDR = "" +L2_ERC1155_GATEWAY_PROXY_ADDR = "" +L2_SCROLL_STANDARD_ERC20_ADDR = "" +L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = "" +L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = "" +L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = "" +L1_ETH_GATEWAY_IMPLEMENTATION_ADDR = "" +L1_WETH_GATEWAY_IMPLEMENTATION_ADDR = "" +L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = "" +L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR = "" +L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = "" +L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = "" +L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = "" +L2_GATEWAY_ROUTER_PROXY_ADDR = "" +L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = "" +L2_ETH_GATEWAY_IMPLEMENTATION_ADDR = "" +L2_WETH_GATEWAY_IMPLEMENTATION_ADDR = "" +L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = "" +L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR = "" +L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = "" diff --git a/contracts/configuration/config.toml b/contracts/configuration/config.toml new file mode 100644 index 0000000000..729f68dab9 --- /dev/null +++ b/contracts/configuration/config.toml @@ -0,0 +1,41 @@ +[contracts] + +SALT_PREFIX = "" + +CHAIN_ID_L2 = 222222 +MAX_TX_IN_CHUNK = 100 +MAX_L1_MESSAGE_GAS_LIMIT = 10000 + +DEPLOYER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +OWNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" + + +L1_COMMIT_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L1_FINALIZE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L1_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L2_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" + +DEPLOYER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +OWNER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" + +# // contracts deployed outside this script +L1_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000001" +L1_PLONK_VERIFIER_ADDR = "0x0000000000000000000000000000000000000001" + + +L2_MESSAGE_QUEUE_OVERRIDE = "0x5300000000000000000000000000000000000000" +L1_GAS_PRICE_ORACLE_OVERRIDE = "0x5300000000000000000000000000000000000002" +L2_WHITELIST_OVERRIDE = "0x5300000000000000000000000000000000000003" +L2_WETH_OVERRIDE = "0x5300000000000000000000000000000000000004" +L2_TX_FEE_VAULT_OVERRIDE = "0x5300000000000000000000000000000000000005" + +L1_WETH_OVERRIDE = "0x5300000000000000000000000000000000000004" + + + +# export BROADCAST_LAYER = "L1" +# export FOUNDRY_EVM_VERSION="cancun" +# export FOUNDRY_BYTECODE_HASH="none" +# export L2_DEPLOYER_INITIAL_BALANCE="1" +# export L2_SCROLL_MESSENGER_INITIAL_BALANCE="1" +# export DEPLOYER_ADDR=0x00a329c0648769A73afAc7F9381E08FB43dBEA71 \ No newline at end of file diff --git a/contracts/foundry.toml b/contracts/foundry.toml index bbf66c3b37..c93a256e85 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -8,14 +8,13 @@ remappings = [] # a list of remapp libraries = [] # a list of deployed libraries to link against cache = true # whether to cache builds or not force = true # whether to ignore the cache (clean build) -# evm_version = 'london' # the evm version (by hardfork name) -solc_version = '0.8.24' # override for the solc version (setting this ignores `auto_detect_solc`) +evm_version = 'cancun' # the evm version (by hardfork name) +solc_version = '0.8.24' # override for the solc version (setting this ignores `auto_detect_solc`) optimizer = true # enable or disable the solc optimizer optimizer_runs = 200 # the number of optimizer runs verbosity = 2 # the verbosity of tests ignored_error_codes = [] # a list of ignored solc error codes fuzz_runs = 256 # the number of fuzz runs for tests -ffi = false # whether to enable ffi or not sender = '0x00a329c0648769a73afac7f9381e08fb43dbea72' # the address of `msg.sender` in tests tx_origin = '0x00a329c0648769a73afac7f9381e08fb43dbea72' # the address of `tx.origin` in tests initial_balance = '0xffffffffffffffffffffffff' # the initial balance of the test contract @@ -28,6 +27,10 @@ block_timestamp = 0 # the value of `bl block_difficulty = 0 # the value of `block.difficulty` in tests # remove bytecode hash for reliable deterministic addresses -bytecode_hash = "none" +bytecode_hash = 'none' + +# file system permissions +ffi = true +fs_permissions = [{ access='read-write', path='./configuration' }] gas_reports = ["L2GasPriceOracle"] diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 3db6121a30..2be111a616 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -3,9 +3,11 @@ pragma solidity =0.8.24; import {Script, console} from "forge-std/Script.sol"; import {VmSafe} from "forge-std/Vm.sol"; +import {stdToml} from "forge-std/StdToml.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {EmptyContract} from "../../src/misc/EmptyContract.sol"; @@ -47,6 +49,9 @@ address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920 /// @dev The default salt prefix used for deriving deterministic deployment addresses. string constant DEFAULT_SALT_PREFIX = "ScrollStack"; +string constant CONFIG_PATH = "./configuration/config.toml"; +string constant CONTRACTS_CONFIG_PATH = "./configuration/config-contracts.toml"; + contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise /// DeterministicDeploymentProxy would become the owner. @@ -55,6 +60,19 @@ contract ProxyAdminSetOwner is ProxyAdmin { } } +contract MultipleVersionRollupVerifierSetOwner is MultipleVersionRollupVerifier { + /// @dev allow setting the owner in the constructor, otherwise + /// DeterministicDeploymentProxy would become the owner. + constructor( + address owner, + address _scrollChain, + uint256[] memory _versions, + address[] memory _verifiers + ) MultipleVersionRollupVerifier(_scrollChain, _versions, _verifiers) { + _transferOwnership(owner); + } +} + contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory { /// @dev allow setting the owner in the constructor, otherwise /// DeterministicDeploymentProxy would become the owner. @@ -63,15 +81,94 @@ contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory { } } -contract DeterminsticDeploymentScript is Script { - string internal saltPrefix; +contract Configuration is Script { + using stdToml for string; + + enum ScriptMode { + LogAddresses, + WriteConfig, + VerifyConfig + } + + enum Layer { + None, + L1, + L2 + } + + string internal cfg; + string internal contractsCfg; + + ScriptMode internal mode = ScriptMode.LogAddresses; + + constructor() { + cfg = vm.readFile(CONFIG_PATH); + contractsCfg = vm.readFile(CONTRACTS_CONFIG_PATH); + } + + function parseScriptMode(string memory raw) internal pure returns (ScriptMode) { + if (keccak256(bytes(raw)) == keccak256(bytes("write-config"))) { + return ScriptMode.WriteConfig; + } else if (keccak256(bytes(raw)) == keccak256(bytes("verify-config"))) { + return ScriptMode.VerifyConfig; + } else { + return ScriptMode.LogAddresses; + } + } - constructor(string memory _saltPrefix) { - saltPrefix = _saltPrefix; + function parseLayer(string memory raw) internal pure returns (Layer) { + if (keccak256(bytes(raw)) == keccak256(bytes("L1"))) { + return Layer.L1; + } else if (keccak256(bytes(raw)) == keccak256(bytes("L2"))) { + return Layer.L2; + } else { + return Layer.None; + } } - function deploy(string memory name, bytes memory code) internal returns (address) { - return _deploy(name, code); + function _label(string memory name, address addr) internal { + vm.label(addr, name); + + if (mode == ScriptMode.LogAddresses) { + console.log(string(abi.encodePacked(name, "_ADDR=", vm.toString(address(addr))))); + } + + string memory tomlPath = string(abi.encodePacked(".", name, "_ADDR")); + + if (mode == ScriptMode.WriteConfig) { + vm.writeToml(vm.toString(addr), CONTRACTS_CONFIG_PATH, tomlPath); + } + + if (mode == ScriptMode.VerifyConfig) { + address expectedAddr = contractsCfg.readAddress(tomlPath); + + if (addr != expectedAddr) { + console.log( + string( + abi.encodePacked( + "[ERROR] unexpected address for ", + name, + ", expected = ", + vm.toString(expectedAddr), + " (from toml config), got = ", + vm.toString(addr) + ) + ) + ); + + revert(); + } + } + } +} + +contract DeterminsticDeploymentScript is Configuration { + using stdToml for string; + + string internal saltPrefix; + + function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { + return _deploy(name, codeWithArgs); } function deploy( @@ -82,29 +179,30 @@ contract DeterminsticDeploymentScript is Script { return _deploy(name, abi.encodePacked(code, args)); } + function predict(string memory name, bytes memory codeWithArgs) internal view returns (address) { + return _predict(name, codeWithArgs); + } + + function predict( + string memory name, + bytes memory code, + bytes memory args + ) internal view returns (address) { + return _predict(name, abi.encodePacked(code, args)); + } + function _deploy(string memory name, bytes memory codeWithArgs) private returns (address) { // check override (mainly used with predeploys) - address addr = vm.envOr(string(abi.encodePacked(name, "_OVERRIDE")), address(0)); + address addr = tryGetOverride(name); if (addr != address(0)) { - if (addr.code.length == 0) { - (VmSafe.CallerMode mode, , ) = vm.readCallers(); - - // if we're ready to start broadcasting transactions, then we - // must ensure that the override contract has been deployed. - if (mode == VmSafe.CallerMode.Broadcast || mode == VmSafe.CallerMode.RecurrentBroadcast) { - console.log(string(abi.encodePacked("[ERROR] ", name, "_OVERRIDE=", vm.toString(addr), " not deployed in broadcast mode"))); - revert(); - } - } - - logAddress(name, addr); + _label(name, addr); return addr; } // predict determinstic deployment address addr = _predict(name, codeWithArgs); - logAddress(name, addr); + _label(name, addr); // return if the contract is already deployed, // in this case the subsequent initialization steps will probably break @@ -123,6 +221,40 @@ contract DeterminsticDeploymentScript is Script { return addr; } + function tryGetOverride(string memory name) private returns (address) { + address addr; + string memory key = string(abi.encodePacked(".contracts.", name, "_OVERRIDE")); + + if (!vm.keyExistsToml(cfg, key)) { + return address(0); + } + + addr = cfg.readAddress(key); + + if (addr.code.length == 0) { + (VmSafe.CallerMode callerMode, , ) = vm.readCallers(); + + // if we're ready to start broadcasting transactions, then we + // must ensure that the override contract has been deployed. + if (callerMode == VmSafe.CallerMode.Broadcast || callerMode == VmSafe.CallerMode.RecurrentBroadcast) { + console.log( + string( + abi.encodePacked( + "[ERROR] ", + name, + "_OVERRIDE=", + vm.toString(addr), + " not deployed in broadcast mode" + ) + ) + ); + revert(); + } + } + + return addr; + } + function _getSalt(string memory name) internal view returns (bytes32) { return keccak256(abi.encodePacked(saltPrefix, name)); } @@ -130,20 +262,84 @@ contract DeterminsticDeploymentScript is Script { function _predict(string memory name, bytes memory codeWithArgs) private view returns (address) { bytes32 salt = _getSalt(name); - return address(uint160(uint256(keccak256(abi.encodePacked( - bytes1(0xff), - DETERMINISTIC_DEPLOYMENT_PROXY_ADDR, - salt, - keccak256(codeWithArgs) - ))))); - } - - function logAddress(string memory name, address addr) internal view { - console.log(string(abi.encodePacked(name, "_ADDR=", vm.toString(address(addr))))); + return + address( + uint160( + uint256( + keccak256( + abi.encodePacked( + bytes1(0xff), + DETERMINISTIC_DEPLOYMENT_PROXY_ADDR, + salt, + keccak256(codeWithArgs) + ) + ) + ) + ) + ); } } contract DeployScroll is DeterminsticDeploymentScript { + using stdToml for string; + + /*************************** + * Configuration parameters * + ***************************/ + + // general configurations + Layer BROADCAST_LAYER; + + string SALT_PREFIX; + uint64 CHAIN_ID_L2; + uint256 MAX_TX_IN_CHUNK; + uint256 MAX_L1_MESSAGE_GAS_LIMIT; + + // accounts + uint256 DEPLOYER_PRIVATE_KEY; + address DEPLOYER_ADDR; + + address OWNER_ADDR; + + address L1_COMMIT_SENDER_ADDR; + address L1_FINALIZE_SENDER_ADDR; + address L1_GAS_ORACLE_SENDER_ADDR; + address L2_GAS_ORACLE_SENDER_ADDR; + + // contracts deployed outside this script + address L1_FEE_VAULT_ADDR; + address L1_PLONK_VERIFIER_ADDR; + + function initConfig() private { + CHAIN_ID_L2 = uint64(cfg.readUint(".contracts.CHAIN_ID_L2")); + MAX_TX_IN_CHUNK = cfg.readUint(".contracts.MAX_TX_IN_CHUNK"); + MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".contracts.MAX_L1_MESSAGE_GAS_LIMIT"); + + DEPLOYER_PRIVATE_KEY = cfg.readUint(".contracts.DEPLOYER_PRIVATE_KEY"); + DEPLOYER_ADDR = cfg.readAddress(".contracts.DEPLOYER_ADDR"); + + // config sanity check + if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { + console.log(string(abi.encodePacked("[ERROR] DEPLOYER_ADDR does not match DEPLOYER_PRIVATE_KEY"))); + revert(); + } + + OWNER_ADDR = cfg.readAddress(".contracts.OWNER_ADDR"); + + L1_COMMIT_SENDER_ADDR = cfg.readAddress(".contracts.L1_COMMIT_SENDER_ADDR"); + L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".contracts.L1_FINALIZE_SENDER_ADDR"); + L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".contracts.L1_GAS_ORACLE_SENDER_ADDR"); + L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".contracts.L2_GAS_ORACLE_SENDER_ADDR"); + + L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); + L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); + + saltPrefix = cfg.readString(".contracts.SALT_PREFIX"); + if (bytes(saltPrefix).length == 0) { + saltPrefix = DEFAULT_SALT_PREFIX; + } + } + /********************** * Contracts to deploy * **********************/ @@ -207,53 +403,21 @@ contract DeployScroll is DeterminsticDeploymentScript { address L2_WETH_GATEWAY_PROXY_ADDR; address L2_WHITELIST_ADDR; - /*************************** - * Configuration parameters * - ***************************/ - - // general configurations - uint64 CHAIN_ID_L2 = uint64(vm.envUint("CHAIN_ID_L2")); - uint256 MAX_TX_IN_CHUNK = vm.envUint("MAX_TX_IN_CHUNK"); - uint256 MAX_L1_MESSAGE_GAS_LIMIT = vm.envUint("MAX_L1_MESSAGE_GAS_LIMIT"); - - string SALT_PREFIX = vm.envOr("SALT_PREFIX", DEFAULT_SALT_PREFIX); - string BROADCAST_LAYER = vm.envOr("BROADCAST_LAYER", string("")); - - // accounts - address L1_COMMIT_SENDER_ADDR = vm.envAddress("L1_COMMIT_SENDER_ADDR"); - address L1_FINALIZE_SENDER_ADDR = vm.envAddress("L1_FINALIZE_SENDER_ADDR"); - address L1_GAS_ORACLE_SENDER_ADDR = vm.envAddress("L1_GAS_ORACLE_SENDER_ADDR"); - address L2_GAS_ORACLE_SENDER_ADDR = vm.envAddress("L2_GAS_ORACLE_SENDER_ADDR"); - - address DEPLOYER_ADDR; // implicit, derived from private key / wallet - - // contracts deployed outside this script - address L1_FEE_VAULT_ADDR = vm.envAddress("L1_FEE_VAULT_ADDR"); - address L1_PLONK_VERIFIER_ADDR = vm.envAddress("L1_PLONK_VERIFIER_ADDR"); - - /************** - * Constructor * - **************/ - - constructor() DeterminsticDeploymentScript(SALT_PREFIX) { - // empty - } - /************ * Utilities * ************/ /// @dev Ensure that `addr` is not the zero address. /// This helps catch bugs arising from incorrect deployment order. - function notnull(address addr) internal returns (address) { + function notnull(address addr) internal pure returns (address) { require(addr != address(0), "null address"); return addr; } /// @dev Only broadcast code block if we run the script on the specified layer. - modifier broadcast(string memory layer) { - if (keccak256(bytes(BROADCAST_LAYER)) == keccak256(bytes(layer))) { - vm.startBroadcast(); + modifier broadcast(Layer layer) { + if (BROADCAST_LAYER == layer) { + vm.startBroadcast(DEPLOYER_PRIVATE_KEY); } else { // make sure we use the correct sender in simulation vm.startPrank(DEPLOYER_ADDR); @@ -261,7 +425,7 @@ contract DeployScroll is DeterminsticDeploymentScript { _; - if (keccak256(bytes(BROADCAST_LAYER)) == keccak256(bytes(layer))) { + if (BROADCAST_LAYER == layer) { vm.stopBroadcast(); } else { vm.stopPrank(); @@ -269,8 +433,8 @@ contract DeployScroll is DeterminsticDeploymentScript { } /// @dev Only execute block if we run the script on the specified layer. - modifier only(string memory layer) { - if (keccak256(bytes(BROADCAST_LAYER)) != keccak256(bytes(layer))) { + modifier only(Layer layer) { + if (BROADCAST_LAYER != layer) { return; } _; @@ -280,15 +444,25 @@ contract DeployScroll is DeterminsticDeploymentScript { * Deployment entry point * *************************/ - function run() public { - DEPLOYER_ADDR = msg.sender; - logAddress("DEPLOYER", DEPLOYER_ADDR); + function run(string memory layer, string memory scriptMode) public { + BROADCAST_LAYER = parseLayer(layer); + mode = parseScriptMode(scriptMode); if (DETERMINISTIC_DEPLOYMENT_PROXY_ADDR.code.length == 0) { - console.log(string(abi.encodePacked("[ERROR] DeterministicDeploymentProxy (", vm.toString(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR), ") is not available"))); + console.log( + string( + abi.encodePacked( + "[ERROR] DeterministicDeploymentProxy (", + vm.toString(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR), + ") is not available" + ) + ) + ); revert(); } + initConfig(); + deployL1Contracts1stPass(); deployL2Contracts1stPass(); deployL1Contracts2ndPass(); @@ -298,7 +472,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL1Contracts1stPass deploys L1 contracts whose initialization does not depend on any L2 addresses. - function deployL1Contracts1stPass() internal broadcast("L1") { + function deployL1Contracts1stPass() internal broadcast(Layer.L1) { deployL1Weth(); deployL1ProxyAdmin(); deployL1PlaceHolder(); @@ -321,7 +495,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL2Contracts1stPass deploys L2 contracts whose initialization does not depend on any L1 addresses. - function deployL2Contracts1stPass() internal broadcast("L2") { + function deployL2Contracts1stPass() internal broadcast(Layer.L2) { deployL2MessageQueue(); deployL1GasPriceOracle(); deployL2Whitelist(); @@ -340,7 +514,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL1Contracts2ndPass deploys L1 contracts whose initialization depends on some L2 addresses. - function deployL1Contracts2ndPass() internal broadcast("L1") { + function deployL1Contracts2ndPass() internal broadcast(Layer.L1) { deployL1ScrollMessenger(); deployL1StandardERC20Gateway(); deployL1ETHGateway(); @@ -351,7 +525,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL2Contracts2ndPass deploys L2 contracts whose initialization depends on some L1 addresses. - function deployL2Contracts2ndPass() internal broadcast("L2") { + function deployL2Contracts2ndPass() internal broadcast(Layer.L2) { // upgradable deployL2ScrollMessenger(); deployL2GatewayRouter(); @@ -364,7 +538,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice initializeL1Contracts initializes contracts deployed on L1. - function initializeL1Contracts() internal broadcast("L1") only("L1") { + function initializeL1Contracts() internal broadcast(Layer.L1) only(Layer.L1) { initializeScrollChain(); initializeL2GasPriceOracle(); initializeL1MessageQueue(); @@ -378,10 +552,12 @@ contract DeployScroll is DeterminsticDeploymentScript { initializeL1StandardERC20Gateway(); initializeL1WETHGateway(); initializeL1Whitelist(); + + transferL1ContractOwnership(); } // @notice initializeL2Contracts initializes contracts deployed on L2. - function initializeL2Contracts() internal broadcast("L2") only("L2") { + function initializeL2Contracts() internal broadcast(Layer.L2) only(Layer.L2) { initializeL2MessageQueue(); initializeL2TxFeeVault(); initializeL1GasPriceOracle(); @@ -395,6 +571,8 @@ contract DeployScroll is DeterminsticDeploymentScript { initializeL2WETHGateway(); initializeScrollStandardERC20Factory(); initializeL2Whitelist(); + + transferL2ContractOwnership(); } /*************************** @@ -411,7 +589,10 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployL1PlaceHolder() internal { - L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy("L1_PROXY_IMPLEMENTATION_PLACEHOLDER", type(EmptyContract).creationCode); + L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy( + "L1_PROXY_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); } function deployL1Whitelist() internal { @@ -420,7 +601,10 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployL2GasPriceOracle() internal { - L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR = deploy("L2_GAS_PRICE_ORACLE_IMPLEMENTATION", type(L2GasPriceOracle).creationCode); + L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR = deploy( + "L2_GAS_PRICE_ORACLE_IMPLEMENTATION", + type(L2GasPriceOracle).creationCode + ); bytes memory args = abi.encode( notnull(L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR), @@ -428,7 +612,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_GAS_PRICE_ORACLE_PROXY_ADDR = deploy("L2_GAS_PRICE_ORACLE_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_GAS_PRICE_ORACLE_PROXY_ADDR = deploy( + "L2_GAS_PRICE_ORACLE_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1ScrollChainProxy() internal { @@ -438,7 +626,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_SCROLL_CHAIN_PROXY_ADDR = deploy("L1_SCROLL_CHAIN_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_SCROLL_CHAIN_PROXY_ADDR = deploy( + "L1_SCROLL_CHAIN_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1ScrollMessengerProxy() internal { @@ -448,11 +640,18 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_SCROLL_MESSENGER_PROXY_ADDR = deploy("L1_SCROLL_MESSENGER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_SCROLL_MESSENGER_PROXY_ADDR = deploy( + "L1_SCROLL_MESSENGER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1EnforcedTxGateway() internal { - L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION", type(EnforcedTxGateway).creationCode); + L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION", + type(EnforcedTxGateway).creationCode + ); bytes memory args = abi.encode( notnull(L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR), @@ -460,11 +659,14 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = deploy("L1_ENFORCED_TX_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = deploy( + "L1_ENFORCED_TX_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1ZkEvmVerifierV1() internal { - logAddress("L1_PLONK_VERIFIER", L1_PLONK_VERIFIER_ADDR); bytes memory args = abi.encode(notnull(L1_PLONK_VERIFIER_ADDR)); L1_ZKEVM_VERIFIER_V1_ADDR = deploy("L1_ZKEVM_VERIFIER_V1", type(ZkEvmVerifierV1).creationCode, args); } @@ -475,8 +677,13 @@ contract DeployScroll is DeterminsticDeploymentScript { _versions[0] = 1; _verifiers[0] = notnull(L1_ZKEVM_VERIFIER_V1_ADDR); - bytes memory args = abi.encode(notnull(L1_SCROLL_CHAIN_PROXY_ADDR), _versions, _verifiers); - L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR = deploy("L1_MULTIPLE_VERSION_ROLLUP_VERIFIER", type(MultipleVersionRollupVerifier).creationCode, args); + bytes memory args = abi.encode(DEPLOYER_ADDR, notnull(L1_SCROLL_CHAIN_PROXY_ADDR), _versions, _verifiers); + + L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR = deploy( + "L1_MULTIPLE_VERSION_ROLLUP_VERIFIER", + type(MultipleVersionRollupVerifierSetOwner).creationCode, + args + ); } function deployL1MessageQueue() internal { @@ -486,7 +693,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR) ); - L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = deploy("L1_MESSAGE_QUEUE_IMPLEMENTATION", type(L1MessageQueueWithGasPriceOracle).creationCode, args); + L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = deploy( + "L1_MESSAGE_QUEUE_IMPLEMENTATION", + type(L1MessageQueueWithGasPriceOracle).creationCode, + args + ); bytes memory args2 = abi.encode( notnull(L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR), @@ -494,7 +705,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_MESSAGE_QUEUE_PROXY_ADDR = deploy("L1_MESSAGE_QUEUE_PROXY", type(TransparentUpgradeableProxy).creationCode, args2); + L1_MESSAGE_QUEUE_PROXY_ADDR = deploy( + "L1_MESSAGE_QUEUE_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args2 + ); } function deployL1ScrollChain() internal { @@ -504,7 +719,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR) ); - L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = deploy("L1_SCROLL_CHAIN_IMPLEMENTATION", type(ScrollChain).creationCode, args); + L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = deploy( + "L1_SCROLL_CHAIN_IMPLEMENTATION", + type(ScrollChain).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_SCROLL_CHAIN_PROXY_ADDR)), @@ -513,7 +732,10 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployL1GatewayRouter() internal { - L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy("L1_GATEWAY_ROUTER_IMPLEMENTATION", type(L1GatewayRouter).creationCode); + L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy( + "L1_GATEWAY_ROUTER_IMPLEMENTATION", + type(L1GatewayRouter).creationCode + ); bytes memory args = abi.encode( notnull(L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR), @@ -521,7 +743,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_GATEWAY_ROUTER_PROXY_ADDR = deploy("L1_GATEWAY_ROUTER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_GATEWAY_ROUTER_PROXY_ADDR = deploy( + "L1_GATEWAY_ROUTER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1ETHGatewayProxy() internal { @@ -531,7 +757,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_ETH_GATEWAY_PROXY_ADDR = deploy("L1_ETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_ETH_GATEWAY_PROXY_ADDR = deploy( + "L1_ETH_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1WETHGatewayProxy() internal { @@ -541,7 +771,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_WETH_GATEWAY_PROXY_ADDR = deploy("L1_WETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_WETH_GATEWAY_PROXY_ADDR = deploy( + "L1_WETH_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1StandardERC20GatewayProxy() internal { @@ -551,7 +785,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = deploy("L1_STANDARD_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = deploy( + "L1_STANDARD_ERC20_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1CustomERC20GatewayProxy() internal { @@ -561,7 +799,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = deploy("L1_CUSTOM_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = deploy( + "L1_CUSTOM_ERC20_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1ERC721GatewayProxy() internal { @@ -571,7 +813,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_ERC721_GATEWAY_PROXY_ADDR = deploy("L1_ERC721_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_ERC721_GATEWAY_PROXY_ADDR = deploy( + "L1_ERC721_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL1ERC1155GatewayProxy() internal { @@ -581,7 +827,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L1_ERC1155_GATEWAY_PROXY_ADDR = deploy("L1_ERC1155_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L1_ERC1155_GATEWAY_PROXY_ADDR = deploy( + "L1_ERC1155_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } /*************************** @@ -608,11 +858,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployTxFeeVault() internal { - bytes memory args = abi.encode( - DEPLOYER_ADDR, - L1_FEE_VAULT_ADDR, - 10 ether - ); + bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, 10 ether); L2_TX_FEE_VAULT_ADDR = deploy("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); } @@ -623,7 +869,10 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployL2PlaceHolder() internal { - L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy("L2_PROXY_IMPLEMENTATION_PLACEHOLDER", type(EmptyContract).creationCode); + L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy( + "L2_PROXY_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); } function deployL2ScrollMessengerProxy() internal { @@ -633,7 +882,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_SCROLL_MESSENGER_PROXY_ADDR = deploy("L2_SCROLL_MESSENGER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_SCROLL_MESSENGER_PROXY_ADDR = deploy( + "L2_SCROLL_MESSENGER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2StandardERC20GatewayProxy() internal { @@ -643,7 +896,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = deploy("L2_STANDARD_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = deploy( + "L2_STANDARD_ERC20_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2ETHGatewayProxy() internal { @@ -653,7 +910,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_ETH_GATEWAY_PROXY_ADDR = deploy("L2_ETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_ETH_GATEWAY_PROXY_ADDR = deploy( + "L2_ETH_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2WETHGatewayProxy() internal { @@ -663,7 +924,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_WETH_GATEWAY_PROXY_ADDR = deploy("L2_WETH_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_WETH_GATEWAY_PROXY_ADDR = deploy( + "L2_WETH_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2CustomERC20GatewayProxy() internal { @@ -673,7 +938,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = deploy("L2_CUSTOM_ERC20_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = deploy( + "L2_CUSTOM_ERC20_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2ERC721GatewayProxy() internal { @@ -683,7 +952,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_ERC721_GATEWAY_PROXY_ADDR = deploy("L2_ERC721_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_ERC721_GATEWAY_PROXY_ADDR = deploy( + "L2_ERC721_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2ERC1155GatewayProxy() internal { @@ -693,18 +966,23 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_ERC1155_GATEWAY_PROXY_ADDR = deploy("L2_ERC1155_GATEWAY_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_ERC1155_GATEWAY_PROXY_ADDR = deploy( + "L2_ERC1155_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployScrollStandardERC20Factory() internal { L2_SCROLL_STANDARD_ERC20_ADDR = deploy("L2_SCROLL_STANDARD_ERC20", type(ScrollStandardERC20).creationCode); - bytes memory args = abi.encode( - DEPLOYER_ADDR, - notnull(L2_SCROLL_STANDARD_ERC20_ADDR) - ); + bytes memory args = abi.encode(DEPLOYER_ADDR, notnull(L2_SCROLL_STANDARD_ERC20_ADDR)); - L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = deploy("L2_SCROLL_STANDARD_ERC20_FACTORY", type(ScrollStandardERC20FactorySetOwner).creationCode, args); + L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = deploy( + "L2_SCROLL_STANDARD_ERC20_FACTORY", + type(ScrollStandardERC20FactorySetOwner).creationCode, + args + ); } /*************************** @@ -718,7 +996,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L1_MESSAGE_QUEUE_PROXY_ADDR) ); - L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy("L1_SCROLL_MESSENGER_IMPLEMENTATION", type(L1ScrollMessenger).creationCode, args); + L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy( + "L1_SCROLL_MESSENGER_IMPLEMENTATION", + type(L1ScrollMessenger).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)), @@ -733,7 +1015,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) ); - L1_ETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ETH_GATEWAY_IMPLEMENTATION", type(L1ETHGateway).creationCode, args); + L1_ETH_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_ETH_GATEWAY_IMPLEMENTATION", + type(L1ETHGateway).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_ETH_GATEWAY_PROXY_ADDR)), @@ -750,7 +1036,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) ); - L1_WETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_WETH_GATEWAY_IMPLEMENTATION", type(L1WETHGateway).creationCode, args); + L1_WETH_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_WETH_GATEWAY_IMPLEMENTATION", + type(L1WETHGateway).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_WETH_GATEWAY_PROXY_ADDR)), @@ -767,7 +1057,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) ); - L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION", type(L1StandardERC20Gateway).creationCode, args); + L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION", + type(L1StandardERC20Gateway).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR)), @@ -782,7 +1076,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) ); - L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION", type(L1CustomERC20Gateway).creationCode, args); + L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION", + type(L1CustomERC20Gateway).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR)), @@ -793,7 +1091,11 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployL1ERC721Gateway() internal { bytes memory args = abi.encode(notnull(L2_ERC721_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); - L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ERC721_GATEWAY_IMPLEMENTATION", type(L1ERC721Gateway).creationCode, args); + L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_ERC721_GATEWAY_IMPLEMENTATION", + type(L1ERC721Gateway).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_ERC721_GATEWAY_PROXY_ADDR)), @@ -804,7 +1106,11 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployL1ERC1155Gateway() internal { bytes memory args = abi.encode(notnull(L2_ERC1155_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); - L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy("L1_ERC1155_GATEWAY_IMPLEMENTATION", type(L1ERC1155Gateway).creationCode, args); + L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L1_ERC1155_GATEWAY_IMPLEMENTATION", + type(L1ERC1155Gateway).creationCode, + args + ); ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L1_ERC1155_GATEWAY_PROXY_ADDR)), @@ -819,7 +1125,11 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployL2ScrollMessenger() internal { bytes memory args = abi.encode(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), notnull(L2_MESSAGE_QUEUE_ADDR)); - L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy("L2_SCROLL_MESSENGER_IMPLEMENTATION", type(L2ScrollMessenger).creationCode, args); + L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy( + "L2_SCROLL_MESSENGER_IMPLEMENTATION", + type(L2ScrollMessenger).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)), @@ -828,7 +1138,10 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployL2GatewayRouter() internal { - L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy("L2_GATEWAY_ROUTER_IMPLEMENTATION", type(L2GatewayRouter).creationCode); + L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy( + "L2_GATEWAY_ROUTER_IMPLEMENTATION", + type(L2GatewayRouter).creationCode + ); bytes memory args = abi.encode( notnull(L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR), @@ -836,7 +1149,11 @@ contract DeployScroll is DeterminsticDeploymentScript { new bytes(0) ); - L2_GATEWAY_ROUTER_PROXY_ADDR = deploy("L2_GATEWAY_ROUTER_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + L2_GATEWAY_ROUTER_PROXY_ADDR = deploy( + "L2_GATEWAY_ROUTER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); } function deployL2StandardERC20Gateway() internal { @@ -847,7 +1164,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) ); - L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION", type(L2StandardERC20Gateway).creationCode, args); + L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION", + type(L2StandardERC20Gateway).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR)), @@ -862,7 +1183,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) ); - L2_ETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_ETH_GATEWAY_IMPLEMENTATION", type(L2ETHGateway).creationCode, args); + L2_ETH_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L2_ETH_GATEWAY_IMPLEMENTATION", + type(L2ETHGateway).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_ETH_GATEWAY_PROXY_ADDR)), @@ -879,7 +1204,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) ); - L2_WETH_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_WETH_GATEWAY_IMPLEMENTATION", type(L2WETHGateway).creationCode, args); + L2_WETH_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L2_WETH_GATEWAY_IMPLEMENTATION", + type(L2WETHGateway).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_WETH_GATEWAY_PROXY_ADDR)), @@ -894,7 +1223,11 @@ contract DeployScroll is DeterminsticDeploymentScript { notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) ); - L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION", type(L2CustomERC20Gateway).creationCode, args); + L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION", + type(L2CustomERC20Gateway).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR)), @@ -905,7 +1238,11 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployL2ERC721Gateway() internal { bytes memory args = abi.encode(notnull(L1_ERC721_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); - L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_ERC721_GATEWAY_IMPLEMENTATION", type(L2ERC721Gateway).creationCode, args); + L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L2_ERC721_GATEWAY_IMPLEMENTATION", + type(L2ERC721Gateway).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_ERC721_GATEWAY_PROXY_ADDR)), @@ -916,7 +1253,11 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployL2ERC1155Gateway() internal { bytes memory args = abi.encode(notnull(L1_ERC1155_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); - L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy("L2_ERC1155_GATEWAY_IMPLEMENTATION", type(L2ERC1155Gateway).creationCode, args); + L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy( + "L2_ERC1155_GATEWAY_IMPLEMENTATION", + type(L2ERC1155Gateway).creationCode, + args + ); ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( ITransparentUpgradeableProxy(notnull(L2_ERC1155_GATEWAY_PROXY_ADDR)), @@ -1051,6 +1392,24 @@ contract DeployScroll is DeterminsticDeploymentScript { Whitelist(L1_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); } + function transferL1ContractOwnership() internal { + Ownable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_ERC1155_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_ERC721_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_ETH_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_GATEWAY_ROUTER_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_MESSAGE_QUEUE_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_SCROLL_MESSENGER_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_WETH_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_GAS_PRICE_ORACLE_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_PROXY_ADMIN_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_SCROLL_CHAIN_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L1_WHITELIST_ADDR).transferOwnership(OWNER_ADDR); + } + /********************** * L2: initialization * *********************/ @@ -1145,4 +1504,20 @@ contract DeployScroll is DeterminsticDeploymentScript { accounts[0] = L2_GAS_ORACLE_SENDER_ADDR; Whitelist(L2_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); } + + function transferL2ContractOwnership() internal { + Ownable(L1_GAS_PRICE_ORACLE_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_ERC1155_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_ERC721_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_ETH_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_GATEWAY_ROUTER_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_MESSAGE_QUEUE_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_SCROLL_MESSENGER_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_TX_FEE_VAULT_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_WETH_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_PROXY_ADMIN_ADDR).transferOwnership(OWNER_ADDR); + Ownable(L2_WHITELIST_ADDR).transferOwnership(OWNER_ADDR); + } } From 7b2228898b179f0bf38b737445209cf1038ca75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 16:38:52 +0800 Subject: [PATCH 05/38] add GenerateGenesisAlloc script --- contracts/configuration/config.toml | 39 ++- contracts/scripts/foundry/DeployScroll.s.sol | 266 +++++++++++++++++-- 2 files changed, 266 insertions(+), 39 deletions(-) diff --git a/contracts/configuration/config.toml b/contracts/configuration/config.toml index 729f68dab9..71571f500c 100644 --- a/contracts/configuration/config.toml +++ b/contracts/configuration/config.toml @@ -1,15 +1,16 @@ -[contracts] - -SALT_PREFIX = "" +[general] +CHAIN_ID_L1 = 111111 CHAIN_ID_L2 = 222222 MAX_TX_IN_CHUNK = 100 MAX_L1_MESSAGE_GAS_LIMIT = 10000 + +[accounts] + DEPLOYER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" OWNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" - L1_COMMIT_SENDER_ADDR = "0x0000000000000000000000000000000000000001" L1_FINALIZE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" L1_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" @@ -18,24 +19,22 @@ L2_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" DEPLOYER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" OWNER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +[genesis] +L2_MAX_ETH_SUPPLY = "226156424291633194186662080095093570025917938800079226639565593765455331328" +L2_DEPLOYER_INITIAL_BALANCE = 1000000000000000000 + +[contracts] +SALT_PREFIX = "" + # // contracts deployed outside this script L1_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000001" L1_PLONK_VERIFIER_ADDR = "0x0000000000000000000000000000000000000001" +[contracts.overrides] +L2_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000" +L1_GAS_PRICE_ORACLE = "0x5300000000000000000000000000000000000002" +L2_WHITELIST = "0x5300000000000000000000000000000000000003" +L2_WETH = "0x5300000000000000000000000000000000000004" +L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005" -L2_MESSAGE_QUEUE_OVERRIDE = "0x5300000000000000000000000000000000000000" -L1_GAS_PRICE_ORACLE_OVERRIDE = "0x5300000000000000000000000000000000000002" -L2_WHITELIST_OVERRIDE = "0x5300000000000000000000000000000000000003" -L2_WETH_OVERRIDE = "0x5300000000000000000000000000000000000004" -L2_TX_FEE_VAULT_OVERRIDE = "0x5300000000000000000000000000000000000005" - -L1_WETH_OVERRIDE = "0x5300000000000000000000000000000000000004" - - - -# export BROADCAST_LAYER = "L1" -# export FOUNDRY_EVM_VERSION="cancun" -# export FOUNDRY_BYTECODE_HASH="none" -# export L2_DEPLOYER_INITIAL_BALANCE="1" -# export L2_SCROLL_MESSENGER_INITIAL_BALANCE="1" -# export DEPLOYER_ADDR=0x00a329c0648769A73afAc7F9381E08FB43dBEA71 \ No newline at end of file +L1_WETH = "0x5300000000000000000000000000000000000004" diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 2be111a616..3f589e46e9 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -49,8 +49,13 @@ address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920 /// @dev The default salt prefix used for deriving deterministic deployment addresses. string constant DEFAULT_SALT_PREFIX = "ScrollStack"; +/// @dev The default minimum withdraw amount configured on L2TxFeeVault. +uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; + +// configuration file paths string constant CONFIG_PATH = "./configuration/config.toml"; string constant CONTRACTS_CONFIG_PATH = "./configuration/config-contracts.toml"; +string constant GENESIS_ALLOCS_JSON_PATH = "./configuration/genesis.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -165,7 +170,7 @@ contract Configuration is Script { contract DeterminsticDeploymentScript is Configuration { using stdToml for string; - string internal saltPrefix; + string internal saltPrefix = DEFAULT_SALT_PREFIX; function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { return _deploy(name, codeWithArgs); @@ -221,9 +226,9 @@ contract DeterminsticDeploymentScript is Configuration { return addr; } - function tryGetOverride(string memory name) private returns (address) { + function tryGetOverride(string memory name) internal returns (address) { address addr; - string memory key = string(abi.encodePacked(".contracts.", name, "_OVERRIDE")); + string memory key = string(abi.encodePacked(".contracts.overrides.", name)); if (!vm.keyExistsToml(cfg, key)) { return address(0); @@ -240,9 +245,9 @@ contract DeterminsticDeploymentScript is Configuration { console.log( string( abi.encodePacked( - "[ERROR] ", + "[ERROR] override ", name, - "_OVERRIDE=", + " = ", vm.toString(addr), " not deployed in broadcast mode" ) @@ -311,12 +316,12 @@ contract DeployScroll is DeterminsticDeploymentScript { address L1_PLONK_VERIFIER_ADDR; function initConfig() private { - CHAIN_ID_L2 = uint64(cfg.readUint(".contracts.CHAIN_ID_L2")); - MAX_TX_IN_CHUNK = cfg.readUint(".contracts.MAX_TX_IN_CHUNK"); - MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".contracts.MAX_L1_MESSAGE_GAS_LIMIT"); + CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); + MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); + MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); - DEPLOYER_PRIVATE_KEY = cfg.readUint(".contracts.DEPLOYER_PRIVATE_KEY"); - DEPLOYER_ADDR = cfg.readAddress(".contracts.DEPLOYER_ADDR"); + DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); // config sanity check if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { @@ -324,19 +329,20 @@ contract DeployScroll is DeterminsticDeploymentScript { revert(); } - OWNER_ADDR = cfg.readAddress(".contracts.OWNER_ADDR"); + OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); - L1_COMMIT_SENDER_ADDR = cfg.readAddress(".contracts.L1_COMMIT_SENDER_ADDR"); - L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".contracts.L1_FINALIZE_SENDER_ADDR"); - L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".contracts.L1_GAS_ORACLE_SENDER_ADDR"); - L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".contracts.L2_GAS_ORACLE_SENDER_ADDR"); + L1_COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.L1_COMMIT_SENDER_ADDR"); + L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.L1_FINALIZE_SENDER_ADDR"); + L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L1_GAS_ORACLE_SENDER_ADDR"); + L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L2_GAS_ORACLE_SENDER_ADDR"); L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); - saltPrefix = cfg.readString(".contracts.SALT_PREFIX"); - if (bytes(saltPrefix).length == 0) { - saltPrefix = DEFAULT_SALT_PREFIX; + // salt prefix used for deterministic deployments + string memory _saltPrefix = cfg.readString(".contracts.SALT_PREFIX"); + if (bytes(_saltPrefix).length != 0) { + saltPrefix = _saltPrefix; } } @@ -858,7 +864,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } function deployTxFeeVault() internal { - bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, 10 ether); + bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); L2_TX_FEE_VAULT_ADDR = deploy("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); } @@ -1521,3 +1527,225 @@ contract DeployScroll is DeterminsticDeploymentScript { Ownable(L2_WHITELIST_ADDR).transferOwnership(OWNER_ADDR); } } + +contract GenerateGenesisAlloc is DeterminsticDeploymentScript { + using stdToml for string; + + /*************************** + * Configuration parameters * + ***************************/ + + // accounts + address DEPLOYER_ADDR; + address OWNER_ADDR; + + // contracts + address L1_FEE_VAULT_ADDR; + + address L2_MESSAGE_QUEUE_OVERRIDE; + address L1_GAS_PRICE_ORACLE_OVERRIDE; + address L2_WHITELIST_OVERRIDE; + address L2_WETH_OVERRIDE; + address L2_TX_FEE_VAULT_OVERRIDE; + + // other + uint256 L2_MAX_ETH_SUPPLY; + uint256 L2_DEPLOYER_INITIAL_BALANCE; + uint256 L2_SCROLL_MESSENGER_INITIAL_BALANCE; + + // generated + address L2_SCROLL_MESSENGER_PROXY_ADDR; + + function initConfig() private { + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); + OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); + + L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); + + L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); + L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); + L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; + + // salt prefix used for deterministic deployments + string memory _saltPrefix = cfg.readString(".contracts.SALT_PREFIX"); + if (bytes(_saltPrefix).length != 0) { + saltPrefix = _saltPrefix; + } + + // deterministically predict L2ScrollMessengerProxy address + bytes memory args = abi.encode(DEPLOYER_ADDR); + address L2_PROXY_ADMIN_ADDR = predict("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + address L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( + "L2_PROXY_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); + bytes memory args2 = abi.encode(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR, L2_PROXY_ADMIN_ADDR, new bytes(0)); + L2_SCROLL_MESSENGER_PROXY_ADDR = predict( + "L2_SCROLL_MESSENGER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args2 + ); + } + + /************* + * Utilities * + ************/ + + /// @notice Sorts the allocs by address + function sortJsonByKeys(string memory _path) internal { + string[] memory commands = new string[](3); + commands[0] = "bash"; + commands[1] = "-c"; + commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path); + vm.ffi(commands); + } + + /************************* + * Deployment entry point * + *************************/ + + function run() public { + initConfig(); + + // predeploys + setL2MessageQueue(); + setL2GasPriceOracle(); + setL2Whitelist(); + setL2Weth(); + setL2FeeVault(); + + // reset sender + vm.resetNonce(msg.sender); + + // prefunded accounts + setL2ScrollMessenger(); + setL2Deployer(); + + // write to file + vm.dumpState(GENESIS_ALLOCS_JSON_PATH); + sortJsonByKeys(GENESIS_ALLOCS_JSON_PATH); + } + + function setL2MessageQueue() internal { + address predeployAddr = tryGetOverride("L2_MESSAGE_QUEUE"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + L2MessageQueue _queue = new L2MessageQueue(OWNER_ADDR); + vm.etch(predeployAddr, address(_queue).code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000052"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_queue), _ownerSlot)); + + // reset so its not included state dump + vm.etch(address(_queue), ""); + vm.resetNonce(address(_queue)); + } + + function setL2GasPriceOracle() internal { + address predeployAddr = tryGetOverride("L1_GAS_PRICE_ORACLE"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + L1GasPriceOracle _oracle = new L1GasPriceOracle(OWNER_ADDR); + vm.etch(predeployAddr, address(_oracle).code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_oracle), _ownerSlot)); + + // reset so its not included state dump + vm.etch(address(_oracle), ""); + vm.resetNonce(address(_oracle)); + } + + function setL2Whitelist() internal { + address predeployAddr = tryGetOverride("L2_WHITELIST"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + Whitelist _whitelist = new Whitelist(OWNER_ADDR); + vm.etch(predeployAddr, address(_whitelist).code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_whitelist), _ownerSlot)); + + // reset so its not included state dump + vm.etch(address(_whitelist), ""); + vm.resetNonce(address(_whitelist)); + } + + function setL2Weth() internal { + address predeployAddr = tryGetOverride("L2_WETH"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + WrappedEther _weth = new WrappedEther(); + vm.etch(predeployAddr, address(_weth).code); + + // set storage + bytes32 _nameSlot = hex"0000000000000000000000000000000000000000000000000000000000000003"; + vm.store(predeployAddr, _nameSlot, vm.load(address(_weth), _nameSlot)); + + bytes32 _symbolSlot = hex"0000000000000000000000000000000000000000000000000000000000000004"; + vm.store(predeployAddr, _symbolSlot, vm.load(address(_weth), _symbolSlot)); + + // reset so its not included state dump + vm.etch(address(_weth), ""); + vm.resetNonce(address(_weth)); + } + + function setL2FeeVault() internal { + address predeployAddr = tryGetOverride("L2_TX_FEE_VAULT"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + L2TxFeeVault _vault = new L2TxFeeVault(OWNER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); + vm.etch(predeployAddr, address(_vault).code); + + vm.prank(OWNER_ADDR); + _vault.updateMessenger(L2_SCROLL_MESSENGER_PROXY_ADDR); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_vault), _ownerSlot)); + + bytes32 _minWithdrawAmountSlot = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(predeployAddr, _minWithdrawAmountSlot, vm.load(address(_vault), _minWithdrawAmountSlot)); + + bytes32 _messengerSlot = hex"0000000000000000000000000000000000000000000000000000000000000002"; + vm.store(predeployAddr, _messengerSlot, vm.load(address(_vault), _messengerSlot)); + + bytes32 _recipientSlot = hex"0000000000000000000000000000000000000000000000000000000000000003"; + vm.store(predeployAddr, _recipientSlot, vm.load(address(_vault), _recipientSlot)); + + // reset so its not included state dump + vm.etch(address(_vault), ""); + vm.resetNonce(address(_vault)); + } + + function setL2ScrollMessenger() internal { + vm.deal(L2_SCROLL_MESSENGER_PROXY_ADDR, L2_SCROLL_MESSENGER_INITIAL_BALANCE); + } + + function setL2Deployer() internal { + vm.deal(OWNER_ADDR, L2_DEPLOYER_INITIAL_BALANCE); + } +} From e56d9a9cffaf6a1b5163afaaa0cd3df20d276064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 16:47:46 +0800 Subject: [PATCH 06/38] fmt --- contracts/configuration/config.toml | 2 +- contracts/scripts/foundry/DeployScroll.s.sol | 52 +++++++++++--------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/contracts/configuration/config.toml b/contracts/configuration/config.toml index 71571f500c..1e381d0277 100644 --- a/contracts/configuration/config.toml +++ b/contracts/configuration/config.toml @@ -24,7 +24,7 @@ L2_MAX_ETH_SUPPLY = "22615642429163319418666208009509357002591793880007922663956 L2_DEPLOYER_INITIAL_BALANCE = 1000000000000000000 [contracts] -SALT_PREFIX = "" +DEPLOYMENT_SALT = "" # // contracts deployed outside this script L1_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000001" diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 3f589e46e9..223aa624b5 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -46,8 +46,8 @@ import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStanda /// See https://github.com/Arachnid/deterministic-deployment-proxy. address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920cA78FbF26c0B4956C; -/// @dev The default salt prefix used for deriving deterministic deployment addresses. -string constant DEFAULT_SALT_PREFIX = "ScrollStack"; +/// @dev The default deterministic deployment salt prefix. +string constant DEFAULT_DEPLOYMENT_SALT = "ScrollStack"; /// @dev The default minimum withdraw amount configured on L2TxFeeVault. uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; @@ -55,7 +55,7 @@ uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; // configuration file paths string constant CONFIG_PATH = "./configuration/config.toml"; string constant CONTRACTS_CONFIG_PATH = "./configuration/config-contracts.toml"; -string constant GENESIS_ALLOCS_JSON_PATH = "./configuration/genesis.json"; +string constant GENESIS_ALLOC_JSON_PATH = "./configuration/genesis-alloc.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -170,7 +170,7 @@ contract Configuration is Script { contract DeterminsticDeploymentScript is Configuration { using stdToml for string; - string internal saltPrefix = DEFAULT_SALT_PREFIX; + string internal saltPrefix = DEFAULT_DEPLOYMENT_SALT; function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { return _deploy(name, codeWithArgs); @@ -295,7 +295,6 @@ contract DeployScroll is DeterminsticDeploymentScript { // general configurations Layer BROADCAST_LAYER; - string SALT_PREFIX; uint64 CHAIN_ID_L2; uint256 MAX_TX_IN_CHUNK; uint256 MAX_L1_MESSAGE_GAS_LIMIT; @@ -340,7 +339,7 @@ contract DeployScroll is DeterminsticDeploymentScript { L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.SALT_PREFIX"); + string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); if (bytes(_saltPrefix).length != 0) { saltPrefix = _saltPrefix; } @@ -865,7 +864,6 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployTxFeeVault() internal { bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); - L2_TX_FEE_VAULT_ADDR = deploy("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); } @@ -981,7 +979,6 @@ contract DeployScroll is DeterminsticDeploymentScript { function deployScrollStandardERC20Factory() internal { L2_SCROLL_STANDARD_ERC20_ADDR = deploy("L2_SCROLL_STANDARD_ERC20", type(ScrollStandardERC20).creationCode); - bytes memory args = abi.encode(DEPLOYER_ADDR, notnull(L2_SCROLL_STANDARD_ERC20_ADDR)); L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = deploy( @@ -1556,6 +1553,26 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { // generated address L2_SCROLL_MESSENGER_PROXY_ADDR; + function predictL2MessengerAddress() private view returns (address) { + bytes memory args = abi.encode(DEPLOYER_ADDR); + address L2_PROXY_ADMIN_ADDR = predict("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + + address L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( + "L2_PROXY_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); + + bytes memory args2 = abi.encode(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR, L2_PROXY_ADMIN_ADDR, new bytes(0)); + + address predictedAddr = predict( + "L2_SCROLL_MESSENGER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args2 + ); + + return predictedAddr; + } + function initConfig() private { DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); @@ -1567,24 +1584,13 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.SALT_PREFIX"); + string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); if (bytes(_saltPrefix).length != 0) { saltPrefix = _saltPrefix; } // deterministically predict L2ScrollMessengerProxy address - bytes memory args = abi.encode(DEPLOYER_ADDR); - address L2_PROXY_ADMIN_ADDR = predict("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); - address L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( - "L2_PROXY_IMPLEMENTATION_PLACEHOLDER", - type(EmptyContract).creationCode - ); - bytes memory args2 = abi.encode(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR, L2_PROXY_ADMIN_ADDR, new bytes(0)); - L2_SCROLL_MESSENGER_PROXY_ADDR = predict( - "L2_SCROLL_MESSENGER_PROXY", - type(TransparentUpgradeableProxy).creationCode, - args2 - ); + L2_SCROLL_MESSENGER_PROXY_ADDR = predictL2MessengerAddress(); } /************* @@ -1622,8 +1628,8 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { setL2Deployer(); // write to file - vm.dumpState(GENESIS_ALLOCS_JSON_PATH); - sortJsonByKeys(GENESIS_ALLOCS_JSON_PATH); + vm.dumpState(GENESIS_ALLOC_JSON_PATH); + sortJsonByKeys(GENESIS_ALLOC_JSON_PATH); } function setL2MessageQueue() internal { From 9f7841a4681b70adaab374c4ec492cb68fde92d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 17:52:49 +0800 Subject: [PATCH 07/38] add GenerateGenesis --- contracts/configuration/config.toml | 4 + contracts/configuration/genesis.json | 49 +++ contracts/scripts/foundry/DeployScroll.s.sol | 401 ++++++++++++++----- 3 files changed, 354 insertions(+), 100 deletions(-) create mode 100644 contracts/configuration/genesis.json diff --git a/contracts/configuration/config.toml b/contracts/configuration/config.toml index 1e381d0277..f33a927cb7 100644 --- a/contracts/configuration/config.toml +++ b/contracts/configuration/config.toml @@ -19,10 +19,14 @@ L2_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" DEPLOYER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" OWNER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +L2GETH_SIGNER_0_ADDRESS = "0x756EA06BDEe36de11F22DCca45a31d8a178eF3c6" + + [genesis] L2_MAX_ETH_SUPPLY = "226156424291633194186662080095093570025917938800079226639565593765455331328" L2_DEPLOYER_INITIAL_BALANCE = 1000000000000000000 + [contracts] DEPLOYMENT_SALT = "" diff --git a/contracts/configuration/genesis.json b/contracts/configuration/genesis.json new file mode 100644 index 0000000000..c429d8f2ff --- /dev/null +++ b/contracts/configuration/genesis.json @@ -0,0 +1,49 @@ +{ + "config": { + "chainId": null, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "archimedesBlock": 0, + "shanghaiBlock": 0, + "bernoulliBlock": 0, + "clique": { + "period": 3, + "epoch": 30000 + }, + "scroll": { + "useZktrie": true, + "maxTxPerBlock": null, + "maxTxPayloadBytesPerBlock": 122880, + "feeVaultAddress": null, + "enableEIP2718": false, + "enableEIP1559": false, + "l1Config": { + "l1ChainId": null, + "l1MessageQueueAddress": null, + "scrollChainAddress": null, + "numL1MessagesPerBlock": "10" + } + } + }, + "nonce": "0x0", + "timestamp": null, + "extraData": null, + "gasLimit": "10000000", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": {}, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null +} \ No newline at end of file diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 223aa624b5..4d4e7c2056 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -56,6 +56,7 @@ uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; string constant CONFIG_PATH = "./configuration/config.toml"; string constant CONTRACTS_CONFIG_PATH = "./configuration/config-contracts.toml"; string constant GENESIS_ALLOC_JSON_PATH = "./configuration/genesis-alloc.json"; +string constant GENESIS_JSON_PATH = "./configuration/genesis.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -90,6 +91,7 @@ contract Configuration is Script { using stdToml for string; enum ScriptMode { + None, LogAddresses, WriteConfig, VerifyConfig @@ -112,12 +114,14 @@ contract Configuration is Script { } function parseScriptMode(string memory raw) internal pure returns (ScriptMode) { - if (keccak256(bytes(raw)) == keccak256(bytes("write-config"))) { + if (keccak256(bytes(raw)) == keccak256(bytes("log-addresses"))) { + return ScriptMode.WriteConfig; + } else if (keccak256(bytes(raw)) == keccak256(bytes("write-config"))) { return ScriptMode.WriteConfig; } else if (keccak256(bytes(raw)) == keccak256(bytes("verify-config"))) { return ScriptMode.VerifyConfig; } else { - return ScriptMode.LogAddresses; + return ScriptMode.None; } } @@ -131,6 +135,13 @@ contract Configuration is Script { } } + /// @dev Ensure that `addr` is not the zero address. + /// This helps catch bugs arising from incorrect deployment order. + function notnull(address addr) internal pure returns (address) { + require(addr != address(0), "null address"); + return addr; + } + function _label(string memory name, address addr) internal { vm.label(addr, name); @@ -171,6 +182,7 @@ contract DeterminsticDeploymentScript is Configuration { using stdToml for string; string internal saltPrefix = DEFAULT_DEPLOYMENT_SALT; + bool internal SKIP_DEPLOY = false; function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { return _deploy(name, codeWithArgs); @@ -209,6 +221,10 @@ contract DeterminsticDeploymentScript is Configuration { addr = _predict(name, codeWithArgs); _label(name, addr); + if (SKIP_DEPLOY) { + return addr; + } + // return if the contract is already deployed, // in this case the subsequent initialization steps will probably break if (addr.code.length > 0) { @@ -293,7 +309,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ***************************/ // general configurations - Layer BROADCAST_LAYER; + Layer BROADCAST_LAYER = Layer.None; uint64 CHAIN_ID_L2; uint256 MAX_TX_IN_CHUNK; @@ -315,6 +331,12 @@ contract DeployScroll is DeterminsticDeploymentScript { address L1_PLONK_VERIFIER_ADDR; function initConfig() private { + // salt prefix used for deterministic deployments + string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); + if (bytes(_saltPrefix).length != 0) { + saltPrefix = _saltPrefix; + } + CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); @@ -337,12 +359,6 @@ contract DeployScroll is DeterminsticDeploymentScript { L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); - - // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); - if (bytes(_saltPrefix).length != 0) { - saltPrefix = _saltPrefix; - } } /********************** @@ -350,75 +366,68 @@ contract DeployScroll is DeterminsticDeploymentScript { **********************/ // L1 addresses - address L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; - address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR; - address L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR; - address L1_ENFORCED_TX_GATEWAY_PROXY_ADDR; - address L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR; - address L1_ERC1155_GATEWAY_PROXY_ADDR; - address L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR; - address L1_ERC721_GATEWAY_PROXY_ADDR; - address L1_ETH_GATEWAY_IMPLEMENTATION_ADDR; - address L1_ETH_GATEWAY_PROXY_ADDR; - address L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR; - address L1_GATEWAY_ROUTER_PROXY_ADDR; - address L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR; - address L1_MESSAGE_QUEUE_PROXY_ADDR; - address L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR; - address L1_PROXY_ADMIN_ADDR; - address L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR; - address L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR; - address L1_SCROLL_CHAIN_PROXY_ADDR; - address L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR; - address L1_SCROLL_MESSENGER_PROXY_ADDR; - address L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR; - address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR; - address L1_WETH_ADDR; - address L1_WETH_GATEWAY_IMPLEMENTATION_ADDR; - address L1_WETH_GATEWAY_PROXY_ADDR; - address L1_WHITELIST_ADDR; - address L1_ZKEVM_VERIFIER_V1_ADDR; - address L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR; - address L2_GAS_PRICE_ORACLE_PROXY_ADDR; + address internal L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR; + address internal L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_ENFORCED_TX_GATEWAY_PROXY_ADDR; + address internal L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_ERC1155_GATEWAY_PROXY_ADDR; + address internal L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_ERC721_GATEWAY_PROXY_ADDR; + address internal L1_ETH_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_ETH_GATEWAY_PROXY_ADDR; + address internal L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR; + address internal L1_GATEWAY_ROUTER_PROXY_ADDR; + address internal L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR; + address internal L1_MESSAGE_QUEUE_PROXY_ADDR; + address internal L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR; + address internal L1_PROXY_ADMIN_ADDR; + address internal L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR; + address internal L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR; + address internal L1_SCROLL_CHAIN_PROXY_ADDR; + address internal L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR; + address internal L1_SCROLL_MESSENGER_PROXY_ADDR; + address internal L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR; + address internal L1_WETH_ADDR; + address internal L1_WETH_GATEWAY_IMPLEMENTATION_ADDR; + address internal L1_WETH_GATEWAY_PROXY_ADDR; + address internal L1_WHITELIST_ADDR; + address internal L1_ZKEVM_VERIFIER_V1_ADDR; + address internal L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR; + address internal L2_GAS_PRICE_ORACLE_PROXY_ADDR; // L2 addresses - address L1_GAS_PRICE_ORACLE_ADDR; - address L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; - address L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR; - address L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR; - address L2_ERC1155_GATEWAY_PROXY_ADDR; - address L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR; - address L2_ERC721_GATEWAY_PROXY_ADDR; - address L2_ETH_GATEWAY_IMPLEMENTATION_ADDR; - address L2_ETH_GATEWAY_PROXY_ADDR; - address L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR; - address L2_GATEWAY_ROUTER_PROXY_ADDR; - address L2_MESSAGE_QUEUE_ADDR; - address L2_PROXY_ADMIN_ADDR; - address L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR; - address L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR; - address L2_SCROLL_MESSENGER_PROXY_ADDR; - address L2_SCROLL_STANDARD_ERC20_ADDR; - address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR; - address L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR; - address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR; - address L2_TX_FEE_VAULT_ADDR; - address L2_WETH_ADDR; - address L2_WETH_GATEWAY_IMPLEMENTATION_ADDR; - address L2_WETH_GATEWAY_PROXY_ADDR; - address L2_WHITELIST_ADDR; + address internal L1_GAS_PRICE_ORACLE_ADDR; + address internal L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address internal L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR; + address internal L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR; + address internal L2_ERC1155_GATEWAY_PROXY_ADDR; + address internal L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR; + address internal L2_ERC721_GATEWAY_PROXY_ADDR; + address internal L2_ETH_GATEWAY_IMPLEMENTATION_ADDR; + address internal L2_ETH_GATEWAY_PROXY_ADDR; + address internal L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR; + address internal L2_GATEWAY_ROUTER_PROXY_ADDR; + address internal L2_MESSAGE_QUEUE_ADDR; + address internal L2_PROXY_ADMIN_ADDR; + address internal L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR; + address internal L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR; + address internal L2_SCROLL_MESSENGER_PROXY_ADDR; + address internal L2_SCROLL_STANDARD_ERC20_ADDR; + address internal L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR; + address internal L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR; + address internal L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR; + address internal L2_TX_FEE_VAULT_ADDR; + address internal L2_WETH_ADDR; + address internal L2_WETH_GATEWAY_IMPLEMENTATION_ADDR; + address internal L2_WETH_GATEWAY_PROXY_ADDR; + address internal L2_WHITELIST_ADDR; /************ * Utilities * ************/ - /// @dev Ensure that `addr` is not the zero address. - /// This helps catch bugs arising from incorrect deployment order. - function notnull(address addr) internal pure returns (address) { - require(addr != address(0), "null address"); - return addr; - } - /// @dev Only broadcast code block if we run the script on the specified layer. modifier broadcast(Layer layer) { if (BROADCAST_LAYER == layer) { @@ -445,9 +454,9 @@ contract DeployScroll is DeterminsticDeploymentScript { _; } - /************************* - * Deployment entry point * - *************************/ + /*************** + * Entry point * + **************/ function run(string memory layer, string memory scriptMode) public { BROADCAST_LAYER = parseLayer(layer); @@ -468,12 +477,16 @@ contract DeployScroll is DeterminsticDeploymentScript { initConfig(); + deployAllContracts(); + initializeL1Contracts(); + initializeL2Contracts(); + } + + function deployAllContracts() internal { deployL1Contracts1stPass(); deployL2Contracts1stPass(); deployL1Contracts2ndPass(); deployL2Contracts2ndPass(); - initializeL1Contracts(); - initializeL2Contracts(); } // @notice deployL1Contracts1stPass deploys L1 contracts whose initialization does not depend on any L2 addresses. @@ -1553,7 +1566,27 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { // generated address L2_SCROLL_MESSENGER_PROXY_ADDR; - function predictL2MessengerAddress() private view returns (address) { + function initConfig() private { + // salt prefix used for deterministic deployments + string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); + if (bytes(_saltPrefix).length != 0) { + saltPrefix = _saltPrefix; + } + + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); + OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); + + L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); + + L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); + L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); + L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; + + // deterministically predict L2ScrollMessengerProxy address + L2_SCROLL_MESSENGER_PROXY_ADDR = predictL2MessengerProxyAddress(); + } + + function predictL2MessengerProxyAddress() private view returns (address) { bytes memory args = abi.encode(DEPLOYER_ADDR); address L2_PROXY_ADMIN_ADDR = predict("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); @@ -1573,26 +1606,6 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { return predictedAddr; } - function initConfig() private { - DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); - OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); - - L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); - - L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); - L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); - L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; - - // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); - if (bytes(_saltPrefix).length != 0) { - saltPrefix = _saltPrefix; - } - - // deterministically predict L2ScrollMessengerProxy address - L2_SCROLL_MESSENGER_PROXY_ADDR = predictL2MessengerAddress(); - } - /************* * Utilities * ************/ @@ -1606,9 +1619,9 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { vm.ffi(commands); } - /************************* - * Deployment entry point * - *************************/ + /*************** + * Entry point * + **************/ function run() public { initConfig(); @@ -1755,3 +1768,191 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { vm.deal(OWNER_ADDR, L2_DEPLOYER_INITIAL_BALANCE); } } + +contract GenerateGenesis is DeterminsticDeploymentScript { + using stdToml for string; + + /*************************** + * Configuration parameters * + ***************************/ + + // general configurations + uint64 CHAIN_ID_L1; + uint64 CHAIN_ID_L2; + uint256 MAX_TX_IN_CHUNK; + + // accounts + address DEPLOYER_ADDR; + address L2GETH_SIGNER_0_ADDRESS; + + // contract addresses + address L1_FEE_VAULT_ADDR; + address L1_MESSAGE_QUEUE_PROXY_ADDR; + address L1_SCROLL_CHAIN_PROXY_ADDR; + address L2_TX_FEE_VAULT_ADDR; + + function initConfig() private { + // salt prefix used for deterministic deployments + string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); + if (bytes(_saltPrefix).length != 0) { + saltPrefix = _saltPrefix; + } + + CHAIN_ID_L1 = uint64(cfg.readUint(".general.CHAIN_ID_L1")); + CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); + MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); + + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); + L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); + + L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); + + ( + L1_SCROLL_CHAIN_PROXY_ADDR, + L1_MESSAGE_QUEUE_PROXY_ADDR + ) = predictL1ScrollChainProxyAndL1MessageQueueProxyAddr(); + L2_TX_FEE_VAULT_ADDR = predictL2TxFeeVaultAddr(); + } + + function predictL1ScrollChainProxyAndL1MessageQueueProxyAddr() private returns (address, address) { + bytes memory args = abi.encode(DEPLOYER_ADDR); + address L1_PROXY_ADMIN_ADDR = predict("L1_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + + address L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( + "L1_PROXY_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); + + args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + address L1_SCROLL_MESSENGER_PROXY_ADDR = predict( + "L1_SCROLL_MESSENGER_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); + + address L1_SCROLL_CHAIN_PROXY_ADDR_PREDICTED = predict( + "L1_SCROLL_CHAIN_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); + + address L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = predict( + "L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION", + type(EnforcedTxGateway).creationCode + ); + + args = abi.encode( + notnull(L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + address L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = predict( + "L1_ENFORCED_TX_GATEWAY_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); + + args = abi.encode( + notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), + notnull(L1_SCROLL_CHAIN_PROXY_ADDR_PREDICTED), + notnull(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR) + ); + + address L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = predict( + "L1_MESSAGE_QUEUE_IMPLEMENTATION", + type(L1MessageQueueWithGasPriceOracle).creationCode, + args + ); + + args = abi.encode(notnull(L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR), notnull(L1_PROXY_ADMIN_ADDR), new bytes(0)); + + address L1_MESSAGE_QUEUE_PROXY_ADDR_PREDICTED = predict( + "L1_MESSAGE_QUEUE_PROXY", + type(TransparentUpgradeableProxy).creationCode, + args + ); + + return (L1_SCROLL_CHAIN_PROXY_ADDR_PREDICTED, L1_MESSAGE_QUEUE_PROXY_ADDR_PREDICTED); + } + + function predictL1ScrollChainProxyAddr() private returns (address) { + bytes memory args = abi.encode(DEPLOYER_ADDR); + address L1_PROXY_ADMIN_ADDR = predict("L1_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + + address L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( + "L1_PROXY_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); + + args = abi.encode( + notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(L1_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + address predictedAddr = predict("L1_SCROLL_CHAIN_PROXY", type(TransparentUpgradeableProxy).creationCode, args); + + return predictedAddr; + } + + function predictL2TxFeeVaultAddr() private returns (address) { + address predeployAddr = tryGetOverride("L2_TX_FEE_VAULT"); + + if (predeployAddr != address(0)) { + return predeployAddr; + } + + bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); + address predictedAddr = predict("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); + + return predictedAddr; + } + + /*************** + * Entry point * + **************/ + + function run() public { + initConfig(); + + // general config + vm.writeJson(vm.toString(CHAIN_ID_L2), GENESIS_JSON_PATH, ".config.chainId"); + + uint256 timestamp = vm.unixTime() / 1000; + vm.writeJson(vm.toString(bytes32(timestamp)), GENESIS_JSON_PATH, ".timestamp"); + + string memory extraData = string( + abi.encodePacked( + vm.toString(L2GETH_SIGNER_0_ADDRESS), + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ) + ); + vm.writeJson(extraData, GENESIS_JSON_PATH, ".extraData"); + + // scroll-specific config + vm.writeJson(vm.toString(MAX_TX_IN_CHUNK), GENESIS_JSON_PATH, ".config.scroll.maxTxPerBlock"); + vm.writeJson(vm.toString(L2_TX_FEE_VAULT_ADDR), GENESIS_JSON_PATH, ".config.scroll.feeVaultAddress"); + + vm.writeJson(vm.toString(CHAIN_ID_L1), GENESIS_JSON_PATH, ".config.scroll.l1Config.l1ChainId"); + vm.writeJson( + vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), + GENESIS_JSON_PATH, + ".config.scroll.l1Config.l1MessageQueueAddress" + ); + vm.writeJson( + vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), + GENESIS_JSON_PATH, + ".config.scroll.l1Config.scrollChainAddress" + ); + + // predeploys and prefunded accounts + string memory alloc = vm.readFile(GENESIS_ALLOC_JSON_PATH); + vm.writeJson(alloc, GENESIS_JSON_PATH, ".alloc"); + } +} From 3c6c86eaad0abd6cf15b37505fcd86a91d294b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 18:10:41 +0800 Subject: [PATCH 08/38] move configurations --- contracts/scripts/foundry/DeployScroll.s.sol | 264 ++++++++----------- 1 file changed, 117 insertions(+), 147 deletions(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 4d4e7c2056..025f69a5b6 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -97,22 +97,89 @@ contract Configuration is Script { VerifyConfig } - enum Layer { - None, - L1, - L2 - } - string internal cfg; string internal contractsCfg; ScriptMode internal mode = ScriptMode.LogAddresses; + /*************************** + * Configuration parameters * + ***************************/ + + // general + uint64 internal CHAIN_ID_L1; + uint64 internal CHAIN_ID_L2; + uint256 internal MAX_TX_IN_CHUNK; + uint256 internal MAX_L1_MESSAGE_GAS_LIMIT; + + // accounts + uint256 internal DEPLOYER_PRIVATE_KEY; + + address internal L1_COMMIT_SENDER_ADDR; + address internal L1_FINALIZE_SENDER_ADDR; + address internal L1_GAS_ORACLE_SENDER_ADDR; + address internal L2_GAS_ORACLE_SENDER_ADDR; + + address internal DEPLOYER_ADDR; + address internal OWNER_ADDR; + + address internal L2GETH_SIGNER_0_ADDRESS; + + // genesis + uint256 internal L2_MAX_ETH_SUPPLY; + uint256 internal L2_DEPLOYER_INITIAL_BALANCE; + uint256 internal L2_SCROLL_MESSENGER_INITIAL_BALANCE; + + // contracts + string internal DEPLOYMENT_SALT; + + address internal L1_FEE_VAULT_ADDR; + address internal L1_PLONK_VERIFIER_ADDR; + + /*************** + * Constructor * + **************/ + constructor() { cfg = vm.readFile(CONFIG_PATH); contractsCfg = vm.readFile(CONTRACTS_CONFIG_PATH); + + DEPLOYMENT_SALT = cfg.readString(".contracts.DEPLOYMENT_SALT"); + + CHAIN_ID_L1 = uint64(cfg.readUint(".general.CHAIN_ID_L1")); + CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); + MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); + MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); + + DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); + + // config sanity check + if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { + console.log(string(abi.encodePacked("[ERROR] DEPLOYER_ADDR does not match DEPLOYER_PRIVATE_KEY"))); + revert(); + } + + OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); + + L1_COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.L1_COMMIT_SENDER_ADDR"); + L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.L1_FINALIZE_SENDER_ADDR"); + L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L1_GAS_ORACLE_SENDER_ADDR"); + L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L2_GAS_ORACLE_SENDER_ADDR"); + L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); + + L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); + L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); + + L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); + L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); + L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; } + /************* + * Utilities * + ************/ + function parseScriptMode(string memory raw) internal pure returns (ScriptMode) { if (keccak256(bytes(raw)) == keccak256(bytes("log-addresses"))) { return ScriptMode.WriteConfig; @@ -125,16 +192,6 @@ contract Configuration is Script { } } - function parseLayer(string memory raw) internal pure returns (Layer) { - if (keccak256(bytes(raw)) == keccak256(bytes("L1"))) { - return Layer.L1; - } else if (keccak256(bytes(raw)) == keccak256(bytes("L2"))) { - return Layer.L2; - } else { - return Layer.None; - } - } - /// @dev Ensure that `addr` is not the zero address. /// This helps catch bugs arising from incorrect deployment order. function notnull(address addr) internal pure returns (address) { @@ -142,7 +199,7 @@ contract Configuration is Script { return addr; } - function _label(string memory name, address addr) internal { + function label(string memory name, address addr) internal { vm.label(addr, name); if (mode == ScriptMode.LogAddresses) { @@ -181,9 +238,32 @@ contract Configuration is Script { contract DeterminsticDeploymentScript is Configuration { using stdToml for string; - string internal saltPrefix = DEFAULT_DEPLOYMENT_SALT; + string private SALT_PREFIX; bool internal SKIP_DEPLOY = false; + constructor() { + // salt prefix used for deterministic deployments + if (bytes(DEPLOYMENT_SALT).length != 0) { + SALT_PREFIX = DEPLOYMENT_SALT; + } else { + SALT_PREFIX = DEFAULT_DEPLOYMENT_SALT; + } + + // sanity check: make sure DeterministicDeploymentProxy exists + if (DETERMINISTIC_DEPLOYMENT_PROXY_ADDR.code.length == 0) { + console.log( + string( + abi.encodePacked( + "[ERROR] DeterministicDeploymentProxy (", + vm.toString(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR), + ") is not available" + ) + ) + ); + revert(); + } + } + function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { return _deploy(name, codeWithArgs); } @@ -213,13 +293,13 @@ contract DeterminsticDeploymentScript is Configuration { address addr = tryGetOverride(name); if (addr != address(0)) { - _label(name, addr); + label(name, addr); return addr; } // predict determinstic deployment address addr = _predict(name, codeWithArgs); - _label(name, addr); + label(name, addr); if (SKIP_DEPLOY) { return addr; @@ -277,7 +357,7 @@ contract DeterminsticDeploymentScript is Configuration { } function _getSalt(string memory name) internal view returns (bytes32) { - return keccak256(abi.encodePacked(saltPrefix, name)); + return keccak256(abi.encodePacked(SALT_PREFIX, name)); } function _predict(string memory name, bytes memory codeWithArgs) private view returns (address) { @@ -302,64 +382,18 @@ contract DeterminsticDeploymentScript is Configuration { } contract DeployScroll is DeterminsticDeploymentScript { - using stdToml for string; + enum Layer { + None, + L1, + L2 + } /*************************** * Configuration parameters * ***************************/ // general configurations - Layer BROADCAST_LAYER = Layer.None; - - uint64 CHAIN_ID_L2; - uint256 MAX_TX_IN_CHUNK; - uint256 MAX_L1_MESSAGE_GAS_LIMIT; - - // accounts - uint256 DEPLOYER_PRIVATE_KEY; - address DEPLOYER_ADDR; - - address OWNER_ADDR; - - address L1_COMMIT_SENDER_ADDR; - address L1_FINALIZE_SENDER_ADDR; - address L1_GAS_ORACLE_SENDER_ADDR; - address L2_GAS_ORACLE_SENDER_ADDR; - - // contracts deployed outside this script - address L1_FEE_VAULT_ADDR; - address L1_PLONK_VERIFIER_ADDR; - - function initConfig() private { - // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); - if (bytes(_saltPrefix).length != 0) { - saltPrefix = _saltPrefix; - } - - CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); - MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); - MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); - - DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); - DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); - - // config sanity check - if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { - console.log(string(abi.encodePacked("[ERROR] DEPLOYER_ADDR does not match DEPLOYER_PRIVATE_KEY"))); - revert(); - } - - OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); - - L1_COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.L1_COMMIT_SENDER_ADDR"); - L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.L1_FINALIZE_SENDER_ADDR"); - L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L1_GAS_ORACLE_SENDER_ADDR"); - L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L2_GAS_ORACLE_SENDER_ADDR"); - - L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); - L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); - } + Layer internal BROADCAST_LAYER = Layer.None; /********************** * Contracts to deploy * @@ -428,6 +462,16 @@ contract DeployScroll is DeterminsticDeploymentScript { * Utilities * ************/ + function parseLayer(string memory raw) internal pure returns (Layer) { + if (keccak256(bytes(raw)) == keccak256(bytes("L1"))) { + return Layer.L1; + } else if (keccak256(bytes(raw)) == keccak256(bytes("L2"))) { + return Layer.L2; + } else { + return Layer.None; + } + } + /// @dev Only broadcast code block if we run the script on the specified layer. modifier broadcast(Layer layer) { if (BROADCAST_LAYER == layer) { @@ -462,21 +506,6 @@ contract DeployScroll is DeterminsticDeploymentScript { BROADCAST_LAYER = parseLayer(layer); mode = parseScriptMode(scriptMode); - if (DETERMINISTIC_DEPLOYMENT_PROXY_ADDR.code.length == 0) { - console.log( - string( - abi.encodePacked( - "[ERROR] DeterministicDeploymentProxy (", - vm.toString(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR), - ") is not available" - ) - ) - ); - revert(); - } - - initConfig(); - deployAllContracts(); initializeL1Contracts(); initializeL2Contracts(); @@ -1545,43 +1574,10 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { * Configuration parameters * ***************************/ - // accounts - address DEPLOYER_ADDR; - address OWNER_ADDR; - - // contracts - address L1_FEE_VAULT_ADDR; - - address L2_MESSAGE_QUEUE_OVERRIDE; - address L1_GAS_PRICE_ORACLE_OVERRIDE; - address L2_WHITELIST_OVERRIDE; - address L2_WETH_OVERRIDE; - address L2_TX_FEE_VAULT_OVERRIDE; - - // other - uint256 L2_MAX_ETH_SUPPLY; - uint256 L2_DEPLOYER_INITIAL_BALANCE; - uint256 L2_SCROLL_MESSENGER_INITIAL_BALANCE; - // generated address L2_SCROLL_MESSENGER_PROXY_ADDR; function initConfig() private { - // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); - if (bytes(_saltPrefix).length != 0) { - saltPrefix = _saltPrefix; - } - - DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); - OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); - - L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); - - L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); - L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); - L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; - // deterministically predict L2ScrollMessengerProxy address L2_SCROLL_MESSENGER_PROXY_ADDR = predictL2MessengerProxyAddress(); } @@ -1776,37 +1772,11 @@ contract GenerateGenesis is DeterminsticDeploymentScript { * Configuration parameters * ***************************/ - // general configurations - uint64 CHAIN_ID_L1; - uint64 CHAIN_ID_L2; - uint256 MAX_TX_IN_CHUNK; - - // accounts - address DEPLOYER_ADDR; - address L2GETH_SIGNER_0_ADDRESS; - - // contract addresses - address L1_FEE_VAULT_ADDR; address L1_MESSAGE_QUEUE_PROXY_ADDR; address L1_SCROLL_CHAIN_PROXY_ADDR; address L2_TX_FEE_VAULT_ADDR; function initConfig() private { - // salt prefix used for deterministic deployments - string memory _saltPrefix = cfg.readString(".contracts.DEPLOYMENT_SALT"); - if (bytes(_saltPrefix).length != 0) { - saltPrefix = _saltPrefix; - } - - CHAIN_ID_L1 = uint64(cfg.readUint(".general.CHAIN_ID_L1")); - CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); - MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); - - DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); - L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); - - L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); - ( L1_SCROLL_CHAIN_PROXY_ADDR, L1_MESSAGE_QUEUE_PROXY_ADDR From 31a636a66b2772bc981ccfacbd2cba54e2dfe1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 18:28:22 +0800 Subject: [PATCH 09/38] simplify contract address prediction --- contracts/scripts/foundry/DeployScroll.s.sol | 259 ++++--------------- 1 file changed, 44 insertions(+), 215 deletions(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 025f69a5b6..0adac03427 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -100,7 +100,7 @@ contract Configuration is Script { string internal cfg; string internal contractsCfg; - ScriptMode internal mode = ScriptMode.LogAddresses; + ScriptMode internal mode = ScriptMode.None; /*************************** * Configuration parameters * @@ -264,6 +264,19 @@ contract DeterminsticDeploymentScript is Configuration { } } + function upgrade( + address proxyAdminAddr, + address proxyAddr, + address implAddr + ) internal { + if (!SKIP_DEPLOY) { + ProxyAdmin(notnull(proxyAdminAddr)).upgrade( + ITransparentUpgradeableProxy(notnull(proxyAddr)), + notnull(implAddr) + ); + } + } + function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { return _deploy(name, codeWithArgs); } @@ -518,6 +531,11 @@ contract DeployScroll is DeterminsticDeploymentScript { deployL2Contracts2ndPass(); } + function predictAllContracts() internal { + SKIP_DEPLOY = true; + deployAllContracts(); + } + // @notice deployL1Contracts1stPass deploys L1 contracts whose initialization does not depend on any L2 addresses. function deployL1Contracts1stPass() internal broadcast(Layer.L1) { deployL1Weth(); @@ -772,10 +790,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_SCROLL_CHAIN_PROXY_ADDR)), - notnull(L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_SCROLL_CHAIN_PROXY_ADDR, L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR); } function deployL1GatewayRouter() internal { @@ -1047,10 +1062,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)), - notnull(L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR, L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR); } function deployL1ETHGateway() internal { @@ -1066,10 +1078,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_ETH_GATEWAY_PROXY_ADDR)), - notnull(L1_ETH_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_ETH_GATEWAY_PROXY_ADDR, L1_ETH_GATEWAY_IMPLEMENTATION_ADDR); } function deployL1WETHGateway() internal { @@ -1087,10 +1096,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_WETH_GATEWAY_PROXY_ADDR)), - notnull(L1_WETH_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_WETH_GATEWAY_PROXY_ADDR, L1_WETH_GATEWAY_IMPLEMENTATION_ADDR); } function deployL1StandardERC20Gateway() internal { @@ -1108,9 +1114,10 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR)), - notnull(L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) + upgrade( + L1_PROXY_ADMIN_ADDR, + L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR, + L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR ); } @@ -1127,10 +1134,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR)), - notnull(L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR, L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR); } function deployL1ERC721Gateway() internal { @@ -1142,10 +1146,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_ERC721_GATEWAY_PROXY_ADDR)), - notnull(L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_ERC721_GATEWAY_PROXY_ADDR, L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR); } function deployL1ERC1155Gateway() internal { @@ -1157,10 +1158,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L1_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L1_ERC1155_GATEWAY_PROXY_ADDR)), - notnull(L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L1_PROXY_ADMIN_ADDR, L1_ERC1155_GATEWAY_PROXY_ADDR, L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR); } /*************************** @@ -1176,10 +1174,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)), - notnull(L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) - ); + upgrade(L2_PROXY_ADMIN_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR, L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR); } function deployL2GatewayRouter() internal { @@ -1215,9 +1210,10 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR)), - notnull(L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) + upgrade( + L2_PROXY_ADMIN_ADDR, + L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR, + L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR ); } @@ -1234,10 +1230,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_ETH_GATEWAY_PROXY_ADDR)), - notnull(L2_ETH_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L2_PROXY_ADMIN_ADDR, L2_ETH_GATEWAY_PROXY_ADDR, L2_ETH_GATEWAY_IMPLEMENTATION_ADDR); } function deployL2WETHGateway() internal { @@ -1255,10 +1248,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_WETH_GATEWAY_PROXY_ADDR)), - notnull(L2_WETH_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L2_PROXY_ADMIN_ADDR, L2_WETH_GATEWAY_PROXY_ADDR, L2_WETH_GATEWAY_IMPLEMENTATION_ADDR); } function deployL2CustomERC20Gateway() internal { @@ -1274,10 +1264,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR)), - notnull(L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L2_PROXY_ADMIN_ADDR, L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR, L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR); } function deployL2ERC721Gateway() internal { @@ -1289,10 +1276,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_ERC721_GATEWAY_PROXY_ADDR)), - notnull(L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L2_PROXY_ADMIN_ADDR, L2_ERC721_GATEWAY_PROXY_ADDR, L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR); } function deployL2ERC1155Gateway() internal { @@ -1304,10 +1288,7 @@ contract DeployScroll is DeterminsticDeploymentScript { args ); - ProxyAdmin(L2_PROXY_ADMIN_ADDR).upgrade( - ITransparentUpgradeableProxy(notnull(L2_ERC1155_GATEWAY_PROXY_ADDR)), - notnull(L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR) - ); + upgrade(L2_PROXY_ADMIN_ADDR, L2_ERC1155_GATEWAY_PROXY_ADDR, L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR); } /********************** @@ -1567,41 +1548,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } } -contract GenerateGenesisAlloc is DeterminsticDeploymentScript { - using stdToml for string; - - /*************************** - * Configuration parameters * - ***************************/ - - // generated - address L2_SCROLL_MESSENGER_PROXY_ADDR; - - function initConfig() private { - // deterministically predict L2ScrollMessengerProxy address - L2_SCROLL_MESSENGER_PROXY_ADDR = predictL2MessengerProxyAddress(); - } - - function predictL2MessengerProxyAddress() private view returns (address) { - bytes memory args = abi.encode(DEPLOYER_ADDR); - address L2_PROXY_ADMIN_ADDR = predict("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); - - address L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( - "L2_PROXY_IMPLEMENTATION_PLACEHOLDER", - type(EmptyContract).creationCode - ); - - bytes memory args2 = abi.encode(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR, L2_PROXY_ADMIN_ADDR, new bytes(0)); - - address predictedAddr = predict( - "L2_SCROLL_MESSENGER_PROXY", - type(TransparentUpgradeableProxy).creationCode, - args2 - ); - - return predictedAddr; - } - +contract GenerateGenesisAlloc is DeployScroll { /************* * Utilities * ************/ @@ -1620,7 +1567,7 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { **************/ function run() public { - initConfig(); + predictAllContracts(); // predeploys setL2MessageQueue(); @@ -1765,131 +1712,13 @@ contract GenerateGenesisAlloc is DeterminsticDeploymentScript { } } -contract GenerateGenesis is DeterminsticDeploymentScript { - using stdToml for string; - - /*************************** - * Configuration parameters * - ***************************/ - - address L1_MESSAGE_QUEUE_PROXY_ADDR; - address L1_SCROLL_CHAIN_PROXY_ADDR; - address L2_TX_FEE_VAULT_ADDR; - - function initConfig() private { - ( - L1_SCROLL_CHAIN_PROXY_ADDR, - L1_MESSAGE_QUEUE_PROXY_ADDR - ) = predictL1ScrollChainProxyAndL1MessageQueueProxyAddr(); - L2_TX_FEE_VAULT_ADDR = predictL2TxFeeVaultAddr(); - } - - function predictL1ScrollChainProxyAndL1MessageQueueProxyAddr() private returns (address, address) { - bytes memory args = abi.encode(DEPLOYER_ADDR); - address L1_PROXY_ADMIN_ADDR = predict("L1_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); - - address L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( - "L1_PROXY_IMPLEMENTATION_PLACEHOLDER", - type(EmptyContract).creationCode - ); - - args = abi.encode( - notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), - notnull(L1_PROXY_ADMIN_ADDR), - new bytes(0) - ); - - address L1_SCROLL_MESSENGER_PROXY_ADDR = predict( - "L1_SCROLL_MESSENGER_PROXY", - type(TransparentUpgradeableProxy).creationCode, - args - ); - - address L1_SCROLL_CHAIN_PROXY_ADDR_PREDICTED = predict( - "L1_SCROLL_CHAIN_PROXY", - type(TransparentUpgradeableProxy).creationCode, - args - ); - - address L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = predict( - "L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION", - type(EnforcedTxGateway).creationCode - ); - - args = abi.encode( - notnull(L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR), - notnull(L1_PROXY_ADMIN_ADDR), - new bytes(0) - ); - - address L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = predict( - "L1_ENFORCED_TX_GATEWAY_PROXY", - type(TransparentUpgradeableProxy).creationCode, - args - ); - - args = abi.encode( - notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), - notnull(L1_SCROLL_CHAIN_PROXY_ADDR_PREDICTED), - notnull(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR) - ); - - address L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = predict( - "L1_MESSAGE_QUEUE_IMPLEMENTATION", - type(L1MessageQueueWithGasPriceOracle).creationCode, - args - ); - - args = abi.encode(notnull(L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR), notnull(L1_PROXY_ADMIN_ADDR), new bytes(0)); - - address L1_MESSAGE_QUEUE_PROXY_ADDR_PREDICTED = predict( - "L1_MESSAGE_QUEUE_PROXY", - type(TransparentUpgradeableProxy).creationCode, - args - ); - - return (L1_SCROLL_CHAIN_PROXY_ADDR_PREDICTED, L1_MESSAGE_QUEUE_PROXY_ADDR_PREDICTED); - } - - function predictL1ScrollChainProxyAddr() private returns (address) { - bytes memory args = abi.encode(DEPLOYER_ADDR); - address L1_PROXY_ADMIN_ADDR = predict("L1_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); - - address L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = predict( - "L1_PROXY_IMPLEMENTATION_PLACEHOLDER", - type(EmptyContract).creationCode - ); - - args = abi.encode( - notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), - notnull(L1_PROXY_ADMIN_ADDR), - new bytes(0) - ); - - address predictedAddr = predict("L1_SCROLL_CHAIN_PROXY", type(TransparentUpgradeableProxy).creationCode, args); - - return predictedAddr; - } - - function predictL2TxFeeVaultAddr() private returns (address) { - address predeployAddr = tryGetOverride("L2_TX_FEE_VAULT"); - - if (predeployAddr != address(0)) { - return predeployAddr; - } - - bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); - address predictedAddr = predict("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); - - return predictedAddr; - } - +contract GenerateGenesis is DeployScroll { /*************** * Entry point * **************/ function run() public { - initConfig(); + predictAllContracts(); // general config vm.writeJson(vm.toString(CHAIN_ID_L2), GENESIS_JSON_PATH, ".config.chainId"); From 421cd7e96ddeb87a5af67e378185074e349a7635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 19:30:42 +0800 Subject: [PATCH 10/38] clean up --- contracts/scripts/foundry/DeployScroll.s.sol | 580 ++++++++++--------- 1 file changed, 322 insertions(+), 258 deletions(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 0adac03427..615861bbf6 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -55,7 +55,7 @@ uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; // configuration file paths string constant CONFIG_PATH = "./configuration/config.toml"; string constant CONTRACTS_CONFIG_PATH = "./configuration/config-contracts.toml"; -string constant GENESIS_ALLOC_JSON_PATH = "./configuration/genesis-alloc.json"; +string constant GENESIS_ALLOC_JSON_PATH = "./configuration/__genesis-alloc.json"; string constant GENESIS_JSON_PATH = "./configuration/genesis.json"; contract ProxyAdminSetOwner is ProxyAdmin { @@ -87,24 +87,20 @@ contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory { } } -contract Configuration is Script { +/// @notice Configuration allows inheriting contracts to read the TOML configuration file. +abstract contract Configuration is Script { using stdToml for string; - enum ScriptMode { - None, - LogAddresses, - WriteConfig, - VerifyConfig - } + /******************* + * State variables * + *******************/ string internal cfg; string internal contractsCfg; - ScriptMode internal mode = ScriptMode.None; - - /*************************** + /**************************** * Configuration parameters * - ***************************/ + ****************************/ // general uint64 internal CHAIN_ID_L1; @@ -138,21 +134,28 @@ contract Configuration is Script { /*************** * Constructor * - **************/ + ***************/ constructor() { cfg = vm.readFile(CONFIG_PATH); contractsCfg = vm.readFile(CONTRACTS_CONFIG_PATH); - DEPLOYMENT_SALT = cfg.readString(".contracts.DEPLOYMENT_SALT"); - CHAIN_ID_L1 = uint64(cfg.readUint(".general.CHAIN_ID_L1")); CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); + + L1_COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.L1_COMMIT_SENDER_ADDR"); + L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.L1_FINALIZE_SENDER_ADDR"); + L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L1_GAS_ORACLE_SENDER_ADDR"); + L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L2_GAS_ORACLE_SENDER_ADDR"); + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); + OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); + + L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); // config sanity check if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { @@ -160,37 +163,19 @@ contract Configuration is Script { revert(); } - OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); + L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); + L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); + L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; - L1_COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.L1_COMMIT_SENDER_ADDR"); - L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.L1_FINALIZE_SENDER_ADDR"); - L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L1_GAS_ORACLE_SENDER_ADDR"); - L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L2_GAS_ORACLE_SENDER_ADDR"); - L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); + DEPLOYMENT_SALT = cfg.readString(".contracts.DEPLOYMENT_SALT"); L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); - - L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); - L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); - L2_SCROLL_MESSENGER_INITIAL_BALANCE = L2_MAX_ETH_SUPPLY - L2_DEPLOYER_INITIAL_BALANCE; } - /************* - * Utilities * - ************/ - - function parseScriptMode(string memory raw) internal pure returns (ScriptMode) { - if (keccak256(bytes(raw)) == keccak256(bytes("log-addresses"))) { - return ScriptMode.WriteConfig; - } else if (keccak256(bytes(raw)) == keccak256(bytes("write-config"))) { - return ScriptMode.WriteConfig; - } else if (keccak256(bytes(raw)) == keccak256(bytes("verify-config"))) { - return ScriptMode.VerifyConfig; - } else { - return ScriptMode.None; - } - } + /********************** + * Internal interface * + **********************/ /// @dev Ensure that `addr` is not the zero address. /// This helps catch bugs arising from incorrect deployment order. @@ -199,54 +184,77 @@ contract Configuration is Script { return addr; } - function label(string memory name, address addr) internal { - vm.label(addr, name); + function tryGetOverride(string memory name) internal returns (address) { + address addr; + string memory key = string(abi.encodePacked(".contracts.overrides.", name)); - if (mode == ScriptMode.LogAddresses) { - console.log(string(abi.encodePacked(name, "_ADDR=", vm.toString(address(addr))))); + if (!vm.keyExistsToml(cfg, key)) { + return address(0); } - string memory tomlPath = string(abi.encodePacked(".", name, "_ADDR")); - - if (mode == ScriptMode.WriteConfig) { - vm.writeToml(vm.toString(addr), CONTRACTS_CONFIG_PATH, tomlPath); - } + addr = cfg.readAddress(key); - if (mode == ScriptMode.VerifyConfig) { - address expectedAddr = contractsCfg.readAddress(tomlPath); + if (addr.code.length == 0) { + (VmSafe.CallerMode callerMode, , ) = vm.readCallers(); - if (addr != expectedAddr) { + // if we're ready to start broadcasting transactions, then we + // must ensure that the override contract has been deployed. + if (callerMode == VmSafe.CallerMode.Broadcast || callerMode == VmSafe.CallerMode.RecurrentBroadcast) { console.log( string( abi.encodePacked( - "[ERROR] unexpected address for ", + "[ERROR] override ", name, - ", expected = ", - vm.toString(expectedAddr), - " (from toml config), got = ", - vm.toString(addr) + " = ", + vm.toString(addr), + " not deployed in broadcast mode" ) ) ); - revert(); } } + + return addr; } } -contract DeterminsticDeploymentScript is Configuration { +/// @notice DeterminsticDeployment provides utilities for deterministic contract deployments. +abstract contract DeterminsticDeployment is Configuration { using stdToml for string; - string private SALT_PREFIX; - bool internal SKIP_DEPLOY = false; + /********* + * Types * + *********/ + + enum ScriptMode { + None, + LogAddresses, + WriteConfig, + VerifyConfig + } + + /******************* + * State variables * + *******************/ + + ScriptMode private mode; + string private saltPrefix; + bool private skipDeploy; + + /*************** + * Constructor * + ***************/ constructor() { + mode = ScriptMode.None; + skipDeploy = false; + // salt prefix used for deterministic deployments if (bytes(DEPLOYMENT_SALT).length != 0) { - SALT_PREFIX = DEPLOYMENT_SALT; + saltPrefix = DEPLOYMENT_SALT; } else { - SALT_PREFIX = DEFAULT_DEPLOYMENT_SALT; + saltPrefix = DEFAULT_DEPLOYMENT_SALT; } // sanity check: make sure DeterministicDeploymentProxy exists @@ -264,19 +272,30 @@ contract DeterminsticDeploymentScript is Configuration { } } - function upgrade( - address proxyAdminAddr, - address proxyAddr, - address implAddr - ) internal { - if (!SKIP_DEPLOY) { - ProxyAdmin(notnull(proxyAdminAddr)).upgrade( - ITransparentUpgradeableProxy(notnull(proxyAddr)), - notnull(implAddr) - ); + /********************** + * Internal interface * + **********************/ + + function setScriptMode(ScriptMode scriptMode) internal { + mode = scriptMode; + } + + function setScriptMode(string memory scriptMode) internal { + if (keccak256(bytes(scriptMode)) == keccak256(bytes("log-addresses"))) { + mode = ScriptMode.WriteConfig; + } else if (keccak256(bytes(scriptMode)) == keccak256(bytes("write-config"))) { + mode = ScriptMode.WriteConfig; + } else if (keccak256(bytes(scriptMode)) == keccak256(bytes("verify-config"))) { + mode = ScriptMode.VerifyConfig; + } else { + mode = ScriptMode.None; } } + function skipDeployment() internal { + skipDeploy = true; + } + function deploy(string memory name, bytes memory codeWithArgs) internal returns (address) { return _deploy(name, codeWithArgs); } @@ -301,20 +320,41 @@ contract DeterminsticDeploymentScript is Configuration { return _predict(name, abi.encodePacked(code, args)); } + function upgrade( + address proxyAdminAddr, + address proxyAddr, + address implAddr + ) internal { + if (!skipDeploy) { + ProxyAdmin(notnull(proxyAdminAddr)).upgrade( + ITransparentUpgradeableProxy(notnull(proxyAddr)), + notnull(implAddr) + ); + } + } + + /********************* + * Private functions * + *********************/ + + function _getSalt(string memory name) internal view returns (bytes32) { + return keccak256(abi.encodePacked(saltPrefix, name)); + } + function _deploy(string memory name, bytes memory codeWithArgs) private returns (address) { // check override (mainly used with predeploys) address addr = tryGetOverride(name); if (addr != address(0)) { - label(name, addr); + _label(name, addr); return addr; } // predict determinstic deployment address addr = _predict(name, codeWithArgs); - label(name, addr); + _label(name, addr); - if (SKIP_DEPLOY) { + if (skipDeploy) { return addr; } @@ -335,44 +375,6 @@ contract DeterminsticDeploymentScript is Configuration { return addr; } - function tryGetOverride(string memory name) internal returns (address) { - address addr; - string memory key = string(abi.encodePacked(".contracts.overrides.", name)); - - if (!vm.keyExistsToml(cfg, key)) { - return address(0); - } - - addr = cfg.readAddress(key); - - if (addr.code.length == 0) { - (VmSafe.CallerMode callerMode, , ) = vm.readCallers(); - - // if we're ready to start broadcasting transactions, then we - // must ensure that the override contract has been deployed. - if (callerMode == VmSafe.CallerMode.Broadcast || callerMode == VmSafe.CallerMode.RecurrentBroadcast) { - console.log( - string( - abi.encodePacked( - "[ERROR] override ", - name, - " = ", - vm.toString(addr), - " not deployed in broadcast mode" - ) - ) - ); - revert(); - } - } - - return addr; - } - - function _getSalt(string memory name) internal view returns (bytes32) { - return keccak256(abi.encodePacked(SALT_PREFIX, name)); - } - function _predict(string memory name, bytes memory codeWithArgs) private view returns (address) { bytes32 salt = _getSalt(name); @@ -392,25 +394,70 @@ contract DeterminsticDeploymentScript is Configuration { ) ); } + + function _label(string memory name, address addr) internal { + vm.label(addr, name); + + if (mode == ScriptMode.None) { + return; + } + + if (mode == ScriptMode.LogAddresses) { + console.log(string(abi.encodePacked(name, "_ADDR=", vm.toString(address(addr))))); + return; + } + + string memory tomlPath = string(abi.encodePacked(".", name, "_ADDR")); + + if (mode == ScriptMode.WriteConfig) { + vm.writeToml(vm.toString(addr), CONTRACTS_CONFIG_PATH, tomlPath); + return; + } + + if (mode == ScriptMode.VerifyConfig) { + address expectedAddr = contractsCfg.readAddress(tomlPath); + + if (addr != expectedAddr) { + console.log( + string( + abi.encodePacked( + "[ERROR] unexpected address for ", + name, + ", expected = ", + vm.toString(expectedAddr), + " (from toml config), got = ", + vm.toString(addr) + ) + ) + ); + + revert(); + } + } + } } -contract DeployScroll is DeterminsticDeploymentScript { +contract DeployScroll is DeterminsticDeployment { + /********* + * Types * + *********/ + enum Layer { None, L1, L2 } - /*************************** - * Configuration parameters * - ***************************/ + /******************* + * State variables * + *******************/ // general configurations - Layer internal BROADCAST_LAYER = Layer.None; + Layer private broadcastLayer = Layer.None; - /********************** + /*********************** * Contracts to deploy * - **********************/ + ***********************/ // L1 addresses address internal L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR; @@ -471,23 +518,13 @@ contract DeployScroll is DeterminsticDeploymentScript { address internal L2_WETH_GATEWAY_PROXY_ADDR; address internal L2_WHITELIST_ADDR; - /************ + /************* * Utilities * - ************/ - - function parseLayer(string memory raw) internal pure returns (Layer) { - if (keccak256(bytes(raw)) == keccak256(bytes("L1"))) { - return Layer.L1; - } else if (keccak256(bytes(raw)) == keccak256(bytes("L2"))) { - return Layer.L2; - } else { - return Layer.None; - } - } + *************/ /// @dev Only broadcast code block if we run the script on the specified layer. modifier broadcast(Layer layer) { - if (BROADCAST_LAYER == layer) { + if (broadcastLayer == layer) { vm.startBroadcast(DEPLOYER_PRIVATE_KEY); } else { // make sure we use the correct sender in simulation @@ -496,7 +533,7 @@ contract DeployScroll is DeterminsticDeploymentScript { _; - if (BROADCAST_LAYER == layer) { + if (broadcastLayer == layer) { vm.stopBroadcast(); } else { vm.stopPrank(); @@ -505,7 +542,7 @@ contract DeployScroll is DeterminsticDeploymentScript { /// @dev Only execute block if we run the script on the specified layer. modifier only(Layer layer) { - if (BROADCAST_LAYER != layer) { + if (broadcastLayer != layer) { return; } _; @@ -513,31 +550,49 @@ contract DeployScroll is DeterminsticDeploymentScript { /*************** * Entry point * - **************/ + ***************/ function run(string memory layer, string memory scriptMode) public { - BROADCAST_LAYER = parseLayer(layer); - mode = parseScriptMode(scriptMode); + broadcastLayer = parseLayer(layer); + setScriptMode(scriptMode); deployAllContracts(); initializeL1Contracts(); initializeL2Contracts(); } - function deployAllContracts() internal { + /********************** + * Internal interface * + **********************/ + + function predictAllContracts() internal { + skipDeployment(); + deployAllContracts(); + } + + /********************* + * Private functions * + *********************/ + + function parseLayer(string memory raw) private pure returns (Layer) { + if (keccak256(bytes(raw)) == keccak256(bytes("L1"))) { + return Layer.L1; + } else if (keccak256(bytes(raw)) == keccak256(bytes("L2"))) { + return Layer.L2; + } else { + return Layer.None; + } + } + + function deployAllContracts() private { deployL1Contracts1stPass(); deployL2Contracts1stPass(); deployL1Contracts2ndPass(); deployL2Contracts2ndPass(); } - function predictAllContracts() internal { - SKIP_DEPLOY = true; - deployAllContracts(); - } - // @notice deployL1Contracts1stPass deploys L1 contracts whose initialization does not depend on any L2 addresses. - function deployL1Contracts1stPass() internal broadcast(Layer.L1) { + function deployL1Contracts1stPass() private broadcast(Layer.L1) { deployL1Weth(); deployL1ProxyAdmin(); deployL1PlaceHolder(); @@ -560,7 +615,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL2Contracts1stPass deploys L2 contracts whose initialization does not depend on any L1 addresses. - function deployL2Contracts1stPass() internal broadcast(Layer.L2) { + function deployL2Contracts1stPass() private broadcast(Layer.L2) { deployL2MessageQueue(); deployL1GasPriceOracle(); deployL2Whitelist(); @@ -579,7 +634,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL1Contracts2ndPass deploys L1 contracts whose initialization depends on some L2 addresses. - function deployL1Contracts2ndPass() internal broadcast(Layer.L1) { + function deployL1Contracts2ndPass() private broadcast(Layer.L1) { deployL1ScrollMessenger(); deployL1StandardERC20Gateway(); deployL1ETHGateway(); @@ -590,7 +645,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice deployL2Contracts2ndPass deploys L2 contracts whose initialization depends on some L1 addresses. - function deployL2Contracts2ndPass() internal broadcast(Layer.L2) { + function deployL2Contracts2ndPass() private broadcast(Layer.L2) { // upgradable deployL2ScrollMessenger(); deployL2GatewayRouter(); @@ -603,7 +658,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice initializeL1Contracts initializes contracts deployed on L1. - function initializeL1Contracts() internal broadcast(Layer.L1) only(Layer.L1) { + function initializeL1Contracts() private broadcast(Layer.L1) only(Layer.L1) { initializeScrollChain(); initializeL2GasPriceOracle(); initializeL1MessageQueue(); @@ -622,7 +677,7 @@ contract DeployScroll is DeterminsticDeploymentScript { } // @notice initializeL2Contracts initializes contracts deployed on L2. - function initializeL2Contracts() internal broadcast(Layer.L2) only(Layer.L2) { + function initializeL2Contracts() private broadcast(Layer.L2) only(Layer.L2) { initializeL2MessageQueue(); initializeL2TxFeeVault(); initializeL1GasPriceOracle(); @@ -642,30 +697,30 @@ contract DeployScroll is DeterminsticDeploymentScript { /*************************** * L1: 1st pass deployment * - **************************/ + ***************************/ - function deployL1Weth() internal { + function deployL1Weth() private { L1_WETH_ADDR = deploy("L1_WETH", type(WrappedEther).creationCode); } - function deployL1ProxyAdmin() internal { + function deployL1ProxyAdmin() private { bytes memory args = abi.encode(DEPLOYER_ADDR); L1_PROXY_ADMIN_ADDR = deploy("L1_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); } - function deployL1PlaceHolder() internal { + function deployL1PlaceHolder() private { L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy( "L1_PROXY_IMPLEMENTATION_PLACEHOLDER", type(EmptyContract).creationCode ); } - function deployL1Whitelist() internal { + function deployL1Whitelist() private { bytes memory args = abi.encode(DEPLOYER_ADDR); L1_WHITELIST_ADDR = deploy("L1_WHITELIST", type(Whitelist).creationCode, args); } - function deployL2GasPriceOracle() internal { + function deployL2GasPriceOracle() private { L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR = deploy( "L2_GAS_PRICE_ORACLE_IMPLEMENTATION", type(L2GasPriceOracle).creationCode @@ -684,7 +739,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ScrollChainProxy() internal { + function deployL1ScrollChainProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -698,7 +753,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ScrollMessengerProxy() internal { + function deployL1ScrollMessengerProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -712,7 +767,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1EnforcedTxGateway() internal { + function deployL1EnforcedTxGateway() private { L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR = deploy( "L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION", type(EnforcedTxGateway).creationCode @@ -731,12 +786,12 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ZkEvmVerifierV1() internal { + function deployL1ZkEvmVerifierV1() private { bytes memory args = abi.encode(notnull(L1_PLONK_VERIFIER_ADDR)); L1_ZKEVM_VERIFIER_V1_ADDR = deploy("L1_ZKEVM_VERIFIER_V1", type(ZkEvmVerifierV1).creationCode, args); } - function deployL1MultipleVersionRollupVerifier() internal { + function deployL1MultipleVersionRollupVerifier() private { uint256[] memory _versions = new uint256[](1); address[] memory _verifiers = new address[](1); _versions[0] = 1; @@ -751,7 +806,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1MessageQueue() internal { + function deployL1MessageQueue() private { bytes memory args = abi.encode( notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), notnull(L1_SCROLL_CHAIN_PROXY_ADDR), @@ -777,7 +832,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ScrollChain() internal { + function deployL1ScrollChain() private { bytes memory args = abi.encode( CHAIN_ID_L2, notnull(L1_MESSAGE_QUEUE_PROXY_ADDR), @@ -793,7 +848,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L1_PROXY_ADMIN_ADDR, L1_SCROLL_CHAIN_PROXY_ADDR, L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR); } - function deployL1GatewayRouter() internal { + function deployL1GatewayRouter() private { L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy( "L1_GATEWAY_ROUTER_IMPLEMENTATION", type(L1GatewayRouter).creationCode @@ -812,7 +867,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ETHGatewayProxy() internal { + function deployL1ETHGatewayProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -826,7 +881,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1WETHGatewayProxy() internal { + function deployL1WETHGatewayProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -840,7 +895,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1StandardERC20GatewayProxy() internal { + function deployL1StandardERC20GatewayProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -854,7 +909,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1CustomERC20GatewayProxy() internal { + function deployL1CustomERC20GatewayProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -868,7 +923,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ERC721GatewayProxy() internal { + function deployL1ERC721GatewayProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -882,7 +937,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1ERC1155GatewayProxy() internal { + function deployL1ERC1155GatewayProxy() private { bytes memory args = abi.encode( notnull(L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L1_PROXY_ADMIN_ADDR), @@ -898,45 +953,45 @@ contract DeployScroll is DeterminsticDeploymentScript { /*************************** * L2: 1st pass deployment * - **************************/ + ***************************/ - function deployL2MessageQueue() internal { + function deployL2MessageQueue() private { bytes memory args = abi.encode(DEPLOYER_ADDR); L2_MESSAGE_QUEUE_ADDR = deploy("L2_MESSAGE_QUEUE", type(L2MessageQueue).creationCode, args); } - function deployL1GasPriceOracle() internal { + function deployL1GasPriceOracle() private { bytes memory args = abi.encode(DEPLOYER_ADDR); L1_GAS_PRICE_ORACLE_ADDR = deploy("L1_GAS_PRICE_ORACLE", type(L1GasPriceOracle).creationCode, args); } - function deployL2Whitelist() internal { + function deployL2Whitelist() private { bytes memory args = abi.encode(DEPLOYER_ADDR); L2_WHITELIST_ADDR = deploy("L2_WHITELIST", type(Whitelist).creationCode, args); } - function deployL2Weth() internal { + function deployL2Weth() private { L2_WETH_ADDR = deploy("L2_WETH", type(WrappedEther).creationCode); } - function deployTxFeeVault() internal { + function deployTxFeeVault() private { bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); L2_TX_FEE_VAULT_ADDR = deploy("L2_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); } - function deployL2ProxyAdmin() internal { + function deployL2ProxyAdmin() private { bytes memory args = abi.encode(DEPLOYER_ADDR); L2_PROXY_ADMIN_ADDR = deploy("L2_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); } - function deployL2PlaceHolder() internal { + function deployL2PlaceHolder() private { L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy( "L2_PROXY_IMPLEMENTATION_PLACEHOLDER", type(EmptyContract).creationCode ); } - function deployL2ScrollMessengerProxy() internal { + function deployL2ScrollMessengerProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -950,7 +1005,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2StandardERC20GatewayProxy() internal { + function deployL2StandardERC20GatewayProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -964,7 +1019,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2ETHGatewayProxy() internal { + function deployL2ETHGatewayProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -978,7 +1033,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2WETHGatewayProxy() internal { + function deployL2WETHGatewayProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -992,7 +1047,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2CustomERC20GatewayProxy() internal { + function deployL2CustomERC20GatewayProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -1006,7 +1061,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2ERC721GatewayProxy() internal { + function deployL2ERC721GatewayProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -1020,7 +1075,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2ERC1155GatewayProxy() internal { + function deployL2ERC1155GatewayProxy() private { bytes memory args = abi.encode( notnull(L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR), notnull(L2_PROXY_ADMIN_ADDR), @@ -1034,7 +1089,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployScrollStandardERC20Factory() internal { + function deployScrollStandardERC20Factory() private { L2_SCROLL_STANDARD_ERC20_ADDR = deploy("L2_SCROLL_STANDARD_ERC20", type(ScrollStandardERC20).creationCode); bytes memory args = abi.encode(DEPLOYER_ADDR, notnull(L2_SCROLL_STANDARD_ERC20_ADDR)); @@ -1047,9 +1102,9 @@ contract DeployScroll is DeterminsticDeploymentScript { /*************************** * L1: 2nd pass deployment * - **************************/ + ***************************/ - function deployL1ScrollMessenger() internal { + function deployL1ScrollMessenger() private { bytes memory args = abi.encode( notnull(L2_SCROLL_MESSENGER_PROXY_ADDR), notnull(L1_SCROLL_CHAIN_PROXY_ADDR), @@ -1065,7 +1120,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L1_PROXY_ADMIN_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR, L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR); } - function deployL1ETHGateway() internal { + function deployL1ETHGateway() private { bytes memory args = abi.encode( notnull(L2_ETH_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1081,7 +1136,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L1_PROXY_ADMIN_ADDR, L1_ETH_GATEWAY_PROXY_ADDR, L1_ETH_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL1WETHGateway() internal { + function deployL1WETHGateway() private { bytes memory args = abi.encode( notnull(L1_WETH_ADDR), notnull(L2_WETH_ADDR), @@ -1099,7 +1154,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L1_PROXY_ADMIN_ADDR, L1_WETH_GATEWAY_PROXY_ADDR, L1_WETH_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL1StandardERC20Gateway() internal { + function deployL1StandardERC20Gateway() private { bytes memory args = abi.encode( notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1121,7 +1176,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL1CustomERC20Gateway() internal { + function deployL1CustomERC20Gateway() private { bytes memory args = abi.encode( notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1137,7 +1192,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L1_PROXY_ADMIN_ADDR, L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR, L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL1ERC721Gateway() internal { + function deployL1ERC721Gateway() private { bytes memory args = abi.encode(notnull(L2_ERC721_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy( @@ -1149,7 +1204,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L1_PROXY_ADMIN_ADDR, L1_ERC721_GATEWAY_PROXY_ADDR, L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL1ERC1155Gateway() internal { + function deployL1ERC1155Gateway() private { bytes memory args = abi.encode(notnull(L2_ERC1155_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy( @@ -1163,9 +1218,9 @@ contract DeployScroll is DeterminsticDeploymentScript { /*************************** * L2: 2nd pass deployment * - **************************/ + ***************************/ - function deployL2ScrollMessenger() internal { + function deployL2ScrollMessenger() private { bytes memory args = abi.encode(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), notnull(L2_MESSAGE_QUEUE_ADDR)); L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = deploy( @@ -1177,7 +1232,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L2_PROXY_ADMIN_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR, L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR); } - function deployL2GatewayRouter() internal { + function deployL2GatewayRouter() private { L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR = deploy( "L2_GATEWAY_ROUTER_IMPLEMENTATION", type(L2GatewayRouter).creationCode @@ -1196,7 +1251,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2StandardERC20Gateway() internal { + function deployL2StandardERC20Gateway() private { bytes memory args = abi.encode( notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1217,7 +1272,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function deployL2ETHGateway() internal { + function deployL2ETHGateway() private { bytes memory args = abi.encode( notnull(L1_ETH_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1233,7 +1288,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L2_PROXY_ADMIN_ADDR, L2_ETH_GATEWAY_PROXY_ADDR, L2_ETH_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL2WETHGateway() internal { + function deployL2WETHGateway() private { bytes memory args = abi.encode( notnull(L2_WETH_ADDR), notnull(L1_WETH_ADDR), @@ -1251,7 +1306,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L2_PROXY_ADMIN_ADDR, L2_WETH_GATEWAY_PROXY_ADDR, L2_WETH_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL2CustomERC20Gateway() internal { + function deployL2CustomERC20Gateway() private { bytes memory args = abi.encode( notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1267,7 +1322,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L2_PROXY_ADMIN_ADDR, L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR, L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL2ERC721Gateway() internal { + function deployL2ERC721Gateway() private { bytes memory args = abi.encode(notnull(L1_ERC721_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR = deploy( @@ -1279,7 +1334,7 @@ contract DeployScroll is DeterminsticDeploymentScript { upgrade(L2_PROXY_ADMIN_ADDR, L2_ERC721_GATEWAY_PROXY_ADDR, L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR); } - function deployL2ERC1155Gateway() internal { + function deployL2ERC1155Gateway() private { bytes memory args = abi.encode(notnull(L1_ERC1155_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = deploy( @@ -1293,9 +1348,9 @@ contract DeployScroll is DeterminsticDeploymentScript { /********************** * L1: initialization * - *********************/ + **********************/ - function initializeScrollChain() internal { + function initializeScrollChain() private { ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).initialize( notnull(L1_MESSAGE_QUEUE_PROXY_ADDR), notnull(L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR), @@ -1306,7 +1361,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addProver(L1_FINALIZE_SENDER_ADDR); } - function initializeL2GasPriceOracle() internal { + function initializeL2GasPriceOracle() private { L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).initialize( 21000, // _txGas 53000, // _txGasContractCreation @@ -1317,7 +1372,7 @@ contract DeployScroll is DeterminsticDeploymentScript { L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).updateWhitelist(L1_WHITELIST_ADDR); } - function initializeL1MessageQueue() internal { + function initializeL1MessageQueue() private { L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initialize( notnull(L1_SCROLL_MESSENGER_PROXY_ADDR), notnull(L1_SCROLL_CHAIN_PROXY_ADDR), @@ -1329,7 +1384,7 @@ contract DeployScroll is DeterminsticDeploymentScript { L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initializeV2(); } - function initializeL1ScrollMessenger() internal { + function initializeL1ScrollMessenger() private { L1ScrollMessenger(payable(L1_SCROLL_MESSENGER_PROXY_ADDR)).initialize( notnull(L2_SCROLL_MESSENGER_PROXY_ADDR), notnull(L1_FEE_VAULT_ADDR), @@ -1338,7 +1393,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeEnforcedTxGateway() internal { + function initializeEnforcedTxGateway() private { EnforcedTxGateway(payable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR)).initialize( notnull(L1_MESSAGE_QUEUE_PROXY_ADDR), notnull(L1_FEE_VAULT_ADDR) @@ -1348,14 +1403,14 @@ contract DeployScroll is DeterminsticDeploymentScript { EnforcedTxGateway(payable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR)).setPause(true); } - function initializeL1GatewayRouter() internal { + function initializeL1GatewayRouter() private { L1GatewayRouter(L1_GATEWAY_ROUTER_PROXY_ADDR).initialize( notnull(L1_ETH_GATEWAY_PROXY_ADDR), notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR) ); } - function initializeL1CustomERC20Gateway() internal { + function initializeL1CustomERC20Gateway() private { L1CustomERC20Gateway(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize( notnull(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1363,21 +1418,21 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeL1ERC1155Gateway() internal { + function initializeL1ERC1155Gateway() private { L1ERC1155Gateway(L1_ERC1155_GATEWAY_PROXY_ADDR).initialize( notnull(L2_ERC1155_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) ); } - function initializeL1ERC721Gateway() internal { + function initializeL1ERC721Gateway() private { L1ERC721Gateway(L1_ERC721_GATEWAY_PROXY_ADDR).initialize( notnull(L2_ERC721_GATEWAY_PROXY_ADDR), notnull(L1_SCROLL_MESSENGER_PROXY_ADDR) ); } - function initializeL1ETHGateway() internal { + function initializeL1ETHGateway() private { L1ETHGateway(L1_ETH_GATEWAY_PROXY_ADDR).initialize( notnull(L2_ETH_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1385,7 +1440,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeL1StandardERC20Gateway() internal { + function initializeL1StandardERC20Gateway() private { L1StandardERC20Gateway(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize( notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1395,7 +1450,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeL1WETHGateway() internal { + function initializeL1WETHGateway() private { L1WETHGateway(payable(L1_WETH_GATEWAY_PROXY_ADDR)).initialize( notnull(L2_WETH_GATEWAY_PROXY_ADDR), notnull(L1_GATEWAY_ROUTER_PROXY_ADDR), @@ -1412,13 +1467,13 @@ contract DeployScroll is DeterminsticDeploymentScript { } } - function initializeL1Whitelist() internal { + function initializeL1Whitelist() private { address[] memory accounts = new address[](1); accounts[0] = L1_GAS_ORACLE_SENDER_ADDR; Whitelist(L1_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); } - function transferL1ContractOwnership() internal { + function transferL1ContractOwnership() private { Ownable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); Ownable(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); Ownable(L1_ERC1155_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); @@ -1438,32 +1493,32 @@ contract DeployScroll is DeterminsticDeploymentScript { /********************** * L2: initialization * - *********************/ + **********************/ - function initializeL2MessageQueue() internal { + function initializeL2MessageQueue() private { L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).initialize(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); } - function initializeL2TxFeeVault() internal { + function initializeL2TxFeeVault() private { L2TxFeeVault(payable(L2_TX_FEE_VAULT_ADDR)).updateMessenger(notnull(L2_SCROLL_MESSENGER_PROXY_ADDR)); } - function initializeL1GasPriceOracle() internal { + function initializeL1GasPriceOracle() private { L1GasPriceOracle(L1_GAS_PRICE_ORACLE_ADDR).updateWhitelist(notnull(L2_WHITELIST_ADDR)); } - function initializeL2ScrollMessenger() internal { + function initializeL2ScrollMessenger() private { L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).initialize(notnull(L1_SCROLL_MESSENGER_PROXY_ADDR)); } - function initializeL2GatewayRouter() internal { + function initializeL2GatewayRouter() private { L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).initialize( notnull(L2_ETH_GATEWAY_PROXY_ADDR), notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR) ); } - function initializeL2CustomERC20Gateway() internal { + function initializeL2CustomERC20Gateway() private { L2CustomERC20Gateway(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize( notnull(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1471,21 +1526,21 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeL2ERC1155Gateway() internal { + function initializeL2ERC1155Gateway() private { L2ERC1155Gateway(L2_ERC1155_GATEWAY_PROXY_ADDR).initialize( notnull(L1_ERC1155_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) ); } - function initializeL2ERC721Gateway() internal { + function initializeL2ERC721Gateway() private { L2ERC721Gateway(L2_ERC721_GATEWAY_PROXY_ADDR).initialize( notnull(L1_ERC721_GATEWAY_PROXY_ADDR), notnull(L2_SCROLL_MESSENGER_PROXY_ADDR) ); } - function initializeL2ETHGateway() internal { + function initializeL2ETHGateway() private { L2ETHGateway(L2_ETH_GATEWAY_PROXY_ADDR).initialize( notnull(L1_ETH_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1493,7 +1548,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeL2StandardERC20Gateway() internal { + function initializeL2StandardERC20Gateway() private { L2StandardERC20Gateway(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize( notnull(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1502,7 +1557,7 @@ contract DeployScroll is DeterminsticDeploymentScript { ); } - function initializeL2WETHGateway() internal { + function initializeL2WETHGateway() private { L2WETHGateway(payable(L2_WETH_GATEWAY_PROXY_ADDR)).initialize( notnull(L1_WETH_GATEWAY_PROXY_ADDR), notnull(L2_GATEWAY_ROUTER_PROXY_ADDR), @@ -1519,19 +1574,19 @@ contract DeployScroll is DeterminsticDeploymentScript { } } - function initializeScrollStandardERC20Factory() internal { + function initializeScrollStandardERC20Factory() private { ScrollStandardERC20Factory(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR).transferOwnership( notnull(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR) ); } - function initializeL2Whitelist() internal { + function initializeL2Whitelist() private { address[] memory accounts = new address[](1); accounts[0] = L2_GAS_ORACLE_SENDER_ADDR; Whitelist(L2_WHITELIST_ADDR).updateWhitelistStatus(accounts, true); } - function transferL2ContractOwnership() internal { + function transferL2ContractOwnership() private { Ownable(L1_GAS_PRICE_ORACLE_ADDR).transferOwnership(OWNER_ADDR); Ownable(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); Ownable(L2_ERC1155_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); @@ -1548,27 +1603,31 @@ contract DeployScroll is DeterminsticDeploymentScript { } } -contract GenerateGenesisAlloc is DeployScroll { - /************* - * Utilities * - ************/ - - /// @notice Sorts the allocs by address - function sortJsonByKeys(string memory _path) internal { - string[] memory commands = new string[](3); - commands[0] = "bash"; - commands[1] = "-c"; - commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path); - vm.ffi(commands); - } - +contract GenerateGenesis is DeployScroll { /*************** * Entry point * - **************/ + ***************/ function run() public { + setScriptMode(ScriptMode.VerifyConfig); predictAllContracts(); + generateGenesisAlloc(); + generateGenesisJson(); + + // clean up temporary files + vm.removeFile(GENESIS_ALLOC_JSON_PATH); + } + + /********************* + * Private functions * + *********************/ + + function generateGenesisAlloc() private { + if (vm.exists(GENESIS_ALLOC_JSON_PATH)) { + vm.removeFile(GENESIS_ALLOC_JSON_PATH); + } + // predeploys setL2MessageQueue(); setL2GasPriceOracle(); @@ -1710,16 +1769,8 @@ contract GenerateGenesisAlloc is DeployScroll { function setL2Deployer() internal { vm.deal(OWNER_ADDR, L2_DEPLOYER_INITIAL_BALANCE); } -} - -contract GenerateGenesis is DeployScroll { - /*************** - * Entry point * - **************/ - - function run() public { - predictAllContracts(); + function generateGenesisJson() private { // general config vm.writeJson(vm.toString(CHAIN_ID_L2), GENESIS_JSON_PATH, ".config.chainId"); @@ -1732,6 +1783,7 @@ contract GenerateGenesis is DeployScroll { "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) ); + vm.writeJson(extraData, GENESIS_JSON_PATH, ".extraData"); // scroll-specific config @@ -1739,11 +1791,13 @@ contract GenerateGenesis is DeployScroll { vm.writeJson(vm.toString(L2_TX_FEE_VAULT_ADDR), GENESIS_JSON_PATH, ".config.scroll.feeVaultAddress"); vm.writeJson(vm.toString(CHAIN_ID_L1), GENESIS_JSON_PATH, ".config.scroll.l1Config.l1ChainId"); + vm.writeJson( vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), GENESIS_JSON_PATH, ".config.scroll.l1Config.l1MessageQueueAddress" ); + vm.writeJson( vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), GENESIS_JSON_PATH, @@ -1754,4 +1808,14 @@ contract GenerateGenesis is DeployScroll { string memory alloc = vm.readFile(GENESIS_ALLOC_JSON_PATH); vm.writeJson(alloc, GENESIS_JSON_PATH, ".alloc"); } + + /// @notice Sorts the allocs by address + // source: https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/scripts/L2Genesis.s.sol + function sortJsonByKeys(string memory _path) private { + string[] memory commands = new string[](3); + commands[0] = "bash"; + commands[1] = "-c"; + commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path); + vm.ffi(commands); + } } From 03fdd8eb0514bd92d5497ae1dc3e85a1a38a4abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 19:49:08 +0800 Subject: [PATCH 11/38] move files --- .../config-contracts.toml | 0 .../config.toml => data/config-example.toml} | 0 .../{configuration => data}/genesis.json | 0 contracts/data/input/.gitignore | 2 ++ contracts/data/output/.gitignore | 2 ++ contracts/foundry.toml | 7 +++- contracts/scripts/foundry/DeployScroll.s.sol | 33 +++++++++++++++---- 7 files changed, 36 insertions(+), 8 deletions(-) rename contracts/{configuration => data}/config-contracts.toml (100%) rename contracts/{configuration/config.toml => data/config-example.toml} (100%) rename contracts/{configuration => data}/genesis.json (100%) create mode 100644 contracts/data/input/.gitignore create mode 100644 contracts/data/output/.gitignore diff --git a/contracts/configuration/config-contracts.toml b/contracts/data/config-contracts.toml similarity index 100% rename from contracts/configuration/config-contracts.toml rename to contracts/data/config-contracts.toml diff --git a/contracts/configuration/config.toml b/contracts/data/config-example.toml similarity index 100% rename from contracts/configuration/config.toml rename to contracts/data/config-example.toml diff --git a/contracts/configuration/genesis.json b/contracts/data/genesis.json similarity index 100% rename from contracts/configuration/genesis.json rename to contracts/data/genesis.json diff --git a/contracts/data/input/.gitignore b/contracts/data/input/.gitignore new file mode 100644 index 0000000000..d6b7ef32c8 --- /dev/null +++ b/contracts/data/input/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/contracts/data/output/.gitignore b/contracts/data/output/.gitignore new file mode 100644 index 0000000000..d6b7ef32c8 --- /dev/null +++ b/contracts/data/output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/contracts/foundry.toml b/contracts/foundry.toml index c93a256e85..fd00eea889 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -31,6 +31,11 @@ bytecode_hash = 'none' # file system permissions ffi = true -fs_permissions = [{ access='read-write', path='./configuration' }] + +fs_permissions = [ + { access='read', path='./data' }, + { access='read', path='./data/input' }, + { access='read-write', path='./data/output' }, +] gas_reports = ["L2GasPriceOracle"] diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 615861bbf6..247113cd78 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -52,11 +52,17 @@ string constant DEFAULT_DEPLOYMENT_SALT = "ScrollStack"; /// @dev The default minimum withdraw amount configured on L2TxFeeVault. uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; -// configuration file paths -string constant CONFIG_PATH = "./configuration/config.toml"; -string constant CONTRACTS_CONFIG_PATH = "./configuration/config-contracts.toml"; -string constant GENESIS_ALLOC_JSON_PATH = "./configuration/__genesis-alloc.json"; -string constant GENESIS_JSON_PATH = "./configuration/genesis.json"; +// input files +string constant CONFIG_PATH = "./data/input/config.toml"; + +// template files +string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./data/config-contracts.toml"; +string constant GENESIS_JSON_TEMPLATE_PATH = "./data/genesis.json"; + +// output files +string constant CONFIG_CONTRACTS_PATH = "./data/output/config-contracts.toml"; +string constant GENESIS_ALLOC_JSON_PATH = "./data/output/__genesis-alloc.json"; +string constant GENESIS_JSON_PATH = "./data/output/genesis.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -137,8 +143,13 @@ abstract contract Configuration is Script { ***************/ constructor() { + if (!vm.exists(CONFIG_CONTRACTS_PATH)) { + string memory template = vm.readFile(CONFIG_CONTRACTS_TEMPLATE_PATH); + vm.writeFile(CONFIG_CONTRACTS_PATH, template); + } + cfg = vm.readFile(CONFIG_PATH); - contractsCfg = vm.readFile(CONTRACTS_CONFIG_PATH); + contractsCfg = vm.readFile(CONFIG_CONTRACTS_PATH); CHAIN_ID_L1 = uint64(cfg.readUint(".general.CHAIN_ID_L1")); CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); @@ -410,7 +421,7 @@ abstract contract DeterminsticDeployment is Configuration { string memory tomlPath = string(abi.encodePacked(".", name, "_ADDR")); if (mode == ScriptMode.WriteConfig) { - vm.writeToml(vm.toString(addr), CONTRACTS_CONFIG_PATH, tomlPath); + vm.writeToml(vm.toString(addr), CONFIG_CONTRACTS_PATH, tomlPath); return; } @@ -1771,6 +1782,14 @@ contract GenerateGenesis is DeployScroll { } function generateGenesisJson() private { + // initialize template file + if (vm.exists(GENESIS_JSON_PATH)) { + vm.removeFile(GENESIS_JSON_PATH); + } + + string memory template = vm.readFile(GENESIS_JSON_TEMPLATE_PATH); + vm.writeFile(GENESIS_JSON_PATH, template); + // general config vm.writeJson(vm.toString(CHAIN_ID_L2), GENESIS_JSON_PATH, ".config.chainId"); From ad5c47509f0d9b089cbcb567b7fb4ae608f08b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 26 Apr 2024 21:10:05 +0800 Subject: [PATCH 12/38] docker --- contracts/Dockerfile.deploy | 26 ++++++++++++++++++++ contracts/Dockerfile.gen-configs | 26 ++++++++++++++++++++ contracts/data/deploy.sh | 14 +++++++++++ contracts/data/gen-configs.sh | 11 +++++++++ contracts/foundry.toml | 8 +++++- contracts/scripts/foundry/DeployScroll.s.sol | 2 +- 6 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 contracts/Dockerfile.deploy create mode 100644 contracts/Dockerfile.gen-configs create mode 100755 contracts/data/deploy.sh create mode 100755 contracts/data/gen-configs.sh diff --git a/contracts/Dockerfile.deploy b/contracts/Dockerfile.deploy new file mode 100644 index 0000000000..f6ea457852 --- /dev/null +++ b/contracts/Dockerfile.deploy @@ -0,0 +1,26 @@ +FROM ghcr.io/foundry-rs/foundry:nightly-19d69f277de96f621d930cdb767a9693c55ae8e1 as foundry + +RUN apk add --no-cache bash jq + +WORKDIR /contracts + +# copy dependencies +COPY ./lib /contracts/lib +COPY ./node_modules/@openzeppelin /contracts/node_modules/@openzeppelin + +# copy configurations +COPY foundry.toml /contracts/foundry.toml +COPY remappings.txt /contracts/remappings.txt +COPY ./data /contracts/data + +# copy source code +COPY ./src /contracts/src +COPY ./scripts /contracts/scripts + +# compile contracts +ENV FOUNDRY_EVM_VERSION="cancun" +ENV FOUNDRY_BYTECODE_HASH="none" + +RUN forge build + +ENTRYPOINT ["/bin/bash", "/contracts/data/deploy.sh"] \ No newline at end of file diff --git a/contracts/Dockerfile.gen-configs b/contracts/Dockerfile.gen-configs new file mode 100644 index 0000000000..aca1bbd0cc --- /dev/null +++ b/contracts/Dockerfile.gen-configs @@ -0,0 +1,26 @@ +FROM ghcr.io/foundry-rs/foundry:nightly-19d69f277de96f621d930cdb767a9693c55ae8e1 as foundry + +RUN apk add --no-cache bash jq + +WORKDIR /contracts + +# copy dependencies +COPY ./lib /contracts/lib +COPY ./node_modules/@openzeppelin /contracts/node_modules/@openzeppelin + +# copy configurations +COPY foundry.toml /contracts/foundry.toml +COPY remappings.txt /contracts/remappings.txt +COPY ./data /contracts/data + +# copy source code +COPY ./src /contracts/src +COPY ./scripts /contracts/scripts + +# compile contracts +ENV FOUNDRY_EVM_VERSION="cancun" +ENV FOUNDRY_BYTECODE_HASH="none" + +RUN forge build + +ENTRYPOINT ["/bin/bash", "/contracts/data/gen-configs.sh"] \ No newline at end of file diff --git a/contracts/data/deploy.sh b/contracts/data/deploy.sh new file mode 100755 index 0000000000..d2140c462e --- /dev/null +++ b/contracts/data/deploy.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +export FOUNDRY_EVM_VERSION="cancun" +export FOUNDRY_BYTECODE_HASH="none" + +# deploy L1 +echo "" +echo "deploying on L1" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ENDPOINT" --sig "run(string,string)" "L1" "none" --broadcast + +# deploy L2 +echo "" +echo "deploying on L2" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "none" --broadcast diff --git a/contracts/data/gen-configs.sh b/contracts/data/gen-configs.sh new file mode 100755 index 0000000000..25758d7e61 --- /dev/null +++ b/contracts/data/gen-configs.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# generate contract addresses +echo "" +echo "generating config-contracts.toml" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --sig "run(string,string)" "none" "write-config" + +# generate genesis +echo "" +echo "generating genesis.json" +forge script scripts/foundry/DeployScroll.s.sol:GenerateGenesis diff --git a/contracts/foundry.toml b/contracts/foundry.toml index fd00eea889..0c2252148e 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -13,7 +13,6 @@ solc_version = '0.8.24' # override for the optimizer = true # enable or disable the solc optimizer optimizer_runs = 200 # the number of optimizer runs verbosity = 2 # the verbosity of tests -ignored_error_codes = [] # a list of ignored solc error codes fuzz_runs = 256 # the number of fuzz runs for tests sender = '0x00a329c0648769a73afac7f9381e08fb43dbea72' # the address of `msg.sender` in tests tx_origin = '0x00a329c0648769a73afac7f9381e08fb43dbea72' # the address of `tx.origin` in tests @@ -26,6 +25,13 @@ block_coinbase = '0x0000000000000000000000000000000000000000' # the address of ` block_timestamp = 0 # the value of `block.timestamp` in tests block_difficulty = 0 # the value of `block.difficulty` in tests +ignored_error_codes = [ + "code-size", + "func-mutability", + "init-code-size", + "unused-param", +] + # remove bytecode hash for reliable deterministic addresses bytecode_hash = 'none' diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 247113cd78..f6ff511c70 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -1832,7 +1832,7 @@ contract GenerateGenesis is DeployScroll { // source: https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/scripts/L2Genesis.s.sol function sortJsonByKeys(string memory _path) private { string[] memory commands = new string[](3); - commands[0] = "bash"; + commands[0] = "/bin/bash"; commands[1] = "-c"; commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path); vm.ffi(commands); From 623cf34fa30fa252ad1772f08df06709b3e7ac27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sat, 27 Apr 2024 19:59:23 +0800 Subject: [PATCH 13/38] improve dockerfiles, better error messages --- contracts/data/deploy.sh | 14 ------ contracts/data/input/.gitignore | 2 - contracts/data/output/.gitignore | 2 - contracts/{ => docker}/Dockerfile.deploy | 8 +++- contracts/{ => docker}/Dockerfile.gen-configs | 8 +++- .../{data => docker}/config-contracts.toml | 0 contracts/docker/deploy.sh | 38 ++++++++++++++++ contracts/{data => docker}/gen-configs.sh | 4 +- contracts/{data => docker}/genesis.json | 0 contracts/foundry.toml | 5 +-- contracts/scripts/foundry/DeployScroll.s.sol | 33 ++++++-------- contracts/volume/.gitignore | 2 + .../{data => volume}/config-example.toml | 0 contracts/volume/config.toml | 44 +++++++++++++++++++ 14 files changed, 114 insertions(+), 46 deletions(-) delete mode 100755 contracts/data/deploy.sh delete mode 100644 contracts/data/input/.gitignore delete mode 100644 contracts/data/output/.gitignore rename contracts/{ => docker}/Dockerfile.deploy (67%) rename contracts/{ => docker}/Dockerfile.gen-configs (66%) rename contracts/{data => docker}/config-contracts.toml (100%) create mode 100755 contracts/docker/deploy.sh rename contracts/{data => docker}/gen-configs.sh (62%) rename contracts/{data => docker}/genesis.json (100%) create mode 100644 contracts/volume/.gitignore rename contracts/{data => volume}/config-example.toml (100%) create mode 100644 contracts/volume/config.toml diff --git a/contracts/data/deploy.sh b/contracts/data/deploy.sh deleted file mode 100755 index d2140c462e..0000000000 --- a/contracts/data/deploy.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -export FOUNDRY_EVM_VERSION="cancun" -export FOUNDRY_BYTECODE_HASH="none" - -# deploy L1 -echo "" -echo "deploying on L1" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ENDPOINT" --sig "run(string,string)" "L1" "none" --broadcast - -# deploy L2 -echo "" -echo "deploying on L2" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "none" --broadcast diff --git a/contracts/data/input/.gitignore b/contracts/data/input/.gitignore deleted file mode 100644 index d6b7ef32c8..0000000000 --- a/contracts/data/input/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/contracts/data/output/.gitignore b/contracts/data/output/.gitignore deleted file mode 100644 index d6b7ef32c8..0000000000 --- a/contracts/data/output/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/contracts/Dockerfile.deploy b/contracts/docker/Dockerfile.deploy similarity index 67% rename from contracts/Dockerfile.deploy rename to contracts/docker/Dockerfile.deploy index f6ea457852..b3856ceb3c 100644 --- a/contracts/Dockerfile.deploy +++ b/contracts/docker/Dockerfile.deploy @@ -11,7 +11,6 @@ COPY ./node_modules/@openzeppelin /contracts/node_modules/@openzeppelin # copy configurations COPY foundry.toml /contracts/foundry.toml COPY remappings.txt /contracts/remappings.txt -COPY ./data /contracts/data # copy source code COPY ./src /contracts/src @@ -23,4 +22,9 @@ ENV FOUNDRY_BYTECODE_HASH="none" RUN forge build -ENTRYPOINT ["/bin/bash", "/contracts/data/deploy.sh"] \ No newline at end of file +# copy script configs +COPY ./docker/config-contracts.toml /contracts/docker/config-contracts.toml +COPY ./docker/deploy.sh /contracts/docker/deploy.sh +COPY ./docker/genesis.json /contracts/docker/genesis.json + +ENTRYPOINT ["/bin/bash", "/contracts/docker/deploy.sh"] diff --git a/contracts/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs similarity index 66% rename from contracts/Dockerfile.gen-configs rename to contracts/docker/Dockerfile.gen-configs index aca1bbd0cc..13e1f0b0ac 100644 --- a/contracts/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -11,7 +11,6 @@ COPY ./node_modules/@openzeppelin /contracts/node_modules/@openzeppelin # copy configurations COPY foundry.toml /contracts/foundry.toml COPY remappings.txt /contracts/remappings.txt -COPY ./data /contracts/data # copy source code COPY ./src /contracts/src @@ -23,4 +22,9 @@ ENV FOUNDRY_BYTECODE_HASH="none" RUN forge build -ENTRYPOINT ["/bin/bash", "/contracts/data/gen-configs.sh"] \ No newline at end of file +# copy script configs +COPY ./docker/config-contracts.toml /contracts/docker/config-contracts.toml +COPY ./docker/gen-configs.sh /contracts/docker/gen-configs.sh +COPY ./docker/genesis.json /contracts/docker/genesis.json + +ENTRYPOINT ["/bin/bash", "/contracts/docker/gen-configs.sh"] diff --git a/contracts/data/config-contracts.toml b/contracts/docker/config-contracts.toml similarity index 100% rename from contracts/data/config-contracts.toml rename to contracts/docker/config-contracts.toml diff --git a/contracts/docker/deploy.sh b/contracts/docker/deploy.sh new file mode 100755 index 0000000000..170ca7ab23 --- /dev/null +++ b/contracts/docker/deploy.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +export FOUNDRY_EVM_VERSION="cancun" +export FOUNDRY_BYTECODE_HASH="none" + +if [ "$L1_RPC_ENDPOINT" = "" ]; then + echo "L1_RPC_ENDPOINT is not set" + exit 1 +else + echo "using L1_RPC_ENDPOINT = $L1_RPC_ENDPOINT" +fi + +if [ "$L2_RPC_ENDPOINT" = "" ]; then + echo "L2_RPC_ENDPOINT is not set" + exit 1 +else + echo "using L2_RPC_ENDPOINT = $L2_RPC_ENDPOINT" +fi + +# simulate L1 +echo "" +echo "simulating on L1" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ENDPOINT" --sig "run(string,string)" "L1" "verify-config" || exit 1 + +# simulate L2 +echo "" +echo "simulating on L2" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" || exit 1 + +# deploy L1 +echo "" +echo "deploying on L1" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ENDPOINT" --sig "run(string,string)" "L1" "verify-config" --broadcast || exit 1 + +# deploy L2 +echo "" +echo "deploying on L2" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" --broadcast || exit 1 diff --git a/contracts/data/gen-configs.sh b/contracts/docker/gen-configs.sh similarity index 62% rename from contracts/data/gen-configs.sh rename to contracts/docker/gen-configs.sh index 25758d7e61..8b1e63b26f 100755 --- a/contracts/data/gen-configs.sh +++ b/contracts/docker/gen-configs.sh @@ -3,9 +3,9 @@ # generate contract addresses echo "" echo "generating config-contracts.toml" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --sig "run(string,string)" "none" "write-config" +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --sig "run(string,string)" "none" "write-config" || exit 1 # generate genesis echo "" echo "generating genesis.json" -forge script scripts/foundry/DeployScroll.s.sol:GenerateGenesis +forge script scripts/foundry/DeployScroll.s.sol:GenerateGenesis || exit 1 diff --git a/contracts/data/genesis.json b/contracts/docker/genesis.json similarity index 100% rename from contracts/data/genesis.json rename to contracts/docker/genesis.json diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 0c2252148e..fa856c1144 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -39,9 +39,8 @@ bytecode_hash = 'none' ffi = true fs_permissions = [ - { access='read', path='./data' }, - { access='read', path='./data/input' }, - { access='read-write', path='./data/output' }, + { access='read', path='./docker' }, + { access='read-write', path='./volume' }, ] gas_reports = ["L2GasPriceOracle"] diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index f6ff511c70..d14d0c1357 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -53,16 +53,16 @@ string constant DEFAULT_DEPLOYMENT_SALT = "ScrollStack"; uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; // input files -string constant CONFIG_PATH = "./data/input/config.toml"; +string constant CONFIG_PATH = "./volume/config.toml"; // template files -string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./data/config-contracts.toml"; -string constant GENESIS_JSON_TEMPLATE_PATH = "./data/genesis.json"; +string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/config-contracts.toml"; +string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/genesis.json"; // output files -string constant CONFIG_CONTRACTS_PATH = "./data/output/config-contracts.toml"; -string constant GENESIS_ALLOC_JSON_PATH = "./data/output/__genesis-alloc.json"; -string constant GENESIS_JSON_PATH = "./data/output/genesis.json"; +string constant CONFIG_CONTRACTS_PATH = "./volume/config-contracts.toml"; +string constant GENESIS_ALLOC_JSON_PATH = "./volume/__genesis-alloc.json"; +string constant GENESIS_JSON_PATH = "./volume/genesis.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -170,8 +170,7 @@ abstract contract Configuration is Script { // config sanity check if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { - console.log(string(abi.encodePacked("[ERROR] DEPLOYER_ADDR does not match DEPLOYER_PRIVATE_KEY"))); - revert(); + revert(string(abi.encodePacked("[ERROR] DEPLOYER_ADDR does not match DEPLOYER_PRIVATE_KEY"))); } L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); @@ -211,7 +210,7 @@ abstract contract Configuration is Script { // if we're ready to start broadcasting transactions, then we // must ensure that the override contract has been deployed. if (callerMode == VmSafe.CallerMode.Broadcast || callerMode == VmSafe.CallerMode.RecurrentBroadcast) { - console.log( + revert( string( abi.encodePacked( "[ERROR] override ", @@ -222,7 +221,6 @@ abstract contract Configuration is Script { ) ) ); - revert(); } } @@ -270,7 +268,7 @@ abstract contract DeterminsticDeployment is Configuration { // sanity check: make sure DeterministicDeploymentProxy exists if (DETERMINISTIC_DEPLOYMENT_PROXY_ADDR.code.length == 0) { - console.log( + revert( string( abi.encodePacked( "[ERROR] DeterministicDeploymentProxy (", @@ -279,7 +277,6 @@ abstract contract DeterminsticDeployment is Configuration { ) ) ); - revert(); } } @@ -369,11 +366,11 @@ abstract contract DeterminsticDeployment is Configuration { return addr; } - // return if the contract is already deployed, - // in this case the subsequent initialization steps will probably break + // revert if the contract is already deployed if (addr.code.length > 0) { - console.log(string(abi.encodePacked("[WARN] contract ", name, " is already deployed"))); - return addr; + revert( + string(abi.encodePacked("[ERROR] contract ", name, "(", vm.toString(addr), ") is already deployed")) + ); } // deploy contract @@ -429,7 +426,7 @@ abstract contract DeterminsticDeployment is Configuration { address expectedAddr = contractsCfg.readAddress(tomlPath); if (addr != expectedAddr) { - console.log( + revert( string( abi.encodePacked( "[ERROR] unexpected address for ", @@ -441,8 +438,6 @@ abstract contract DeterminsticDeployment is Configuration { ) ) ); - - revert(); } } } diff --git a/contracts/volume/.gitignore b/contracts/volume/.gitignore new file mode 100644 index 0000000000..c4562ab58a --- /dev/null +++ b/contracts/volume/.gitignore @@ -0,0 +1,2 @@ +config-contracts.toml +genesis.json \ No newline at end of file diff --git a/contracts/data/config-example.toml b/contracts/volume/config-example.toml similarity index 100% rename from contracts/data/config-example.toml rename to contracts/volume/config-example.toml diff --git a/contracts/volume/config.toml b/contracts/volume/config.toml new file mode 100644 index 0000000000..29073dfa4b --- /dev/null +++ b/contracts/volume/config.toml @@ -0,0 +1,44 @@ +[general] + +CHAIN_ID_L1 = 111111 +CHAIN_ID_L2 = 222222 +MAX_TX_IN_CHUNK = 100 +MAX_L1_MESSAGE_GAS_LIMIT = 10000 + + +[accounts] + +DEPLOYER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +OWNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" + +L1_COMMIT_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L1_FINALIZE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L1_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L2_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" + +DEPLOYER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +OWNER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" + +L2GETH_SIGNER_0_ADDRESS = "0x756EA06BDEe36de11F22DCca45a31d8a178eF3c6" + + +[genesis] +L2_MAX_ETH_SUPPLY = "226156424291633194186662080095093570025917938800079226639565593765455331328" +L2_DEPLOYER_INITIAL_BALANCE = 1000000000000000000 + + +[contracts] +DEPLOYMENT_SALT = "" + +# // contracts deployed outside this script +L1_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000001" +L1_PLONK_VERIFIER_ADDR = "0x0000000000000000000000000000000000000001" + +# [contracts.overrides] +# L2_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000" +# L1_GAS_PRICE_ORACLE = "0x5300000000000000000000000000000000000002" +# L2_WHITELIST = "0x5300000000000000000000000000000000000003" +# L2_WETH = "0x5300000000000000000000000000000000000004" +# L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005" + +# L1_WETH = "0x5300000000000000000000000000000000000004" From dfab7315df5454a58d98df31d6455d967b9e6b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sat, 27 Apr 2024 20:19:22 +0800 Subject: [PATCH 14/38] predeploy DeterministicDeploymentProxy --- contracts/scripts/foundry/DeployScroll.s.sol | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index d14d0c1357..c2da7eae3b 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -1634,13 +1634,16 @@ contract GenerateGenesis is DeployScroll { vm.removeFile(GENESIS_ALLOC_JSON_PATH); } - // predeploys + // Scroll predeploys setL2MessageQueue(); setL2GasPriceOracle(); setL2Whitelist(); setL2Weth(); setL2FeeVault(); + // other predeploys + setDeterministicDeploymentProxy(); + // reset sender vm.resetNonce(msg.sender); @@ -1768,6 +1771,12 @@ contract GenerateGenesis is DeployScroll { vm.resetNonce(address(_vault)); } + function setDeterministicDeploymentProxy() internal { + bytes + memory code = hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"; + vm.etch(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR, code); + } + function setL2ScrollMessenger() internal { vm.deal(L2_SCROLL_MESSENGER_PROXY_ADDR, L2_SCROLL_MESSENGER_INITIAL_BALANCE); } From 7ac34b3196beb4ebb3aa21a4e36befb5ed937c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sat, 27 Apr 2024 20:23:56 +0800 Subject: [PATCH 15/38] fmt --- contracts/scripts/foundry/DeployScroll.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index c2da7eae3b..a50210f04b 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -369,7 +369,7 @@ abstract contract DeterminsticDeployment is Configuration { // revert if the contract is already deployed if (addr.code.length > 0) { revert( - string(abi.encodePacked("[ERROR] contract ", name, "(", vm.toString(addr), ") is already deployed")) + string(abi.encodePacked("[ERROR] contract ", name, " (", vm.toString(addr), ") is already deployed")) ); } From d4bbb252de7344eab5044b379489fb3c6dc909ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sun, 28 Apr 2024 10:37:36 +0800 Subject: [PATCH 16/38] enable cache --- contracts/foundry.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index fa856c1144..acfac6d08b 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -7,7 +7,7 @@ libs = [] # a list of librar remappings = [] # a list of remappings libraries = [] # a list of deployed libraries to link against cache = true # whether to cache builds or not -force = true # whether to ignore the cache (clean build) +force = false # whether to ignore the cache (clean build) evm_version = 'cancun' # the evm version (by hardfork name) solc_version = '0.8.24' # override for the solc version (setting this ignores `auto_detect_solc`) optimizer = true # enable or disable the solc optimizer From 98d2c333bd312e44c34bed1c4f90d38d34449ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sun, 28 Apr 2024 12:25:01 +0800 Subject: [PATCH 17/38] move files --- contracts/docker/Dockerfile.deploy | 9 ++-- contracts/docker/Dockerfile.gen-configs | 9 ++-- .../{volume => docker}/config-example.toml | 0 contracts/docker/{ => scripts}/deploy.sh | 0 contracts/docker/{ => scripts}/gen-configs.sh | 0 .../{ => templates}/config-contracts.toml | 0 contracts/docker/{ => templates}/genesis.json | 0 contracts/foundry.toml | 7 --- contracts/scripts/foundry/DeployScroll.s.sol | 8 ++-- contracts/volume/.gitignore | 2 - contracts/volume/config.toml | 44 ------------------- 11 files changed, 14 insertions(+), 65 deletions(-) rename contracts/{volume => docker}/config-example.toml (100%) rename contracts/docker/{ => scripts}/deploy.sh (100%) rename contracts/docker/{ => scripts}/gen-configs.sh (100%) rename contracts/docker/{ => templates}/config-contracts.toml (100%) rename contracts/docker/{ => templates}/genesis.json (100%) delete mode 100644 contracts/volume/.gitignore delete mode 100644 contracts/volume/config.toml diff --git a/contracts/docker/Dockerfile.deploy b/contracts/docker/Dockerfile.deploy index b3856ceb3c..d2b3660279 100644 --- a/contracts/docker/Dockerfile.deploy +++ b/contracts/docker/Dockerfile.deploy @@ -23,8 +23,9 @@ ENV FOUNDRY_BYTECODE_HASH="none" RUN forge build # copy script configs -COPY ./docker/config-contracts.toml /contracts/docker/config-contracts.toml -COPY ./docker/deploy.sh /contracts/docker/deploy.sh -COPY ./docker/genesis.json /contracts/docker/genesis.json +COPY ./docker/templates/config-contracts.toml /contracts/docker/templates/config-contracts.toml +COPY ./docker/templates/genesis.json /contracts/docker/templates/genesis.json -ENTRYPOINT ["/bin/bash", "/contracts/docker/deploy.sh"] +COPY ./docker/scripts/deploy.sh /contracts/docker/scripts/deploy.sh + +ENTRYPOINT ["/bin/bash", "/contracts/docker/scripts/deploy.sh"] diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index 13e1f0b0ac..4fd6900226 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -23,8 +23,9 @@ ENV FOUNDRY_BYTECODE_HASH="none" RUN forge build # copy script configs -COPY ./docker/config-contracts.toml /contracts/docker/config-contracts.toml -COPY ./docker/gen-configs.sh /contracts/docker/gen-configs.sh -COPY ./docker/genesis.json /contracts/docker/genesis.json +COPY ./docker/templates/config-contracts.toml /contracts/docker/templates/config-contracts.toml +COPY ./docker/templates/genesis.json /contracts/docker/templates/genesis.json -ENTRYPOINT ["/bin/bash", "/contracts/docker/gen-configs.sh"] +COPY ./docker/scripts/gen-configs.sh /contracts/docker/scripts/gen-configs.sh + +ENTRYPOINT ["/bin/bash", "/contracts/docker/scripts/gen-configs.sh"] diff --git a/contracts/volume/config-example.toml b/contracts/docker/config-example.toml similarity index 100% rename from contracts/volume/config-example.toml rename to contracts/docker/config-example.toml diff --git a/contracts/docker/deploy.sh b/contracts/docker/scripts/deploy.sh similarity index 100% rename from contracts/docker/deploy.sh rename to contracts/docker/scripts/deploy.sh diff --git a/contracts/docker/gen-configs.sh b/contracts/docker/scripts/gen-configs.sh similarity index 100% rename from contracts/docker/gen-configs.sh rename to contracts/docker/scripts/gen-configs.sh diff --git a/contracts/docker/config-contracts.toml b/contracts/docker/templates/config-contracts.toml similarity index 100% rename from contracts/docker/config-contracts.toml rename to contracts/docker/templates/config-contracts.toml diff --git a/contracts/docker/genesis.json b/contracts/docker/templates/genesis.json similarity index 100% rename from contracts/docker/genesis.json rename to contracts/docker/templates/genesis.json diff --git a/contracts/foundry.toml b/contracts/foundry.toml index acfac6d08b..50041341e6 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -25,13 +25,6 @@ block_coinbase = '0x0000000000000000000000000000000000000000' # the address of ` block_timestamp = 0 # the value of `block.timestamp` in tests block_difficulty = 0 # the value of `block.difficulty` in tests -ignored_error_codes = [ - "code-size", - "func-mutability", - "init-code-size", - "unused-param", -] - # remove bytecode hash for reliable deterministic addresses bytecode_hash = 'none' diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index a50210f04b..2a2011963b 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -52,13 +52,13 @@ string constant DEFAULT_DEPLOYMENT_SALT = "ScrollStack"; /// @dev The default minimum withdraw amount configured on L2TxFeeVault. uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; +// template files +string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/templates/config-contracts.toml"; +string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/templates/genesis.json"; + // input files string constant CONFIG_PATH = "./volume/config.toml"; -// template files -string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/config-contracts.toml"; -string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/genesis.json"; - // output files string constant CONFIG_CONTRACTS_PATH = "./volume/config-contracts.toml"; string constant GENESIS_ALLOC_JSON_PATH = "./volume/__genesis-alloc.json"; diff --git a/contracts/volume/.gitignore b/contracts/volume/.gitignore deleted file mode 100644 index c4562ab58a..0000000000 --- a/contracts/volume/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -config-contracts.toml -genesis.json \ No newline at end of file diff --git a/contracts/volume/config.toml b/contracts/volume/config.toml deleted file mode 100644 index 29073dfa4b..0000000000 --- a/contracts/volume/config.toml +++ /dev/null @@ -1,44 +0,0 @@ -[general] - -CHAIN_ID_L1 = 111111 -CHAIN_ID_L2 = 222222 -MAX_TX_IN_CHUNK = 100 -MAX_L1_MESSAGE_GAS_LIMIT = 10000 - - -[accounts] - -DEPLOYER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" -OWNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" - -L1_COMMIT_SENDER_ADDR = "0x0000000000000000000000000000000000000001" -L1_FINALIZE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" -L1_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" -L2_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" - -DEPLOYER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" -OWNER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" - -L2GETH_SIGNER_0_ADDRESS = "0x756EA06BDEe36de11F22DCca45a31d8a178eF3c6" - - -[genesis] -L2_MAX_ETH_SUPPLY = "226156424291633194186662080095093570025917938800079226639565593765455331328" -L2_DEPLOYER_INITIAL_BALANCE = 1000000000000000000 - - -[contracts] -DEPLOYMENT_SALT = "" - -# // contracts deployed outside this script -L1_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000001" -L1_PLONK_VERIFIER_ADDR = "0x0000000000000000000000000000000000000001" - -# [contracts.overrides] -# L2_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000" -# L1_GAS_PRICE_ORACLE = "0x5300000000000000000000000000000000000002" -# L2_WHITELIST = "0x5300000000000000000000000000000000000003" -# L2_WETH = "0x5300000000000000000000000000000000000004" -# L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005" - -# L1_WETH = "0x5300000000000000000000000000000000000004" From 1d856821df3d9d3fbbe94bc8e45a9495c930f61c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sun, 28 Apr 2024 12:58:33 +0800 Subject: [PATCH 18/38] small improvements --- contracts/scripts/foundry/DeployScroll.s.sol | 41 +++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 2a2011963b..30dee004fd 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -52,6 +52,9 @@ string constant DEFAULT_DEPLOYMENT_SALT = "ScrollStack"; /// @dev The default minimum withdraw amount configured on L2TxFeeVault. uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; +/// @dev The minimum deployer account balance. +uint256 constant MINIMUM_DEPLOYER_BALANCE = 0.1 ether; + // template files string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/templates/config-contracts.toml"; string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/templates/genesis.json"; @@ -170,7 +173,15 @@ abstract contract Configuration is Script { // config sanity check if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { - revert(string(abi.encodePacked("[ERROR] DEPLOYER_ADDR does not match DEPLOYER_PRIVATE_KEY"))); + revert( + string( + abi.encodePacked( + "[ERROR] DEPLOYER_ADDR (", + vm.toString(DEPLOYER_ADDR), + ") does not match DEPLOYER_PRIVATE_KEY" + ) + ) + ); } L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); @@ -562,6 +573,7 @@ contract DeployScroll is DeterminsticDeployment { broadcastLayer = parseLayer(layer); setScriptMode(scriptMode); + checkDeployerBalance(); deployAllContracts(); initializeL1Contracts(); initializeL2Contracts(); @@ -590,6 +602,25 @@ contract DeployScroll is DeterminsticDeployment { } } + function checkDeployerBalance() private view { + // ignore balance during simulation + if (broadcastLayer == Layer.None) { + return; + } + + if (DEPLOYER_ADDR.balance < MINIMUM_DEPLOYER_BALANCE) { + revert( + string( + abi.encodePacked( + "[ERROR] insufficient funds on deployer account (", + vm.toString(DEPLOYER_ADDR), + ")" + ) + ) + ); + } + } + function deployAllContracts() private { deployL1Contracts1stPass(); deployL2Contracts1stPass(); @@ -1480,6 +1511,10 @@ contract DeployScroll is DeterminsticDeployment { } function transferL1ContractOwnership() private { + if (DEPLOYER_ADDR == OWNER_ADDR) { + return; + } + Ownable(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); Ownable(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); Ownable(L1_ERC1155_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); @@ -1593,6 +1628,10 @@ contract DeployScroll is DeterminsticDeployment { } function transferL2ContractOwnership() private { + if (DEPLOYER_ADDR == OWNER_ADDR) { + return; + } + Ownable(L1_GAS_PRICE_ORACLE_ADDR).transferOwnership(OWNER_ADDR); Ownable(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); Ownable(L2_ERC1155_GATEWAY_PROXY_ADDR).transferOwnership(OWNER_ADDR); From 5e59373cf4fe1b9df72a85bc44ab161832cb88de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sun, 28 Apr 2024 13:11:20 +0800 Subject: [PATCH 19/38] add simple build script --- contracts/docker/scripts/build.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 contracts/docker/scripts/build.sh diff --git a/contracts/docker/scripts/build.sh b/contracts/docker/scripts/build.sh new file mode 100755 index 0000000000..661d8232de --- /dev/null +++ b/contracts/docker/scripts/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +latest_commit=$(git log -1 --pretty=format:%h) +tag=${latest_commit:0:8} +echo "Using Docker image tag: $tag" + +docker build -f docker/Dockerfile.gen-configs -t scrolltech/scroll-stack-contracts:gen-configs-$tag --platform linux/amd64 . + +docker build -f docker/Dockerfile.deploy -t scrolltech/scroll-stack-contracts:deploy-$tag --platform linux/amd64 . \ No newline at end of file From 180f3c63fbe19f2867ee868234135868cb642ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 29 Apr 2024 18:51:33 +0800 Subject: [PATCH 20/38] ensure l1ChainId is serialized as string --- contracts/scripts/foundry/DeployScroll.s.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 30dee004fd..783bd6c08b 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -1852,7 +1852,9 @@ contract GenerateGenesis is DeployScroll { vm.writeJson(vm.toString(MAX_TX_IN_CHUNK), GENESIS_JSON_PATH, ".config.scroll.maxTxPerBlock"); vm.writeJson(vm.toString(L2_TX_FEE_VAULT_ADDR), GENESIS_JSON_PATH, ".config.scroll.feeVaultAddress"); - vm.writeJson(vm.toString(CHAIN_ID_L1), GENESIS_JSON_PATH, ".config.scroll.l1Config.l1ChainId"); + // serialize explicitly as string, otherwise foundry will serialize it as number + string memory l1ChainId = string(abi.encodePacked('"', vm.toString(CHAIN_ID_L1), '"')); + vm.writeJson(l1ChainId, GENESIS_JSON_PATH, ".config.scroll.l1Config.l1ChainId"); vm.writeJson( vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), From 53b14bc0908e41f0d0d4b00d8858ef8f384a9ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 29 Apr 2024 20:05:50 +0800 Subject: [PATCH 21/38] fix genesis extradata --- contracts/docker/scripts/build.sh | 1 + contracts/scripts/foundry/DeployScroll.s.sol | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/docker/scripts/build.sh b/contracts/docker/scripts/build.sh index 661d8232de..c7fb778450 100755 --- a/contracts/docker/scripts/build.sh +++ b/contracts/docker/scripts/build.sh @@ -3,6 +3,7 @@ latest_commit=$(git log -1 --pretty=format:%h) tag=${latest_commit:0:8} echo "Using Docker image tag: $tag" +echo "" docker build -f docker/Dockerfile.gen-configs -t scrolltech/scroll-stack-contracts:gen-configs-$tag --platform linux/amd64 . diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 783bd6c08b..729bc9fb4a 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -1841,7 +1841,8 @@ contract GenerateGenesis is DeployScroll { string memory extraData = string( abi.encodePacked( - vm.toString(L2GETH_SIGNER_0_ADDRESS), + "0x0000000000000000000000000000000000000000000000000000000000000000", + vm.replace(vm.toString(L2GETH_SIGNER_0_ADDRESS), "0x", ""), "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) ); From 5b3a65b208b1ae46a7d230d9702c6fc12fceaffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 29 Apr 2024 22:29:15 +0800 Subject: [PATCH 22/38] use legacy txs on L2 --- contracts/docker/scripts/deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/docker/scripts/deploy.sh b/contracts/docker/scripts/deploy.sh index 170ca7ab23..b7ef232a1c 100755 --- a/contracts/docker/scripts/deploy.sh +++ b/contracts/docker/scripts/deploy.sh @@ -25,7 +25,7 @@ forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ # simulate L2 echo "" echo "simulating on L2" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" || exit 1 +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" --legacy || exit 1 # deploy L1 echo "" @@ -35,4 +35,4 @@ forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ # deploy L2 echo "" echo "deploying on L2" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" --broadcast || exit 1 +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" --broadcast --legacy || exit 1 From 2d14457c91a527525591180c8ed1c285b952de1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 3 May 2024 14:43:20 +0800 Subject: [PATCH 23/38] make envs more configurable --- contracts/docker/scripts/deploy.sh | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/contracts/docker/scripts/deploy.sh b/contracts/docker/scripts/deploy.sh index b7ef232a1c..64547f9462 100755 --- a/contracts/docker/scripts/deploy.sh +++ b/contracts/docker/scripts/deploy.sh @@ -3,20 +3,28 @@ export FOUNDRY_EVM_VERSION="cancun" export FOUNDRY_BYTECODE_HASH="none" -if [ "$L1_RPC_ENDPOINT" = "" ]; then +if [ "${L1_RPC_ENDPOINT}" = "" ]; then echo "L1_RPC_ENDPOINT is not set" - exit 1 -else - echo "using L1_RPC_ENDPOINT = $L1_RPC_ENDPOINT" + L1_RPC_ENDPOINT="http://host.docker.internal:8543" fi if [ "$L2_RPC_ENDPOINT" = "" ]; then echo "L2_RPC_ENDPOINT is not set" - exit 1 -else - echo "using L2_RPC_ENDPOINT = $L2_RPC_ENDPOINT" + L2_RPC_ENDPOINT="http://host.docker.internal:8545" fi +if [ "${L1_RPC_ENDPOINT}" = "" ]; then + echo "L1_RPC_ENDPOINT is not set" + L1_RPC_ENDPOINT="http://host.docker.internal:8543" +fi + +if [ "${BATCH_SIZE}" = "" ]; then + BATCH_SIZE="100" +fi + +echo "using L1_RPC_ENDPOINT = $L1_RPC_ENDPOINT" +echo "using L2_RPC_ENDPOINT = $L2_RPC_ENDPOINT" + # simulate L1 echo "" echo "simulating on L1" @@ -30,9 +38,9 @@ forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ # deploy L1 echo "" echo "deploying on L1" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ENDPOINT" --sig "run(string,string)" "L1" "verify-config" --broadcast || exit 1 +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L1_RPC_ENDPOINT" --batch-size "$BATCH_SIZE" --sig "run(string,string)" "L1" "verify-config" --broadcast || exit 1 # deploy L2 echo "" echo "deploying on L2" -forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --sig "run(string,string)" "L2" "verify-config" --broadcast --legacy || exit 1 +forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --rpc-url "$L2_RPC_ENDPOINT" --batch-size "$BATCH_SIZE" --sig "run(string,string)" "L2" "verify-config" --broadcast --legacy || exit 1 From 39db5634e20e10f14567afa35169356170a44af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 7 May 2024 16:30:52 +0800 Subject: [PATCH 24/38] wip: generate other config files --- .../templates/bridge-history-config.json | 56 ++++ contracts/docker/templates/rollup-config.json | 87 +++++++ contracts/scripts/foundry/DeployScroll.s.sol | 246 +++++++++++++++++- 3 files changed, 375 insertions(+), 14 deletions(-) create mode 100644 contracts/docker/templates/bridge-history-config.json create mode 100644 contracts/docker/templates/rollup-config.json diff --git a/contracts/docker/templates/bridge-history-config.json b/contracts/docker/templates/bridge-history-config.json new file mode 100644 index 0000000000..a423654e37 --- /dev/null +++ b/contracts/docker/templates/bridge-history-config.json @@ -0,0 +1,56 @@ +{ + "L1": { + "confirmation": 0, + "endpoint": null, + "startHeight": 0, + "blockTime": 12, + "fetchLimit": 16, + "MessageQueueAddr": null, + "MessengerAddr": null, + "ScrollChainAddr": null, + "GatewayRouterAddr": null, + "ETHGatewayAddr": null, + "WETHGatewayAddr": null, + "StandardERC20GatewayAddr": null, + "CustomERC20GatewayAddr": null, + "ERC721GatewayAddr": null, + "ERC1155GatewayAddr": null, + "USDCGatewayAddr": "0x0000000000000000000000000000000000000000", + "LIDOGatewayAddr": "0x0000000000000000000000000000000000000000", + "DAIGatewayAddr": "0x0000000000000000000000000000000000000000", + "PufferGatewayAddr": "0x0000000000000000000000000000000000000000" + }, + "L2": { + "confirmation": 0, + "endpoint": null, + "blockTime": 3, + "fetchLimit": 64, + "MessageQueueAddr": null, + "MessengerAddr": null, + "GatewayRouterAddr": null, + "ETHGatewayAddr": null, + "WETHGatewayAddr": null, + "StandardERC20GatewayAddr": null, + "CustomERC20GatewayAddr": null, + "ERC721GatewayAddr": null, + "ERC1155GatewayAddr": null, + "USDCGatewayAddr": "0x0000000000000000000000000000000000000000", + "LIDOGatewayAddr": "0x0000000000000000000000000000000000000000", + "DAIGatewayAddr": "0x0000000000000000000000000000000000000000", + "PufferGatewayAddr": "0x0000000000000000000000000000000000000000" + }, + "db": { + "dsn": null, + "driverName": "postgres", + "maxOpenNum": 200, + "maxIdleNum": 20 + }, + "redis": { + "address": null, + "username": null, + "password": null, + "local":null, + "minIdleConns": 10, + "readTimeoutMs": 500 + } +} diff --git a/contracts/docker/templates/rollup-config.json b/contracts/docker/templates/rollup-config.json new file mode 100644 index 0000000000..8d3923bf50 --- /dev/null +++ b/contracts/docker/templates/rollup-config.json @@ -0,0 +1,87 @@ +{ + "l1_config": { + "confirmations": "0x0", + "endpoint": null, + "l1_message_queue_address": null, + "scroll_chain_address": null, + "start_height": 0, + "relayer_config": { + "gas_price_oracle_contract_address": null, + "sender_config": { + "endpoint": null, + "escalate_blocks": 100, + "escalate_multiple_num": 11, + "escalate_multiple_den": 10, + "max_gas_price": 10000000000000, + "tx_type": "LegacyTx", + "check_pending_time": 3, + "confirmations": "0x0" + }, + "gas_oracle_config": { + "min_gas_price": 0, + "gas_price_diff": 50000, + "l1_base_fee_weight": 0.086, + "l1_blob_base_fee_weight": 0.030 + }, + "gas_oracle_sender_private_key": null + } + }, + "l2_config": { + "confirmations": "0x0", + "endpoint": null, + "l2_message_queue_address": null, + "relayer_config": { + "rollup_contract_address": null, + "gas_price_oracle_contract_address": null, + "sender_config": { + "endpoint": null, + "escalate_blocks": 4, + "escalate_multiple_num": 12, + "escalate_multiple_den": 10, + "max_gas_price": 200000000000, + "max_blob_gas_price": 200000000000, + "tx_type": "DynamicFeeTx", + "check_pending_time": 10, + "confirmations": "0x0" + }, + "gas_oracle_config": { + "min_gas_price": 0, + "gas_price_diff": 50000 + }, + "chain_monitor": { + "enabled": true, + "timeout": 3, + "try_times": 5, + "base_url": "http://chain-monitorv2:8080" + }, + "enable_test_env_bypass_features": true, + "finalize_batch_without_proof_timeout_sec": 3600, + "gas_oracle_sender_private_key": null, + "commit_sender_private_key": null, + "finalize_sender_private_key": null, + "l1_commit_gas_limit_multiplier": 1.2 + }, + "chunk_proposer_config": { + "max_block_num_per_chunk": null, + "max_tx_num_per_chunk": null, + "max_l1_commit_gas_per_chunk": 5000000, + "max_l1_commit_calldata_size_per_chunk": 110000, + "chunk_timeout_sec": 2700, + "max_row_consumption_per_chunk": 1000000, + "gas_cost_increase_multiplier": 1.2 + }, + "batch_proposer_config": { + "max_chunk_num_per_batch": 15, + "max_l1_commit_gas_per_batch": 5000000, + "max_l1_commit_calldata_size_per_batch": 110000, + "batch_timeout_sec": 2700, + "gas_cost_increase_multiplier": 1.2 + } + }, + "db_config": { + "driver_name": "postgres", + "dsn": null, + "maxOpenNum": 50, + "maxIdleNum": 20 + } +} \ No newline at end of file diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 729bc9fb4a..3889a05c37 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -58,6 +58,8 @@ uint256 constant MINIMUM_DEPLOYER_BALANCE = 0.1 ether; // template files string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/templates/config-contracts.toml"; string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/templates/genesis.json"; +string constant ROLLUP_CONFIG_TEMPLATE_PATH = "./docker/templates/rollup-config.json"; +string constant BRIDGE_HISTORY_CONFIG_TEMPLATE_PATH = "./docker/templates/bridge-history-config.json"; // input files string constant CONFIG_PATH = "./volume/config.toml"; @@ -66,6 +68,8 @@ string constant CONFIG_PATH = "./volume/config.toml"; string constant CONFIG_CONTRACTS_PATH = "./volume/config-contracts.toml"; string constant GENESIS_ALLOC_JSON_PATH = "./volume/__genesis-alloc.json"; string constant GENESIS_JSON_PATH = "./volume/genesis.json"; +string constant ROLLUP_CONFIG_PATH = "./volume/rollup-config.json"; +string constant BRIDGE_HISTORY_CONFIG_PATH = "./volume/bridge-history-config.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -112,24 +116,37 @@ abstract contract Configuration is Script { ****************************/ // general + string internal L1_RPC_ENDPOINT; + string internal L2_RPC_ENDPOINT; + uint64 internal CHAIN_ID_L1; uint64 internal CHAIN_ID_L2; + uint256 internal MAX_TX_IN_CHUNK; + uint256 internal MAX_BLOCK_IN_CHUNK; uint256 internal MAX_L1_MESSAGE_GAS_LIMIT; // accounts uint256 internal DEPLOYER_PRIVATE_KEY; + uint256 internal L1_COMMIT_SENDER_PRIVATE_KEY; + uint256 internal L1_FINALIZE_SENDER_PRIVATE_KEY; + uint256 internal L1_GAS_ORACLE_SENDER_PRIVATE_KEY; + uint256 internal L2_GAS_ORACLE_SENDER_PRIVATE_KEY; + address internal DEPLOYER_ADDR; address internal L1_COMMIT_SENDER_ADDR; address internal L1_FINALIZE_SENDER_ADDR; address internal L1_GAS_ORACLE_SENDER_ADDR; address internal L2_GAS_ORACLE_SENDER_ADDR; - address internal DEPLOYER_ADDR; address internal OWNER_ADDR; address internal L2GETH_SIGNER_0_ADDRESS; + // db + string internal SCROLL_DB_CONNECTION_STRING; + string internal BRIDGE_HISTORY_DB_CONNECTION_STRING; + // genesis uint256 internal L2_MAX_ETH_SUPPLY; uint256 internal L2_DEPLOYER_INITIAL_BALANCE; @@ -154,35 +171,34 @@ abstract contract Configuration is Script { cfg = vm.readFile(CONFIG_PATH); contractsCfg = vm.readFile(CONFIG_CONTRACTS_PATH); + L1_RPC_ENDPOINT = cfg.readString(".general.L1_RPC_ENDPOINT"); + L2_RPC_ENDPOINT = cfg.readString(".general.L2_RPC_ENDPOINT"); + CHAIN_ID_L1 = uint64(cfg.readUint(".general.CHAIN_ID_L1")); CHAIN_ID_L2 = uint64(cfg.readUint(".general.CHAIN_ID_L2")); + MAX_TX_IN_CHUNK = cfg.readUint(".general.MAX_TX_IN_CHUNK"); + MAX_BLOCK_IN_CHUNK = cfg.readUint(".general.MAX_BLOCK_IN_CHUNK"); MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); + L1_COMMIT_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_COMMIT_SENDER_PRIVATE_KEY"); + L1_FINALIZE_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_FINALIZE_SENDER_PRIVATE_KEY"); + L1_GAS_ORACLE_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_GAS_ORACLE_SENDER_PRIVATE_KEY"); + L2_GAS_ORACLE_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L2_GAS_ORACLE_SENDER_PRIVATE_KEY"); + DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); L1_COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.L1_COMMIT_SENDER_ADDR"); L1_FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.L1_FINALIZE_SENDER_ADDR"); L1_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L1_GAS_ORACLE_SENDER_ADDR"); L2_GAS_ORACLE_SENDER_ADDR = cfg.readAddress(".accounts.L2_GAS_ORACLE_SENDER_ADDR"); - DEPLOYER_ADDR = cfg.readAddress(".accounts.DEPLOYER_ADDR"); OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR"); L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); - // config sanity check - if (vm.addr(DEPLOYER_PRIVATE_KEY) != DEPLOYER_ADDR) { - revert( - string( - abi.encodePacked( - "[ERROR] DEPLOYER_ADDR (", - vm.toString(DEPLOYER_ADDR), - ") does not match DEPLOYER_PRIVATE_KEY" - ) - ) - ); - } + SCROLL_DB_CONNECTION_STRING = cfg.readString(".db.SCROLL_DB_CONNECTION_STRING"); + BRIDGE_HISTORY_DB_CONNECTION_STRING = cfg.readString(".db.BRIDGE_HISTORY_DB_CONNECTION_STRING"); L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); L2_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".genesis.L2_DEPLOYER_INITIAL_BALANCE"); @@ -192,6 +208,8 @@ abstract contract Configuration is Script { L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); + + runSanityCheck(); } /********************** @@ -237,6 +255,40 @@ abstract contract Configuration is Script { return addr; } + + /********************* + * Private functions * + *********************/ + + function runSanityCheck() private view { + verifyAccount("DEPLOYER", DEPLOYER_PRIVATE_KEY, DEPLOYER_ADDR); + verifyAccount("L1_COMMIT_SENDER", L1_COMMIT_SENDER_PRIVATE_KEY, L1_COMMIT_SENDER_ADDR); + verifyAccount("L1_FINALIZE_SENDER", L1_FINALIZE_SENDER_PRIVATE_KEY, L1_FINALIZE_SENDER_ADDR); + verifyAccount("L1_GAS_ORACLE_SENDER", L1_GAS_ORACLE_SENDER_PRIVATE_KEY, L1_GAS_ORACLE_SENDER_ADDR); + verifyAccount("L2_GAS_ORACLE_SENDER", L2_GAS_ORACLE_SENDER_PRIVATE_KEY, L2_GAS_ORACLE_SENDER_ADDR); + } + + function verifyAccount( + string memory name, + uint256 privateKey, + address addr + ) private pure { + if (vm.addr(privateKey) != addr) { + revert( + string( + abi.encodePacked( + "[ERROR] ", + name, + "_ADDR (", + vm.toString(addr), + ") does not match ", + name, + "_PRIVATE_KEY" + ) + ) + ); + } + } } /// @notice DeterminsticDeployment provides utilities for deterministic contract deployments. @@ -1884,3 +1936,169 @@ contract GenerateGenesis is DeployScroll { vm.ffi(commands); } } + +contract GenerateRollupConfig is DeployScroll { + /*************** + * Entry point * + ***************/ + + function run() public { + setScriptMode(ScriptMode.VerifyConfig); + predictAllContracts(); + + generateRollupConfig(); + } + + /********************* + * Private functions * + *********************/ + + function generateRollupConfig() private { + // initialize template file + if (vm.exists(ROLLUP_CONFIG_PATH)) { + vm.removeFile(ROLLUP_CONFIG_PATH); + } + + string memory template = vm.readFile(ROLLUP_CONFIG_TEMPLATE_PATH); + vm.writeFile(ROLLUP_CONFIG_PATH, template); + + // endpoints + vm.writeJson(L1_RPC_ENDPOINT, ROLLUP_CONFIG_PATH, ".l1_config.endpoint"); + vm.writeJson(L2_RPC_ENDPOINT, ROLLUP_CONFIG_PATH, ".l1_config.relayer_config.sender_config.endpoint"); + vm.writeJson(L2_RPC_ENDPOINT, ROLLUP_CONFIG_PATH, ".l2_config.endpoint"); + vm.writeJson(L1_RPC_ENDPOINT, ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.sender_config.endpoint"); + + // contracts + vm.writeJson( + vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), + ROLLUP_CONFIG_PATH, + ".l1_config.l1_message_queue_address" + ); + vm.writeJson(vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), ROLLUP_CONFIG_PATH, ".l1_config.scroll_chain_address"); + vm.writeJson( + vm.toString(L1_GAS_PRICE_ORACLE_ADDR), + ROLLUP_CONFIG_PATH, + ".l1_config.relayer_config.gas_price_oracle_contract_address" + ); + vm.writeJson(vm.toString(L2_MESSAGE_QUEUE_ADDR), ROLLUP_CONFIG_PATH, ".l2_config.l2_message_queue_address"); + vm.writeJson( + vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), + ROLLUP_CONFIG_PATH, + ".l2_config.relayer_config.rollup_contract_address" + ); + vm.writeJson( + vm.toString(L2_GAS_PRICE_ORACLE_PROXY_ADDR), + ROLLUP_CONFIG_PATH, + ".l2_config.relayer_config.gas_price_oracle_contract_address" + ); + + // private keys + vm.writeJson( + vm.toString(bytes32(L1_GAS_ORACLE_SENDER_PRIVATE_KEY)), + ROLLUP_CONFIG_PATH, + ".l2_config.relayer_config.gas_oracle_sender_private_key" + ); + vm.writeJson( + vm.toString(bytes32(L1_COMMIT_SENDER_PRIVATE_KEY)), + ROLLUP_CONFIG_PATH, + ".l2_config.relayer_config.commit_sender_private_key" + ); + vm.writeJson( + vm.toString(bytes32(L1_FINALIZE_SENDER_PRIVATE_KEY)), + ROLLUP_CONFIG_PATH, + ".l2_config.relayer_config.finalize_sender_private_key" + ); + vm.writeJson( + vm.toString(bytes32(L2_GAS_ORACLE_SENDER_PRIVATE_KEY)), + ROLLUP_CONFIG_PATH, + ".l1_config.relayer_config.gas_oracle_sender_private_key" + ); + + // other + vm.writeJson( + vm.toString(MAX_BLOCK_IN_CHUNK), + ROLLUP_CONFIG_PATH, + ".l2_config.chunk_proposer_config.max_block_num_per_chunk" + ); + vm.writeJson( + vm.toString(MAX_TX_IN_CHUNK), + ROLLUP_CONFIG_PATH, + ".l2_config.chunk_proposer_config.max_tx_num_per_chunk" + ); + + vm.writeJson(SCROLL_DB_CONNECTION_STRING, ROLLUP_CONFIG_PATH, ".db_config.dsn"); + } +} + +contract GenerateBridgeHistoryConfig is DeployScroll { + /*************** + * Entry point * + ***************/ + + function run() public { + setScriptMode(ScriptMode.VerifyConfig); + predictAllContracts(); + + generateRollupConfig(); + } + + /********************* + * Private functions * + *********************/ + + function generateRollupConfig() private { + // initialize template file + if (vm.exists(BRIDGE_HISTORY_CONFIG_PATH)) { + vm.removeFile(BRIDGE_HISTORY_CONFIG_PATH); + } + + string memory template = vm.readFile(BRIDGE_HISTORY_CONFIG_TEMPLATE_PATH); + vm.writeFile(BRIDGE_HISTORY_CONFIG_PATH, template); + + // L1 contracts + vm.writeJson(vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.MessageQueueAddr"); + vm.writeJson(vm.toString(L1_SCROLL_MESSENGER_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.MessengerAddr"); + vm.writeJson(vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ScrollChainAddr"); + vm.writeJson(vm.toString(L1_GATEWAY_ROUTER_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.GatewayRouterAddr"); + vm.writeJson(vm.toString(L1_ETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ETHGatewayAddr"); + vm.writeJson(vm.toString(L1_WETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.WETHGatewayAddr"); + vm.writeJson( + vm.toString(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), + BRIDGE_HISTORY_CONFIG_PATH, + ".L1.StandardERC20GatewayAddr" + ); + vm.writeJson( + vm.toString(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), + BRIDGE_HISTORY_CONFIG_PATH, + ".L1.CustomERC20GatewayAddr" + ); + vm.writeJson(vm.toString(L1_ERC721_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ERC721GatewayAddr"); + vm.writeJson(vm.toString(L1_ERC1155_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ERC1155GatewayAddr"); + + // L2 contracts + vm.writeJson(vm.toString(L2_MESSAGE_QUEUE_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.MessageQueueAddr"); + vm.writeJson(vm.toString(L2_SCROLL_MESSENGER_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.MessengerAddr"); + vm.writeJson(vm.toString(L2_GATEWAY_ROUTER_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.GatewayRouterAddr"); + vm.writeJson(vm.toString(L2_ETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.ETHGatewayAddr"); + vm.writeJson(vm.toString(L2_WETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.WETHGatewayAddr"); + vm.writeJson( + vm.toString(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), + BRIDGE_HISTORY_CONFIG_PATH, + ".L2.StandardERC20GatewayAddr" + ); + vm.writeJson( + vm.toString(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), + BRIDGE_HISTORY_CONFIG_PATH, + ".L2.CustomERC20GatewayAddr" + ); + vm.writeJson(vm.toString(L2_ERC721_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.ERC721GatewayAddr"); + vm.writeJson(vm.toString(L2_ERC1155_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.ERC1155GatewayAddr"); + + // endpoints + vm.writeJson(L1_RPC_ENDPOINT, BRIDGE_HISTORY_CONFIG_PATH, ".L1.endpoint"); + vm.writeJson(L2_RPC_ENDPOINT, BRIDGE_HISTORY_CONFIG_PATH, ".L2.endpoint"); + + // others + vm.writeJson(BRIDGE_HISTORY_DB_CONNECTION_STRING, BRIDGE_HISTORY_CONFIG_PATH, ".db.dsn"); + } +} From 5497777c88ba61d12e83e4181268e135d8ad28f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 13 May 2024 16:18:15 +0100 Subject: [PATCH 25/38] update dockerfile --- contracts/docker/config-example.toml | 38 +++++++++++++++++++------ contracts/docker/scripts/gen-configs.sh | 5 ++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/contracts/docker/config-example.toml b/contracts/docker/config-example.toml index f33a927cb7..e80431600c 100644 --- a/contracts/docker/config-example.toml +++ b/contracts/docker/config-example.toml @@ -1,44 +1,64 @@ [general] +L1_RPC_ENDPOINT = "http://l1geth:8545" +L2_RPC_ENDPOINT = "http://l2geth:8545" + CHAIN_ID_L1 = 111111 CHAIN_ID_L2 = 222222 + MAX_TX_IN_CHUNK = 100 +MAX_BLOCK_IN_CHUNK = 100 MAX_L1_MESSAGE_GAS_LIMIT = 10000 [accounts] +# note: for now we simply use Anvil's dev accounts + DEPLOYER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" -OWNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" +OWNER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" -L1_COMMIT_SENDER_ADDR = "0x0000000000000000000000000000000000000001" -L1_FINALIZE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" -L1_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" -L2_GAS_ORACLE_SENDER_ADDR = "0x0000000000000000000000000000000000000001" +L1_COMMIT_SENDER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" +L1_FINALIZE_SENDER_PRIVATE_KEY = "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a" +L1_GAS_ORACLE_SENDER_PRIVATE_KEY = "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6" +L2_GAS_ORACLE_SENDER_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" DEPLOYER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" -OWNER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +OWNER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + +L1_COMMIT_SENDER_ADDR = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +L1_FINALIZE_SENDER_ADDR = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +L1_GAS_ORACLE_SENDER_ADDR = "0x90F79bf6EB2c4f870365E785982E1f101E93b906" +L2_GAS_ORACLE_SENDER_ADDR = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" L2GETH_SIGNER_0_ADDRESS = "0x756EA06BDEe36de11F22DCca45a31d8a178eF3c6" +[db] + +SCROLL_DB_CONNECTION_STRING = "postgres://postgres:scroll2022@db:5432/scroll?sslmode=disable" +BRIDGE_HISTORY_DB_CONNECTION_STRING = "postgres://postgres:scroll2022@db:5432/bridge_history?sslmode=disable" + [genesis] + L2_MAX_ETH_SUPPLY = "226156424291633194186662080095093570025917938800079226639565593765455331328" L2_DEPLOYER_INITIAL_BALANCE = 1000000000000000000 [contracts] + DEPLOYMENT_SALT = "" -# // contracts deployed outside this script +# contracts deployed outside this script L1_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000001" L1_PLONK_VERIFIER_ADDR = "0x0000000000000000000000000000000000000001" [contracts.overrides] + +# L1_WETH = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14" + L2_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000" L1_GAS_PRICE_ORACLE = "0x5300000000000000000000000000000000000002" L2_WHITELIST = "0x5300000000000000000000000000000000000003" L2_WETH = "0x5300000000000000000000000000000000000004" L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005" - -L1_WETH = "0x5300000000000000000000000000000000000004" diff --git a/contracts/docker/scripts/gen-configs.sh b/contracts/docker/scripts/gen-configs.sh index 8b1e63b26f..dad31584f7 100755 --- a/contracts/docker/scripts/gen-configs.sh +++ b/contracts/docker/scripts/gen-configs.sh @@ -9,3 +9,8 @@ forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --sig "run(string,s echo "" echo "generating genesis.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateGenesis || exit 1 + +# generate config files +echo "" +echo "generating rollup-config.json and bridge-history-config.json" +forge script scripts/foundry/DeployScroll.s.sol:GenerateRollupConfig || exit 1 From bc1cb1f86e526c3c009b8bd8dd36e346a76fe47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 13 May 2024 16:27:40 +0100 Subject: [PATCH 26/38] add missing files to container --- contracts/docker/Dockerfile.gen-configs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index 4fd6900226..d364c6dd05 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -23,8 +23,10 @@ ENV FOUNDRY_BYTECODE_HASH="none" RUN forge build # copy script configs +COPY ./docker/templates/bridge-history-config.json /contracts/docker/templates/bridge-history-config.json COPY ./docker/templates/config-contracts.toml /contracts/docker/templates/config-contracts.toml COPY ./docker/templates/genesis.json /contracts/docker/templates/genesis.json +COPY ./docker/templates/rollup-config.json /contracts/docker/templates/rollup-config.json COPY ./docker/scripts/gen-configs.sh /contracts/docker/scripts/gen-configs.sh From cbd3f54b6bdbf3045938f850c2646cbecb89c006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 13 May 2024 16:29:34 +0100 Subject: [PATCH 27/38] update scripts --- contracts/docker/scripts/gen-configs.sh | 9 +++++---- contracts/scripts/foundry/DeployScroll.s.sol | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/contracts/docker/scripts/gen-configs.sh b/contracts/docker/scripts/gen-configs.sh index dad31584f7..de056c6d85 100755 --- a/contracts/docker/scripts/gen-configs.sh +++ b/contracts/docker/scripts/gen-configs.sh @@ -1,16 +1,17 @@ #!/bin/bash -# generate contract addresses echo "" echo "generating config-contracts.toml" forge script scripts/foundry/DeployScroll.s.sol:DeployScroll --sig "run(string,string)" "none" "write-config" || exit 1 -# generate genesis echo "" echo "generating genesis.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateGenesis || exit 1 -# generate config files echo "" -echo "generating rollup-config.json and bridge-history-config.json" +echo "generating rollup-config.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateRollupConfig || exit 1 + +echo "" +echo "generating bridge-history-config.json" +forge script scripts/foundry/DeployScroll.s.sol:GenerateBridgeHistoryConfig || exit 1 diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 3889a05c37..2b2601798e 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -2039,14 +2039,14 @@ contract GenerateBridgeHistoryConfig is DeployScroll { setScriptMode(ScriptMode.VerifyConfig); predictAllContracts(); - generateRollupConfig(); + generateBridgeHistoryConfig(); } /********************* * Private functions * *********************/ - function generateRollupConfig() private { + function generateBridgeHistoryConfig() private { // initialize template file if (vm.exists(BRIDGE_HISTORY_CONFIG_PATH)) { vm.removeFile(BRIDGE_HISTORY_CONFIG_PATH); From f27d27cb8a929c6f46b5419490b4769abe3eca53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 21 May 2024 16:48:03 +0200 Subject: [PATCH 28/38] add coordinator-config.json --- contracts/docker/Dockerfile.deploy | 1 - contracts/docker/Dockerfile.gen-configs | 1 + contracts/docker/config-example.toml | 5 +++ contracts/docker/scripts/gen-configs.sh | 4 ++ .../docker/templates/coordinator-config.json | 30 +++++++++++++++ contracts/scripts/foundry/DeployScroll.s.sol | 38 +++++++++++++++++++ 6 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 contracts/docker/templates/coordinator-config.json diff --git a/contracts/docker/Dockerfile.deploy b/contracts/docker/Dockerfile.deploy index d2b3660279..3c92d17cfe 100644 --- a/contracts/docker/Dockerfile.deploy +++ b/contracts/docker/Dockerfile.deploy @@ -24,7 +24,6 @@ RUN forge build # copy script configs COPY ./docker/templates/config-contracts.toml /contracts/docker/templates/config-contracts.toml -COPY ./docker/templates/genesis.json /contracts/docker/templates/genesis.json COPY ./docker/scripts/deploy.sh /contracts/docker/scripts/deploy.sh diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index d364c6dd05..f073cef6f8 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -25,6 +25,7 @@ RUN forge build # copy script configs COPY ./docker/templates/bridge-history-config.json /contracts/docker/templates/bridge-history-config.json COPY ./docker/templates/config-contracts.toml /contracts/docker/templates/config-contracts.toml +COPY ./docker/templates/coordinator-config.json /contracts/docker/templates/coordinator-config.json COPY ./docker/templates/genesis.json /contracts/docker/templates/genesis.json COPY ./docker/templates/rollup-config.json /contracts/docker/templates/rollup-config.json diff --git a/contracts/docker/config-example.toml b/contracts/docker/config-example.toml index e80431600c..7a9baed5f7 100644 --- a/contracts/docker/config-example.toml +++ b/contracts/docker/config-example.toml @@ -62,3 +62,8 @@ L1_GAS_PRICE_ORACLE = "0x5300000000000000000000000000000000000002" L2_WHITELIST = "0x5300000000000000000000000000000000000003" L2_WETH = "0x5300000000000000000000000000000000000004" L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005" + + +[coordinator] + +COORDINATOR_JWT_SECRET_KEY = "e788b62d39254928a821ac1c76b274a8c835aa1e20ecfb6f50eb10e87847de44" diff --git a/contracts/docker/scripts/gen-configs.sh b/contracts/docker/scripts/gen-configs.sh index de056c6d85..4bb37c7eeb 100755 --- a/contracts/docker/scripts/gen-configs.sh +++ b/contracts/docker/scripts/gen-configs.sh @@ -12,6 +12,10 @@ echo "" echo "generating rollup-config.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateRollupConfig || exit 1 +echo "" +echo "generating coordinator-config.json" +forge script scripts/foundry/DeployScroll.s.sol:GenerateCoordinatorConfig || exit 1 + echo "" echo "generating bridge-history-config.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateBridgeHistoryConfig || exit 1 diff --git a/contracts/docker/templates/coordinator-config.json b/contracts/docker/templates/coordinator-config.json new file mode 100644 index 0000000000..f495637ee7 --- /dev/null +++ b/contracts/docker/templates/coordinator-config.json @@ -0,0 +1,30 @@ +{ + "prover_manager": { + "provers_per_session": 1, + "session_attempts": 100, + "chunk_collection_time_sec": 3600, + "batch_collection_time_sec": 600, + "verifier": { + "fork_name": "bernoulli", + "mock_mode": false, + "params_path": "/verifier/params", + "assets_path": "/verifier/assets" + }, + "max_verifier_workers": 4, + "min_prover_version": "v4.3.41" + }, + "db": { + "driver_name": "postgres", + "dsn": null, + "maxOpenNum": 200, + "maxIdleNum": 20 + }, + "l2": { + "chain_id": null + }, + "auth": { + "secret": null, + "challenge_expire_duration_sec": 10, + "login_expire_duration_sec": 3600 + } +} \ No newline at end of file diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 2b2601798e..b48766e9b2 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -59,6 +59,7 @@ uint256 constant MINIMUM_DEPLOYER_BALANCE = 0.1 ether; string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/templates/config-contracts.toml"; string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/templates/genesis.json"; string constant ROLLUP_CONFIG_TEMPLATE_PATH = "./docker/templates/rollup-config.json"; +string constant COORDINATOR_CONFIG_TEMPLATE_PATH = "./docker/templates/coordinator-config.json"; string constant BRIDGE_HISTORY_CONFIG_TEMPLATE_PATH = "./docker/templates/bridge-history-config.json"; // input files @@ -69,6 +70,7 @@ string constant CONFIG_CONTRACTS_PATH = "./volume/config-contracts.toml"; string constant GENESIS_ALLOC_JSON_PATH = "./volume/__genesis-alloc.json"; string constant GENESIS_JSON_PATH = "./volume/genesis.json"; string constant ROLLUP_CONFIG_PATH = "./volume/rollup-config.json"; +string constant COORDINATOR_CONFIG_PATH = "./volume/coordinator-config.json"; string constant BRIDGE_HISTORY_CONFIG_PATH = "./volume/bridge-history-config.json"; contract ProxyAdminSetOwner is ProxyAdmin { @@ -158,6 +160,9 @@ abstract contract Configuration is Script { address internal L1_FEE_VAULT_ADDR; address internal L1_PLONK_VERIFIER_ADDR; + // coordinator + string internal COORDINATOR_JWT_SECRET_KEY; + /*************** * Constructor * ***************/ @@ -209,6 +214,8 @@ abstract contract Configuration is Script { L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR"); L1_PLONK_VERIFIER_ADDR = cfg.readAddress(".contracts.L1_PLONK_VERIFIER_ADDR"); + COORDINATOR_JWT_SECRET_KEY = cfg.readString(".coordinator.COORDINATOR_JWT_SECRET_KEY"); + runSanityCheck(); } @@ -2030,6 +2037,37 @@ contract GenerateRollupConfig is DeployScroll { } } +contract GenerateCoordinatorConfig is DeployScroll { + /*************** + * Entry point * + ***************/ + + function run() public { + setScriptMode(ScriptMode.VerifyConfig); + predictAllContracts(); + + generateCoordinatorConfig(); + } + + /********************* + * Private functions * + *********************/ + + function generateCoordinatorConfig() private { + // initialize template file + if (vm.exists(COORDINATOR_CONFIG_PATH)) { + vm.removeFile(COORDINATOR_CONFIG_PATH); + } + + string memory template = vm.readFile(COORDINATOR_CONFIG_TEMPLATE_PATH); + vm.writeFile(COORDINATOR_CONFIG_PATH, template); + + vm.writeJson(vm.toString(CHAIN_ID_L2), COORDINATOR_CONFIG_PATH, ".l2.chain_id"); + vm.writeJson(SCROLL_DB_CONNECTION_STRING, COORDINATOR_CONFIG_PATH, ".db.dsn"); + vm.writeJson(COORDINATOR_JWT_SECRET_KEY, COORDINATOR_CONFIG_PATH, ".auth.secret"); + } +} + contract GenerateBridgeHistoryConfig is DeployScroll { /*************** * Entry point * From 4ab710359d8e99d853367a03805c4b7ce765b25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 22 May 2024 14:52:34 +0200 Subject: [PATCH 29/38] update redis config values --- contracts/docker/templates/bridge-history-config.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/docker/templates/bridge-history-config.json b/contracts/docker/templates/bridge-history-config.json index a423654e37..de8f0a6cc8 100644 --- a/contracts/docker/templates/bridge-history-config.json +++ b/contracts/docker/templates/bridge-history-config.json @@ -46,10 +46,10 @@ "maxIdleNum": 20 }, "redis": { - "address": null, - "username": null, - "password": null, - "local":null, + "address": "localhost:6379", + "username": "default", + "password": "", + "local": true, "minIdleConns": 10, "readTimeoutMs": 500 } From e2b87879dab1a3f871c0b03fdb81e6249b9cb548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 22 May 2024 15:19:03 +0200 Subject: [PATCH 30/38] add chain-monitor and balance-checker config gen --- contracts/docker/Dockerfile.gen-configs | 2 + contracts/docker/config-example.toml | 3 + contracts/docker/scripts/gen-configs.sh | 8 + .../templates/balance-checker-config.json | 42 ++++ .../templates/chain-monitor-config.json | 56 +++++ contracts/scripts/foundry/DeployScroll.s.sol | 197 +++++++++++------- 6 files changed, 238 insertions(+), 70 deletions(-) create mode 100644 contracts/docker/templates/balance-checker-config.json create mode 100644 contracts/docker/templates/chain-monitor-config.json diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index f073cef6f8..9befa04ae7 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -23,7 +23,9 @@ ENV FOUNDRY_BYTECODE_HASH="none" RUN forge build # copy script configs +COPY ./docker/templates/balance-checker-config.json /contracts/docker/templates/balance-checker-config.json COPY ./docker/templates/bridge-history-config.json /contracts/docker/templates/bridge-history-config.json +COPY ./docker/templates/chain-monitor-config.json /contracts/docker/templates/chain-monitor-config.json COPY ./docker/templates/config-contracts.toml /contracts/docker/templates/config-contracts.toml COPY ./docker/templates/coordinator-config.json /contracts/docker/templates/coordinator-config.json COPY ./docker/templates/genesis.json /contracts/docker/templates/genesis.json diff --git a/contracts/docker/config-example.toml b/contracts/docker/config-example.toml index 7a9baed5f7..be41effa8f 100644 --- a/contracts/docker/config-example.toml +++ b/contracts/docker/config-example.toml @@ -10,6 +10,8 @@ MAX_TX_IN_CHUNK = 100 MAX_BLOCK_IN_CHUNK = 100 MAX_L1_MESSAGE_GAS_LIMIT = 10000 +L1_CONTRACT_DEPLOYMENT_BLOCK = 0 + [accounts] @@ -36,6 +38,7 @@ L2GETH_SIGNER_0_ADDRESS = "0x756EA06BDEe36de11F22DCca45a31d8a178eF3c6" [db] SCROLL_DB_CONNECTION_STRING = "postgres://postgres:scroll2022@db:5432/scroll?sslmode=disable" +CHAIN_MONITOR_DB_CONNECTION_STRING = "postgres://postgres:scroll2022@db:5432/chain_monitor?sslmode=disable" BRIDGE_HISTORY_DB_CONNECTION_STRING = "postgres://postgres:scroll2022@db:5432/bridge_history?sslmode=disable" diff --git a/contracts/docker/scripts/gen-configs.sh b/contracts/docker/scripts/gen-configs.sh index 4bb37c7eeb..25cffaed59 100755 --- a/contracts/docker/scripts/gen-configs.sh +++ b/contracts/docker/scripts/gen-configs.sh @@ -16,6 +16,14 @@ echo "" echo "generating coordinator-config.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateCoordinatorConfig || exit 1 +echo "" +echo "generating chain-monitor-config.json" +forge script scripts/foundry/DeployScroll.s.sol:GenerateChainMonitorConfig || exit 1 + echo "" echo "generating bridge-history-config.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateBridgeHistoryConfig || exit 1 + +echo "" +echo "generating balance-checker-config.json" +forge script scripts/foundry/DeployScroll.s.sol:GenerateBalanceCheckerConfig || exit 1 diff --git a/contracts/docker/templates/balance-checker-config.json b/contracts/docker/templates/balance-checker-config.json new file mode 100644 index 0000000000..79011d9401 --- /dev/null +++ b/contracts/docker/templates/balance-checker-config.json @@ -0,0 +1,42 @@ +{ + "addresses": [ + { + "rpc_url": "${SCROLL_L1_RPC}", + "min_balance_ether": "10", + "address": "${L1_COMMIT_SENDER_ADDRESS}", + "name": "L1_COMMIT_SENDER" + }, + { + "rpc_url": "${SCROLL_L1_RPC}", + "min_balance_ether": "10", + "address": "${L1_FINALIZE_SENDER_ADDRESS}", + "name": "L1_FINALIZE_SENDER" + }, + { + "rpc_url": "${SCROLL_L1_RPC}", + "min_balance_ether": "1.1", + "address": "${L1_GAS_ORACLE_SENDER_ADDRESS}", + "name": "L1_GAS_ORACLE_SENDER" + }, + { + "rpc_url": "${SCROLL_L1_RPC}", + "min_balance_ether": "0", + "address": "${L1_SCROLL_FEE_VAULT_ADDRESS}", + "name": "L1_SCROLL_FEE_VAULT" + }, + { + "rpc_url": "${SCROLL_L2_RPC}", + "min_balance_ether": "1.1", + "address": "${L2_GAS_ORACLE_SENDER_ADDRESS}", + "name": "L2_GAS_ORACLE_SENDER" + }, + { + "rpc_url": "${SCROLL_L2_RPC}", + "min_balance_ether": "0", + "address": "${L2_TX_FEE_VAULT_ADDR}", + "name": "L2_TX_FEE_VAULT" + } + ], + "JOB_INTERVAL_SECS": 60, + "BIND_PORT": 8080 +} \ No newline at end of file diff --git a/contracts/docker/templates/chain-monitor-config.json b/contracts/docker/templates/chain-monitor-config.json new file mode 100644 index 0000000000..09fb89bcb7 --- /dev/null +++ b/contracts/docker/templates/chain-monitor-config.json @@ -0,0 +1,56 @@ +{ + "l1_config": { + "l1_url": null, + "confirm": "0x20", + "start_number": null, + "l1_contracts": { + "l1_gateways": { + "eth_gateway": null, + "weth_gateway": null, + "standard_erc20_gateway": null, + "custom_erc20_gateway": null, + "erc721_gateway": null, + "erc1155_gateway": null, + "dai_gateway": "0x0000000000000000000000000000000000000000", + "usdc_gateway": "0x0000000000000000000000000000000000000000", + "lido_gateway": "0x0000000000000000000000000000000000000000", + "puffer_gateway": "0x0000000000000000000000000000000000000000" + }, + "scroll_messenger": null, + "message_queue": null, + "scroll_chain": null + }, + "start_messenger_balance": null + }, + "l2_config": { + "l2_url": null, + "confirm": "0x80", + "l2_contracts": { + "l2_gateways": { + "eth_gateway": null, + "weth_gateway": null, + "standard_erc20_gateway": null, + "custom_erc20_gateway": null, + "erc721_gateway": null, + "erc1155_gateway": null, + "dai_gateway": "0x0000000000000000000000000000000000000000", + "usdc_gateway": "0x0000000000000000000000000000000000000000", + "lido_gateway": "0x0000000000000000000000000000000000000000", + "puffer_gateway": "0x0000000000000000000000000000000000000000" + }, + "scroll_messenger": null, + "message_queue": null + } + }, + "slack_webhook_config": { + "webhook_url": "http://localhost:1234", + "worker_count": 5, + "worker_buffer_size": 1000 + }, + "db_config": { + "driver_name": "postgres", + "dsn": null, + "maxOpenNum": 100, + "maxIdleNum": 20 + } +} diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index b48766e9b2..9ee6188033 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -60,7 +60,9 @@ string constant CONFIG_CONTRACTS_TEMPLATE_PATH = "./docker/templates/config-cont string constant GENESIS_JSON_TEMPLATE_PATH = "./docker/templates/genesis.json"; string constant ROLLUP_CONFIG_TEMPLATE_PATH = "./docker/templates/rollup-config.json"; string constant COORDINATOR_CONFIG_TEMPLATE_PATH = "./docker/templates/coordinator-config.json"; +string constant CHAIN_MONITOR_CONFIG_TEMPLATE_PATH = "./docker/templates/chain-monitor-config.json"; string constant BRIDGE_HISTORY_CONFIG_TEMPLATE_PATH = "./docker/templates/bridge-history-config.json"; +string constant BALANCE_CHECKER_CONFIG_TEMPLATE_PATH = "./docker/templates/balance-checker-config.json"; // input files string constant CONFIG_PATH = "./volume/config.toml"; @@ -71,7 +73,9 @@ string constant GENESIS_ALLOC_JSON_PATH = "./volume/__genesis-alloc.json"; string constant GENESIS_JSON_PATH = "./volume/genesis.json"; string constant ROLLUP_CONFIG_PATH = "./volume/rollup-config.json"; string constant COORDINATOR_CONFIG_PATH = "./volume/coordinator-config.json"; +string constant CHAIN_MONITOR_CONFIG_PATH = "./volume/chain-monitor-config.json"; string constant BRIDGE_HISTORY_CONFIG_PATH = "./volume/bridge-history-config.json"; +string constant BALANCE_CHECKER_CONFIG_PATH = "./volume/balance-checker-config.json"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -128,6 +132,8 @@ abstract contract Configuration is Script { uint256 internal MAX_BLOCK_IN_CHUNK; uint256 internal MAX_L1_MESSAGE_GAS_LIMIT; + uint256 internal L1_CONTRACT_DEPLOYMENT_BLOCK; + // accounts uint256 internal DEPLOYER_PRIVATE_KEY; uint256 internal L1_COMMIT_SENDER_PRIVATE_KEY; @@ -147,6 +153,7 @@ abstract contract Configuration is Script { // db string internal SCROLL_DB_CONNECTION_STRING; + string internal CHAIN_MONITOR_DB_CONNECTION_STRING; string internal BRIDGE_HISTORY_DB_CONNECTION_STRING; // genesis @@ -186,6 +193,8 @@ abstract contract Configuration is Script { MAX_BLOCK_IN_CHUNK = cfg.readUint(".general.MAX_BLOCK_IN_CHUNK"); MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".general.MAX_L1_MESSAGE_GAS_LIMIT"); + L1_CONTRACT_DEPLOYMENT_BLOCK = cfg.readUint(".general.L1_CONTRACT_DEPLOYMENT_BLOCK"); + DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); L1_COMMIT_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_COMMIT_SENDER_PRIVATE_KEY"); L1_FINALIZE_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_FINALIZE_SENDER_PRIVATE_KEY"); @@ -203,6 +212,7 @@ abstract contract Configuration is Script { L2GETH_SIGNER_0_ADDRESS = cfg.readAddress(".accounts.L2GETH_SIGNER_0_ADDRESS"); SCROLL_DB_CONNECTION_STRING = cfg.readString(".db.SCROLL_DB_CONNECTION_STRING"); + CHAIN_MONITOR_DB_CONNECTION_STRING = cfg.readString(".db.CHAIN_MONITOR_DB_CONNECTION_STRING"); BRIDGE_HISTORY_DB_CONNECTION_STRING = cfg.readString(".db.BRIDGE_HISTORY_DB_CONNECTION_STRING"); L2_MAX_ETH_SUPPLY = cfg.readUint(".genesis.L2_MAX_ETH_SUPPLY"); @@ -1960,6 +1970,7 @@ contract GenerateRollupConfig is DeployScroll { * Private functions * *********************/ + // prettier-ignore function generateRollupConfig() private { // initialize template file if (vm.exists(ROLLUP_CONFIG_PATH)) { @@ -1976,62 +1987,22 @@ contract GenerateRollupConfig is DeployScroll { vm.writeJson(L1_RPC_ENDPOINT, ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.sender_config.endpoint"); // contracts - vm.writeJson( - vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), - ROLLUP_CONFIG_PATH, - ".l1_config.l1_message_queue_address" - ); + vm.writeJson(vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), ROLLUP_CONFIG_PATH, ".l1_config.l1_message_queue_address"); vm.writeJson(vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), ROLLUP_CONFIG_PATH, ".l1_config.scroll_chain_address"); - vm.writeJson( - vm.toString(L1_GAS_PRICE_ORACLE_ADDR), - ROLLUP_CONFIG_PATH, - ".l1_config.relayer_config.gas_price_oracle_contract_address" - ); + vm.writeJson(vm.toString(L1_GAS_PRICE_ORACLE_ADDR), ROLLUP_CONFIG_PATH, ".l1_config.relayer_config.gas_price_oracle_contract_address"); vm.writeJson(vm.toString(L2_MESSAGE_QUEUE_ADDR), ROLLUP_CONFIG_PATH, ".l2_config.l2_message_queue_address"); - vm.writeJson( - vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), - ROLLUP_CONFIG_PATH, - ".l2_config.relayer_config.rollup_contract_address" - ); - vm.writeJson( - vm.toString(L2_GAS_PRICE_ORACLE_PROXY_ADDR), - ROLLUP_CONFIG_PATH, - ".l2_config.relayer_config.gas_price_oracle_contract_address" - ); + vm.writeJson(vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.rollup_contract_address"); + vm.writeJson(vm.toString(L2_GAS_PRICE_ORACLE_PROXY_ADDR), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.gas_price_oracle_contract_address"); // private keys - vm.writeJson( - vm.toString(bytes32(L1_GAS_ORACLE_SENDER_PRIVATE_KEY)), - ROLLUP_CONFIG_PATH, - ".l2_config.relayer_config.gas_oracle_sender_private_key" - ); - vm.writeJson( - vm.toString(bytes32(L1_COMMIT_SENDER_PRIVATE_KEY)), - ROLLUP_CONFIG_PATH, - ".l2_config.relayer_config.commit_sender_private_key" - ); - vm.writeJson( - vm.toString(bytes32(L1_FINALIZE_SENDER_PRIVATE_KEY)), - ROLLUP_CONFIG_PATH, - ".l2_config.relayer_config.finalize_sender_private_key" - ); - vm.writeJson( - vm.toString(bytes32(L2_GAS_ORACLE_SENDER_PRIVATE_KEY)), - ROLLUP_CONFIG_PATH, - ".l1_config.relayer_config.gas_oracle_sender_private_key" - ); + vm.writeJson(vm.toString(bytes32(L1_GAS_ORACLE_SENDER_PRIVATE_KEY)), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.gas_oracle_sender_private_key"); + vm.writeJson(vm.toString(bytes32(L1_COMMIT_SENDER_PRIVATE_KEY)), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.commit_sender_private_key"); + vm.writeJson(vm.toString(bytes32(L1_FINALIZE_SENDER_PRIVATE_KEY)), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.finalize_sender_private_key"); + vm.writeJson(vm.toString(bytes32(L2_GAS_ORACLE_SENDER_PRIVATE_KEY)), ROLLUP_CONFIG_PATH, ".l1_config.relayer_config.gas_oracle_sender_private_key"); // other - vm.writeJson( - vm.toString(MAX_BLOCK_IN_CHUNK), - ROLLUP_CONFIG_PATH, - ".l2_config.chunk_proposer_config.max_block_num_per_chunk" - ); - vm.writeJson( - vm.toString(MAX_TX_IN_CHUNK), - ROLLUP_CONFIG_PATH, - ".l2_config.chunk_proposer_config.max_tx_num_per_chunk" - ); + vm.writeJson(vm.toString(MAX_BLOCK_IN_CHUNK), ROLLUP_CONFIG_PATH, ".l2_config.chunk_proposer_config.max_block_num_per_chunk"); + vm.writeJson(vm.toString(MAX_TX_IN_CHUNK), ROLLUP_CONFIG_PATH, ".l2_config.chunk_proposer_config.max_tx_num_per_chunk"); vm.writeJson(SCROLL_DB_CONNECTION_STRING, ROLLUP_CONFIG_PATH, ".db_config.dsn"); } @@ -2068,6 +2039,62 @@ contract GenerateCoordinatorConfig is DeployScroll { } } +contract GenerateChainMonitorConfig is DeployScroll { + /*************** + * Entry point * + ***************/ + + function run() public { + setScriptMode(ScriptMode.VerifyConfig); + predictAllContracts(); + + generateChainMonitorConfig(); + } + + /********************* + * Private functions * + *********************/ + + // prettier-ignore + function generateChainMonitorConfig() private { + // initialize template file + if (vm.exists(CHAIN_MONITOR_CONFIG_PATH)) { + vm.removeFile(CHAIN_MONITOR_CONFIG_PATH); + } + + string memory template = vm.readFile(CHAIN_MONITOR_CONFIG_TEMPLATE_PATH); + vm.writeFile(CHAIN_MONITOR_CONFIG_PATH, template); + + // L1 + vm.writeJson(L1_RPC_ENDPOINT, CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_url"); + vm.writeJson(vm.toString(L1_CONTRACT_DEPLOYMENT_BLOCK), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.start_number"); + vm.writeJson(vm.toString(L1_ETH_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.l1_gateways.eth_gateway"); + vm.writeJson(vm.toString(L1_WETH_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.l1_gateways.weth_gateway"); + vm.writeJson(vm.toString(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.l1_gateways.standard_erc20_gateway"); + vm.writeJson(vm.toString(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.l1_gateways.custom_erc20_gateway"); + vm.writeJson(vm.toString(L1_ERC721_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.l1_gateways.erc721_gateway"); + vm.writeJson(vm.toString(L1_ERC1155_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.l1_gateways.erc1155_gateway"); + vm.writeJson(vm.toString(L1_SCROLL_MESSENGER_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.scroll_messenger"); + vm.writeJson(vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.message_queue"); + vm.writeJson(vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.l1_contracts.scroll_chain"); + vm.writeJson(vm.toString(L2_DEPLOYER_INITIAL_BALANCE), CHAIN_MONITOR_CONFIG_PATH, ".l1_config.start_messenger_balance"); + + // L2 + vm.writeJson(L2_RPC_ENDPOINT, CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_url"); + vm.writeJson(vm.toString(L2_ETH_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.l2_gateways.eth_gateway"); + vm.writeJson(vm.toString(L2_WETH_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.l2_gateways.weth_gateway"); + vm.writeJson(vm.toString(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.l2_gateways.standard_erc20_gateway"); + vm.writeJson(vm.toString(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.l2_gateways.custom_erc20_gateway"); + vm.writeJson(vm.toString(L2_ERC721_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.l2_gateways.erc721_gateway"); + vm.writeJson(vm.toString(L2_ERC1155_GATEWAY_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.l2_gateways.erc1155_gateway"); + vm.writeJson(vm.toString(L2_SCROLL_MESSENGER_PROXY_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.scroll_messenger"); + vm.writeJson(vm.toString(L2_MESSAGE_QUEUE_ADDR), CHAIN_MONITOR_CONFIG_PATH, ".l2_config.l2_contracts.message_queue"); + + // misc + vm.writeJson(CHAIN_MONITOR_DB_CONNECTION_STRING, CHAIN_MONITOR_CONFIG_PATH, ".db_config.dsn"); + } +} + contract GenerateBridgeHistoryConfig is DeployScroll { /*************** * Entry point * @@ -2084,6 +2111,7 @@ contract GenerateBridgeHistoryConfig is DeployScroll { * Private functions * *********************/ + // prettier-ignore function generateBridgeHistoryConfig() private { // initialize template file if (vm.exists(BRIDGE_HISTORY_CONFIG_PATH)) { @@ -2100,16 +2128,8 @@ contract GenerateBridgeHistoryConfig is DeployScroll { vm.writeJson(vm.toString(L1_GATEWAY_ROUTER_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.GatewayRouterAddr"); vm.writeJson(vm.toString(L1_ETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ETHGatewayAddr"); vm.writeJson(vm.toString(L1_WETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.WETHGatewayAddr"); - vm.writeJson( - vm.toString(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), - BRIDGE_HISTORY_CONFIG_PATH, - ".L1.StandardERC20GatewayAddr" - ); - vm.writeJson( - vm.toString(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), - BRIDGE_HISTORY_CONFIG_PATH, - ".L1.CustomERC20GatewayAddr" - ); + vm.writeJson(vm.toString(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.StandardERC20GatewayAddr"); + vm.writeJson(vm.toString(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.CustomERC20GatewayAddr"); vm.writeJson(vm.toString(L1_ERC721_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ERC721GatewayAddr"); vm.writeJson(vm.toString(L1_ERC1155_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L1.ERC1155GatewayAddr"); @@ -2119,16 +2139,8 @@ contract GenerateBridgeHistoryConfig is DeployScroll { vm.writeJson(vm.toString(L2_GATEWAY_ROUTER_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.GatewayRouterAddr"); vm.writeJson(vm.toString(L2_ETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.ETHGatewayAddr"); vm.writeJson(vm.toString(L2_WETH_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.WETHGatewayAddr"); - vm.writeJson( - vm.toString(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), - BRIDGE_HISTORY_CONFIG_PATH, - ".L2.StandardERC20GatewayAddr" - ); - vm.writeJson( - vm.toString(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), - BRIDGE_HISTORY_CONFIG_PATH, - ".L2.CustomERC20GatewayAddr" - ); + vm.writeJson(vm.toString(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.StandardERC20GatewayAddr"); + vm.writeJson(vm.toString(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.CustomERC20GatewayAddr"); vm.writeJson(vm.toString(L2_ERC721_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.ERC721GatewayAddr"); vm.writeJson(vm.toString(L2_ERC1155_GATEWAY_PROXY_ADDR), BRIDGE_HISTORY_CONFIG_PATH, ".L2.ERC1155GatewayAddr"); @@ -2140,3 +2152,48 @@ contract GenerateBridgeHistoryConfig is DeployScroll { vm.writeJson(BRIDGE_HISTORY_DB_CONNECTION_STRING, BRIDGE_HISTORY_CONFIG_PATH, ".db.dsn"); } } + +contract GenerateBalanceCheckerConfig is DeployScroll { + /*************** + * Entry point * + ***************/ + + function run() public { + setScriptMode(ScriptMode.VerifyConfig); + predictAllContracts(); + + generateBalanceCheckerConfig(); + } + + /********************* + * Private functions * + *********************/ + + function generateBalanceCheckerConfig() private { + // initialize template file + if (vm.exists(BALANCE_CHECKER_CONFIG_PATH)) { + vm.removeFile(BALANCE_CHECKER_CONFIG_PATH); + } + + string memory template = vm.readFile(BALANCE_CHECKER_CONFIG_TEMPLATE_PATH); + vm.writeFile(BALANCE_CHECKER_CONFIG_PATH, template); + + vm.writeJson(L1_RPC_ENDPOINT, BALANCE_CHECKER_CONFIG_PATH, ".addresses[0].rpc_url"); + vm.writeJson(vm.toString(L1_COMMIT_SENDER_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[0].address"); + + vm.writeJson(L1_RPC_ENDPOINT, BALANCE_CHECKER_CONFIG_PATH, ".addresses[1].rpc_url"); + vm.writeJson(vm.toString(L1_FINALIZE_SENDER_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[1].address"); + + vm.writeJson(L1_RPC_ENDPOINT, BALANCE_CHECKER_CONFIG_PATH, ".addresses[2].rpc_url"); + vm.writeJson(vm.toString(L1_GAS_ORACLE_SENDER_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[2].address"); + + vm.writeJson(L1_RPC_ENDPOINT, BALANCE_CHECKER_CONFIG_PATH, ".addresses[3].rpc_url"); + vm.writeJson(vm.toString(L1_FEE_VAULT_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[3].address"); + + vm.writeJson(L2_RPC_ENDPOINT, BALANCE_CHECKER_CONFIG_PATH, ".addresses[4].rpc_url"); + vm.writeJson(vm.toString(L2_GAS_ORACLE_SENDER_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[4].address"); + + vm.writeJson(L2_RPC_ENDPOINT, BALANCE_CHECKER_CONFIG_PATH, ".addresses[5].rpc_url"); + vm.writeJson(vm.toString(L2_TX_FEE_VAULT_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[5].address"); + } +} From 2b5b82d4668309a4c1c0b1ffc9c194cfb84d5dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 31 May 2024 09:37:48 +0200 Subject: [PATCH 31/38] init frontend config --- contracts/docker/scripts/gen-configs.sh | 4 + contracts/scripts/foundry/DeployScroll.s.sol | 77 ++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/contracts/docker/scripts/gen-configs.sh b/contracts/docker/scripts/gen-configs.sh index 25cffaed59..988b6830c6 100755 --- a/contracts/docker/scripts/gen-configs.sh +++ b/contracts/docker/scripts/gen-configs.sh @@ -27,3 +27,7 @@ forge script scripts/foundry/DeployScroll.s.sol:GenerateBridgeHistoryConfig || e echo "" echo "generating balance-checker-config.json" forge script scripts/foundry/DeployScroll.s.sol:GenerateBalanceCheckerConfig || exit 1 + +echo "" +echo "generating .env.frontend" +forge script scripts/foundry/DeployScroll.s.sol:GenerateFrontendConfig || exit 1 diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 9ee6188033..d653bdd487 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -76,6 +76,7 @@ string constant COORDINATOR_CONFIG_PATH = "./volume/coordinator-config.json"; string constant CHAIN_MONITOR_CONFIG_PATH = "./volume/chain-monitor-config.json"; string constant BRIDGE_HISTORY_CONFIG_PATH = "./volume/bridge-history-config.json"; string constant BALANCE_CHECKER_CONFIG_PATH = "./volume/balance-checker-config.json"; +string constant FRONTEND_ENV_PATH = "./volume/.env.frontend"; contract ProxyAdminSetOwner is ProxyAdmin { /// @dev allow setting the owner in the constructor, otherwise @@ -2197,3 +2198,79 @@ contract GenerateBalanceCheckerConfig is DeployScroll { vm.writeJson(vm.toString(L2_TX_FEE_VAULT_ADDR), BALANCE_CHECKER_CONFIG_PATH, ".addresses[5].address"); } } + +contract GenerateFrontendConfig is DeployScroll { + /*************** + * Entry point * + ***************/ + + function run() public { + setScriptMode(ScriptMode.VerifyConfig); + predictAllContracts(); + + generateFrontendConfig(); + } + + /********************* + * Private functions * + *********************/ + + // prettier-ignore + function generateFrontendConfig() private { + // use writeFile to start a new file + vm.writeFile(FRONTEND_ENV_PATH, "REACT_APP_ETH_SYMBOL = \"ETH\"\n"); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_BASE_CHAIN = \"Ethereum\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_ROLLUP = \"Scroll Stack\""); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_CHAIN_ID_L1 = \"", vm.toString(CHAIN_ID_L1), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_CHAIN_ID_L2 = \"", vm.toString(CHAIN_ID_L2), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_CONNECT_WALLET_PROJECT_ID = \"14efbaafcf5232a47d93a68229b71028\""); + + // API endpoints + vm.writeLine(FRONTEND_ENV_PATH, ""); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_EXTERNAL_RPC_URI_L1 = \"", L1_RPC_ENDPOINT, "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_EXTERNAL_RPC_URI_L2 = \"", L2_RPC_ENDPOINT, "\"")); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_BRIDGE_API_URI = \"https://sepolia-api-bridge-v2.scroll.io/api\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_ROLLUPSCAN_API_URI = \"https://sepolia-api-re.scroll.io/api\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_EXPLORER_URI_L1 = \"https://sepolia.etherscan.io\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_EXPLORER_URI_L2 = \"https://sepolia.scrollscan.com\""); + + // L1 contracts + vm.writeLine(FRONTEND_ENV_PATH, ""); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = \"", vm.toString(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_ETH_GATEWAY_PROXY_ADDR = \"", vm.toString(L1_ETH_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_GAS_PRICE_ORACLE = \"", vm.toString(L1_GAS_PRICE_ORACLE_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_GATEWAY_ROUTER_PROXY_ADDR = \"", vm.toString(L1_GATEWAY_ROUTER_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_MESSAGE_QUEUE = \"", vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_MESSAGE_QUEUE_WITH_GAS_PRICE_ORACLE = \"", vm.toString(L1_MESSAGE_QUEUE_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_SCROLL_MESSENGER = \"", vm.toString(L1_SCROLL_MESSENGER_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = \"", vm.toString(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L1_WETH_GATEWAY_PROXY_ADDR = \"", vm.toString(L1_WETH_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_SCROLL_CHAIN = \"", vm.toString(L1_SCROLL_CHAIN_PROXY_ADDR), "\"")); + + // L2 contracts + vm.writeLine(FRONTEND_ENV_PATH, ""); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = \"", vm.toString(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L2_ETH_GATEWAY_PROXY_ADDR = \"", vm.toString(L2_ETH_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L2_GATEWAY_ROUTER_PROXY_ADDR = \"", vm.toString(L2_GATEWAY_ROUTER_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L2_SCROLL_MESSENGER = \"", vm.toString(L2_SCROLL_MESSENGER_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = \"", vm.toString(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR), "\"")); + vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_L2_WETH_GATEWAY_PROXY_ADDR = \"", vm.toString(L2_WETH_GATEWAY_PROXY_ADDR), "\"")); + + // custom token gateways (currently not set) + vm.writeLine(FRONTEND_ENV_PATH, ""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L1_USDC_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L2_USDC_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L1_DAI_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L2_DAI_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L1_LIDO_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L2_LIDO_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L1_PUFFER_GATEWAY_PROXY_ADDR = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L2_PUFFER_GATEWAY_PROXY_ADDR = \"\""); + + // misc + vm.writeLine(FRONTEND_ENV_PATH, ""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_SCROLL_ORIGINS_NFT = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_SCROLL_ORIGINS_NFT_V2 = \"\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_L1_BATCH_BRIDGE_GATEWAY_PROXY_ADDR = \"\""); + } +} From fc0cb979f0e656f51196b95bd974f841d2f8a78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Jun 2024 20:21:31 +0200 Subject: [PATCH 32/38] set mock finalization params --- contracts/docker/config-example.toml | 3 + contracts/docker/templates/rollup-config.json | 4 +- contracts/scripts/foundry/DeployScroll.s.sol | 23 +++- contracts/src/L1/rollup/ScrollChain.sol | 5 +- .../src/mocks/ScrollChainMockFinalize.sol | 119 ++++++++++++++++++ 5 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 contracts/src/mocks/ScrollChainMockFinalize.sol diff --git a/contracts/docker/config-example.toml b/contracts/docker/config-example.toml index be41effa8f..284236c6f6 100644 --- a/contracts/docker/config-example.toml +++ b/contracts/docker/config-example.toml @@ -12,6 +12,9 @@ MAX_L1_MESSAGE_GAS_LIMIT = 10000 L1_CONTRACT_DEPLOYMENT_BLOCK = 0 +TEST_ENV_MOCK_FINALIZE_ENABLED = true +TEST_ENV_MOCK_FINALIZE_TIMEOUT_SEC = 3600 + [accounts] diff --git a/contracts/docker/templates/rollup-config.json b/contracts/docker/templates/rollup-config.json index 8d3923bf50..d080925ece 100644 --- a/contracts/docker/templates/rollup-config.json +++ b/contracts/docker/templates/rollup-config.json @@ -54,8 +54,8 @@ "try_times": 5, "base_url": "http://chain-monitorv2:8080" }, - "enable_test_env_bypass_features": true, - "finalize_batch_without_proof_timeout_sec": 3600, + "enable_test_env_bypass_features": null, + "finalize_batch_without_proof_timeout_sec": null, "gas_oracle_sender_private_key": null, "commit_sender_private_key": null, "finalize_sender_private_key": null, diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index d653bdd487..a0cd2cc0b7 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -42,6 +42,8 @@ import {WrappedEther} from "../../src/L2/predeploys/WrappedEther.sol"; import {ScrollStandardERC20} from "../../src/libraries/token/ScrollStandardERC20.sol"; import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol"; +import {ScrollChainMockFinalize} from "../../src/mocks/ScrollChainMockFinalize.sol"; + /// @dev The address of DeterministicDeploymentProxy. /// See https://github.com/Arachnid/deterministic-deployment-proxy. address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920cA78FbF26c0B4956C; @@ -135,6 +137,9 @@ abstract contract Configuration is Script { uint256 internal L1_CONTRACT_DEPLOYMENT_BLOCK; + bool internal TEST_ENV_MOCK_FINALIZE_ENABLED; + uint256 internal TEST_ENV_MOCK_FINALIZE_TIMEOUT_SEC; + // accounts uint256 internal DEPLOYER_PRIVATE_KEY; uint256 internal L1_COMMIT_SENDER_PRIVATE_KEY; @@ -196,6 +201,9 @@ abstract contract Configuration is Script { L1_CONTRACT_DEPLOYMENT_BLOCK = cfg.readUint(".general.L1_CONTRACT_DEPLOYMENT_BLOCK"); + TEST_ENV_MOCK_FINALIZE_ENABLED = cfg.readBool(".general.TEST_ENV_MOCK_FINALIZE_ENABLED"); + TEST_ENV_MOCK_FINALIZE_TIMEOUT_SEC = cfg.readUint(".general.TEST_ENV_MOCK_FINALIZE_TIMEOUT_SEC"); + DEPLOYER_PRIVATE_KEY = cfg.readUint(".accounts.DEPLOYER_PRIVATE_KEY"); L1_COMMIT_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_COMMIT_SENDER_PRIVATE_KEY"); L1_FINALIZE_SENDER_PRIVATE_KEY = cfg.readUint(".accounts.L1_FINALIZE_SENDER_PRIVATE_KEY"); @@ -946,11 +954,13 @@ contract DeployScroll is DeterminsticDeployment { notnull(L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR) ); - L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = deploy( - "L1_SCROLL_CHAIN_IMPLEMENTATION", - type(ScrollChain).creationCode, - args - ); + bytes memory creationCode = type(ScrollChain).creationCode; + + if (TEST_ENV_MOCK_FINALIZE_ENABLED) { + creationCode = type(ScrollChainMockFinalize).creationCode; + } + + L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = deploy("L1_SCROLL_CHAIN_IMPLEMENTATION", creationCode, args); upgrade(L1_PROXY_ADMIN_ADDR, L1_SCROLL_CHAIN_PROXY_ADDR, L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR); } @@ -2002,6 +2012,9 @@ contract GenerateRollupConfig is DeployScroll { vm.writeJson(vm.toString(bytes32(L2_GAS_ORACLE_SENDER_PRIVATE_KEY)), ROLLUP_CONFIG_PATH, ".l1_config.relayer_config.gas_oracle_sender_private_key"); // other + vm.writeJson(vm.toString(TEST_ENV_MOCK_FINALIZE_ENABLED), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.enable_test_env_bypass_features"); + vm.writeJson(vm.toString(TEST_ENV_MOCK_FINALIZE_TIMEOUT_SEC), ROLLUP_CONFIG_PATH, ".l2_config.relayer_config.finalize_batch_without_proof_timeout_sec"); + vm.writeJson(vm.toString(MAX_BLOCK_IN_CHUNK), ROLLUP_CONFIG_PATH, ".l2_config.chunk_proposer_config.max_block_num_per_chunk"); vm.writeJson(vm.toString(MAX_TX_IN_CHUNK), ROLLUP_CONFIG_PATH, ".l2_config.chunk_proposer_config.max_tx_num_per_chunk"); diff --git a/contracts/src/L1/rollup/ScrollChain.sol b/contracts/src/L1/rollup/ScrollChain.sol index fb6a72beb2..0f2727cd21 100644 --- a/contracts/src/L1/rollup/ScrollChain.sol +++ b/contracts/src/L1/rollup/ScrollChain.sol @@ -115,11 +115,12 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain { *************/ /// @dev Address of the point evaluation precompile used for EIP-4844 blob verification. - address private constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A); + address internal constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A); /// @dev BLS Modulus value defined in EIP-4844 and the magic value returned from a successful call to the /// point evaluation precompile - uint256 private constant BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513; + uint256 internal constant BLS_MODULUS = + 52435875175126190479447740508185965837690552500527637822603658699938581184513; /// @notice The chain id of the corresponding layer 2 chain. uint64 public immutable layer2ChainId; diff --git a/contracts/src/mocks/ScrollChainMockFinalize.sol b/contracts/src/mocks/ScrollChainMockFinalize.sol new file mode 100644 index 0000000000..a7d7a8ecaf --- /dev/null +++ b/contracts/src/mocks/ScrollChainMockFinalize.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT + +pragma solidity =0.8.24; + +import {ScrollChain} from "../L1/rollup/ScrollChain.sol"; + +import {BatchHeaderV0Codec} from "../libraries/codec/BatchHeaderV0Codec.sol"; +import {BatchHeaderV1Codec} from "../libraries/codec/BatchHeaderV1Codec.sol"; + +contract ScrollChainMockFinalize is ScrollChain { + /*************** + * Constructor * + ***************/ + + /// @notice Constructor for `ScrollChain` implementation contract. + /// + /// @param _chainId The chain id of L2. + /// @param _messageQueue The address of `L1MessageQueue` contract. + /// @param _verifier The address of zkevm verifier contract. + constructor( + uint64 _chainId, + address _messageQueue, + address _verifier + ) ScrollChain(_chainId, _messageQueue, _verifier) {} + + /***************************** + * Public Mutating Functions * + *****************************/ + + function finalizeBatch( + bytes calldata _batchHeader, + bytes32 _prevStateRoot, + bytes32 _postStateRoot, + bytes32 _withdrawRoot + ) external OnlyProver whenNotPaused { + require(_prevStateRoot != bytes32(0), "previous state root is zero"); + require(_postStateRoot != bytes32(0), "new state root is zero"); + + // compute batch hash and verify + (uint256 memPtr, bytes32 _batchHash, uint256 _batchIndex, ) = _loadBatchHeader(_batchHeader); + + // verify previous state root. + require(finalizedStateRoots[_batchIndex - 1] == _prevStateRoot, "incorrect previous state root"); + + // avoid duplicated verification + require(finalizedStateRoots[_batchIndex] == bytes32(0), "batch already verified"); + + // check and update lastFinalizedBatchIndex + unchecked { + require(lastFinalizedBatchIndex + 1 == _batchIndex, "incorrect batch index"); + lastFinalizedBatchIndex = _batchIndex; + } + + // record state root and withdraw root + finalizedStateRoots[_batchIndex] = _postStateRoot; + withdrawRoots[_batchIndex] = _withdrawRoot; + + // Pop finalized and non-skipped message from L1MessageQueue. + _popL1Messages( + BatchHeaderV0Codec.getSkippedBitmapPtr(memPtr), + BatchHeaderV0Codec.getTotalL1MessagePopped(memPtr), + BatchHeaderV0Codec.getL1MessagePopped(memPtr) + ); + + emit FinalizeBatch(_batchIndex, _batchHash, _postStateRoot, _withdrawRoot); + } + + function finalizeBatch4844( + bytes calldata _batchHeader, + bytes32 _prevStateRoot, + bytes32 _postStateRoot, + bytes32 _withdrawRoot, + bytes calldata _blobDataProof + ) external OnlyProver whenNotPaused { + if (_prevStateRoot == bytes32(0)) revert ErrorPreviousStateRootIsZero(); + if (_postStateRoot == bytes32(0)) revert ErrorStateRootIsZero(); + + // compute batch hash and verify + (uint256 memPtr, bytes32 _batchHash, uint256 _batchIndex, ) = _loadBatchHeader(_batchHeader); + bytes32 _blobVersionedHash = BatchHeaderV1Codec.getBlobVersionedHash(memPtr); + + // Calls the point evaluation precompile and verifies the output + { + (bool success, bytes memory data) = POINT_EVALUATION_PRECOMPILE_ADDR.staticcall( + abi.encodePacked(_blobVersionedHash, _blobDataProof) + ); + // We verify that the point evaluation precompile call was successful by testing the latter 32 bytes of the + // response is equal to BLS_MODULUS as defined in https://eips.ethereum.org/EIPS/eip-4844#point-evaluation-precompile + if (!success) revert ErrorCallPointEvaluationPrecompileFailed(); + (, uint256 result) = abi.decode(data, (uint256, uint256)); + if (result != BLS_MODULUS) revert ErrorUnexpectedPointEvaluationPrecompileOutput(); + } + + // verify previous state root. + if (finalizedStateRoots[_batchIndex - 1] != _prevStateRoot) revert ErrorIncorrectPreviousStateRoot(); + + // avoid duplicated verification + if (finalizedStateRoots[_batchIndex] != bytes32(0)) revert ErrorBatchIsAlreadyVerified(); + + // check and update lastFinalizedBatchIndex + unchecked { + if (lastFinalizedBatchIndex + 1 != _batchIndex) revert ErrorIncorrectBatchIndex(); + lastFinalizedBatchIndex = _batchIndex; + } + + // record state root and withdraw root + finalizedStateRoots[_batchIndex] = _postStateRoot; + withdrawRoots[_batchIndex] = _withdrawRoot; + + // Pop finalized and non-skipped message from L1MessageQueue. + _popL1Messages( + BatchHeaderV1Codec.getSkippedBitmapPtr(memPtr), + BatchHeaderV1Codec.getTotalL1MessagePopped(memPtr), + BatchHeaderV1Codec.getL1MessagePopped(memPtr) + ); + + emit FinalizeBatch(_batchIndex, _batchHash, _postStateRoot, _withdrawRoot); + } +} From 15969d34ce5ac94d2bee1004b8b32d8933c89d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Mon, 10 Jun 2024 16:32:53 +0200 Subject: [PATCH 33/38] update frontend URLs --- contracts/scripts/foundry/DeployScroll.s.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index a0cd2cc0b7..87e8a9167b 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -2240,12 +2240,12 @@ contract GenerateFrontendConfig is DeployScroll { // API endpoints vm.writeLine(FRONTEND_ENV_PATH, ""); - vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_EXTERNAL_RPC_URI_L1 = \"", L1_RPC_ENDPOINT, "\"")); - vm.writeLine(FRONTEND_ENV_PATH, string.concat("REACT_APP_EXTERNAL_RPC_URI_L2 = \"", L2_RPC_ENDPOINT, "\"")); - vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_BRIDGE_API_URI = \"https://sepolia-api-bridge-v2.scroll.io/api\""); - vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_ROLLUPSCAN_API_URI = \"https://sepolia-api-re.scroll.io/api\""); - vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_EXPLORER_URI_L1 = \"https://sepolia.etherscan.io\""); - vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_EXPLORER_URI_L2 = \"https://sepolia.scrollscan.com\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_RPC_URI_L1 = \"http://l1geth-devnet.scrollsdk\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_RPC_URI_L2 = \"http://l2-rpc.scrollsdk\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_BRIDGE_API_URI = \"http://bridge-history-api.scrollsdk/api\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_ROLLUPSCAN_API_URI = \"https://rollup-explorer-backend.scrollsdk/api\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_EXPLORER_URI_L1 = \"http://l1-explorer.scrollsdk\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_EXPLORER_URI_L2 = \"http://blockscout.scrollsdk\""); // L1 contracts vm.writeLine(FRONTEND_ENV_PATH, ""); From 53d0389ba7f72fc12d631b7c9c6ab41d1926c2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Thu, 13 Jun 2024 17:26:56 +0200 Subject: [PATCH 34/38] update base image to arm-friendly one --- contracts/docker/Dockerfile.deploy | 23 ++++++++++++++++++++--- contracts/docker/Dockerfile.gen-configs | 23 ++++++++++++++++++++--- contracts/docker/scripts/build.sh | 20 ++++++++++++++++++-- contracts/docker/scripts/push.sh | 24 ++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 8 deletions(-) create mode 100755 contracts/docker/scripts/push.sh diff --git a/contracts/docker/Dockerfile.deploy b/contracts/docker/Dockerfile.deploy index 3c92d17cfe..cd9d8500f0 100644 --- a/contracts/docker/Dockerfile.deploy +++ b/contracts/docker/Dockerfile.deploy @@ -1,8 +1,24 @@ -FROM ghcr.io/foundry-rs/foundry:nightly-19d69f277de96f621d930cdb767a9693c55ae8e1 as foundry +# Use the latest node Debian slim base image +# This makes installing yarn dep much easier +FROM node:20-bookworm-slim -RUN apk add --no-cache bash jq +# Switch to bash shell +SHELL ["/bin/bash", "-c"] -WORKDIR /contracts +WORKDIR /root + +# Install dependencies +RUN apt update +RUN apt install --yes curl bash coreutils git jq + +# Download and run the Foundry installation script +RUN curl -L https://foundry.paradigm.xyz | bash + +# Set the environment variables to ensure Foundry tools are in the PATH +ENV PATH="/root/.foundry/bin:${PATH}" + +# Run foundryup to update Foundry +RUN foundryup -v nightly-88011569efcebc9152267be217c8cfbedc32c07c # copy dependencies COPY ./lib /contracts/lib @@ -20,6 +36,7 @@ COPY ./scripts /contracts/scripts ENV FOUNDRY_EVM_VERSION="cancun" ENV FOUNDRY_BYTECODE_HASH="none" +WORKDIR /contracts RUN forge build # copy script configs diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index 9befa04ae7..6f338d403d 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -1,8 +1,24 @@ -FROM ghcr.io/foundry-rs/foundry:nightly-19d69f277de96f621d930cdb767a9693c55ae8e1 as foundry +# Use the latest node Debian slim base image +# This makes installing yarn dep much easier +FROM node:20-bookworm-slim -RUN apk add --no-cache bash jq +# Switch to bash shell +SHELL ["/bin/bash", "-c"] -WORKDIR /contracts +WORKDIR /root + +# Install dependencies +RUN apt update +RUN apt install --yes curl bash coreutils git jq + +# Download and run the Foundry installation script +RUN curl -L https://foundry.paradigm.xyz | bash + +# Set the environment variables to ensure Foundry tools are in the PATH +ENV PATH="/root/.foundry/bin:${PATH}" + +# Run foundryup to update Foundry +RUN foundryup -v nightly-88011569efcebc9152267be217c8cfbedc32c07c # copy dependencies COPY ./lib /contracts/lib @@ -20,6 +36,7 @@ COPY ./scripts /contracts/scripts ENV FOUNDRY_EVM_VERSION="cancun" ENV FOUNDRY_BYTECODE_HASH="none" +WORKDIR /contracts RUN forge build # copy script configs diff --git a/contracts/docker/scripts/build.sh b/contracts/docker/scripts/build.sh index c7fb778450..93b15de06a 100755 --- a/contracts/docker/scripts/build.sh +++ b/contracts/docker/scripts/build.sh @@ -5,6 +5,22 @@ tag=${latest_commit:0:8} echo "Using Docker image tag: $tag" echo "" -docker build -f docker/Dockerfile.gen-configs -t scrolltech/scroll-stack-contracts:gen-configs-$tag --platform linux/amd64 . +docker build -f docker/Dockerfile.gen-configs -t scrolltech/scroll-stack-contracts:gen-configs-$tag-amd64 --platform linux/amd64 . +echo +echo "built scrolltech/scroll-stack-contracts:gen-configs-$tag-amd64" +echo -docker build -f docker/Dockerfile.deploy -t scrolltech/scroll-stack-contracts:deploy-$tag --platform linux/amd64 . \ No newline at end of file +docker build -f docker/Dockerfile.gen-configs -t scrolltech/scroll-stack-contracts:gen-configs-$tag-arm64 --platform linux/arm64 . +echo +echo "built scrolltech/scroll-stack-contracts:gen-configs-$tag-arm64" +echo + +docker build -f docker/Dockerfile.deploy -t scrolltech/scroll-stack-contracts:deploy-$tag-amd64 --platform linux/amd64 . +echo +echo "built scrolltech/scroll-stack-contracts:deploy-$tag-amd64" +echo + +docker build -f docker/Dockerfile.deploy -t scrolltech/scroll-stack-contracts:deploy-$tag-arm64 --platform linux/arm64 . +echo +echo "built scrolltech/scroll-stack-contracts:deploy-$tag-arm64" +echo diff --git a/contracts/docker/scripts/push.sh b/contracts/docker/scripts/push.sh new file mode 100755 index 0000000000..da28510e46 --- /dev/null +++ b/contracts/docker/scripts/push.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +latest_commit=$(git log -1 --pretty=format:%h) +tag=${latest_commit:0:8} +echo "Using Docker image tag: $tag" +echo "" + +docker push scrolltech/scroll-stack-contracts:gen-configs-$tag-amd64 +docker push scrolltech/scroll-stack-contracts:gen-configs-$tag-arm64 + +docker manifest create scrolltech/scroll-stack-contracts:gen-configs-$tag \ + --amend scrolltech/scroll-stack-contracts:gen-configs-$tag-amd64 \ + --amend scrolltech/scroll-stack-contracts:gen-configs-$tag-arm64 + +docker manifest push scrolltech/scroll-stack-contracts:gen-configs-$tag + +docker push scrolltech/scroll-stack-contracts:deploy-$tag-amd64 +docker push scrolltech/scroll-stack-contracts:deploy-$tag-arm64 + +docker manifest create scrolltech/scroll-stack-contracts:deploy-$tag \ + --amend scrolltech/scroll-stack-contracts:deploy-$tag-amd64 \ + --amend scrolltech/scroll-stack-contracts:deploy-$tag-arm64 + +docker manifest push scrolltech/scroll-stack-contracts:deploy-$tag From 977f5701fe5508ad65e7bd83d5292c60713077d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 18 Jun 2024 20:10:48 +0200 Subject: [PATCH 35/38] fix REACT_APP_EXTERNAL_RPC_URI_L1 --- contracts/docker/Dockerfile.deploy | 2 +- contracts/docker/Dockerfile.gen-configs | 2 +- contracts/scripts/foundry/DeployScroll.s.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/docker/Dockerfile.deploy b/contracts/docker/Dockerfile.deploy index cd9d8500f0..0d2bd1422a 100644 --- a/contracts/docker/Dockerfile.deploy +++ b/contracts/docker/Dockerfile.deploy @@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash ENV PATH="/root/.foundry/bin:${PATH}" # Run foundryup to update Foundry -RUN foundryup -v nightly-88011569efcebc9152267be217c8cfbedc32c07c +RUN foundryup -v nightly-35356b032ee8dfb8dc4a797ff06419ed56a4e980 # copy dependencies COPY ./lib /contracts/lib diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index 6f338d403d..bdbd89e1f4 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash ENV PATH="/root/.foundry/bin:${PATH}" # Run foundryup to update Foundry -RUN foundryup -v nightly-88011569efcebc9152267be217c8cfbedc32c07c +RUN foundryup -v nightly-35356b032ee8dfb8dc4a797ff06419ed56a4e980 # copy dependencies COPY ./lib /contracts/lib diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index 87e8a9167b..ff199cf6d9 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -2240,7 +2240,7 @@ contract GenerateFrontendConfig is DeployScroll { // API endpoints vm.writeLine(FRONTEND_ENV_PATH, ""); - vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_RPC_URI_L1 = \"http://l1geth-devnet.scrollsdk\""); + vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_RPC_URI_L1 = \"http://l1-devnet.scrollsdk\""); vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_EXTERNAL_RPC_URI_L2 = \"http://l2-rpc.scrollsdk\""); vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_BRIDGE_API_URI = \"http://bridge-history-api.scrollsdk/api\""); vm.writeLine(FRONTEND_ENV_PATH, "REACT_APP_ROLLUPSCAN_API_URI = \"https://rollup-explorer-backend.scrollsdk/api\""); From 0680c0d4d39bf2c5ae858814c2a0faa88e11d4b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 5 Jul 2024 16:53:09 +0200 Subject: [PATCH 36/38] set Curie in genesis --- contracts/docker/templates/genesis.json | 3 +-- contracts/scripts/foundry/DeployScroll.s.sol | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/docker/templates/genesis.json b/contracts/docker/templates/genesis.json index c429d8f2ff..27f8685071 100644 --- a/contracts/docker/templates/genesis.json +++ b/contracts/docker/templates/genesis.json @@ -15,6 +15,7 @@ "archimedesBlock": 0, "shanghaiBlock": 0, "bernoulliBlock": 0, + "curieBlock": 0, "clique": { "period": 3, "epoch": 30000 @@ -24,8 +25,6 @@ "maxTxPerBlock": null, "maxTxPayloadBytesPerBlock": 122880, "feeVaultAddress": null, - "enableEIP2718": false, - "enableEIP1559": false, "l1Config": { "l1ChainId": null, "l1MessageQueueAddress": null, diff --git a/contracts/scripts/foundry/DeployScroll.s.sol b/contracts/scripts/foundry/DeployScroll.s.sol index d259f916a2..d92e8b5ef6 100644 --- a/contracts/scripts/foundry/DeployScroll.s.sol +++ b/contracts/scripts/foundry/DeployScroll.s.sol @@ -1754,7 +1754,7 @@ contract GenerateGenesis is DeployScroll { // Scroll predeploys setL2MessageQueue(); - setL2GasPriceOracle(); + setL1GasPriceOracle(); setL2Whitelist(); setL2Weth(); setL2FeeVault(); @@ -1794,7 +1794,7 @@ contract GenerateGenesis is DeployScroll { vm.resetNonce(address(_queue)); } - function setL2GasPriceOracle() internal { + function setL1GasPriceOracle() internal { address predeployAddr = tryGetOverride("L1_GAS_PRICE_ORACLE"); if (predeployAddr == address(0)) { @@ -1809,6 +1809,9 @@ contract GenerateGenesis is DeployScroll { bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; vm.store(predeployAddr, _ownerSlot, vm.load(address(_oracle), _ownerSlot)); + bytes32 _isCurieSlot = hex"0000000000000000000000000000000000000000000000000000000000000008"; + vm.store(predeployAddr, _isCurieSlot, bytes32(uint256(1))); + // reset so its not included state dump vm.etch(address(_oracle), ""); vm.resetNonce(address(_oracle)); From 6e905352fc465eebe27bf1b7b6a8817df12ca36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 5 Jul 2024 17:08:24 +0200 Subject: [PATCH 37/38] bump foundry version --- contracts/docker/Dockerfile.deploy | 2 +- contracts/docker/Dockerfile.gen-configs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/docker/Dockerfile.deploy b/contracts/docker/Dockerfile.deploy index 0d2bd1422a..02301333b9 100644 --- a/contracts/docker/Dockerfile.deploy +++ b/contracts/docker/Dockerfile.deploy @@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash ENV PATH="/root/.foundry/bin:${PATH}" # Run foundryup to update Foundry -RUN foundryup -v nightly-35356b032ee8dfb8dc4a797ff06419ed56a4e980 +RUN foundryup -v nightly-56dbd20c7179570c53b6c17ff34daa7273a4ddae # copy dependencies COPY ./lib /contracts/lib diff --git a/contracts/docker/Dockerfile.gen-configs b/contracts/docker/Dockerfile.gen-configs index bdbd89e1f4..6a8ad51fc9 100644 --- a/contracts/docker/Dockerfile.gen-configs +++ b/contracts/docker/Dockerfile.gen-configs @@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash ENV PATH="/root/.foundry/bin:${PATH}" # Run foundryup to update Foundry -RUN foundryup -v nightly-35356b032ee8dfb8dc4a797ff06419ed56a4e980 +RUN foundryup -v nightly-56dbd20c7179570c53b6c17ff34daa7273a4ddae # copy dependencies COPY ./lib /contracts/lib From f69fc7b5d58dfed23cd97728b2972f1839c181e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 9 Jul 2024 14:21:14 +0200 Subject: [PATCH 38/38] enable isCurie on deployment --- contracts/src/L2/predeploys/L1GasPriceOracle.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/src/L2/predeploys/L1GasPriceOracle.sol b/contracts/src/L2/predeploys/L1GasPriceOracle.sol index 6d535328b2..de03d9dad2 100644 --- a/contracts/src/L2/predeploys/L1GasPriceOracle.sol +++ b/contracts/src/L2/predeploys/L1GasPriceOracle.sol @@ -113,6 +113,9 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { constructor(address _owner) { _transferOwnership(_owner); + + // by default we enable Curie from genesis + isCurie = true; } /*************************