diff --git a/foundry.toml b/foundry.toml index 3ebf29b5..d574bacb 100644 --- a/foundry.toml +++ b/foundry.toml @@ -36,5 +36,6 @@ ffi = true fs_permissions = [ { access='read-write', path='./scripts/deterministic/scroll/config' }, + { access='read-write', path='./scripts/deterministic/validium/workdir' }, { access='read-write', path='../../config' }, ] \ No newline at end of file diff --git a/scripts/deterministic/Configuration.sol b/scripts/deterministic/Configuration.sol index 89535fa6..3684de53 100644 --- a/scripts/deterministic/Configuration.sol +++ b/scripts/deterministic/Configuration.sol @@ -14,6 +14,7 @@ abstract contract Configuration is Script { string internal cfg; string internal contractsCfg; + string internal contractsCfgPath; /********************** * Internal interface * @@ -23,7 +24,7 @@ abstract contract Configuration is Script { string memory cfgPath = string(abi.encodePacked(workdir, "/config.toml")); cfg = vm.readFile(cfgPath); - string memory contractsCfgPath = string(abi.encodePacked(workdir, "/config-contracts.toml")); + contractsCfgPath = string(abi.encodePacked(workdir, "/config-contracts.toml")); contractsCfg = vm.readFile(contractsCfgPath); } @@ -39,8 +40,8 @@ abstract contract Configuration is Script { return cfg.readString(key); } - function writeToml(address addr, string memory tomlPath) internal { - vm.writeToml(vm.toString(addr), cfg, tomlPath); + function writeContract(address addr, string memory tomlPath) internal { + vm.writeToml(vm.toString(addr), contractsCfgPath, tomlPath); } /// @dev Ensure that `addr` is not the zero address. diff --git a/scripts/deterministic/DeterministicDeployment.sol b/scripts/deterministic/DeterministicDeployment.sol index 01f5821d..3cb0eefe 100644 --- a/scripts/deterministic/DeterministicDeployment.sol +++ b/scripts/deterministic/DeterministicDeployment.sol @@ -207,7 +207,7 @@ abstract contract DeterministicDeployment is Configuration { string memory tomlPath = string(abi.encodePacked(".", name, "_ADDR")); if (mode == ScriptMode.WriteConfig) { - writeToml(addr, tomlPath); + writeContract(addr, tomlPath); return; } diff --git a/scripts/deterministic/validium/Constants.sol b/scripts/deterministic/validium/Constants.sol new file mode 100644 index 00000000..5c9377c1 --- /dev/null +++ b/scripts/deterministic/validium/Constants.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.24; + +/// @dev The default minimum withdraw amount configured on L2TxFeeVault. +uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether; diff --git a/scripts/deterministic/validium/DeployValidium.s.sol b/scripts/deterministic/validium/DeployValidium.s.sol new file mode 100644 index 00000000..cffe80d9 --- /dev/null +++ b/scripts/deterministic/validium/DeployValidium.s.sol @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.24; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +// host contracts +import {L1MessageQueueV2} from "../../../src/L1/rollup/L1MessageQueueV2.sol"; +import {EmptyL1MessageQueueV1} from "../../../src/validium/EmptyL1MessageQueueV1.sol"; +import {L1ScrollMessengerValidium} from "../../../src/validium/L1ScrollMessengerValidium.sol"; +import {ScrollChainValidium} from "../../../src/validium/ScrollChainValidium.sol"; +import {ScrollChainValidiumMock} from "../../../src/mocks/ScrollChainValidiumMock.sol"; +import {L1ERC20GatewayValidium} from "../../../src/validium/L1ERC20GatewayValidium.sol"; +import {L1WETHGatewayValidium} from "../../../src/validium/L1WETHGatewayValidium.sol"; +import {SystemConfig} from "../../../src/L1/system-contract/SystemConfig.sol"; +import {L1GatewayRouter} from "../../../src/L1/gateways/L1GatewayRouter.sol"; +import {L1ETHGateway} from "../../../src/L1/gateways/L1ETHGateway.sol"; +import {FastWithdrawVault} from "../../../src/validium/FastWithdrawVault.sol"; + +// validium contracts +import {L1GasPriceOracle} from "../../../src/L2/predeploys/L1GasPriceOracle.sol"; +import {L2MessageQueue} from "../../../src/L2/predeploys/L2MessageQueue.sol"; +import {L2ScrollMessenger} from "../../../src/L2/L2ScrollMessenger.sol"; +import {L2SystemConfig} from "../../../src/L2/L2SystemConfig.sol"; +import {L2TxFeeVault} from "../../../src/L2/predeploys/L2TxFeeVault.sol"; +import {L2GatewayRouter} from "../../../src/L2/gateways/L2GatewayRouter.sol"; +import {L2ETHGateway} from "../../../src/L2/gateways/L2ETHGateway.sol"; +import {L2StandardERC20Gateway} from "../../../src/L2/gateways/L2StandardERC20Gateway.sol"; +import {ScrollStandardERC20} from "../../../src/libraries/token/ScrollStandardERC20.sol"; +import {ScrollStandardERC20FactorySetOwner} from "../contracts/ScrollStandardERC20FactorySetOwner.sol"; + +// misc +import {DeterministicDeployment} from "../DeterministicDeployment.sol"; +import {EmptyContract} from "../../../src/misc/EmptyContract.sol"; +import {FEE_VAULT_MIN_WITHDRAW_AMOUNT} from "./Constants.sol"; +import {ProxyAdminSetOwner} from "../contracts/ProxyAdminSetOwner.sol"; +import {Whitelist} from "../../../src/L2/predeploys/Whitelist.sol"; +import {WrappedEther} from "../../../src/L2/predeploys/WrappedEther.sol"; + +import {ValidiumConfiguration} from "./ValidiumConfiguration.sol"; + +contract DeployValidium is ValidiumConfiguration, DeterministicDeployment { + using stdToml for string; + + /*********************** + * Contracts to deploy * + ***********************/ + + // Host addresses + address internal HOST_ENFORCED_TX_GATEWAY_ADDR; + address internal HOST_ERC20_GATEWAY_ADDR; + address internal HOST_IMPLEMENTATION_PLACEHOLDER_ADDR; + address internal HOST_MESSAGE_QUEUE_ADDR; + address internal HOST_MESSENGER_ADDR; + address internal HOST_MESSENGER_WHITELIST_ADDR; + address internal HOST_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR; + address internal HOST_PROXY_ADMIN_ADDR; + address internal HOST_SYSTEM_CONFIG_ADDR; + address internal HOST_VALIDIUM_ADDR; + address internal HOST_WETH_ADDR; + address internal HOST_WETH_GATEWAY_ADDR; + address internal HOST_FAST_WITHDRAW_VAULT_ADDR; + + // Validium addresses + address internal VALIDIUM_ERC20_GATEWAY_ADDR; + address internal VALIDIUM_GAS_PRICE_ORACLE_ADDR; + address internal VALIDIUM_GAS_PRICE_ORACLE_WHITELIST_ADDR; + address internal VALIDIUM_GATEWAY_ROUTER_ADDR; + address internal VALIDIUM_IMPLEMENTATION_PLACEHOLDER_ADDR; + address internal VALIDIUM_MESSAGE_QUEUE_ADDR; + address internal VALIDIUM_MESSENGER_ADDR; + address internal VALIDIUM_PROXY_ADMIN_ADDR; + address internal VALIDIUM_STANDARD_ERC20_FACTORY_ADDR; + address internal VALIDIUM_STANDARD_ERC20_TOKEN_ADDR; + address internal VALIDIUM_SYSTEM_CONFIG_ADDR; + address internal VALIDIUM_TX_FEE_VAULT_ADDR; + + /************* + * Utilities * + *************/ + + enum Layer { + None, + Host, // The host layer on which the validium is deployed, usually L2. + Validium // The validium layer, i.e. L3. + } + + Layer private broadcastLayer = Layer.None; + + /// @dev Only broadcast code block if we run the script on the specified layer. + modifier broadcast(Layer layer) { + // live deployment + if (broadcastLayer == layer) { + vm.startBroadcast(DEPLOYER_PRIVATE_KEY); + _; + vm.stopBroadcast(); + } + // simulation + else { + // make sure we use the correct sender in simulation + vm.startPrank(DEPLOYER_ADDR); + _; + vm.stopPrank(); + } + } + + /// @dev Only execute block if we run the script on the specified layer. + modifier only(Layer layer) { + if (broadcastLayer != layer) { + return; + } + _; + } + + function parseLayer(string memory raw) private pure returns (Layer) { + if (keccak256(bytes(raw)) == keccak256(bytes("host"))) { + return Layer.Host; + } else if (keccak256(bytes(raw)) == keccak256(bytes("validium"))) { + return Layer.Validium; + } else if (keccak256(bytes(raw)) == keccak256(bytes(""))) { + return Layer.None; + } else { + revert(string(abi.encodePacked("[ERROR] unknown layer: ", raw))); + } + } + + /*************** + * Entry point * + ***************/ + + function run( + string memory workdir, + string memory layer, + string memory scriptMode + ) public { + readConfig(workdir); + + broadcastLayer = parseLayer(layer); + ScriptMode mode = parseScriptMode(scriptMode); + + DeterministicDeployment.initialize(mode, workdir); + + deployAllContracts(); + initializeHostContracts(); + initializeValidiumContracts(); + } + + /********************** + * Internal interface * + **********************/ + + function predictAllContracts() internal { + skipDeployment(); + deployAllContracts(); + } + + /********************* + * Private functions * + *********************/ + + function deployHostProxy(string memory name) private returns (address) { + bytes memory args = abi.encode( + notnull(HOST_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(HOST_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + return deploy(name, type(TransparentUpgradeableProxy).creationCode, args); + } + + function deployValidiumProxy(string memory name) private returns (address) { + bytes memory args = abi.encode( + notnull(VALIDIUM_IMPLEMENTATION_PLACEHOLDER_ADDR), + notnull(VALIDIUM_PROXY_ADMIN_ADDR), + new bytes(0) + ); + + return deploy(name, type(TransparentUpgradeableProxy).creationCode, args); + } + + // TODO: transfer all contracts to OWNER + function transferOwnership(address addr, address newOwner) private { + if (Ownable(addr).owner() != newOwner) { + Ownable(addr).transferOwnership(newOwner); + } + } + + function deployAllContracts() private { + deployHostContracts1stPass(); + deployValidiumContracts1stPass(); + deployHostContracts2ndPass(); + deployValidiumContracts2ndPass(); + } + + // @notice deployHostContracts1stPass deploys host-layer contracts whose initialization does not depend on any validium-layer addresses. + function deployHostContracts1stPass() private broadcast(Layer.Host) { + deployHostWeth(); + deployHostProxyAdmin(); + + // Note: we do not use the enforced gateway on the validium L3, + // but it is required to be a non-zero address for initializing + // some other contracts. We just use address(1). + HOST_ENFORCED_TX_GATEWAY_ADDR = address(1); + + // TODO: deploy verifier + HOST_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR = address(1); + + // deploy empty proxies + HOST_VALIDIUM_ADDR = deployHostProxy("HOST_VALIDIUM_PROXY"); + HOST_MESSAGE_QUEUE_ADDR = deployHostProxy("HOST_MESSAGE_QUEUE_PROXY"); + HOST_SYSTEM_CONFIG_ADDR = deployHostProxy("HOST_SYSTEM_CONFIG_PROXY"); + HOST_MESSENGER_ADDR = deployHostProxy("HOST_MESSENGER_PROXY"); + HOST_ERC20_GATEWAY_ADDR = deployHostProxy("HOST_ERC20_GATEWAY_PROXY"); + HOST_WETH_GATEWAY_ADDR = deployHostProxy("HOST_WETH_GATEWAY_PROXY"); + HOST_FAST_WITHDRAW_VAULT_ADDR = deployHostProxy("HOST_FAST_WITHDRAW_VAULT_PROXY"); + + // deploy implementations + deployHostValidium(); + deployHostMessageQueue(); + deployHostSystemConfig(); + deployHostMessengerWhitelist(); + deployHostWethGateway(); + deployHostFastWithdrawVault(); + } + + // @notice deployValidiumContracts1stPass deploys validium-layer contracts whose initialization does not depend on any host-layer addresses. + function deployValidiumContracts1stPass() private broadcast(Layer.Validium) { + deployValidiumProxyAdmin(); + + // Note: we do not use the gateway router on the validium L3, + // but it is required to be a non-zero address for initializing + // some other contracts. We just use address(1). + VALIDIUM_GATEWAY_ROUTER_ADDR = address(1); + + // predeploys + deployValidiumMessageQueue(); + deployValidiumGasPriceOracle(); + deployValidiumWhitelist(); + deployValidiumTxFeeVault(); + + // deploy empty proxies + VALIDIUM_MESSENGER_ADDR = deployValidiumProxy("VALIDIUM_MESSENGER_PROXY"); + VALIDIUM_SYSTEM_CONFIG_ADDR = deployValidiumProxy("VALIDIUM_SYSTEM_CONFIG_PROXY"); + VALIDIUM_ERC20_GATEWAY_ADDR = deployValidiumProxy("VALIDIUM_ERC20_GATEWAY_PROXY"); + + // deploy implementations + deployValidiumSystemConfig(); + deployValidiumStandardErc20Factory(); + } + + // @notice deployHostContracts2ndPass deploys host-layer contracts whose initialization depends on some validium-layer addresses. + function deployHostContracts2ndPass() private broadcast(Layer.Host) { + deployHostMessenger(); // depends on VALIDIUM_MESSENGER_ADDR + deployHostErc20Gateway(); // depends on VALIDIUM_ERC20_GATEWAY_ADDR + } + + // @notice deployValidiumContracts2ndPass deploys validium-layer contracts whose initialization depends on some host-layer addresses. + function deployValidiumContracts2ndPass() private broadcast(Layer.Validium) { + deployValidiumMessenger(); // depends on HOST_MESSENGER_ADDR + deployValidiumErc20Gateway(); // depends on HOST_ERC20_GATEWAY_ADDR + } + + // @notice initializeHostContracts initializes contracts deployed on the host layer. + function initializeHostContracts() private broadcast(Layer.Host) only(Layer.Host) { + initializeHostValidium(); + initializeHostSystemConfig(); + initializeHostMessageQueue(); + initializeHostMessenger(); + initializeHostMessengerWhitelist(); + + initializeHostErc20Gateway(); + initializeHostFastWithdrawVault(); + + transferHostContractOwnership(); + } + + // @notice initializeValidiumContracts initializes contracts deployed on the validium layer. + function initializeValidiumContracts() private broadcast(Layer.Validium) only(Layer.Validium) { + initializeValidiumMessageQueue(); + initializeValidiumTxFeeVault(); + initializeValidiumGasPriceOracle(); + initializeValidiumMessenger(); + initializeValidiumSystemConfig(); + initializeValidiumErc20Gateway(); + + transferValidiumContractOwnership(); + } + + /******************** + * Host: Deployment * + *******************/ + + function deployHostWeth() private { + HOST_WETH_ADDR = deploy("HOST_WETH", type(WrappedEther).creationCode); + } + + function deployHostProxyAdmin() private { + bytes memory args = abi.encode(DEPLOYER_ADDR); + HOST_PROXY_ADMIN_ADDR = deploy("HOST_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + + HOST_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy( + "HOST_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); + } + + function deployHostValidium() private { + bytes memory args = abi.encode( + CHAIN_ID_VALIDIUM, + notnull(HOST_MESSAGE_QUEUE_ADDR), + notnull(HOST_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR) + ); + + // TODO: disable mock mode + // bytes memory creationCode = type(ScrollChainValidium).creationCode; + bytes memory creationCode = type(ScrollChainValidiumMock).creationCode; + + // if (TEST_ENV_MOCK_FINALIZE_ENABLED) { + // creationCode = type(ScrollChainValidiumMockFinalize).creationCode; + // } + + address impl = deploy("HOST_VALIDIUM_IMPLEMENTATION", creationCode, args); + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_VALIDIUM_ADDR, impl); + } + + function deployHostMessageQueue() private { + address queueV1 = deploy("HOST_EMPTY_MESSAGE_QUEUE_V1", type(EmptyL1MessageQueueV1).creationCode); + + bytes memory args = abi.encode( + notnull(HOST_MESSENGER_ADDR), + notnull(HOST_VALIDIUM_ADDR), + notnull(HOST_ENFORCED_TX_GATEWAY_ADDR), + notnull(queueV1), + notnull(HOST_SYSTEM_CONFIG_ADDR) + ); + + address impl = deploy("HOST_MESSAGE_QUEUE_IMPLEMENTATION", type(L1MessageQueueV2).creationCode, args); + + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_MESSAGE_QUEUE_ADDR, impl); + } + + function deployHostSystemConfig() private { + address impl = deploy("HOST_SYSTEM_CONFIG_IMPLEMENTATION", type(SystemConfig).creationCode); + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_SYSTEM_CONFIG_ADDR, impl); + } + + function deployHostMessengerWhitelist() private { + bytes memory args = abi.encode(notnull(DEPLOYER_ADDR)); + HOST_MESSENGER_WHITELIST_ADDR = deploy("HOST_MESSENGER_WHITELIST", type(Whitelist).creationCode, args); + } + + function deployHostWethGateway() private { + bytes memory args = abi.encode(notnull(HOST_WETH_ADDR), notnull(HOST_ERC20_GATEWAY_ADDR)); + + address impl = deploy("HOST_WETH_GATEWAY_IMPLEMENTATION", type(L1WETHGatewayValidium).creationCode, args); + + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_WETH_GATEWAY_ADDR, impl); + } + + function deployHostFastWithdrawVault() private { + bytes memory args = abi.encode(notnull(HOST_WETH_ADDR), notnull(HOST_ERC20_GATEWAY_ADDR)); + + address impl = deploy("HOST_FAST_WITHDRAW_VAULT_IMPLEMENTATION", type(FastWithdrawVault).creationCode, args); + + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_FAST_WITHDRAW_VAULT_ADDR, impl); + } + + function deployHostMessenger() private { + bytes memory args = abi.encode( + notnull(VALIDIUM_MESSENGER_ADDR), + notnull(HOST_VALIDIUM_ADDR), + notnull(HOST_MESSAGE_QUEUE_ADDR), + notnull(HOST_MESSENGER_WHITELIST_ADDR) + ); + + address impl = deploy("HOST_MESSENGER_IMPLEMENTATION", type(L1ScrollMessengerValidium).creationCode, args); + + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_MESSENGER_ADDR, impl); + } + + function deployHostErc20Gateway() private { + bytes memory args = abi.encode( + notnull(VALIDIUM_ERC20_GATEWAY_ADDR), + notnull(HOST_MESSENGER_ADDR), + notnull(VALIDIUM_STANDARD_ERC20_TOKEN_ADDR), + notnull(VALIDIUM_STANDARD_ERC20_FACTORY_ADDR), + notnull(HOST_VALIDIUM_ADDR) + ); + + address impl = deploy("HOST_ERC20_GATEWAY_IMPLEMENTATION", type(L1ERC20GatewayValidium).creationCode, args); + + upgrade(HOST_PROXY_ADMIN_ADDR, HOST_ERC20_GATEWAY_ADDR, impl); + } + + /************************ + * Validium: Deployment * + ***********************/ + + function deployValidiumProxyAdmin() private { + bytes memory args = abi.encode(DEPLOYER_ADDR); + VALIDIUM_PROXY_ADMIN_ADDR = deploy("VALIDIUM_PROXY_ADMIN", type(ProxyAdminSetOwner).creationCode, args); + + VALIDIUM_IMPLEMENTATION_PLACEHOLDER_ADDR = deploy( + "VALIDIUM_IMPLEMENTATION_PLACEHOLDER", + type(EmptyContract).creationCode + ); + } + + function deployValidiumMessageQueue() private { + bytes memory args = abi.encode(DEPLOYER_ADDR); + VALIDIUM_MESSAGE_QUEUE_ADDR = deploy("VALIDIUM_MESSAGE_QUEUE", type(L2MessageQueue).creationCode, args); + } + + function deployValidiumGasPriceOracle() private { + bytes memory args = abi.encode(DEPLOYER_ADDR, true); + VALIDIUM_GAS_PRICE_ORACLE_ADDR = deploy("VALIDIUM_GAS_PRICE_ORACLE", type(L1GasPriceOracle).creationCode, args); + } + + function deployValidiumWhitelist() private { + bytes memory args = abi.encode(DEPLOYER_ADDR); + VALIDIUM_GAS_PRICE_ORACLE_WHITELIST_ADDR = deploy( + "VALIDIUM_GAS_PRICE_ORACLE_WHITELIST", + type(Whitelist).creationCode, + args + ); + } + + function deployValidiumTxFeeVault() private { + bytes memory args = abi.encode(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); + VALIDIUM_TX_FEE_VAULT_ADDR = deploy("VALIDIUM_TX_FEE_VAULT", type(L2TxFeeVault).creationCode, args); + } + + function deployValidiumSystemConfig() private { + address impl = deploy("VALIDIUM_SYSTEM_CONFIG_IMPLEMENTATION", type(L2SystemConfig).creationCode, new bytes(0)); + upgrade(VALIDIUM_PROXY_ADMIN_ADDR, VALIDIUM_SYSTEM_CONFIG_ADDR, impl); + } + + function deployValidiumStandardErc20Factory() private { + VALIDIUM_STANDARD_ERC20_TOKEN_ADDR = deploy( + "VALIDIUM_STANDARD_ERC20_TOKEN", + type(ScrollStandardERC20).creationCode + ); + + bytes memory args = abi.encode( + VALIDIUM_ERC20_GATEWAY_ADDR, // Note: The factory contract must be owned by the ERC20 gateway contract. + notnull(VALIDIUM_STANDARD_ERC20_TOKEN_ADDR) + ); + + VALIDIUM_STANDARD_ERC20_FACTORY_ADDR = deploy( + "VALIDIUM_STANDARD_ERC20_FACTORY", + type(ScrollStandardERC20FactorySetOwner).creationCode, + args + ); + } + + function deployValidiumMessenger() private { + bytes memory args = abi.encode(notnull(HOST_MESSENGER_ADDR), notnull(VALIDIUM_MESSAGE_QUEUE_ADDR)); + + address impl = deploy("VALIDIUM_MESSENGER_IMPLEMENTATION", type(L2ScrollMessenger).creationCode, args); + + upgrade(VALIDIUM_PROXY_ADMIN_ADDR, VALIDIUM_MESSENGER_ADDR, impl); + } + + function deployValidiumErc20Gateway() private { + bytes memory args = abi.encode( + notnull(HOST_ERC20_GATEWAY_ADDR), + notnull(VALIDIUM_GATEWAY_ROUTER_ADDR), + notnull(VALIDIUM_MESSENGER_ADDR), + notnull(VALIDIUM_STANDARD_ERC20_FACTORY_ADDR) + ); + + address impl = deploy("VALIDIUM_ERC20_GATEWAY_IMPLEMENTATION", type(L2StandardERC20Gateway).creationCode, args); + + upgrade(VALIDIUM_PROXY_ADMIN_ADDR, VALIDIUM_ERC20_GATEWAY_ADDR, impl); + } + + /************************ + * Host: initialization * + ************************/ + + function initializeHostValidium() private { + ScrollChainValidium validium = ScrollChainValidium(HOST_VALIDIUM_ADDR); + + if (getInitializeCount(HOST_VALIDIUM_ADDR) != 0) { + // assume initialization went through correctly + return; + } + + // temporarily set deployer as admin + validium.initialize(notnull(DEPLOYER_ADDR)); + + // grant operational roles + validium.grantRole(validium.GENESIS_IMPORTER_ROLE(), notnull(COMMIT_SENDER_ADDR)); + validium.grantRole(validium.SEQUENCER_ROLE(), notnull(COMMIT_SENDER_ADDR)); + validium.grantRole(validium.PROVER_ROLE(), notnull(FINALIZE_SENDER_ADDR)); + validium.grantRole(validium.KEY_MANAGER_ROLE(), notnull(DEPLOYER_ADDR)); + + // register initial sequencer key + validium.registerNewEncryptionKey(vm.parseBytes(SEQUENCER_ENCRYPTION_KEY)); + + // transfer roles to owner + validium.grantRole(validium.KEY_MANAGER_ROLE(), notnull(OWNER_ADDR)); + validium.renounceRole(validium.KEY_MANAGER_ROLE(), DEPLOYER_ADDR); + + validium.grantRole(validium.DEFAULT_ADMIN_ROLE(), notnull(OWNER_ADDR)); + validium.renounceRole(validium.DEFAULT_ADMIN_ROLE(), DEPLOYER_ADDR); + } + + function initializeHostSystemConfig() private { + address owner = OWNER_ADDR; + address signer = SEQUENCER_SIGNER_ADDRESS; + + SystemConfig.MessageQueueParameters memory messageQueueParameters = SystemConfig.MessageQueueParameters({ + maxGasLimit: uint32(VALIDIUM_GAS_LIMIT), + baseFeeOverhead: 0, + baseFeeScalar: 0 + }); + + SystemConfig.EnforcedBatchParameters memory enforcedBatchParameters = SystemConfig.EnforcedBatchParameters({ + maxDelayEnterEnforcedMode: uint24(2**24 - 1), + maxDelayMessageQueue: uint24(2**24 - 1) + }); + + if (getInitializeCount(HOST_SYSTEM_CONFIG_ADDR) == 0) { + SystemConfig(HOST_SYSTEM_CONFIG_ADDR).initialize( + owner, + signer, + messageQueueParameters, + enforcedBatchParameters + ); + } + } + + function initializeHostMessageQueue() private { + if (getInitializeCount(HOST_MESSAGE_QUEUE_ADDR) == 0) { + L1MessageQueueV2(HOST_MESSAGE_QUEUE_ADDR).initialize(); + } + } + + function initializeHostMessenger() private { + if (getInitializeCount(HOST_MESSENGER_ADDR) == 0) { + L1ScrollMessengerValidium(payable(HOST_MESSENGER_ADDR)).initialize( + notnull(VALIDIUM_MESSENGER_ADDR), + notnull(L1_FEE_VAULT_ADDR), + notnull(HOST_VALIDIUM_ADDR), + notnull(HOST_MESSAGE_QUEUE_ADDR) + ); + } + } + + function initializeHostMessengerWhitelist() private { + address[] memory gateways = new address[](1); + gateways[0] = HOST_ERC20_GATEWAY_ADDR; + Whitelist(HOST_MESSENGER_WHITELIST_ADDR).updateWhitelistStatus(gateways, true); + } + + function initializeHostErc20Gateway() private { + if (getInitializeCount(HOST_ERC20_GATEWAY_ADDR) == 0) { + L1ERC20GatewayValidium(payable(HOST_ERC20_GATEWAY_ADDR)).initialize(); + } + } + + function initializeHostFastWithdrawVault() private { + if (getInitializeCount(HOST_FAST_WITHDRAW_VAULT_ADDR) == 0) { + FastWithdrawVault(payable(HOST_FAST_WITHDRAW_VAULT_ADDR)).initialize( + notnull(OWNER_ADDR), + notnull(FAST_WITHDRAW_SIGNER_ADDR) + ); + } + } + + function transferHostContractOwnership() private { + transferOwnership(HOST_PROXY_ADMIN_ADDR, OWNER_ADDR); + // HOST_VALIDIUM_ADDR already coverd in initializeHostValidium + transferOwnership(HOST_MESSAGE_QUEUE_ADDR, OWNER_ADDR); + transferOwnership(HOST_SYSTEM_CONFIG_ADDR, OWNER_ADDR); + transferOwnership(HOST_MESSENGER_ADDR, OWNER_ADDR); + transferOwnership(HOST_MESSENGER_WHITELIST_ADDR, OWNER_ADDR); + transferOwnership(HOST_ERC20_GATEWAY_ADDR, OWNER_ADDR); + // HOST_FAST_WITHDRAW_VAULT_ADDR already covered in initializeHostFastWithdrawVault + } + + /**************************** + * Validium: initialization * + ***************************/ + + function initializeValidiumMessageQueue() private { + if (L2MessageQueue(VALIDIUM_MESSAGE_QUEUE_ADDR).messenger() != notnull(VALIDIUM_MESSENGER_ADDR)) { + L2MessageQueue(VALIDIUM_MESSAGE_QUEUE_ADDR).initialize(VALIDIUM_MESSENGER_ADDR); + } + } + + function initializeValidiumTxFeeVault() private { + if (L2TxFeeVault(payable(VALIDIUM_TX_FEE_VAULT_ADDR)).messenger() != notnull(VALIDIUM_MESSENGER_ADDR)) { + L2TxFeeVault(payable(VALIDIUM_TX_FEE_VAULT_ADDR)).updateMessenger(VALIDIUM_MESSENGER_ADDR); + } + } + + function initializeValidiumGasPriceOracle() private { + if ( + address(L1GasPriceOracle(VALIDIUM_GAS_PRICE_ORACLE_ADDR).whitelist()) != + notnull(VALIDIUM_GAS_PRICE_ORACLE_WHITELIST_ADDR) + ) { + L1GasPriceOracle(VALIDIUM_GAS_PRICE_ORACLE_ADDR).updateWhitelist(VALIDIUM_GAS_PRICE_ORACLE_WHITELIST_ADDR); + } + } + + function initializeValidiumMessenger() private { + if (getInitializeCount(VALIDIUM_MESSENGER_ADDR) == 0) { + L2ScrollMessenger(payable(VALIDIUM_MESSENGER_ADDR)).initialize(notnull(HOST_MESSENGER_ADDR)); + } + } + + function initializeValidiumSystemConfig() private { + if (getInitializeCount(VALIDIUM_SYSTEM_CONFIG_ADDR) == 0) { + L2SystemConfig(payable(VALIDIUM_SYSTEM_CONFIG_ADDR)).initialize(notnull(OWNER_ADDR)); + } + } + + function initializeValidiumErc20Gateway() private { + if (getInitializeCount(VALIDIUM_ERC20_GATEWAY_ADDR) == 0) { + L2StandardERC20Gateway(VALIDIUM_ERC20_GATEWAY_ADDR).initialize( + notnull(HOST_ERC20_GATEWAY_ADDR), + notnull(VALIDIUM_GATEWAY_ROUTER_ADDR), + notnull(VALIDIUM_MESSENGER_ADDR), + notnull(VALIDIUM_STANDARD_ERC20_FACTORY_ADDR) + ); + } + } + + function transferValidiumContractOwnership() private { + transferOwnership(VALIDIUM_MESSAGE_QUEUE_ADDR, OWNER_ADDR); + transferOwnership(VALIDIUM_GAS_PRICE_ORACLE_ADDR, OWNER_ADDR); + transferOwnership(VALIDIUM_GAS_PRICE_ORACLE_WHITELIST_ADDR, OWNER_ADDR); + transferOwnership(VALIDIUM_TX_FEE_VAULT_ADDR, OWNER_ADDR); + + transferOwnership(VALIDIUM_PROXY_ADMIN_ADDR, OWNER_ADDR); + transferOwnership(VALIDIUM_MESSENGER_ADDR, OWNER_ADDR); + transferOwnership(VALIDIUM_SYSTEM_CONFIG_ADDR, OWNER_ADDR); + transferOwnership(VALIDIUM_ERC20_GATEWAY_ADDR, OWNER_ADDR); + } +} diff --git a/scripts/deterministic/validium/GenerateGenesis.s.sol b/scripts/deterministic/validium/GenerateGenesis.s.sol new file mode 100644 index 00000000..cc0b436b --- /dev/null +++ b/scripts/deterministic/validium/GenerateGenesis.s.sol @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.24; + +import {console} from "forge-std/console.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 {FEE_VAULT_MIN_WITHDRAW_AMOUNT} from "./Constants.sol"; +import {DeployValidium} from "./DeployValidium.s.sol"; +import {DeterministicDeployment, DETERMINISTIC_DEPLOYMENT_PROXY_ADDR} from "../DeterministicDeployment.sol"; + +contract GenerateGenesis is DeployValidium { + /*************** + * Entry point * + ***************/ + + string private genesisAllocTmpPath; + + function run(string memory workdir) public { + readConfig(workdir); + + string memory templatePath = string(abi.encodePacked(workdir, "/genesis.json.template")); + string memory outPath = string(abi.encodePacked(workdir, "/genesis.json")); + genesisAllocTmpPath = string(abi.encodePacked(workdir, "/__genesis-alloc.json")); + + DeterministicDeployment.initialize(ScriptMode.VerifyConfig, workdir); + predictAllContracts(); + + generateGenesisAlloc(); + generateGenesisJson(templatePath, outPath); + + // clean up temporary files + vm.removeFile(genesisAllocTmpPath); + } + + /********************* + * Private functions * + *********************/ + + function generateGenesisAlloc() private { + if (vm.exists(genesisAllocTmpPath)) { + vm.removeFile(genesisAllocTmpPath); + } + + // Scroll predeploys + setValidiumMessageQueue(); + setValidiumGasPriceOracle(); + setValidiumWhitelist(); + setValidiumFeeVault(); + + // other predeploys + setDeterministicDeploymentProxy(); + setSafeSingletonFactory(); + + // reset sender + vm.resetNonce(msg.sender); + + // prefunded accounts + prefundValidiumMessenger(); + prefundL2Deployer(); + + // write to file + vm.dumpState(genesisAllocTmpPath); + sortJsonByKeys(genesisAllocTmpPath); + } + + function setValidiumMessageQueue() internal { + address predeployAddr = tryGetOverride("VALIDIUM_MESSAGE_QUEUE"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + L2MessageQueue _queue = new L2MessageQueue(DEPLOYER_ADDR); + vm.etch(predeployAddr, address(_queue).code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000052"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_queue), _ownerSlot)); + + // reset so it's not included state dump + vm.etch(address(_queue), ""); + vm.resetNonce(address(_queue)); + } + + function setValidiumGasPriceOracle() internal { + address predeployAddr = tryGetOverride("VALIDIUM_GAS_PRICE_ORACLE"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + L1GasPriceOracle _oracle = new L1GasPriceOracle(DEPLOYER_ADDR); + vm.etch(predeployAddr, address(_oracle).code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_oracle), _ownerSlot)); + + bytes32 _isCurieSlot = hex"0000000000000000000000000000000000000000000000000000000000000008"; + vm.store(predeployAddr, _isCurieSlot, bytes32(uint256(1))); + + bytes32 _penaltyThresholdSlot = hex"0000000000000000000000000000000000000000000000000000000000000009"; + vm.store(predeployAddr, _penaltyThresholdSlot, bytes32(uint256(1e9))); + + bytes32 _penaltyFactorSlot = hex"000000000000000000000000000000000000000000000000000000000000000a"; + vm.store(predeployAddr, _penaltyFactorSlot, bytes32(uint256(1e9))); + + bytes32 _isFeynmanSlot = hex"000000000000000000000000000000000000000000000000000000000000000b"; + vm.store(predeployAddr, _isFeynmanSlot, bytes32(uint256(1))); + + // reset so it's not included state dump + vm.etch(address(_oracle), ""); + vm.resetNonce(address(_oracle)); + } + + function setValidiumWhitelist() internal { + address predeployAddr = tryGetOverride("VALIDIUM_GAS_PRICE_ORACLE_WHITELIST"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + Whitelist _whitelist = new Whitelist(DEPLOYER_ADDR); + vm.etch(predeployAddr, address(_whitelist).code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + vm.store(predeployAddr, _ownerSlot, vm.load(address(_whitelist), _ownerSlot)); + + // reset so it's not included state dump + vm.etch(address(_whitelist), ""); + vm.resetNonce(address(_whitelist)); + } + + function setValidiumFeeVault() internal { + address predeployAddr = tryGetOverride("VALIDIUM_TX_FEE_VAULT"); + + if (predeployAddr == address(0)) { + return; + } + + // set code + address _vaultAddr; + vm.prank(DEPLOYER_ADDR); + L2TxFeeVault _vault = new L2TxFeeVault(DEPLOYER_ADDR, L1_FEE_VAULT_ADDR, FEE_VAULT_MIN_WITHDRAW_AMOUNT); + vm.prank(DEPLOYER_ADDR); + _vault.updateMessenger(VALIDIUM_MESSENGER_ADDR); + _vaultAddr = address(_vault); + + vm.etch(predeployAddr, _vaultAddr.code); + + // set storage + bytes32 _ownerSlot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + vm.store(predeployAddr, _ownerSlot, vm.load(_vaultAddr, _ownerSlot)); + + bytes32 _minWithdrawAmountSlot = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(predeployAddr, _minWithdrawAmountSlot, vm.load(_vaultAddr, _minWithdrawAmountSlot)); + + bytes32 _messengerSlot = hex"0000000000000000000000000000000000000000000000000000000000000002"; + vm.store(predeployAddr, _messengerSlot, vm.load(_vaultAddr, _messengerSlot)); + + bytes32 _recipientSlot = hex"0000000000000000000000000000000000000000000000000000000000000003"; + vm.store(predeployAddr, _recipientSlot, vm.load(_vaultAddr, _recipientSlot)); + + // reset so it's not included state dump + vm.etch(_vaultAddr, ""); + vm.resetNonce(_vaultAddr); + } + + function setDeterministicDeploymentProxy() internal { + bytes + memory code = hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"; + vm.etch(DETERMINISTIC_DEPLOYMENT_PROXY_ADDR, code); + } + + function setSafeSingletonFactory() internal { + bytes + memory code = hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"; + vm.etch(0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7, code); + } + + function prefundValidiumMessenger() internal { + vm.deal(VALIDIUM_MESSENGER_ADDR, VALIDIUM_MESSENGER_INITIAL_BALANCE); + } + + function prefundL2Deployer() internal { + vm.deal(DEPLOYER_ADDR, VALIDIUM_DEPLOYER_INITIAL_BALANCE); + } + + function generateGenesisJson(string memory templatePath, string memory outPath) private { + // initialize template file + if (vm.exists(outPath)) { + vm.removeFile(outPath); + } + + string memory template = vm.readFile(templatePath); + vm.writeFile(outPath, template); + + // general config + vm.writeJson(vm.toString(CHAIN_ID_VALIDIUM), outPath, ".config.chainId"); + + uint256 timestamp = vm.unixTime() / 1000; + vm.writeJson(vm.toString(bytes32(timestamp)), outPath, ".timestamp"); + + // serialize explicitly as string, otherwise foundry will serialize it as number + string memory gasLimit = string(abi.encodePacked('"', vm.toString(VALIDIUM_GAS_LIMIT), '"')); + vm.writeJson(gasLimit, outPath, ".gasLimit"); + + // scroll-specific config + vm.writeJson(vm.toString(HOST_SYSTEM_CONFIG_ADDR), outPath, ".config.systemContract.system_contract_address"); + + vm.writeJson(vm.toString(VALIDIUM_TX_FEE_VAULT_ADDR), outPath, ".config.scroll.feeVaultAddress"); + + // serialize explicitly as string, otherwise foundry will serialize it as number + string memory l1ChainId = string(abi.encodePacked('"', vm.toString(CHAIN_ID_HOST), '"')); + vm.writeJson(l1ChainId, outPath, ".config.scroll.l1Config.l1ChainId"); + + vm.writeJson(vm.toString(HOST_MESSAGE_QUEUE_ADDR), outPath, ".config.scroll.l1Config.l1MessageQueueV2Address"); + + vm.writeJson(vm.toString(HOST_VALIDIUM_ADDR), outPath, ".config.scroll.l1Config.scrollChainAddress"); + + vm.writeJson( + vm.toString(VALIDIUM_SYSTEM_CONFIG_ADDR), + outPath, + ".config.scroll.l1Config.l2SystemConfigAddress" + ); + + // predeploys and prefunded accounts + string memory alloc = vm.readFile(genesisAllocTmpPath); + vm.writeJson(alloc, outPath, ".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] = "/bin/bash"; + commands[1] = "-c"; + commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path); + vm.ffi(commands); + } +} diff --git a/scripts/deterministic/validium/ValidiumConfiguration.sol b/scripts/deterministic/validium/ValidiumConfiguration.sol new file mode 100644 index 00000000..3275eb80 --- /dev/null +++ b/scripts/deterministic/validium/ValidiumConfiguration.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.24; + +import {stdToml} from "forge-std/StdToml.sol"; + +import {Configuration} from "../Configuration.sol"; + +/// @notice Configuration allows inheriting contracts to read the TOML configuration file. +abstract contract ValidiumConfiguration is Configuration { + using stdToml for string; + + /**************************** + * Configuration parameters * + ****************************/ + + // general + uint64 internal CHAIN_ID_HOST; + uint64 internal CHAIN_ID_VALIDIUM; + + uint256 internal VALIDIUM_GAS_LIMIT; + uint256 internal VALIDIUM_MAX_ETH_SUPPLY; + uint256 internal VALIDIUM_DEPLOYER_INITIAL_BALANCE; + uint256 internal VALIDIUM_MESSENGER_INITIAL_BALANCE; + + // accounts + address internal DEPLOYER_ADDR; + address internal OWNER_ADDR; + address internal L1_FEE_VAULT_ADDR; + address internal SEQUENCER_SIGNER_ADDRESS; + address internal COMMIT_SENDER_ADDR; + address internal FINALIZE_SENDER_ADDR; + address internal FAST_WITHDRAW_SIGNER_ADDR; + + // keys + uint256 internal DEPLOYER_PRIVATE_KEY; + string internal SEQUENCER_ENCRYPTION_KEY; + string internal SEQUENCER_DECRYPTION_KEY; + + /********************** + * Internal interface * + **********************/ + + function readConfig(string memory workdir) internal { + super.initialize(workdir); + + CHAIN_ID_HOST = uint64(cfg.readUint(".general.chain_id_host")); + CHAIN_ID_VALIDIUM = uint64(cfg.readUint(".general.chain_id_validium")); + + VALIDIUM_GAS_LIMIT = cfg.readUint(".general.gas_limit"); + VALIDIUM_MAX_ETH_SUPPLY = cfg.readUint(".general.max_eth_supply"); + VALIDIUM_DEPLOYER_INITIAL_BALANCE = cfg.readUint(".general.deployer_initial_balance"); + VALIDIUM_MESSENGER_INITIAL_BALANCE = VALIDIUM_MAX_ETH_SUPPLY - VALIDIUM_DEPLOYER_INITIAL_BALANCE; + + DEPLOYER_ADDR = cfg.readAddress(".accounts.deployer"); + OWNER_ADDR = cfg.readAddress(".accounts.owner"); + L1_FEE_VAULT_ADDR = cfg.readAddress(".accounts.fee_vault"); + SEQUENCER_SIGNER_ADDRESS = cfg.readAddress(".accounts.sequencer"); + COMMIT_SENDER_ADDR = cfg.readAddress(".accounts.commit_sender"); + FINALIZE_SENDER_ADDR = cfg.readAddress(".accounts.finalize_sender"); + FAST_WITHDRAW_SIGNER_ADDR = cfg.readAddress(".accounts.fast_withdraw_signer"); + + DEPLOYER_PRIVATE_KEY = cfg.readUint(".keys.deployer"); + SEQUENCER_ENCRYPTION_KEY = cfg.readString(".keys.sequencer_encryption"); + SEQUENCER_DECRYPTION_KEY = cfg.readString(".keys.sequencer_decryption"); + } +} diff --git a/scripts/deterministic/validium/workdir/.gitignore b/scripts/deterministic/validium/workdir/.gitignore new file mode 100644 index 00000000..c222e5d6 --- /dev/null +++ b/scripts/deterministic/validium/workdir/.gitignore @@ -0,0 +1 @@ +genesis.json diff --git a/scripts/deterministic/validium/workdir/config-contracts.toml b/scripts/deterministic/validium/workdir/config-contracts.toml new file mode 100644 index 00000000..552e4a0b --- /dev/null +++ b/scripts/deterministic/validium/workdir/config-contracts.toml @@ -0,0 +1,33 @@ +HOST_WETH_ADDR = "0x0000000000000000000000000000000000000000" +HOST_PROXY_ADMIN_ADDR = "0x0000000000000000000000000000000000000000" +HOST_IMPLEMENTATION_PLACEHOLDER_ADDR = "0x0000000000000000000000000000000000000000" +HOST_VALIDIUM_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_MESSAGE_QUEUE_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_SYSTEM_CONFIG_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_MESSENGER_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_ERC20_GATEWAY_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_WETH_GATEWAY_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_FAST_WITHDRAW_VAULT_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +HOST_MESSENGER_WHITELIST_ADDR = "0x0000000000000000000000000000000000000000" +HOST_VALIDIUM_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +HOST_EMPTY_MESSAGE_QUEUE_V1_ADDR = "0x0000000000000000000000000000000000000000" +HOST_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +HOST_SYSTEM_CONFIG_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +HOST_MESSENGER_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +HOST_ERC20_GATEWAY_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +HOST_WETH_GATEWAY_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +HOST_FAST_WITHDRAW_VAULT_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_PROXY_ADMIN_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_IMPLEMENTATION_PLACEHOLDER_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_MESSAGE_QUEUE_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_GAS_PRICE_ORACLE_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_GAS_PRICE_ORACLE_WHITELIST_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_TX_FEE_VAULT_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_MESSENGER_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_SYSTEM_CONFIG_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_ERC20_GATEWAY_PROXY_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_STANDARD_ERC20_TOKEN_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_STANDARD_ERC20_FACTORY_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_MESSENGER_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_SYSTEM_CONFIG_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" +VALIDIUM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = "0x0000000000000000000000000000000000000000" \ No newline at end of file diff --git a/scripts/deterministic/validium/workdir/config.toml b/scripts/deterministic/validium/workdir/config.toml new file mode 100644 index 00000000..612b2769 --- /dev/null +++ b/scripts/deterministic/validium/workdir/config.toml @@ -0,0 +1,46 @@ +[general] + +chain_id_host = 22222222 +chain_id_validium = 33333333 + +gas_limit = 20_000_000 +max_eth_supply = "226156424291633194186662080095093570025917938800079226639565593765455331328" +deployer_initial_balance = 1000000000000000000 + + +[accounts] + +deployer = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +fee_vault = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +sequencer = "0x20fc66f922534612f9185734e92b5e99edd53ecf" +commit_sender = "0x22Cda1e7cB5BFFE17bcedE09aa277D50D689CD15" +finalize_sender = "0x9d842De42C7b467c9862c29F57Ed487e25e154Ad" +fast_withdraw_signer = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + + +[keys] + +# note: for now we simply use Anvil's dev accounts +deployer = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + +# Public key used for encrypting deposits. +sequencer_encryption = "02bce905b751cbf4032d6b853904e23cea1c2fd1d6b0c84b4888b0ec6af97cbcd7" + +# Private key used for decrypting deposits. +sequencer_decryption = "9fca2e8bf31078e47ac0cce462867b8093f2649ffd5be1cca89215d9e23822c4" + + +[contracts] + +DEPLOYMENT_SALT = "devnetSalt-000" + +[contracts.overrides] + +# Uncomment the following line for Sepolia deployment. +# HOST_WETH = "0x5300000000000000000000000000000000000004" + +VALIDIUM_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000" +VALIDIUM_GAS_PRICE_ORACLE = "0x5300000000000000000000000000000000000002" +VALIDIUM_GAS_PRICE_ORACLE_WHITELIST = "0x5300000000000000000000000000000000000003" +VALIDIUM_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005" diff --git a/scripts/deterministic/validium/workdir/genesis.json.template b/scripts/deterministic/validium/workdir/genesis.json.template new file mode 100644 index 00000000..7b412dd2 --- /dev/null +++ b/scripts/deterministic/validium/workdir/genesis.json.template @@ -0,0 +1,55 @@ +{ + "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, + "curieBlock": 0, + "darwinTime": 0, + "darwinV2Time": 0, + "euclidTime": 0, + "euclidV2Time": 0, + "feynmanTime": 0, + "systemContract": { + "period": 1, + "blocks_per_second": 2, + "system_contract_address": null, + "system_contract_slot": "0x0000000000000000000000000000000000000000000000000000000000000067" + }, + "scroll": { + "useZktrie": false, + "maxTxPerBlock": 100, + "maxTxPayloadBytesPerBlock": 122880, + "feeVaultAddress": null, + "l1Config": { + "l1ChainId": null, + "l1MessageQueueAddress": "0x0000000000000000000000000000000000000001", + "l1MessageQueueV2Address": null, + "l1MessageQueueV2DeploymentBlock": 0, + "scrollChainAddress": null, + "l2SystemConfigAddress": null, + "numL1MessagesPerBlock": "10" + } + } + }, + "nonce": "0x0", + "timestamp": null, + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": null, + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "0x1", + "alloc": null +}