Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ bytecode_hash = 'none'
ffi = true

fs_permissions = [
{ access='read-write', path='./scripts/deterministic/config' },
{ access='read-write', path='./scripts/deterministic/scroll/config' },
{ access='read-write', path='../../config' },
]
174 changes: 17 additions & 157 deletions scripts/deterministic/Configuration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import {Script} from "forge-std/Script.sol";
import {VmSafe} from "forge-std/Vm.sol";
import {stdToml} from "forge-std/StdToml.sol";

import {CONFIG_PATH, CONFIG_CONTRACTS_PATH, CONFIG_CONTRACTS_TEMPLATE_PATH} from "./Constants.sol";

/// @notice Configuration allows inheriting contracts to read the TOML configuration file.
abstract contract Configuration is Script {
using stdToml for string;

Expand All @@ -18,135 +15,32 @@ abstract contract Configuration is Script {
string internal cfg;
string internal contractsCfg;

/****************************
* Configuration parameters *
****************************/

// general
string internal L1_RPC_ENDPOINT;
string internal L2_RPC_ENDPOINT;

string internal CHAIN_NAME_L1;
string internal CHAIN_NAME_L2;
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_BATCH_IN_BUNDLE;
uint256 internal MAX_L1_MESSAGE_GAS_LIMIT;
uint256 internal FINALIZE_BATCH_DEADLINE_SEC;
uint256 internal RELAY_MESSAGE_DEADLINE_SEC;

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;
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 OWNER_ADDR;

address internal L2GETH_SIGNER_ADDRESS;

// db
string internal ROLLUP_EXPLORER_BACKEND_DB_CONNECTION_STRING;

// 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;

// coordinator
string internal CHUNK_COLLECTION_TIME_SEC;
string internal BATCH_COLLECTION_TIME_SEC;
string internal BUNDLE_COLLECTION_TIME_SEC;
string internal COORDINATOR_JWT_SECRET_KEY;

// frontend
string internal EXTERNAL_RPC_URI_L1;
string internal EXTERNAL_RPC_URI_L2;
string internal BRIDGE_API_URI;
string internal ROLLUPSCAN_API_URI;
string internal EXTERNAL_EXPLORER_URI_L1;
string internal EXTERNAL_EXPLORER_URI_L2;
string internal ADMIN_SYSTEM_DASHBOARD_URI;
string internal GRAFANA_URI;

/**********************
* Internal interface *
**********************/

function readConfig() internal {
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(CONFIG_CONTRACTS_PATH);

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(".rollup.MAX_TX_IN_CHUNK");
MAX_BLOCK_IN_CHUNK = cfg.readUint(".rollup.MAX_BLOCK_IN_CHUNK");
MAX_BATCH_IN_BUNDLE = cfg.readUint(".rollup.MAX_BATCH_IN_BUNDLE");
MAX_L1_MESSAGE_GAS_LIMIT = cfg.readUint(".rollup.MAX_L1_MESSAGE_GAS_LIMIT");
FINALIZE_BATCH_DEADLINE_SEC = cfg.readUint(".rollup.FINALIZE_BATCH_DEADLINE_SEC");
RELAY_MESSAGE_DEADLINE_SEC = cfg.readUint(".rollup.RELAY_MESSAGE_DEADLINE_SEC");

L1_CONTRACT_DEPLOYMENT_BLOCK = cfg.readUint(".general.L1_CONTRACT_DEPLOYMENT_BLOCK");

TEST_ENV_MOCK_FINALIZE_ENABLED = cfg.readBool(".rollup.TEST_ENV_MOCK_FINALIZE_ENABLED");
TEST_ENV_MOCK_FINALIZE_TIMEOUT_SEC = cfg.readUint(".rollup.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");
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");

OWNER_ADDR = cfg.readAddress(".accounts.OWNER_ADDR");

L2GETH_SIGNER_ADDRESS = cfg.readAddress(".sequencer.L2GETH_SIGNER_ADDRESS");
function initialize(string memory workdir) internal {
string memory cfgPath = string(abi.encodePacked(workdir, "/config.toml"));
cfg = vm.readFile(cfgPath);

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;
string memory contractsCfgPath = string(abi.encodePacked(workdir, "/config-contracts.toml"));
contractsCfg = vm.readFile(contractsCfgPath);
}

DEPLOYMENT_SALT = cfg.readString(".contracts.DEPLOYMENT_SALT");
function readUint(string memory key) internal view returns (uint256) {
return cfg.readUint(key);
}

L1_FEE_VAULT_ADDR = cfg.readAddress(".contracts.L1_FEE_VAULT_ADDR");
function readAddress(string memory key) internal view returns (address) {
return cfg.readAddress(key);
}

CHUNK_COLLECTION_TIME_SEC = cfg.readString(".coordinator.CHUNK_COLLECTION_TIME_SEC");
BATCH_COLLECTION_TIME_SEC = cfg.readString(".coordinator.BATCH_COLLECTION_TIME_SEC");
BUNDLE_COLLECTION_TIME_SEC = cfg.readString(".coordinator.BUNDLE_COLLECTION_TIME_SEC");
COORDINATOR_JWT_SECRET_KEY = cfg.readString(".coordinator.COORDINATOR_JWT_SECRET_KEY");
function readString(string memory key) internal view returns (string memory) {
return cfg.readString(key);
}

runSanityCheck();
function writeToml(address addr, string memory tomlPath) internal {
vm.writeToml(vm.toString(addr), cfg, tomlPath);
}

/// @dev Ensure that `addr` is not the zero address.
Expand Down Expand Up @@ -193,38 +87,4 @@ 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"
)
)
);
}
}
}
14 changes: 9 additions & 5 deletions scripts/deterministic/DeterministicDeployment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.s
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ERC1967Upgrade} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";

import {CONFIG_CONTRACTS_PATH, DEFAULT_DEPLOYMENT_SALT, DETERMINISTIC_DEPLOYMENT_PROXY_ADDR} from "./Constants.sol";
import {Configuration} from "./Configuration.sol";

/// @dev The address of DeterministicDeploymentProxy.
/// See https://github.com/Arachnid/deterministic-deployment-proxy.
address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920cA78FbF26c0B4956C;

/// @notice DeterministicDeployment provides utilities for deterministic contract deployments.
abstract contract DeterministicDeployment is Configuration {
using stdToml for string;
Expand Down Expand Up @@ -39,19 +42,20 @@ abstract contract DeterministicDeployment is Configuration {
* Internal interface *
**********************/

function initialize(ScriptMode _mode) internal {
function initialize(ScriptMode _mode, string memory workdir) internal {
mode = _mode;
skipDeploy = false;

if (mode != ScriptMode.EmptyConfig) {
readConfig();
super.initialize(workdir);
}

// salt prefix used for deterministic deployments
string memory DEPLOYMENT_SALT = readString(".contracts.DEPLOYMENT_SALT");
if (bytes(DEPLOYMENT_SALT).length != 0) {
saltPrefix = DEPLOYMENT_SALT;
} else {
saltPrefix = DEFAULT_DEPLOYMENT_SALT;
revert("Missing deployment salt");
}

// sanity check: make sure DeterministicDeploymentProxy exists
Expand Down Expand Up @@ -203,7 +207,7 @@ abstract contract DeterministicDeployment is Configuration {
string memory tomlPath = string(abi.encodePacked(".", name, "_ADDR"));

if (mode == ScriptMode.WriteConfig) {
vm.writeToml(vm.toString(addr), CONFIG_CONTRACTS_PATH, tomlPath);
writeToml(addr, tomlPath);
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.24;

/// @dev The default deterministic deployment salt prefix.
string constant DEFAULT_DEPLOYMENT_SALT = "ScrollStack";

/// @dev The address of DeterministicDeploymentProxy.
/// See https://github.com/Arachnid/deterministic-deployment-proxy.
address constant DETERMINISTIC_DEPLOYMENT_PROXY_ADDR = 0x4e59b44847b379578588920cA78FbF26c0B4956C;

/// @dev The default minimum withdraw amount configured on L2TxFeeVault.
uint256 constant FEE_VAULT_MIN_WITHDRAW_AMOUNT = 1 ether;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,55 @@
pragma solidity =0.8.24;

import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ProxyAdminSetOwner} from "./contracts/ProxyAdminSetOwner.sol";
import {ProxyAdminSetOwner} from "../contracts/ProxyAdminSetOwner.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";

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 {L1MessageQueueV1WithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueV1WithGasPriceOracle.sol";
import {L1MessageQueueV2} from "../../src/L1/rollup/L1MessageQueueV2.sol";
import {SystemConfig} from "../../src/L1/system-contract/SystemConfig.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 {MultipleVersionRollupVerifierSetOwner} from "./contracts/MultipleVersionRollupVerifierSetOwner.sol";
import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
import {ZkEvmVerifierV2} from "../../src/libraries/verifier/ZkEvmVerifierV2.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 {ScrollStandardERC20FactorySetOwner} from "./contracts/ScrollStandardERC20FactorySetOwner.sol";

import {ScrollChainMockFinalize} from "../../src/mocks/ScrollChainMockFinalize.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 {L1MessageQueueV1WithGasPriceOracle} from "../../../src/L1/rollup/L1MessageQueueV1WithGasPriceOracle.sol";
import {L1MessageQueueV2} from "../../../src/L1/rollup/L1MessageQueueV2.sol";
import {SystemConfig} from "../../../src/L1/system-contract/SystemConfig.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 {ScrollChain} from "../../../src/L1/rollup/ScrollChain.sol";
import {ZkEvmVerifierV2} from "../../../src/libraries/verifier/ZkEvmVerifierV2.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 {MultipleVersionRollupVerifierSetOwner} from "../contracts/MultipleVersionRollupVerifierSetOwner.sol";
import {ScrollStandardERC20FactorySetOwner} from "../contracts/ScrollStandardERC20FactorySetOwner.sol";

import {ScrollChainMockFinalize} from "../../../src/mocks/ScrollChainMockFinalize.sol";

import "./Constants.sol";
import "./Configuration.sol";
import "./DeterministicDeployment.sol";
import {ScrollConfiguration} from "./ScrollConfiguration.sol";
import "../DeterministicDeployment.sol";

/// @dev The minimum deployer account balance.
uint256 constant MINIMUM_DEPLOYER_BALANCE = 0.1 ether;

contract DeployScroll is DeterministicDeployment {
contract DeployScroll is DeterministicDeployment, ScrollConfiguration {
using stdToml for string;

/*********
Expand Down Expand Up @@ -178,11 +179,15 @@ contract DeployScroll is DeterministicDeployment {
* Entry point *
***************/

function run(string memory layer, string memory scriptMode) public {
function run(
string memory workdir,
string memory layer,
string memory scriptMode
) public {
broadcastLayer = parseLayer(layer);
ScriptMode mode = parseScriptMode(scriptMode);

DeterministicDeployment.initialize(mode);
DeterministicDeployment.initialize(mode, workdir);

checkDeployerBalance();
deployAllContracts();
Expand Down
Loading
Loading