diff --git a/.gitmodules b/.gitmodules index 445344c3f20..dd5b3b3bc82 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "contracts"] path = contracts -url = https://github.com/matter-labs/era-contracts.git +url = https://github.com/matter-labs/era-contracts-private.git diff --git a/Cargo.lock b/Cargo.lock index 30368383981..d718a2b221b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10235,6 +10235,7 @@ dependencies = [ "tracing", "vise", "zksync_concurrency", + "zksync_config", "zksync_contracts", "zksync_dal", "zksync_eth_client", @@ -11276,6 +11277,7 @@ version = "0.1.0" dependencies = [ "anyhow", "assert_matches", + "async-trait", "bigdecimal", "bincode", "blake2 0.10.6", diff --git a/contracts b/contracts index 53b0283f82f..9771f8e73fb 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 53b0283f82f4262c973eb3faed56ee8f6cda47b9 +Subproject commit 9771f8e73fb58e0e6cea003b7e85e1bf1eac7962 diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 420a6941c81..42bc9f0c091 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -104,6 +104,7 @@ pub(crate) struct RemoteENConfig { pub bridgehub_proxy_addr: Option
, pub state_transition_proxy_addr: Option
, pub transparent_proxy_admin_addr: Option
, + pub l1_bytecodes_supplier_addr: Option
, /// Should not be accessed directly. Use [`ExternalNodeConfig::diamond_proxy_address`] instead. pub user_facing_diamond_proxy: Address, // While on L1 shared bridge and legacy bridge are different contracts with different addresses, @@ -196,6 +197,9 @@ impl RemoteENConfig { transparent_proxy_admin_addr: ecosystem_contracts .as_ref() .map(|a| a.transparent_proxy_admin_addr), + l1_bytecodes_supplier_addr: ecosystem_contracts + .as_ref() + .and_then(|a| a.l1_bytecodes_supplier_addr), user_facing_diamond_proxy, user_facing_bridgehub, l2_testnet_paymaster_addr, @@ -224,6 +228,7 @@ impl RemoteENConfig { bridgehub_proxy_addr: None, state_transition_proxy_addr: None, transparent_proxy_admin_addr: None, + l1_bytecodes_supplier_addr: None, user_facing_diamond_proxy: Address::repeat_byte(1), user_facing_bridgehub: None, l1_erc20_bridge_proxy_addr: Some(Address::repeat_byte(2)), @@ -1428,6 +1433,7 @@ impl From<&ExternalNodeConfig> for InternalApiConfig { l1_weth_bridge: config.remote.l1_weth_bridge_addr, l2_weth_bridge: config.remote.l2_weth_bridge_addr, }, + l1_bytecodes_supplier_addr: config.remote.l1_bytecodes_supplier_addr, bridgehub_proxy_addr: config.remote.bridgehub_proxy_addr, state_transition_proxy_addr: config.remote.state_transition_proxy_addr, transparent_proxy_admin_addr: config.remote.transparent_proxy_admin_addr, diff --git a/core/bin/system-constants-generator/src/main.rs b/core/bin/system-constants-generator/src/main.rs index cc2e031106b..cd795f9f532 100644 --- a/core/bin/system-constants-generator/src/main.rs +++ b/core/bin/system-constants-generator/src/main.rs @@ -3,7 +3,9 @@ use std::fs; use codegen::{Block, Scope}; use serde::{Deserialize, Serialize}; use zksync_multivm::{ - utils::{get_bootloader_encoding_space, get_bootloader_max_txs_in_batch}, + utils::{ + get_bootloader_encoding_space, get_bootloader_max_txs_in_batch, get_max_new_factory_deps, + }, vm_latest::constants::MAX_VM_PUBDATA_PER_BATCH, zk_evm_latest::zkevm_opcode_defs::{ circuit_prices::{ @@ -15,7 +17,7 @@ use zksync_multivm::{ }; use zksync_types::{ IntrinsicSystemGasConstants, ProtocolVersionId, GUARANTEED_PUBDATA_IN_TX, - L1_GAS_PER_PUBDATA_BYTE, MAX_NEW_FACTORY_DEPS, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, + L1_GAS_PER_PUBDATA_BYTE, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, }; use zksync_utils::env::Workspace; @@ -73,7 +75,7 @@ pub fn generate_l1_contracts_system_config(gas_constants: &IntrinsicSystemGasCon l1_tx_delta_544_encoding_bytes: gas_constants.l1_tx_delta_544_encoding_bytes, l1_tx_delta_factory_deps_l2_gas: gas_constants.l1_tx_delta_factory_dep_gas, l1_tx_delta_factory_deps_pubdata: gas_constants.l1_tx_delta_factory_dep_pubdata, - max_new_factory_deps: MAX_NEW_FACTORY_DEPS as u32, + max_new_factory_deps: get_max_new_factory_deps(ProtocolVersionId::latest().into()) as u32, required_l2_gas_price_per_pubdata: REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, }; diff --git a/core/lib/basic_types/src/protocol_version.rs b/core/lib/basic_types/src/protocol_version.rs index 88513360916..2cf941510d9 100644 --- a/core/lib/basic_types/src/protocol_version.rs +++ b/core/lib/basic_types/src/protocol_version.rs @@ -144,7 +144,11 @@ impl ProtocolVersionId { } pub fn is_pre_gateway(&self) -> bool { - self <= &Self::Version26 + self < &Self::gateway_upgrade() + } + + pub fn is_post_gateway(&self) -> bool { + self >= &Self::gateway_upgrade() } pub fn is_1_4_0(&self) -> bool { @@ -182,6 +186,10 @@ impl ProtocolVersionId { pub fn is_post_1_5_0(&self) -> bool { self >= &ProtocolVersionId::Version23 } + + pub const fn gateway_upgrade() -> Self { + ProtocolVersionId::Version26 + } } impl Default for ProtocolVersionId { diff --git a/core/lib/config/src/configs/contracts.rs b/core/lib/config/src/configs/contracts.rs index 1d49a09d213..5cb738f118e 100644 --- a/core/lib/config/src/configs/contracts.rs +++ b/core/lib/config/src/configs/contracts.rs @@ -1,13 +1,14 @@ // External uses use serde::{Deserialize, Serialize}; // Workspace uses -use zksync_basic_types::Address; +use zksync_basic_types::{Address, H256}; #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct EcosystemContracts { pub bridgehub_proxy_addr: Address, pub state_transition_proxy_addr: Address, pub transparent_proxy_admin_addr: Address, + pub l1_bytecodes_supplier_addr: Option
, } impl EcosystemContracts { @@ -16,6 +17,7 @@ impl EcosystemContracts { bridgehub_proxy_addr: Address::repeat_byte(0x14), state_transition_proxy_addr: Address::repeat_byte(0x15), transparent_proxy_admin_addr: Address::repeat_byte(0x15), + l1_bytecodes_supplier_addr: Some(Address::repeat_byte(0x16)), } } } @@ -45,6 +47,10 @@ pub struct ContractsConfig { pub ecosystem_contracts: Option, // Used by the RPC API and by the node builder in wiring the BaseTokenRatioProvider layer. pub base_token_addr: Option
, + pub base_token_asset_id: Option, + + pub predeployed_l2_wrapped_base_token_address: Option
, + // FIXME: maybe refactor pub user_facing_bridgehub_proxy_addr: Option
, pub user_facing_diamond_proxy_addr: Option
, @@ -71,6 +77,8 @@ impl ContractsConfig { l1_multicall3_addr: Address::repeat_byte(0x12), governance_addr: Address::repeat_byte(0x13), base_token_addr: Some(Address::repeat_byte(0x14)), + base_token_asset_id: Some(H256::repeat_byte(0x15)), + predeployed_l2_wrapped_base_token_address: Some(Address::repeat_byte(0x1b)), ecosystem_contracts: Some(EcosystemContracts::for_tests()), user_facing_bridgehub_proxy_addr: Some(Address::repeat_byte(0x15)), user_facing_diamond_proxy_addr: Some(Address::repeat_byte(0x16)), diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 4e6930a3384..eb648902ac5 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -272,6 +272,8 @@ impl Distribution for EncodeDist { user_facing_bridgehub_proxy_addr: rng.gen(), user_facing_diamond_proxy_addr: rng.gen(), base_token_addr: self.sample_opt(|| rng.gen()), + base_token_asset_id: self.sample_opt(|| rng.gen()), + predeployed_l2_wrapped_base_token_address: self.sample_opt(|| rng.gen()), chain_admin_addr: self.sample_opt(|| rng.gen()), settlement_layer: self.sample_opt(|| rng.gen()), l2_da_validator_addr: self.sample_opt(|| rng.gen()), @@ -763,6 +765,7 @@ impl Distribution for EncodeDist { bridgehub_proxy_addr: rng.gen(), state_transition_proxy_addr: rng.gen(), transparent_proxy_admin_addr: rng.gen(), + l1_bytecodes_supplier_addr: rng.gen(), } } } diff --git a/core/lib/constants/src/contracts.rs b/core/lib/constants/src/contracts.rs index f9138b2bbf1..faee06e6fc1 100644 --- a/core/lib/constants/src/contracts.rs +++ b/core/lib/constants/src/contracts.rs @@ -165,6 +165,14 @@ pub const L2_MESSAGE_ROOT_ADDRESS: Address = H160([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, ]); +pub const SLOAD_CONTRACT_ADDRESS: Address = H160([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x06, +]); +pub const L2_WRAPPED_BASE_TOKEN_IMPL: Address = H160([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x07, +]); pub const ERC20_TRANSFER_TOPIC: H256 = H256([ 221, 242, 82, 173, 27, 226, 200, 155, 105, 194, 176, 104, 252, 55, 141, 170, 149, 43, 167, 241, diff --git a/core/lib/constants/src/crypto.rs b/core/lib/constants/src/crypto.rs index ead2cc31837..0260ee578c8 100644 --- a/core/lib/constants/src/crypto.rs +++ b/core/lib/constants/src/crypto.rs @@ -3,8 +3,6 @@ pub const ZKPORTER_IS_AVAILABLE: bool = false; /// Depth of the account tree. pub const ROOT_TREE_DEPTH: usize = 256; -pub const MAX_NEW_FACTORY_DEPS: usize = 32; - /// To avoid DDoS we limit the size of the transactions size. /// TODO(X): remove this as a constant and introduce a config. pub const MAX_ENCODED_TX_SIZE: usize = 1 << 24; diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index af9b5fe99f2..ce0c6231da2 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -38,6 +38,8 @@ const STATE_TRANSITION_CONTRACT_FILE: (&str, &str) = ( "state-transition", "IChainTypeManager.sol/IChainTypeManager.json", ); +const BYTECODE_SUPPLIER_CONTRACT_FILE: (&str, &str) = + ("upgrades", "BytecodesSupplier.sol/BytecodesSupplier.json"); const ZKSYNC_HYPERCHAIN_CONTRACT_FILE: (&str, &str) = ( "state-transition/chain-interfaces", "IZKChain.sol/IZKChain.json", @@ -157,6 +159,10 @@ pub fn state_transition_manager_contract() -> Contract { load_contract_for_both_compilers(STATE_TRANSITION_CONTRACT_FILE) } +pub fn bytecode_supplier_contract() -> Contract { + load_contract_for_both_compilers(BYTECODE_SUPPLIER_CONTRACT_FILE) +} + pub fn hyperchain_contract() -> Contract { load_contract_for_both_compilers(ZKSYNC_HYPERCHAIN_CONTRACT_FILE) } @@ -209,13 +215,11 @@ pub fn l1_messenger_contract() -> Contract { } pub fn l2_message_root() -> Contract { - load_contract( - "contracts/l1-contracts/artifacts-zk/contracts/bridgehub/MessageRoot.sol/MessageRoot.json", - ) + load_contract("contracts/l1-contracts/zkout/MessageRoot.sol/MessageRoot.json") } pub fn l2_rollup_da_validator_bytecode() -> Vec { - read_bytecode("contracts/l2-contracts/artifacts-zk/contracts/data-availability/RollupL2DAValidator.sol/RollupL2DAValidator.json") + read_bytecode("contracts/l2-contracts/zkout/RollupL2DAValidator.sol/RollupL2DAValidator.json") } /// Reads bytecode from the path RELATIVE to the Cargo workspace location. @@ -326,21 +330,10 @@ pub fn read_bootloader_code(bootloader_type: &str) -> Vec { { return contract; }; - - let artifacts_path = - Path::new(&home_path()).join("contracts/system-contracts/bootloader/build/artifacts"); - let bytecode_path = artifacts_path.join(format!("{bootloader_type}.yul.zbin")); - if fs::exists(bytecode_path).unwrap_or_default() { - read_yul_bytecode( - "contracts/system-contracts/bootloader/build/artifacts", - bootloader_type, - ) - } else { - read_yul_bytecode( - "contracts/system-contracts/bootloader/tests/artifacts", - bootloader_type, - ) - } + read_yul_bytecode( + "contracts/system-contracts/bootloader/build/artifacts", + bootloader_type, + ) } fn read_proved_batch_bootloader_bytecode() -> Vec { @@ -540,10 +533,8 @@ impl BaseSystemContracts { } pub fn playground_gateway() -> Self { - let bootloader_bytecode = read_zbin_bytecode( - "contracts/system-contracts/bootloader/build/artifacts/playground_batch.yul.zbin", - // "etc/multivm_bootloaders/vm_gateway/playground_batch.yul/playground_batch.yul.zbin", - ); + // TODO: the value should be taken from the `multivm_bootloaders` folder + let bootloader_bytecode = read_bootloader_code("playground_batch"); BaseSystemContracts::load_with_bootloader(bootloader_bytecode) } @@ -618,10 +609,8 @@ impl BaseSystemContracts { } pub fn estimate_gas_gateway() -> Self { - let bootloader_bytecode = read_zbin_bytecode( - "contracts/system-contracts/bootloader/build/artifacts/fee_estimate.yul.zbin", - // "etc/multivm_bootloaders/vm_gateway/fee_estimate.yul/fee_estimate.yul.zbin", - ); + // TODO: the value should be taken from the `multivm_bootloaders` folder + let bootloader_bytecode = read_bootloader_code("fee_estimate"); BaseSystemContracts::load_with_bootloader(bootloader_bytecode) } diff --git a/core/lib/dal/src/factory_deps_dal.rs b/core/lib/dal/src/factory_deps_dal.rs index 857e2973ae3..0ad5b9a7eab 100644 --- a/core/lib/dal/src/factory_deps_dal.rs +++ b/core/lib/dal/src/factory_deps_dal.rs @@ -3,10 +3,10 @@ use std::collections::{HashMap, HashSet}; use anyhow::Context as _; use zksync_contracts::{BaseSystemContracts, SystemContractCode}; use zksync_db_connection::{connection::Connection, error::DalResult, instrument::InstrumentExt}; -use zksync_types::{L2BlockNumber, H256, U256}; -use zksync_utils::{bytes_to_be_words, bytes_to_chunks}; +use zksync_types::{L2BlockNumber, ProtocolVersionId, H256, U256}; +use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, bytes_to_chunks}; -use crate::Core; +use crate::{Core, CoreDal}; /// DAL methods related to factory dependencies. #[derive(Debug)] @@ -90,31 +90,26 @@ impl FactoryDepsDal<'_, '_> { .map(|row| row.bytecode)) } - pub async fn get_base_system_contracts( + pub async fn get_base_system_contracts_from_factory_deps( &mut self, bootloader_hash: H256, default_aa_hash: H256, evm_emulator_hash: Option, - ) -> anyhow::Result { + ) -> anyhow::Result> { let bootloader_bytecode = self .get_sealed_factory_dep(bootloader_hash) .await - .context("failed loading bootloader code")? - .with_context(|| format!("bootloader code with hash {bootloader_hash:?} should be present in the database"))?; - let bootloader_code = SystemContractCode { - code: bytes_to_be_words(bootloader_bytecode), - hash: bootloader_hash, - }; + .context("failed loading bootloader code")?; let default_aa_bytecode = self .get_sealed_factory_dep(default_aa_hash) .await - .context("failed loading default account code")? - .with_context(|| format!("default account code with hash {default_aa_hash:?} should be present in the database"))?; + .context("failed loading default account code")?; - let default_aa_code = SystemContractCode { - code: bytes_to_be_words(default_aa_bytecode), - hash: default_aa_hash, + let (Some(bootloader_bytecode), Some(default_aa_bytecode)) = + (bootloader_bytecode, default_aa_bytecode) + else { + return Ok(None); }; let evm_emulator_code = if let Some(evm_emulator_hash) = evm_emulator_hash { @@ -132,11 +127,20 @@ impl FactoryDepsDal<'_, '_> { None }; - Ok(BaseSystemContracts { + let bootloader_code = SystemContractCode { + code: bytes_to_be_words(bootloader_bytecode), + hash: bootloader_hash, + }; + + let default_aa_code = SystemContractCode { + code: bytes_to_be_words(default_aa_bytecode), + hash: default_aa_hash, + }; + Ok(Some(BaseSystemContracts { bootloader: bootloader_code, default_aa: default_aa_code, evm_emulator: evm_emulator_code, - }) + })) } /// Returns bytecodes for factory deps with the specified `hashes`. diff --git a/core/lib/dal/src/protocol_versions_dal.rs b/core/lib/dal/src/protocol_versions_dal.rs index fcc756e3006..efa23dd4cd4 100644 --- a/core/lib/dal/src/protocol_versions_dal.rs +++ b/core/lib/dal/src/protocol_versions_dal.rs @@ -190,9 +190,7 @@ impl ProtocolVersionsDal<'_, '_> { ProtocolVersionId::try_from(row.id as u16).map_err(|err| sqlx::Error::Decode(err.into())) } - /// Returns base system contracts' hashes. Prefer `load_base_system_contracts_by_version_id` if - /// you also want to load the contracts themselves AND expect the contracts to be in the DB - /// already. + /// Returns base system contracts' hashes. pub async fn get_base_system_contract_hashes_by_version_id( &mut self, version_id: u16, @@ -227,45 +225,6 @@ impl ProtocolVersionsDal<'_, '_> { }) } - pub async fn load_base_system_contracts_by_version_id( - &mut self, - version_id: u16, - ) -> anyhow::Result> { - let row = sqlx::query!( - r#" - SELECT - bootloader_code_hash, - default_account_code_hash, - evm_emulator_code_hash - FROM - protocol_versions - WHERE - id = $1 - "#, - i32::from(version_id) - ) - .instrument("load_base_system_contracts_by_version_id") - .with_arg("version_id", &version_id) - .fetch_optional(self.storage) - .await - .context("cannot fetch system contract hashes")?; - - Ok(if let Some(row) = row { - let contracts = self - .storage - .factory_deps_dal() - .get_base_system_contracts( - H256::from_slice(&row.bootloader_code_hash), - H256::from_slice(&row.default_account_code_hash), - row.evm_emulator_code_hash.as_deref().map(H256::from_slice), - ) - .await?; - Some(contracts) - } else { - None - }) - } - pub async fn get_protocol_version_with_latest_patch( &mut self, version_id: ProtocolVersionId, diff --git a/core/lib/env_config/src/contracts.rs b/core/lib/env_config/src/contracts.rs index 250cfe8f002..90ed0c47c2a 100644 --- a/core/lib/env_config/src/contracts.rs +++ b/core/lib/env_config/src/contracts.rs @@ -22,6 +22,9 @@ impl FromEnvVariant for EcosystemContracts { "{variant}CONTRACTS_TRANSPARENT_PROXY_ADMIN_ADDR" ))? .parse()?, + l1_bytecodes_supplier_addr: Some( + std::env::var(format!("{variant}CONTRACTS_L1_BYTECODE_SUPPLIER_ADDR"))?.parse()?, + ), }) } } @@ -60,6 +63,9 @@ impl FromEnvVariant for ContractsConfig { #[cfg(test)] mod tests { + use std::str::FromStr; + + use zksync_basic_types::H256; use zksync_config::configs::EcosystemContracts; use zksync_system_constants::SHARED_BRIDGE_ETHER_TOKEN_ADDRESS; @@ -88,8 +94,20 @@ mod tests { bridgehub_proxy_addr: addr("0x35ea7f92f4c5f433efe15284e99c040110cf6297"), state_transition_proxy_addr: addr("0xd90f1c081c6117241624e97cb6147257c3cb2097"), transparent_proxy_admin_addr: addr("0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347e5"), + l1_bytecodes_supplier_addr: Some(addr( + "0x36ea7f92f4c5f433efe15284e99c040110cf6297", + )), }), base_token_addr: Some(SHARED_BRIDGE_ETHER_TOKEN_ADDRESS), + base_token_asset_id: Some( + H256::from_str( + "0x0000000000000000000000000000000000000001000000000000000000000000", + ) + .unwrap(), + ), + predeployed_l2_wrapped_base_token_address: Some(addr( + "0x35ea7f92f4c5f433efe15284e99c040110cf6299", + )), user_facing_bridgehub_proxy_addr: Some(addr( "0x35ea7f92f4c5f433efe15284e99c040110cf6297", )), @@ -120,11 +138,14 @@ CONTRACTS_L2_CONSENSUS_REGISTRY_ADDR="D64e136566a9E04eb05B30184fF577F52682D182" CONTRACTS_L1_MULTICALL3_ADDR="0xcA11bde05977b3631167028862bE2a173976CA11" CONTRACTS_L1_SHARED_BRIDGE_PROXY_ADDR="0x8656770FA78c830456B00B4fFCeE6b1De0e1b888" CONTRACTS_L2_SHARED_BRIDGE_ADDR="0x8656770FA78c830456B00B4fFCeE6b1De0e1b888" +CONTRACTS_L1_BYTECODE_SUPPLIER_ADDR="0x36ea7f92f4c5f433efe15284e99c040110cf6297" CONTRACTS_L2_LEGACY_SHARED_BRIDGE_ADDR="0x8656770FA78c830456B00B4fFCeE6b1De0e1b888" CONTRACTS_BRIDGEHUB_PROXY_ADDR="0x35ea7f92f4c5f433efe15284e99c040110cf6297" CONTRACTS_STATE_TRANSITION_PROXY_ADDR="0xd90f1c081c6117241624e97cb6147257c3cb2097" CONTRACTS_TRANSPARENT_PROXY_ADMIN_ADDR="0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347e5" CONTRACTS_BASE_TOKEN_ADDR="0x0000000000000000000000000000000000000001" +CONTRACTS_BASE_TOKEN_ASSET_ID="0x0000000000000000000000000000000000000001000000000000000000000000" +CONTRACTS_PREDEPLOYED_L2_WETH_TOKEN_ADDRESS="0x35ea7f92f4c5f433efe15284e99c040110cf6299" CONTRACTS_USER_FACING_BRIDGEHUB_PROXY_ADDR="0x35ea7f92f4c5f433efe15284e99c040110cf6297" CONTRACTS_USER_FACING_DIAMOND_PROXY_ADDR="0xF00B988a98Ca742e7958DeF9F7823b5908715f4a CONTRACTS_L2_NATIVE_TOKEN_VAULT_PROXY_ADDR="0xfc073319977e314f251eae6ae6be76b0b3baeecf" diff --git a/core/lib/multivm/src/utils/mod.rs b/core/lib/multivm/src/utils/mod.rs index a55adb16c85..89282d08bc6 100644 --- a/core/lib/multivm/src/utils/mod.rs +++ b/core/lib/multivm/src/utils/mod.rs @@ -517,6 +517,32 @@ pub fn get_max_batch_base_layer_circuits(version: VmVersion) -> usize { } } +pub fn get_max_new_factory_deps(version: VmVersion) -> usize { + match version { + VmVersion::M5WithRefunds | VmVersion::M5WithoutRefunds => { + crate::vm_m5::vm_with_bootloader::MAX_NEW_FACTORY_DEPS + } + VmVersion::M6Initial | VmVersion::M6BugWithCompressionFixed => { + crate::vm_m6::vm_with_bootloader::MAX_NEW_FACTORY_DEPS + } + VmVersion::Vm1_3_2 => crate::vm_1_3_2::vm_with_bootloader::MAX_NEW_FACTORY_DEPS, + VmVersion::VmVirtualBlocks => crate::vm_virtual_blocks::constants::MAX_NEW_FACTORY_DEPS, + VmVersion::VmVirtualBlocksRefundsEnhancement => { + crate::vm_refunds_enhancement::constants::MAX_NEW_FACTORY_DEPS + } + VmVersion::VmBoojumIntegration => { + crate::vm_boojum_integration::constants::MAX_NEW_FACTORY_DEPS + } + VmVersion::Vm1_4_1 => crate::vm_1_4_1::constants::MAX_NEW_FACTORY_DEPS, + VmVersion::Vm1_4_2 => crate::vm_1_4_2::constants::MAX_NEW_FACTORY_DEPS, + version @ VmVersion::Vm1_5_0SmallBootloaderMemory + | version @ VmVersion::Vm1_5_0IncreasedBootloaderMemory + | version @ VmVersion::VmGateway => { + crate::vm_latest::constants::get_max_new_factory_deps(version.try_into().unwrap()) + } + } +} + /// Holds information about number of cycles used per circuit type. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub(crate) struct CircuitCycleStatistic { diff --git a/core/lib/multivm/src/versions/testonly/gas_limit.rs b/core/lib/multivm/src/versions/testonly/gas_limit.rs index 5e31eb2b159..b104d37585f 100644 --- a/core/lib/multivm/src/versions/testonly/gas_limit.rs +++ b/core/lib/multivm/src/versions/testonly/gas_limit.rs @@ -4,7 +4,10 @@ use zksync_types::{fee::Fee, Execute}; use super::{tester::VmTesterBuilder, TestedVm}; use crate::{ interface::TxExecutionMode, - vm_latest::constants::{TX_DESCRIPTION_OFFSET, TX_GAS_LIMIT_OFFSET}, + vm_latest::{ + constants::{get_tx_description_offset, TX_GAS_LIMIT_OFFSET}, + MultiVMSubversion, + }, }; /// Checks that `TX_GAS_LIMIT_OFFSET` constant is correct. @@ -29,6 +32,7 @@ pub(crate) fn test_tx_gas_limit_offset() { vm.vm.push_transaction(tx); - let slot = (TX_DESCRIPTION_OFFSET + TX_GAS_LIMIT_OFFSET) as u32; + let slot = + (get_tx_description_offset(MultiVMSubversion::latest()) + TX_GAS_LIMIT_OFFSET) as u32; vm.vm.verify_required_bootloader_heap(&[(slot, gas_limit)]); } diff --git a/core/lib/multivm/src/versions/testonly/l2_blocks.rs b/core/lib/multivm/src/versions/testonly/l2_blocks.rs index 947d8b5859f..b28a455ff14 100644 --- a/core/lib/multivm/src/versions/testonly/l2_blocks.rs +++ b/core/lib/multivm/src/versions/testonly/l2_blocks.rs @@ -21,8 +21,9 @@ use crate::{ TxExecutionMode, VmInterfaceExt, }, vm_latest::{ - constants::{TX_OPERATOR_L2_BLOCK_INFO_OFFSET, TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO}, + constants::{get_tx_operator_l2_block_info_offset, TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO}, utils::l2_blocks::get_l2_block_hash_key, + MultiVMSubversion, }, }; @@ -400,7 +401,8 @@ pub(crate) fn test_l2_block_first_in_batch() { fn set_manual_l2_block_info(vm: &mut impl TestedVm, tx_number: usize, block_info: L2BlockEnv) { let fictive_miniblock_position = - TX_OPERATOR_L2_BLOCK_INFO_OFFSET + TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO * tx_number; + get_tx_operator_l2_block_info_offset(MultiVMSubversion::latest()) + + TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO * tx_number; vm.write_to_bootloader_heap(&[ (fictive_miniblock_position, block_info.number.into()), (fictive_miniblock_position + 1, block_info.timestamp.into()), diff --git a/core/lib/multivm/src/versions/vm_1_3_2/vm_with_bootloader.rs b/core/lib/multivm/src/versions/vm_1_3_2/vm_with_bootloader.rs index fd4d483fba5..1581f73ad8a 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/vm_with_bootloader.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/vm_with_bootloader.rs @@ -16,7 +16,7 @@ use zksync_contracts::BaseSystemContracts; use zksync_system_constants::MAX_L2_TX_GAS_LIMIT; use zksync_types::{ fee_model::L1PeggedBatchFeeModelInput, l1::is_l1_tx_type, Address, Transaction, - BOOTLOADER_ADDRESS, L1_GAS_PER_PUBDATA_BYTE, MAX_NEW_FACTORY_DEPS, U256, + BOOTLOADER_ADDRESS, L1_GAS_PER_PUBDATA_BYTE, U256, }; use zksync_utils::{ address_to_u256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256, misc::ceil_div, @@ -132,6 +132,8 @@ impl From for DerivedBlockContext { } } +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; + /// The size of the bootloader memory in bytes which is used by the protocol. /// While the maximal possible size is a lot higher, we restrict ourselves to a certain limit to reduce /// the requirements on RAM. diff --git a/core/lib/multivm/src/versions/vm_1_4_1/constants.rs b/core/lib/multivm/src/versions/vm_1_4_1/constants.rs index 9cf0a0b220a..ec75f809ec4 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/constants.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/constants.rs @@ -2,7 +2,9 @@ use zk_evm_1_4_1::aux_structures::MemoryPage; pub use zk_evm_1_4_1::zkevm_opcode_defs::system_params::{ ERGS_PER_CIRCUIT, INITIAL_STORAGE_WRITE_PUBDATA_BYTES, MAX_PUBDATA_PER_BLOCK, }; -use zksync_system_constants::{MAX_L2_TX_GAS_LIMIT, MAX_NEW_FACTORY_DEPS}; +use zksync_system_constants::MAX_L2_TX_GAS_LIMIT; + +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; use crate::vm_1_4_1::old_vm::utils::heap_page_from_base; diff --git a/core/lib/multivm/src/versions/vm_1_4_2/constants.rs b/core/lib/multivm/src/versions/vm_1_4_2/constants.rs index 79f20660c14..65abb389eee 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/constants.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/constants.rs @@ -3,7 +3,9 @@ use zk_evm_1_4_1::aux_structures::MemoryPage; pub use zk_evm_1_4_1::zkevm_opcode_defs::system_params::{ ERGS_PER_CIRCUIT, INITIAL_STORAGE_WRITE_PUBDATA_BYTES, }; -use zksync_system_constants::{MAX_L2_TX_GAS_LIMIT, MAX_NEW_FACTORY_DEPS}; +use zksync_system_constants::MAX_L2_TX_GAS_LIMIT; + +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; use crate::vm_1_4_2::old_vm::utils::heap_page_from_base; diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/constants.rs b/core/lib/multivm/src/versions/vm_boojum_integration/constants.rs index 61749acd5e4..7b0442b7f97 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/constants.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/constants.rs @@ -2,10 +2,12 @@ use zk_evm_1_4_0::aux_structures::MemoryPage; pub use zk_evm_1_4_0::zkevm_opcode_defs::system_params::{ ERGS_PER_CIRCUIT, INITIAL_STORAGE_WRITE_PUBDATA_BYTES, MAX_PUBDATA_PER_BLOCK, }; -use zksync_system_constants::{L1_GAS_PER_PUBDATA_BYTE, MAX_L2_TX_GAS_LIMIT, MAX_NEW_FACTORY_DEPS}; +use zksync_system_constants::{L1_GAS_PER_PUBDATA_BYTE, MAX_L2_TX_GAS_LIMIT}; use crate::vm_boojum_integration::old_vm::utils::heap_page_from_base; +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; + /// The amount of ergs to be reserved at the end of the batch to ensure that it has enough ergs to verify compression, etc. pub(crate) const BOOTLOADER_BATCH_TIP_OVERHEAD: u32 = 80_000_000; diff --git a/core/lib/multivm/src/versions/vm_fast/bootloader_state/state.rs b/core/lib/multivm/src/versions/vm_fast/bootloader_state/state.rs index 15b4daf02a7..c2351ffd5f4 100644 --- a/core/lib/multivm/src/versions/vm_fast/bootloader_state/state.rs +++ b/core/lib/multivm/src/versions/vm_fast/bootloader_state/state.rs @@ -12,7 +12,7 @@ use super::{ use crate::{ interface::{BootloaderMemory, CompressedBytecodeInfo, L2BlockEnv, TxExecutionMode}, versions::vm_fast::{pubdata::PubdataInput, transaction_data::TransactionData}, - vm_latest::{constants::TX_DESCRIPTION_OFFSET, utils::l2_blocks::assert_next_block}, + vm_latest::{constants::get_tx_description_offset, utils::l2_blocks::assert_next_block}, }; /// Intermediate bootloader-related VM state. @@ -220,7 +220,9 @@ impl BootloaderState { /// Get offset of tx description pub(crate) fn get_tx_description_offset(&self, tx_index: usize) -> usize { - TX_DESCRIPTION_OFFSET + self.find_tx(tx_index).offset + // FIXME: support gateway inside fast vm + get_tx_description_offset(crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory) + + self.find_tx(tx_index).offset } pub(crate) fn insert_fictive_l2_block(&mut self) -> &BootloaderL2Block { diff --git a/core/lib/multivm/src/versions/vm_fast/bootloader_state/utils.rs b/core/lib/multivm/src/versions/vm_fast/bootloader_state/utils.rs index 770f232019b..781e5bab2b8 100644 --- a/core/lib/multivm/src/versions/vm_fast/bootloader_state/utils.rs +++ b/core/lib/multivm/src/versions/vm_fast/bootloader_state/utils.rs @@ -7,11 +7,11 @@ use crate::{ utils::bytecode, versions::vm_fast::pubdata::PubdataInput, vm_latest::constants::{ - BOOTLOADER_TX_DESCRIPTION_OFFSET, BOOTLOADER_TX_DESCRIPTION_SIZE, - COMPRESSED_BYTECODES_OFFSET, OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET, - OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, OPERATOR_REFUNDS_OFFSET, - TX_DESCRIPTION_OFFSET, TX_OPERATOR_L2_BLOCK_INFO_OFFSET, - TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, TX_OVERHEAD_OFFSET, TX_TRUSTED_GAS_LIMIT_OFFSET, + get_bootloader_tx_description_offset, get_compressed_bytecodes_offset, + get_operator_provided_l1_messenger_pubdata_offset, get_operator_refunds_offset, + get_tx_description_offset, get_tx_operator_l2_block_info_offset, get_tx_overhead_offset, + get_tx_trusted_gas_limit_offset, BOOTLOADER_TX_DESCRIPTION_SIZE, + OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, }, }; @@ -37,9 +37,13 @@ pub(super) fn apply_tx_to_memory( execution_mode: TxExecutionMode, start_new_l2_block: bool, ) -> usize { - let bootloader_description_offset = - BOOTLOADER_TX_DESCRIPTION_OFFSET + BOOTLOADER_TX_DESCRIPTION_SIZE * tx_index; - let tx_description_offset = TX_DESCRIPTION_OFFSET + tx_offset; + // FIXME: not supported in fast vm + let bootloader_description_offset = get_bootloader_tx_description_offset( + crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, + ) + BOOTLOADER_TX_DESCRIPTION_SIZE * tx_index; + let tx_description_offset = + get_tx_description_offset(crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory) + + tx_offset; memory.push(( bootloader_description_offset, @@ -51,13 +55,19 @@ pub(super) fn apply_tx_to_memory( U256::from_big_endian(&(32 * tx_description_offset).to_be_bytes()), )); - let refund_offset = OPERATOR_REFUNDS_OFFSET + tx_index; + let refund_offset = + get_operator_refunds_offset(crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory) + + tx_index; memory.push((refund_offset, bootloader_tx.refund.into())); - let overhead_offset = TX_OVERHEAD_OFFSET + tx_index; + let overhead_offset = + get_tx_overhead_offset(crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory) + + tx_index; memory.push((overhead_offset, bootloader_tx.gas_overhead.into())); - let trusted_gas_limit_offset = TX_TRUSTED_GAS_LIMIT_OFFSET + tx_index; + let trusted_gas_limit_offset = get_tx_trusted_gas_limit_offset( + crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, + ) + tx_index; memory.push((trusted_gas_limit_offset, bootloader_tx.trusted_gas_limit)); memory.extend( @@ -67,7 +77,10 @@ pub(super) fn apply_tx_to_memory( apply_l2_block_inner(memory, bootloader_l2_block, tx_index, start_new_l2_block); // Note, +1 is moving for pointer - let compressed_bytecodes_offset = COMPRESSED_BYTECODES_OFFSET + 1 + compressed_bytecodes_size; + let compressed_bytecodes_offset = get_compressed_bytecodes_offset( + crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, + ) + 1 + + compressed_bytecodes_size; let encoded_compressed_bytecodes = get_memory_for_compressed_bytecodes(&bootloader_tx.compressed_bytecodes); @@ -99,8 +112,9 @@ fn apply_l2_block_inner( // L2 block info takes `TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO` slots, the position where the L2 block info // for this transaction needs to be written is: - let block_position = - TX_OPERATOR_L2_BLOCK_INFO_OFFSET + txs_index * TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO; + let block_position = get_tx_operator_l2_block_info_offset( + crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, + ) + txs_index * TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO; memory.extend(vec![ (block_position, bootloader_l2_block.number.into()), @@ -127,7 +141,9 @@ pub(crate) fn apply_pubdata_to_memory( // Skipping two slots as they will be filled by the bootloader itself: // - One slot is for the selector of the call to the L1Messenger. // - The other slot is for the 0x20 offset for the calldata. - let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 2; + let l1_messenger_pubdata_start_slot = get_operator_provided_l1_messenger_pubdata_offset( + crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, + ) + 2; // Need to skip first word as it represents array offset // while bootloader expects only [len || data] diff --git a/core/lib/multivm/src/versions/vm_fast/vm.rs b/core/lib/multivm/src/versions/vm_fast/vm.rs index d2ace9b7771..cf742ec983e 100644 --- a/core/lib/multivm/src/versions/vm_fast/vm.rs +++ b/core/lib/multivm/src/versions/vm_fast/vm.rs @@ -51,8 +51,9 @@ use crate::{ }, vm_latest::{ constants::{ - get_result_success_first_slot, get_vm_hook_params_start_position, get_vm_hook_position, - OPERATOR_REFUNDS_OFFSET, TX_GAS_LIMIT_OFFSET, VM_HOOK_PARAMS_COUNT, + get_operator_refunds_offset, get_result_success_first_slot, + get_vm_hook_params_start_position, get_vm_hook_position, TX_GAS_LIMIT_OFFSET, + VM_HOOK_PARAMS_COUNT, }, MultiVMSubversion, }, @@ -266,7 +267,9 @@ impl Vm { pubdata_before = pubdata_after; let refund_value = refunds.operator_suggested_refund; self.write_to_bootloader_heap([( - OPERATOR_REFUNDS_OFFSET + current_tx_index, + get_operator_refunds_offset( + crate::vm_latest::MultiVMSubversion::IncreasedBootloaderMemory, + ) + current_tx_index, refund_value.into(), )]); self.bootloader_state diff --git a/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs b/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs index 2085bbaba31..97c5587eba7 100644 --- a/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs +++ b/core/lib/multivm/src/versions/vm_latest/bootloader_state/state.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use once_cell::sync::OnceCell; -use zksync_types::{L2ChainId, ProtocolVersionId, U256}; +use zksync_types::{vm::VmVersion, L2ChainId, ProtocolVersionId, U256}; use zksync_vm_interface::pubdata::PubdataBuilder; use super::{tx::BootloaderTx, utils::apply_pubdata_to_memory}; @@ -16,9 +16,10 @@ use crate::{ snapshot::BootloaderStateSnapshot, utils::{apply_l2_block, apply_tx_to_memory}, }, - constants::TX_DESCRIPTION_OFFSET, + constants::get_tx_description_offset, types::internals::TransactionData, utils::l2_blocks::assert_next_block, + MultiVMSubversion, }, }; @@ -51,6 +52,8 @@ pub struct BootloaderState { pubdata_information: OnceCell, /// Protocol version. protocol_version: ProtocolVersionId, + /// Protocol subversion + subversion: MultiVMSubversion, } impl BootloaderState { @@ -70,6 +73,7 @@ impl BootloaderState { free_tx_offset: 0, pubdata_information: Default::default(), protocol_version, + subversion: MultiVMSubversion::try_from(VmVersion::from(protocol_version)).unwrap(), } } @@ -103,6 +107,10 @@ impl BootloaderState { .push(BootloaderL2Block::new(l2_block, self.free_tx_index())) } + pub(crate) fn get_vm_subversion(&self) -> MultiVMSubversion { + self.subversion + } + pub(crate) fn push_tx( &mut self, tx: TransactionData, @@ -133,6 +141,7 @@ impl BootloaderState { self.compressed_bytecodes_encoding, self.execution_mode, self.last_l2_block().txs.is_empty(), + self.subversion, ); self.compressed_bytecodes_encoding += compressed_bytecode_size; self.free_tx_offset = tx_offset + bootloader_tx.encoded_len(); @@ -183,13 +192,14 @@ impl BootloaderState { compressed_bytecodes_offset, self.execution_mode, num == 0, + self.subversion, ); offset += tx.encoded_len(); compressed_bytecodes_offset += compressed_bytecodes_size; tx_index += 1; } if l2_block.txs.is_empty() { - apply_l2_block(&mut initial_memory, l2_block, tx_index) + apply_l2_block(&mut initial_memory, l2_block, tx_index, self.subversion) } } @@ -247,7 +257,7 @@ impl BootloaderState { /// Get offset of tx description pub(crate) fn get_tx_description_offset(&self, tx_index: usize) -> usize { - TX_DESCRIPTION_OFFSET + self.find_tx(tx_index).offset + get_tx_description_offset(self.subversion) + self.find_tx(tx_index).offset } pub(crate) fn insert_fictive_l2_block(&mut self) -> &BootloaderL2Block { diff --git a/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs b/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs index c409bda35c1..3a3149e2cee 100644 --- a/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs +++ b/core/lib/multivm/src/versions/vm_latest/bootloader_state/utils.rs @@ -1,4 +1,4 @@ -use zksync_types::{ethabi, ProtocolVersionId, U256}; +use zksync_types::{ethabi, vm::VmVersion, ProtocolVersionId, U256}; use zksync_utils::{bytes_to_be_words, h256_to_u256}; use super::tx::BootloaderTx; @@ -11,12 +11,14 @@ use crate::{ vm_latest::{ bootloader_state::l2_block::BootloaderL2Block, constants::{ - BOOTLOADER_TX_DESCRIPTION_OFFSET, BOOTLOADER_TX_DESCRIPTION_SIZE, - COMPRESSED_BYTECODES_OFFSET, OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET, - OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, OPERATOR_REFUNDS_OFFSET, - TX_DESCRIPTION_OFFSET, TX_OPERATOR_L2_BLOCK_INFO_OFFSET, - TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, TX_OVERHEAD_OFFSET, TX_TRUSTED_GAS_LIMIT_OFFSET, + get_bootloader_tx_description_offset, get_compressed_bytecodes_offset, + get_operator_provided_l1_messenger_pubdata_offset, get_operator_refunds_offset, + get_tx_description_offset, get_tx_operator_l2_block_info_offset, + get_tx_overhead_offset, get_tx_trusted_gas_limit_offset, + BOOTLOADER_TX_DESCRIPTION_SIZE, OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, + TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO, }, + MultiVMSubversion, }, }; @@ -41,10 +43,11 @@ pub(super) fn apply_tx_to_memory( compressed_bytecodes_size: usize, execution_mode: TxExecutionMode, start_new_l2_block: bool, + subversion: MultiVMSubversion, ) -> usize { - let bootloader_description_offset = - BOOTLOADER_TX_DESCRIPTION_OFFSET + BOOTLOADER_TX_DESCRIPTION_SIZE * tx_index; - let tx_description_offset = TX_DESCRIPTION_OFFSET + tx_offset; + let bootloader_description_offset = get_bootloader_tx_description_offset(subversion) + + BOOTLOADER_TX_DESCRIPTION_SIZE * tx_index; + let tx_description_offset = get_tx_description_offset(subversion) + tx_offset; memory.push(( bootloader_description_offset, @@ -56,13 +59,13 @@ pub(super) fn apply_tx_to_memory( U256::from_big_endian(&(32 * tx_description_offset).to_be_bytes()), )); - let refund_offset = OPERATOR_REFUNDS_OFFSET + tx_index; + let refund_offset = get_operator_refunds_offset(subversion) + tx_index; memory.push((refund_offset, bootloader_tx.refund.into())); - let overhead_offset = TX_OVERHEAD_OFFSET + tx_index; + let overhead_offset = get_tx_overhead_offset(subversion) + tx_index; memory.push((overhead_offset, bootloader_tx.gas_overhead.into())); - let trusted_gas_limit_offset = TX_TRUSTED_GAS_LIMIT_OFFSET + tx_index; + let trusted_gas_limit_offset = get_tx_trusted_gas_limit_offset(subversion) + tx_index; memory.push((trusted_gas_limit_offset, bootloader_tx.trusted_gas_limit)); memory.extend( @@ -70,10 +73,17 @@ pub(super) fn apply_tx_to_memory( .zip(bootloader_tx.encoded.clone()), ); - apply_l2_block_inner(memory, bootloader_l2_block, tx_index, start_new_l2_block); + apply_l2_block_inner( + memory, + bootloader_l2_block, + tx_index, + start_new_l2_block, + subversion, + ); // Note, +1 is moving for pointer - let compressed_bytecodes_offset = COMPRESSED_BYTECODES_OFFSET + 1 + compressed_bytecodes_size; + let compressed_bytecodes_offset = + get_compressed_bytecodes_offset(subversion) + 1 + compressed_bytecodes_size; let encoded_compressed_bytecodes = get_memory_for_compressed_bytecodes(&bootloader_tx.compressed_bytecodes); @@ -91,8 +101,9 @@ pub(crate) fn apply_l2_block( memory: &mut BootloaderMemory, bootloader_l2_block: &BootloaderL2Block, txs_index: usize, + subversion: MultiVMSubversion, ) { - apply_l2_block_inner(memory, bootloader_l2_block, txs_index, true) + apply_l2_block_inner(memory, bootloader_l2_block, txs_index, true, subversion) } fn apply_l2_block_inner( @@ -100,13 +111,14 @@ fn apply_l2_block_inner( bootloader_l2_block: &BootloaderL2Block, txs_index: usize, start_new_l2_block: bool, + subversion: MultiVMSubversion, ) { // Since L2 block information start from the `TX_OPERATOR_L2_BLOCK_INFO_OFFSET` and each // L2 block info takes `TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO` slots, the position where the L2 block info // for this transaction needs to be written is: - let block_position = - TX_OPERATOR_L2_BLOCK_INFO_OFFSET + txs_index * TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO; + let block_position = get_tx_operator_l2_block_info_offset(subversion) + + txs_index * TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO; memory.extend(vec![ (block_position, bootloader_l2_block.number.into()), @@ -146,40 +158,46 @@ pub(crate) fn apply_pubdata_to_memory( pubdata_information: &PubdataInput, protocol_version: ProtocolVersionId, ) { - let (l1_messenger_pubdata_start_slot, pubdata) = if protocol_version.is_pre_gateway() { - // Skipping two slots as they will be filled by the bootloader itself: - // - One slot is for the selector of the call to the L1Messenger. - // - The other slot is for the 0x20 offset for the calldata. - let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 2; - - // Need to skip first word as it represents array offset - // while bootloader expects only [len || data] - let pubdata = ethabi::encode(&[ethabi::Token::Bytes( - pubdata_builder.l1_messenger_operator_input(pubdata_information, protocol_version), - )])[32..] - .to_vec(); - - assert!( - pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2, - "The encoded pubdata is too big" - ); - - (l1_messenger_pubdata_start_slot, pubdata) - } else { - // Skipping the first slot as it will be filled by the bootloader itself: - // It is for the selector of the call to the L1Messenger. - let l1_messenger_pubdata_start_slot = OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + 1; - - let pubdata = - bootloader_memory_input(pubdata_builder, pubdata_information, protocol_version); - - assert!( - // Note that unlike the previous version, the difference is `1`, since now it also includes the offset - pubdata.len() / 32 < OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, - "The encoded pubdata is too big" - ); - - (l1_messenger_pubdata_start_slot, pubdata) + let subversion = MultiVMSubversion::try_from(VmVersion::from(protocol_version)).unwrap(); + let (l1_messenger_pubdata_start_slot, pubdata) = match subversion { + MultiVMSubversion::SmallBootloaderMemory | MultiVMSubversion::IncreasedBootloaderMemory => { + // Skipping two slots as they will be filled by the bootloader itself: + // - One slot is for the selector of the call to the L1Messenger. + // - The other slot is for the 0x20 offset for the calldata. + let l1_messenger_pubdata_start_slot = + get_operator_provided_l1_messenger_pubdata_offset(subversion) + 2; + + // Need to skip first word as it represents array offset + // while bootloader expects only [len || data] + let pubdata = ethabi::encode(&[ethabi::Token::Bytes( + pubdata_builder.l1_messenger_operator_input(pubdata_information, protocol_version), + )])[32..] + .to_vec(); + + assert!( + pubdata.len() / 32 <= OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS - 2, + "The encoded pubdata is too big" + ); + + (l1_messenger_pubdata_start_slot, pubdata) + } + MultiVMSubversion::Gateway => { + // Skipping the first slot as it will be filled by the bootloader itself: + // It is for the selector of the call to the L1Messenger. + let l1_messenger_pubdata_start_slot = + get_operator_provided_l1_messenger_pubdata_offset(subversion) + 1; + + let pubdata = + bootloader_memory_input(pubdata_builder, pubdata_information, protocol_version); + + assert!( + // Note that unlike the previous version, the difference is `1`, since now it also includes the offset + pubdata.len() / 32 < OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS, + "The encoded pubdata is too big" + ); + + (l1_messenger_pubdata_start_slot, pubdata) + } }; pubdata diff --git a/core/lib/multivm/src/versions/vm_latest/constants.rs b/core/lib/multivm/src/versions/vm_latest/constants.rs index c047e6ffa3b..643047cedb0 100644 --- a/core/lib/multivm/src/versions/vm_latest/constants.rs +++ b/core/lib/multivm/src/versions/vm_latest/constants.rs @@ -3,7 +3,6 @@ use zk_evm_1_5_0::aux_structures::MemoryPage; pub use zk_evm_1_5_0::zkevm_opcode_defs::system_params::{ ERGS_PER_CIRCUIT, INITIAL_STORAGE_WRITE_PUBDATA_BYTES, }; -use zksync_system_constants::MAX_NEW_FACTORY_DEPS; use super::vm::MultiVMSubversion; use crate::vm_latest::old_vm::utils::heap_page_from_base; @@ -61,35 +60,72 @@ pub(crate) const MAX_POSTOP_SLOTS: usize = PAYMASTER_CONTEXT_SLOTS + 7; /// to be used for signing the transaction's content. const CURRENT_L2_TX_HASHES_SLOTS: usize = 2; +pub(crate) const fn get_max_new_factory_deps(subversion: MultiVMSubversion) -> usize { + match subversion { + MultiVMSubversion::SmallBootloaderMemory | MultiVMSubversion::IncreasedBootloaderMemory => { + 32 + } + // With gateway upgrade we increased max number of factory dependencies + MultiVMSubversion::Gateway => 64, + } +} + /// Slots used to store the calldata for the KnownCodesStorage to mark new factory /// dependencies as known ones. Besides the slots for the new factory dependencies themselves /// another 4 slots are needed for: selector, marker of whether the user should pay for the pubdata, /// the offset for the encoding of the array as well as the length of the array. -const NEW_FACTORY_DEPS_RESERVED_SLOTS: usize = MAX_NEW_FACTORY_DEPS + 4; +pub(crate) const fn get_new_factory_deps_reserved_slots(subversion: MultiVMSubversion) -> usize { + get_max_new_factory_deps(subversion) + 4 +} /// The operator can provide for each transaction the proposed minimal refund pub(crate) const OPERATOR_REFUNDS_SLOTS: usize = MAX_TXS_IN_BATCH; -pub(crate) const OPERATOR_REFUNDS_OFFSET: usize = DEBUG_SLOTS_OFFSET - + DEBUG_FIRST_SLOTS - + PAYMASTER_CONTEXT_SLOTS - + CURRENT_L2_TX_HASHES_SLOTS - + NEW_FACTORY_DEPS_RESERVED_SLOTS; +pub(crate) const fn get_operator_refunds_offset(subversion: MultiVMSubversion) -> usize { + DEBUG_SLOTS_OFFSET + + DEBUG_FIRST_SLOTS + + PAYMASTER_CONTEXT_SLOTS + + CURRENT_L2_TX_HASHES_SLOTS + + get_new_factory_deps_reserved_slots(subversion) +} + +pub(crate) const fn get_tx_overhead_offset(subversion: MultiVMSubversion) -> usize { + get_operator_refunds_offset(subversion) + OPERATOR_REFUNDS_SLOTS +} -pub(crate) const TX_OVERHEAD_OFFSET: usize = OPERATOR_REFUNDS_OFFSET + OPERATOR_REFUNDS_SLOTS; pub(crate) const TX_OVERHEAD_SLOTS: usize = MAX_TXS_IN_BATCH; -pub(crate) const TX_TRUSTED_GAS_LIMIT_OFFSET: usize = TX_OVERHEAD_OFFSET + TX_OVERHEAD_SLOTS; +pub(crate) const fn get_tx_trusted_gas_limit_offset(subversion: MultiVMSubversion) -> usize { + get_tx_overhead_offset(subversion) + TX_OVERHEAD_SLOTS +} + pub(crate) const TX_TRUSTED_GAS_LIMIT_SLOTS: usize = MAX_TXS_IN_BATCH; +pub(crate) const fn get_tx_operator_l2_block_info_offset(subversion: MultiVMSubversion) -> usize { + get_tx_trusted_gas_limit_offset(subversion) + TX_TRUSTED_GAS_LIMIT_SLOTS +} + +pub(crate) const TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO: usize = 4; +pub(crate) const TX_OPERATOR_L2_BLOCK_INFO_SLOTS: usize = + (MAX_TXS_IN_BATCH + 1) * TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO; + +pub(crate) const fn get_compressed_bytecodes_offset(subversion: MultiVMSubversion) -> usize { + get_tx_operator_l2_block_info_offset(subversion) + TX_OPERATOR_L2_BLOCK_INFO_SLOTS +} + pub(crate) const COMPRESSED_BYTECODES_SLOTS: usize = 196608; -pub(crate) const PRIORITY_TXS_L1_DATA_OFFSET: usize = - COMPRESSED_BYTECODES_OFFSET + COMPRESSED_BYTECODES_SLOTS; +pub(crate) const fn get_priority_txs_l1_data_offset(subversion: MultiVMSubversion) -> usize { + get_compressed_bytecodes_offset(subversion) + COMPRESSED_BYTECODES_SLOTS +} + pub(crate) const PRIORITY_TXS_L1_DATA_SLOTS: usize = 2; -pub const OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET: usize = - PRIORITY_TXS_L1_DATA_OFFSET + PRIORITY_TXS_L1_DATA_SLOTS; +pub const fn get_operator_provided_l1_messenger_pubdata_offset( + subversion: MultiVMSubversion, +) -> usize { + get_priority_txs_l1_data_offset(subversion) + PRIORITY_TXS_L1_DATA_SLOTS +} /// One of "worst case" scenarios for the number of state diffs in a batch is when 780kb of pubdata is spent /// on repeated writes, that are all zeroed out. In this case, the number of diffs is `780kb / 5 = 156k`. This means that they will have @@ -101,12 +137,16 @@ pub const OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET: usize = /// operator to ensure that it can form the correct calldata for the L1Messenger. pub(crate) const OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS: usize = 1360000; -pub(crate) const BOOTLOADER_TX_DESCRIPTION_OFFSET: usize = - OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_OFFSET + OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS; +pub(crate) const fn get_bootloader_tx_description_offset(subversion: MultiVMSubversion) -> usize { + get_operator_provided_l1_messenger_pubdata_offset(subversion) + + OPERATOR_PROVIDED_L1_MESSENGER_PUBDATA_SLOTS +} /// The size of the bootloader memory dedicated to the encodings of transactions pub(crate) const fn get_bootloader_tx_encoding_space(subversion: MultiVMSubversion) -> u32 { - (get_used_bootloader_memory_words(subversion) - TX_DESCRIPTION_OFFSET - MAX_TXS_IN_BATCH) as u32 + (get_used_bootloader_memory_words(subversion) + - get_tx_description_offset(subversion) + - MAX_TXS_IN_BATCH) as u32 } // Size of the bootloader tx description in words @@ -114,9 +154,11 @@ pub(crate) const BOOTLOADER_TX_DESCRIPTION_SIZE: usize = 2; /// The actual descriptions of transactions should start after the minor descriptions and a MAX_POSTOP_SLOTS /// free slots to allow postOp encoding. -pub(crate) const TX_DESCRIPTION_OFFSET: usize = BOOTLOADER_TX_DESCRIPTION_OFFSET - + BOOTLOADER_TX_DESCRIPTION_SIZE * MAX_TXS_IN_BATCH - + MAX_POSTOP_SLOTS; +pub(crate) const fn get_tx_description_offset(subversion: MultiVMSubversion) -> usize { + get_bootloader_tx_description_offset(subversion) + + BOOTLOADER_TX_DESCRIPTION_SIZE * MAX_TXS_IN_BATCH + + MAX_POSTOP_SLOTS +} pub(crate) const TX_GAS_LIMIT_OFFSET: usize = 4; @@ -166,16 +208,6 @@ pub const ETH_CALL_GAS_LIMIT: u64 = BATCH_GAS_LIMIT; /// ID of the transaction from L1 pub const L1_TX_TYPE: u8 = 255; -pub(crate) const TX_OPERATOR_L2_BLOCK_INFO_OFFSET: usize = - TX_TRUSTED_GAS_LIMIT_OFFSET + TX_TRUSTED_GAS_LIMIT_SLOTS; - -pub(crate) const TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO: usize = 4; -pub(crate) const TX_OPERATOR_L2_BLOCK_INFO_SLOTS: usize = - (MAX_TXS_IN_BATCH + 1) * TX_OPERATOR_SLOTS_PER_L2_BLOCK_INFO; - -pub(crate) const COMPRESSED_BYTECODES_OFFSET: usize = - TX_OPERATOR_L2_BLOCK_INFO_OFFSET + TX_OPERATOR_L2_BLOCK_INFO_SLOTS; - /// The maximal gas limit that gets passed as compute for an L2 transaction. This is also the maximal limit allowed /// for L1->L2 transactions. /// diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs index 2ae5e81a328..49e74feb9a7 100755 --- a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs @@ -116,10 +116,11 @@ impl DefaultExecutionTracer { bootloader_state: &mut BootloaderState, ) { let current_timestamp = Timestamp(state.local_state.timestamp); + let subversion = bootloader_state.get_vm_subversion(); let txs_index = bootloader_state.free_tx_index(); let l2_block = bootloader_state.insert_fictive_l2_block(); let mut memory = vec![]; - apply_l2_block(&mut memory, l2_block, txs_index); + apply_l2_block(&mut memory, l2_block, txs_index, subversion); state.memory.populate_page( BOOTLOADER_HEAP_PAGE as usize, memory, diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/refunds.rs b/core/lib/multivm/src/versions/vm_latest/tracers/refunds.rs index 78826a16313..3166f487b86 100644 --- a/core/lib/multivm/src/versions/vm_latest/tracers/refunds.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/refunds.rs @@ -17,7 +17,7 @@ use crate::{ tracers::dynamic::vm_1_5_0::DynTracer, vm_latest::{ bootloader_state::BootloaderState, - constants::{BOOTLOADER_HEAP_PAGE, OPERATOR_REFUNDS_OFFSET, TX_GAS_LIMIT_OFFSET}, + constants::{get_operator_refunds_offset, BOOTLOADER_HEAP_PAGE, TX_GAS_LIMIT_OFFSET}, old_vm::{history_recorder::HistoryMode, memory::SimpleMemory}, tracers::{ traits::VmTracer, @@ -273,7 +273,8 @@ impl VmTracer for RefundsTracer { let refund_to_propose = tx_body_refund + self.block_overhead_refund(); - let refund_slot = OPERATOR_REFUNDS_OFFSET + current_tx_index; + let refund_slot = get_operator_refunds_offset(bootloader_state.get_vm_subversion()) + + current_tx_index; // Writing the refund into memory state.memory.populate_page( diff --git a/core/lib/multivm/src/versions/vm_m5/vm_with_bootloader.rs b/core/lib/multivm/src/versions/vm_m5/vm_with_bootloader.rs index cd2979db5e5..0c039c182e9 100644 --- a/core/lib/multivm/src/versions/vm_m5/vm_with_bootloader.rs +++ b/core/lib/multivm/src/versions/vm_m5/vm_with_bootloader.rs @@ -15,7 +15,7 @@ use zksync_contracts::BaseSystemContracts; use zksync_system_constants::MAX_L2_TX_GAS_LIMIT; use zksync_types::{ fee_model::L1PeggedBatchFeeModelInput, Address, Transaction, BOOTLOADER_ADDRESS, - L1_GAS_PER_PUBDATA_BYTE, MAX_NEW_FACTORY_DEPS, U256, + L1_GAS_PER_PUBDATA_BYTE, U256, }; use zksync_utils::{ address_to_u256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256, misc::ceil_div, @@ -154,6 +154,8 @@ pub const MAX_POSTOP_SLOTS: usize = PAYMASTER_CONTEXT_SLOTS + 7; // to be used for signing the transaction's content. const CURRENT_L2_TX_HASHES_SLOTS: usize = 2; +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; + // Slots used to store the calldata for the KnownCodesStorage to mark new factory // dependencies as known ones. Besides the slots for the new factory dependencies themselves // another 4 slots are needed for: selector, marker of whether the user should pay for the pubdata, diff --git a/core/lib/multivm/src/versions/vm_m6/vm_with_bootloader.rs b/core/lib/multivm/src/versions/vm_m6/vm_with_bootloader.rs index ae44e721b0d..0b2bef4fd10 100644 --- a/core/lib/multivm/src/versions/vm_m6/vm_with_bootloader.rs +++ b/core/lib/multivm/src/versions/vm_m6/vm_with_bootloader.rs @@ -15,7 +15,7 @@ use zksync_contracts::BaseSystemContracts; use zksync_system_constants::MAX_L2_TX_GAS_LIMIT; use zksync_types::{ fee_model::L1PeggedBatchFeeModelInput, Address, Transaction, BOOTLOADER_ADDRESS, - L1_GAS_PER_PUBDATA_BYTE, MAX_NEW_FACTORY_DEPS, U256, + L1_GAS_PER_PUBDATA_BYTE, U256, }; use zksync_utils::{ address_to_u256, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256, misc::ceil_div, @@ -37,6 +37,8 @@ use crate::{ }, }; +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; + // TODO (SMA-1703): move these to config and make them programmatically generable. // fill these values in the similar fashion as other overhead-related constants pub const BLOCK_OVERHEAD_GAS: u32 = 1200000; diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/constants.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/constants.rs index 27ce59f5709..90faf03a2d1 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/constants.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/constants.rs @@ -2,10 +2,12 @@ use zk_evm_1_3_3::aux_structures::MemoryPage; pub use zk_evm_1_3_3::zkevm_opcode_defs::system_params::{ ERGS_PER_CIRCUIT, INITIAL_STORAGE_WRITE_PUBDATA_BYTES, MAX_PUBDATA_PER_BLOCK, }; -use zksync_system_constants::{L1_GAS_PER_PUBDATA_BYTE, MAX_L2_TX_GAS_LIMIT, MAX_NEW_FACTORY_DEPS}; +use zksync_system_constants::{L1_GAS_PER_PUBDATA_BYTE, MAX_L2_TX_GAS_LIMIT}; use crate::vm_refunds_enhancement::old_vm::utils::heap_page_from_base; +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; + /// The size of the bootloader memory in bytes which is used by the protocol. /// While the maximal possible size is a lot higher, we restrict ourselves to a certain limit to reduce /// the requirements on RAM. diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/constants.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/constants.rs index 69b713e2e9f..c695f67ea30 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/constants.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/constants.rs @@ -2,7 +2,7 @@ use zk_evm_1_3_3::aux_structures::MemoryPage; pub use zk_evm_1_3_3::zkevm_opcode_defs::system_params::{ ERGS_PER_CIRCUIT, INITIAL_STORAGE_WRITE_PUBDATA_BYTES, MAX_PUBDATA_PER_BLOCK, }; -use zksync_system_constants::{L1_GAS_PER_PUBDATA_BYTE, MAX_L2_TX_GAS_LIMIT, MAX_NEW_FACTORY_DEPS}; +use zksync_system_constants::{L1_GAS_PER_PUBDATA_BYTE, MAX_L2_TX_GAS_LIMIT}; use crate::vm_virtual_blocks::old_vm::utils::heap_page_from_base; @@ -42,6 +42,8 @@ pub(crate) const MAX_POSTOP_SLOTS: usize = PAYMASTER_CONTEXT_SLOTS + 7; /// to be used for signing the transaction's content. const CURRENT_L2_TX_HASHES_SLOTS: usize = 2; +pub(crate) const MAX_NEW_FACTORY_DEPS: usize = 32; + /// Slots used to store the calldata for the KnownCodesStorage to mark new factory /// dependencies as known ones. Besides the slots for the new factory dependencies themselves /// another 4 slots are needed for: selector, marker of whether the user should pay for the pubdata, diff --git a/core/lib/protobuf_config/src/contracts.rs b/core/lib/protobuf_config/src/contracts.rs index dc5b1c567e8..aee0c00162b 100644 --- a/core/lib/protobuf_config/src/contracts.rs +++ b/core/lib/protobuf_config/src/contracts.rs @@ -2,7 +2,7 @@ use anyhow::Context as _; use zksync_config::configs::{ContractsConfig, EcosystemContracts}; use zksync_protobuf::{repr::ProtoRepr, required}; -use crate::{parse_h160, proto::contracts as proto}; +use crate::{parse_h160, parse_h256, proto::contracts as proto}; impl ProtoRepr for proto::Contracts { type Type = ContractsConfig; @@ -30,6 +30,10 @@ impl ProtoRepr for proto::Contracts { ) .and_then(|x| parse_h160(x)) .context("transparent_proxy_admin_addr")?, + l1_bytecodes_supplier_addr: ecosystem_contracts + .l1_bytecodes_supplier_addr + .as_ref() + .map(|x| parse_h160(x).expect("Invalid address")), }) } else { None @@ -79,6 +83,7 @@ impl ProtoRepr for proto::Contracts { l2_legacy_shared_bridge_addr: l2 .legacy_shared_bridge_addr .as_ref() + .and_then(|x| (!x.is_empty()).then_some(x)) .map(|x| parse_h160(x)) .transpose() .context("l2_legacy_shared_bridge_addr")?, @@ -107,6 +112,18 @@ impl ProtoRepr for proto::Contracts { .map(|x| parse_h160(x)) .transpose() .context("base_token_addr")?, + base_token_asset_id: l1 + .base_token_asset_id + .as_ref() + .map(|x| parse_h256(x)) + .transpose() + .context("base_token_asset_id")?, + predeployed_l2_wrapped_base_token_address: l2 + .predeployed_l2_wrapped_base_token_address + .as_ref() + .map(|x| parse_h160(x)) + .transpose() + .context("predeployed_l2_wrapped_base_token_address")?, user_facing_bridgehub_proxy_addr: self .user_facing_bridgehub .as_ref() @@ -152,6 +169,9 @@ impl ProtoRepr for proto::Contracts { "{:?}", ecosystem_contracts.transparent_proxy_admin_addr, )), + l1_bytecodes_supplier_addr: ecosystem_contracts + .l1_bytecodes_supplier_addr + .map(|x| format!("{:?}", x)), }); Self { ecosystem_contracts, @@ -163,6 +183,7 @@ impl ProtoRepr for proto::Contracts { default_upgrade_addr: Some(format!("{:?}", this.default_upgrade_addr)), multicall3_addr: Some(format!("{:?}", this.l1_multicall3_addr)), base_token_addr: this.base_token_addr.map(|a| format!("{:?}", a)), + base_token_asset_id: this.base_token_asset_id.map(|x| format!("{:?}", x)), chain_admin_addr: this.chain_admin_addr.map(|a| format!("{:?}", a)), }), l2: Some(proto::L2 { @@ -171,6 +192,9 @@ impl ProtoRepr for proto::Contracts { legacy_shared_bridge_addr: this .l2_legacy_shared_bridge_addr .map(|a| format!("{:?}", a)), + predeployed_l2_wrapped_base_token_address: this + .predeployed_l2_wrapped_base_token_address + .map(|x| format!("{:?}", x)), }), bridges: Some(proto::Bridges { shared: Some(proto::Bridge { diff --git a/core/lib/protobuf_config/src/proto/config/contracts.proto b/core/lib/protobuf_config/src/proto/config/contracts.proto index 11fbdcacdce..7f1fe1d700e 100644 --- a/core/lib/protobuf_config/src/proto/config/contracts.proto +++ b/core/lib/protobuf_config/src/proto/config/contracts.proto @@ -6,6 +6,7 @@ message EcosystemContracts { optional string bridgehub_proxy_addr = 1; // optional; h160 optional string state_transition_proxy_addr = 2; // optional; h160 optional string transparent_proxy_admin_addr = 3; // optional; h160 + optional string l1_bytecodes_supplier_addr = 4; // optional; h160 } message L1 { @@ -17,12 +18,14 @@ message L1 { optional string multicall3_addr = 6; // required; H160 optional string base_token_addr = 7; // required; H160 optional string chain_admin_addr = 8; // required; H160 + optional string base_token_asset_id = 9; // required; H256 } message L2 { optional string testnet_paymaster_addr = 1; // optional; H160 optional string da_validator_addr = 2; // optional; H160 optional string legacy_shared_bridge_addr = 3; // optional; H160 + optional string predeployed_l2_wrapped_base_token_address = 10; // optional; H160 } message Bridge { diff --git a/core/lib/types/Cargo.toml b/core/lib/types/Cargo.toml index 5176d90cfd4..e785b27da10 100644 --- a/core/lib/types/Cargo.toml +++ b/core/lib/types/Cargo.toml @@ -20,6 +20,7 @@ zksync_mini_merkle_tree.workspace = true zksync_protobuf.workspace = true zksync_crypto_primitives.workspace = true +async-trait.workspace = true anyhow.workspace = true chrono = { workspace = true, features = ["serde"] } derive_more = { workspace = true, features = ["debug"] } diff --git a/core/lib/types/src/abi.rs b/core/lib/types/src/abi.rs index 2931323fd60..f037f7db226 100644 --- a/core/lib/types/src/abi.rs +++ b/core/lib/types/src/abi.rs @@ -195,7 +195,6 @@ pub struct VerifierParams { /// `ProposedUpgrade` from, `l1-contracts/contracts/upgrades/BazeZkSyncUpgrade.sol`. pub struct ProposedUpgrade { pub l2_protocol_upgrade_tx: Box, - pub factory_deps: Vec>, pub bootloader_hash: [u8; 32], pub default_account_hash: [u8; 32], pub verifier: Address, @@ -253,16 +252,15 @@ impl ProposedUpgrade { /// RLP schema of the `ProposedUpgrade`. pub fn schema() -> ParamType { ParamType::Tuple(vec![ - L2CanonicalTransaction::schema(), // transaction data - ParamType::Array(ParamType::Bytes.into()), // factory deps - ParamType::FixedBytes(32), // bootloader code hash - ParamType::FixedBytes(32), // default account code hash - ParamType::Address, // verifier address - VerifierParams::schema(), // verifier params - ParamType::Bytes, // l1 custom data - ParamType::Bytes, // l1 post-upgrade custom data - ParamType::Uint(256), // timestamp - ParamType::Uint(256), // version id + L2CanonicalTransaction::schema(), // transaction data + ParamType::FixedBytes(32), // bootloader code hash + ParamType::FixedBytes(32), // default account code hash + ParamType::Address, // verifier address + VerifierParams::schema(), // verifier params + ParamType::Bytes, // l1 custom data + ParamType::Bytes, // l1 post-upgrade custom data + ParamType::Uint(256), // timestamp + ParamType::Uint(256), // version id ]) } @@ -270,12 +268,6 @@ impl ProposedUpgrade { pub fn encode(&self) -> Token { Token::Tuple(vec![ self.l2_protocol_upgrade_tx.encode(), - Token::Array( - self.factory_deps - .iter() - .map(|b| Token::Bytes(b.clone())) - .collect(), - ), Token::FixedBytes(self.bootloader_hash.into()), Token::FixedBytes(self.default_account_hash.into()), Token::Address(self.verifier), @@ -291,21 +283,13 @@ impl ProposedUpgrade { /// Returns an error if token doesn't match the `schema()`. pub fn decode(token: Token) -> anyhow::Result { let tokens = token.into_tuple().context("not a tuple")?; - anyhow::ensure!(tokens.len() == 10); + anyhow::ensure!(tokens.len() == 9); let mut t = tokens.into_iter(); let mut next = || t.next().unwrap(); Ok(Self { l2_protocol_upgrade_tx: L2CanonicalTransaction::decode(next()) .context("l2_protocol_upgrade_tx")? .into(), - factory_deps: next() - .into_array() - .context("factory_deps")? - .into_iter() - .enumerate() - .map(|(i, b)| b.into_bytes().context(i)) - .collect::>() - .context("factory_deps")?, bootloader_hash: next() .into_fixed_bytes() .and_then(|b| b.try_into().ok()) @@ -365,3 +349,164 @@ impl Transaction { }) } } + +pub struct ForceDeployment { + pub bytecode_hash: H256, + pub new_address: Address, + pub call_constructor: bool, + pub value: U256, + pub input: Vec, +} + +impl ForceDeployment { + /// ABI schema of the `ForceDeployment`. + pub fn schema() -> ParamType { + ParamType::Tuple(vec![ + ParamType::FixedBytes(32), + ParamType::Address, + ParamType::Bool, + ParamType::Uint(256), + ParamType::Bytes, + ]) + } + + /// Encodes `ProposedUpgrade` to a RLP token. + pub fn encode(&self) -> Token { + Token::Tuple(vec![ + Token::FixedBytes(self.bytecode_hash.0.to_vec()), + Token::Address(self.new_address), + Token::Bool(self.call_constructor), + Token::Uint(self.value), + Token::Bytes(self.input.clone()), + ]) + } + + /// Decodes `ProposedUpgrade` from a RLP token. + /// Returns an error if token doesn't match the `schema()`. + pub fn decode(token: Token) -> anyhow::Result { + let tokens = token.into_tuple().context("not a tuple")?; + anyhow::ensure!(tokens.len() == 5); + let mut t = tokens.into_iter(); + let mut next = || t.next().unwrap(); + Ok(Self { + bytecode_hash: next() + .into_fixed_bytes() + .and_then(|b| Some(H256(b.try_into().ok()?))) + .context("bytecode_hash")?, + new_address: next().into_address().context("new_address")?, + call_constructor: next().into_bool().context("call_constructor")?, + value: next().into_uint().context("value")?, + input: next().into_bytes().context("input")?, + }) + } +} + +pub struct GatewayUpgradeEncodedInput { + pub force_deployments: Vec, + pub l2_gateway_upgrade_position: usize, + pub fixed_force_deployments_data: Vec, + pub ctm_deployer: Address, + pub old_validator_timelock: Address, + pub new_validator_timelock: Address, + pub wrapped_base_token_store: Address, +} + +impl GatewayUpgradeEncodedInput { + /// ABI schema of the `ProposedUpgrade`. + pub fn schema() -> ParamType { + ParamType::Tuple(vec![ + ParamType::Array(Box::new(ForceDeployment::schema())), + ParamType::Uint(256), + ParamType::Bytes, + ParamType::Address, + ParamType::Address, + ParamType::Address, + ParamType::Address, + ]) + } + + /// Decodes `ProposedUpgrade` from a RLP token. + /// Returns an error if token doesn't match the `schema()`. + pub fn decode(token: Token) -> anyhow::Result { + let tokens = token.into_tuple().context("not a tuple")?; + anyhow::ensure!(tokens.len() == 7); + let mut t = tokens.into_iter(); + let mut next = || t.next().unwrap(); + + let force_deployments_array = next().into_array().context("force_deployments_array")?; + let mut force_deployments = vec![]; + for token in force_deployments_array { + force_deployments.push(ForceDeployment::decode(token)?); + } + + Ok(Self { + force_deployments, + l2_gateway_upgrade_position: next() + .into_uint() + .context("l2_gateway_upgrade_position")? + .as_usize(), + fixed_force_deployments_data: next() + .into_bytes() + .context("fixed_force_deployments_data")?, + ctm_deployer: next().into_address().context("ctm_deployer")?, + old_validator_timelock: next().into_address().context("old_validator_timelock")?, + new_validator_timelock: next().into_address().context("new_validator_timelock")?, + wrapped_base_token_store: next().into_address().context("wrapped_base_token_store")?, + }) + } +} + +#[derive(Debug, Clone)] +pub struct ZkChainSpecificUpgradeData { + pub base_token_asset_id: H256, + pub l2_legacy_shared_bridge: Address, + pub predeployed_l2_weth_address: Address, + pub base_token_l1_address: Address, + pub base_token_name: String, + pub base_token_symbol: String, +} + +impl ZkChainSpecificUpgradeData { + pub fn from_partial_components( + base_token_asset_id: Option, + l2_legacy_shared_bridge: Option
, + predeployed_l2_weth_address: Option
, + base_token_l1_address: Option
, + base_token_name: Option, + base_token_symbol: Option, + ) -> Option { + Some(Self { + base_token_asset_id: base_token_asset_id?, + l2_legacy_shared_bridge: l2_legacy_shared_bridge?, + predeployed_l2_weth_address: predeployed_l2_weth_address?, + base_token_l1_address: base_token_l1_address?, + base_token_name: base_token_name?, + base_token_symbol: base_token_symbol?, + }) + } + + /// ABI schema of the `ProposedUpgrade`. + pub fn schema() -> ParamType { + ParamType::Tuple(vec![ + ParamType::FixedBytes(32), + ParamType::Address, + ParamType::Address, + ]) + } + + /// Encodes `ProposedUpgrade` to a RLP token. + pub fn encode(&self) -> Token { + Token::Tuple(vec![ + Token::FixedBytes(self.base_token_asset_id.0.to_vec()), + Token::Address(self.l2_legacy_shared_bridge), + Token::Address(self.predeployed_l2_weth_address), + Token::Address(self.base_token_l1_address), + Token::String(self.base_token_name.clone()), + Token::String(self.base_token_symbol.clone()), + ]) + } + + pub fn encode_bytes(&self) -> Vec { + ethabi::encode(&[self.encode()]) + } +} diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index 2461db26593..698d2768b4d 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -1,6 +1,7 @@ use std::convert::{TryFrom, TryInto}; use anyhow::Context as _; +use ethabi::{decode, encode}; use serde::{Deserialize, Serialize}; use zksync_basic_types::{ ethabi, @@ -8,14 +9,14 @@ use zksync_basic_types::{ L1VerifierConfig, ProtocolSemanticVersion, ProtocolVersionId, VerifierParams, }, }; -use zksync_contracts::{ - BaseSystemContractsHashes, ADMIN_EXECUTE_UPGRADE_FUNCTION, - ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION, DIAMOND_CUT, -}; -use zksync_utils::h256_to_u256; +use zksync_contracts::{BaseSystemContractsHashes, DIAMOND_CUT}; +use zksync_utils::{h256_to_u256, u256_to_h256}; use crate::{ - abi, + abi::{ + self, ForceDeployment, GatewayUpgradeEncodedInput, ProposedUpgrade, + ZkChainSpecificUpgradeData, + }, ethabi::{ParamType, Token}, web3::Log, Address, Execute, ExecuteTransactionCommon, Transaction, TransactionType, H256, U256, @@ -96,26 +97,137 @@ impl From for VerifierParams { } } +/// Protocol upgrade transactions do not contain preimages within them. +/// Instead, they are expected to be known and need to be fetched, typically from L1. +#[async_trait::async_trait] +pub trait ProtocolUpgradePreimageOracle: Send + Sync { + async fn get_protocol_upgrade_preimages(&self, hash: Vec) + -> anyhow::Result>>; +} + +/// Some upgrades have chain-dependent calldata +/// that has to be prepared properly +async fn prepare_upgrade_call( + proposed_upgrade: &ProposedUpgrade, + chain_specific: Option, +) -> anyhow::Result> { + // No upgrade + if proposed_upgrade.l2_protocol_upgrade_tx.tx_type == U256::zero() { + return Ok(vec![]); + } + + let minor_version = proposed_upgrade.l2_protocol_upgrade_tx.nonce; + if ProtocolVersionId::try_from(minor_version.as_u32() as u16).unwrap() + != ProtocolVersionId::gateway_upgrade() + { + // We'll just keep it the same for non-Gateway upgrades + return Ok(proposed_upgrade.l2_protocol_upgrade_tx.data.clone()); + } + + // For gateway upgrade, things are bit more complex. + // The source of truth for the code below is the one that is present in + // `GatewayUpgrade.sol`. + let mut encoded_input = GatewayUpgradeEncodedInput::decode( + decode( + &[GatewayUpgradeEncodedInput::schema()], + &proposed_upgrade.post_upgrade_calldata, + )?[0] + .clone(), + )?; + + let gateway_upgrade_calldata = encode(&[ + Token::Address(encoded_input.ctm_deployer), + Token::Bytes(encoded_input.fixed_force_deployments_data), + Token::Bytes(chain_specific.context("chain_specific")?.encode_bytes()), + ]); + + // May not be very idiomatic, but we do it in the same way as it was done in Solidity + // for easier review + encoded_input.force_deployments[encoded_input.l2_gateway_upgrade_position].input = + gateway_upgrade_calldata; + + let force_deployments_as_tokens: Vec<_> = encoded_input + .force_deployments + .iter() + .map(ForceDeployment::encode) + .collect(); + + let full_data = zksync_contracts::deployer_contract() + .function("forceDeployOnAddresses") + .unwrap() + .encode_input(&[Token::Array(force_deployments_as_tokens)]) + .unwrap(); + + Ok(full_data) +} + impl ProtocolUpgrade { - pub fn try_from_diamond_cut(diamond_cut_data: &[u8]) -> anyhow::Result { + pub async fn try_from_diamond_cut( + diamond_cut_data: &[u8], + preimage_oracle: impl ProtocolUpgradePreimageOracle, + chain_specific: Option, + ) -> anyhow::Result { // Unwraps are safe because we have validated the input against the function signature. let diamond_cut_tokens = DIAMOND_CUT.decode_input(diamond_cut_data)?[0] .clone() .into_tuple() .unwrap(); - Self::try_from_init_calldata(&diamond_cut_tokens[2].clone().into_bytes().unwrap()) + Self::try_from_init_calldata( + &diamond_cut_tokens[2].clone().into_bytes().unwrap(), + preimage_oracle, + chain_specific, + ) + .await } /// `l1-contracts/contracts/state-transition/libraries/diamond.sol:DiamondCutData.initCalldata` - fn try_from_init_calldata(init_calldata: &[u8]) -> anyhow::Result { + async fn try_from_init_calldata( + init_calldata: &[u8], + preimage_oracle: impl ProtocolUpgradePreimageOracle, + chain_specific: Option, + ) -> anyhow::Result { let upgrade = ethabi::decode( &[abi::ProposedUpgrade::schema()], init_calldata.get(4..).context("need >= 4 bytes")?, ) .context("ethabi::decode()")?; - let upgrade = abi::ProposedUpgrade::decode(upgrade.into_iter().next().unwrap()).unwrap(); + let mut upgrade = + abi::ProposedUpgrade::decode(upgrade.into_iter().next().unwrap()).unwrap(); let bootloader_hash = H256::from_slice(&upgrade.bootloader_hash); let default_account_hash = H256::from_slice(&upgrade.default_account_hash); + + let tx = if upgrade.l2_protocol_upgrade_tx.tx_type != U256::zero() { + let factory_deps = preimage_oracle + .get_protocol_upgrade_preimages( + upgrade + .l2_protocol_upgrade_tx + .factory_deps + .iter() + .map(|&x| u256_to_h256(x)) + .collect(), + ) + .await?; + + upgrade.l2_protocol_upgrade_tx.data = + prepare_upgrade_call(&upgrade, chain_specific).await?; + + Some( + Transaction::from_abi( + abi::Transaction::L1 { + tx: upgrade.l2_protocol_upgrade_tx, + factory_deps, + eth_block: 0, + }, + false, + ) + .context("Transaction::try_from()")? + .try_into() + .map_err(|err| anyhow::format_err!("try_into::(): {err}"))?, + ) + } else { + None + }; + Ok(Self { version: ProtocolSemanticVersion::try_from_packed(upgrade.new_protocol_version) .map_err(|err| anyhow::format_err!("Version is not supported: {err}"))?, @@ -127,21 +239,7 @@ impl ProtocolUpgrade { .then_some(upgrade.verifier_params.into()), verifier_address: (upgrade.verifier != Address::zero()).then_some(upgrade.verifier), timestamp: upgrade.upgrade_timestamp.try_into().unwrap(), - tx: (upgrade.l2_protocol_upgrade_tx.tx_type != U256::zero()) - .then(|| { - Transaction::from_abi( - abi::Transaction::L1 { - tx: upgrade.l2_protocol_upgrade_tx, - factory_deps: upgrade.factory_deps, - eth_block: 0, - }, - true, - ) - .context("Transaction::try_from()")? - .try_into() - .map_err(|err| anyhow::format_err!("try_into::(): {err}")) - }) - .transpose()?, + tx, }) } } @@ -192,50 +290,6 @@ pub fn decode_genesis_upgrade_event( )) } -impl TryFrom for ProtocolUpgrade { - type Error = anyhow::Error; - - fn try_from(call: Call) -> Result { - anyhow::ensure!(call.data.len() >= 4); - let (signature, data) = call.data.split_at(4); - - let diamond_cut_tokens = - if signature.to_vec() == ADMIN_EXECUTE_UPGRADE_FUNCTION.short_signature().to_vec() { - // Unwraps are safe, because we validate the input against the function signature. - ADMIN_EXECUTE_UPGRADE_FUNCTION - .decode_input(data)? - .pop() - .unwrap() - .into_tuple() - .unwrap() - } else if signature.to_vec() - == ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION - .short_signature() - .to_vec() - { - let mut data = ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION.decode_input(data)?; - - assert_eq!( - data.len(), - 2, - "The second method is expected to accept exactly 2 arguments" - ); - - // The second item must be a tuple of diamond cut data - // Unwraps are safe, because we validate the input against the function signature. - data.pop().unwrap().into_tuple().unwrap() - } else { - anyhow::bail!("unknown function"); - }; - - ProtocolUpgrade::try_from_init_calldata( - // Unwrap is safe because we have validated the input against the function signature. - &diamond_cut_tokens[2].clone().into_bytes().unwrap(), - ) - .context("ProtocolUpgrade::try_from_init_calldata()") - } -} - impl TryFrom for GovernanceOperation { type Error = crate::ethabi::Error; diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index 643aa56a1f1..28d8def5927 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -6,7 +6,8 @@ use zksync_system_constants::{ BOOTLOADER_UTILITIES_ADDRESS, CODE_ORACLE_ADDRESS, COMPRESSOR_ADDRESS, CREATE2_FACTORY_ADDRESS, EVENT_WRITER_ADDRESS, EVM_GAS_MANAGER_ADDRESS, L2_ASSET_ROUTER_ADDRESS, L2_BRIDGEHUB_ADDRESS, L2_GENESIS_UPGRADE_ADDRESS, L2_MESSAGE_ROOT_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, - P256VERIFY_PRECOMPILE_ADDRESS, PUBDATA_CHUNK_PUBLISHER_ADDRESS, + L2_WRAPPED_BASE_TOKEN_IMPL, P256VERIFY_PRECOMPILE_ADDRESS, PUBDATA_CHUNK_PUBLISHER_ADDRESS, + SLOAD_CONTRACT_ADDRESS, }; use crate::{ @@ -26,7 +27,7 @@ use crate::{ pub const TX_NONCE_INCREMENT: U256 = U256([1, 0, 0, 0]); // 1 pub const DEPLOYMENT_NONCE_INCREMENT: U256 = U256([0, 0, 1, 0]); // 2^128 -static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 31] = [ +static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 33] = [ ( "", "AccountCodeStorage", @@ -182,29 +183,41 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 31] = [ ContractLanguage::Sol, ), ( - "../../../l1-contracts/artifacts-zk/contracts/bridgehub/", + "../../l1-contracts/zkout/", "Bridgehub", L2_BRIDGEHUB_ADDRESS, ContractLanguage::Sol, ), ( - "../../../l1-contracts/artifacts-zk/contracts/bridgehub/", + "../../l1-contracts/zkout/", "MessageRoot", L2_MESSAGE_ROOT_ADDRESS, ContractLanguage::Sol, ), ( - "../../../l1-contracts/artifacts-zk/contracts/bridge/asset-router/", + "../../l1-contracts/zkout/", "L2AssetRouter", L2_ASSET_ROUTER_ADDRESS, ContractLanguage::Sol, ), ( - "../../../l1-contracts/artifacts-zk/contracts/bridge/ntv/", + "../../l1-contracts/zkout/", "L2NativeTokenVault", L2_NATIVE_TOKEN_VAULT_ADDRESS, ContractLanguage::Sol, ), + ( + "", + "SloadContract", + SLOAD_CONTRACT_ADDRESS, + ContractLanguage::Sol, + ), + ( + "../../l1-contracts/zkout/", + "L2WrappedBaseToken", + L2_WRAPPED_BASE_TOKEN_IMPL, + ContractLanguage::Sol, + ), ]; /// Gets default set of system contracts, based on Cargo workspace location. diff --git a/core/lib/vm_executor/src/batch/factory.rs b/core/lib/vm_executor/src/batch/factory.rs index 124194f3431..d7e14b918cc 100644 --- a/core/lib/vm_executor/src/batch/factory.rs +++ b/core/lib/vm_executor/src/batch/factory.rs @@ -238,6 +238,7 @@ impl BatchVm { .expect("failed extracting call traces") .take() .unwrap_or_default(); + BatchTransactionExecutionResult { tx_result: Box::new(tx_result), compressed_bytecodes, diff --git a/core/lib/vm_executor/src/storage.rs b/core/lib/vm_executor/src/storage.rs index e5a2d404233..2be2ad67974 100644 --- a/core/lib/vm_executor/src/storage.rs +++ b/core/lib/vm_executor/src/storage.rs @@ -3,7 +3,7 @@ use std::time::{Duration, Instant}; use anyhow::Context; -use zksync_contracts::BaseSystemContracts; +use zksync_contracts::{BaseSystemContracts, SystemContractCode}; use zksync_dal::{Connection, Core, CoreDal, DalError}; use zksync_multivm::interface::{L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode}; use zksync_types::{ @@ -11,6 +11,7 @@ use zksync_types::{ snapshots::SnapshotRecoveryStatus, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersionId, H256, ZKPORTER_IS_AVAILABLE, }; +use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words}; const BATCH_COMPUTATIONAL_GAS_LIMIT: u32 = u32::MAX; @@ -308,15 +309,15 @@ impl L1BatchParamsProvider { ); let contract_hashes = first_l2_block_in_batch.header.base_system_contracts_hashes; - let base_system_contracts = storage - .factory_deps_dal() - .get_base_system_contracts( - contract_hashes.bootloader, - contract_hashes.default_aa, - contract_hashes.evm_emulator, - ) - .await - .context("failed getting base system contracts")?; + let base_system_contracts = get_base_system_contracts( + storage, + first_l2_block_in_batch.header.protocol_version, + contract_hashes.bootloader, + contract_hashes.default_aa, + contract_hashes.evm_emulator, + ) + .await + .context("failed getting base system contracts")?; let (system_env, l1_batch_env) = l1_batch_params( first_l2_block_in_batch.l1_batch_number, @@ -373,3 +374,97 @@ impl L1BatchParamsProvider { .map(Some) } } + +async fn get_base_system_contracts( + storage: &mut Connection<'_, Core>, + protocol_version: Option, + bootloader_hash: H256, + default_aa_hash: H256, + evm_simulator_hash: Option, +) -> anyhow::Result { + // There are two potential sources of base contracts bytecode: + // - Factory deps table in case the upgrade transaction has been executed before. + // - Factory deps of the upgrade transaction. + + // Firstly trying from factory deps + if let Some(deps) = storage + .factory_deps_dal() + .get_base_system_contracts_from_factory_deps( + bootloader_hash, + default_aa_hash, + evm_simulator_hash, + ) + .await? + { + return Ok(deps); + } + + let error_msg = format!("Could not find either of the following factoey deps: bootloader {bootloader_hash:?} or {default_aa_hash:?}"); + + let protocol_version = protocol_version.context("Protocol version not provided")?; + + let upgrade_tx = storage + .protocol_versions_dal() + .get_protocol_upgrade_tx(protocol_version) + .await? + .context(error_msg.clone())?; + + anyhow::ensure!( + upgrade_tx.execute.factory_deps.len() >= 2, + "Upgrade transaction does not have enough factory deps" + ); + + let bootloader_preimage = upgrade_tx.execute.factory_deps[0].clone(); + let default_aa_preimage = upgrade_tx.execute.factory_deps[1].clone(); + + anyhow::ensure!( + hash_bytecode(&bootloader_preimage) == bootloader_hash, + "Bootloader hash mismatch" + ); + anyhow::ensure!( + hash_bytecode(&default_aa_preimage) == default_aa_hash, + "Default account hash mismatch" + ); + + if evm_simulator_hash.is_some() { + // For now, it is not yet decided whether Gateway upgrade will happen before + // or after the EVM equivalence upgrade. + panic!("EVM simulator not supported as part of gateway upgrade"); + } + + Ok(BaseSystemContracts { + bootloader: SystemContractCode { + code: bytes_to_be_words(bootloader_preimage), + hash: bootloader_hash, + }, + default_aa: SystemContractCode { + code: bytes_to_be_words(default_aa_preimage), + hash: default_aa_hash, + }, + evm_emulator: None, + }) +} + +pub async fn get_base_system_contracts_hashes_by_version_id( + storage: &mut Connection<'_, Core>, + version_id: u16, +) -> anyhow::Result> { + let hashes = storage + .protocol_versions_dal() + .get_base_system_contract_hashes_by_version_id(version_id) + .await?; + let Some(hashes) = hashes else { + return Ok(None); + }; + + Ok(Some( + get_base_system_contracts( + storage, + Some(ProtocolVersionId::try_from(version_id).unwrap()), + hashes.bootloader, + hashes.default_aa, + hashes.evm_emulator, + ) + .await?, + )) +} diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 75cc1ad602f..ae0808877c3 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -10,7 +10,9 @@ use zksync_dal::{ }; use zksync_multivm::{ interface::{OneshotTracingParams, TransactionExecutionMetrics, VmExecutionResultAndLogs}, - utils::{derive_base_fee_and_gas_per_pubdata, get_max_batch_gas_limit}, + utils::{ + derive_base_fee_and_gas_per_pubdata, get_max_batch_gas_limit, get_max_new_factory_deps, + }, }; use zksync_node_fee_model::{ApiFeeInputProvider, BatchFeeModelInputProvider}; use zksync_state::PostgresStorageCaches; @@ -26,8 +28,7 @@ use zksync_types::{ transaction_request::CallOverrides, utils::storage_key_for_eth_balance, vm::FastVmMode, - AccountTreeId, Address, L2ChainId, Nonce, ProtocolVersionId, Transaction, H160, H256, - MAX_NEW_FACTORY_DEPS, U256, + AccountTreeId, Address, L2ChainId, Nonce, ProtocolVersionId, Transaction, H160, H256, U256, }; use zksync_utils::h256_to_u256; use zksync_vm_executor::oneshot::{ @@ -457,10 +458,11 @@ impl TxSender { ); return Err(SubmitTxError::MaxPriorityFeeGreaterThanMaxFee); } - if tx.execute.factory_deps.len() > MAX_NEW_FACTORY_DEPS { + let max_new_fatory_deps = get_max_new_factory_deps(protocol_version.into()); + if tx.execute.factory_deps.len() > max_new_fatory_deps { return Err(SubmitTxError::TooManyFactoryDependencies( tx.execute.factory_deps.len(), - MAX_NEW_FACTORY_DEPS, + max_new_fatory_deps, )); } diff --git a/core/node/api_server/src/web3/namespaces/en.rs b/core/node/api_server/src/web3/namespaces/en.rs index a09a0cb92fc..89a7693d63f 100644 --- a/core/node/api_server/src/web3/namespaces/en.rs +++ b/core/node/api_server/src/web3/namespaces/en.rs @@ -164,6 +164,7 @@ impl EnNamespace { .api_config .transparent_proxy_admin_addr .unwrap(), + l1_bytecodes_supplier_addr: self.state.api_config.l1_bytecodes_supplier_addr, }) .context("Shared bridge doesn't supported")?) } diff --git a/core/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index 252519d704e..99e95239e55 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -112,6 +112,7 @@ pub struct InternalApiConfig { pub bridgehub_proxy_addr: Option
, pub state_transition_proxy_addr: Option
, pub transparent_proxy_admin_addr: Option
, + pub l1_bytecodes_supplier_addr: Option
, pub user_facing_diamond_proxy_addr: Address, pub l2_testnet_paymaster_addr: Option
, pub req_entities_limit: usize, @@ -176,6 +177,10 @@ impl InternalApiConfig { .ecosystem_contracts .as_ref() .map(|a| a.transparent_proxy_admin_addr), + l1_bytecodes_supplier_addr: contracts_config + .ecosystem_contracts + .as_ref() + .and_then(|a| a.l1_bytecodes_supplier_addr), user_facing_diamond_proxy_addr: contracts_config .user_facing_diamond_proxy_addr .unwrap_or(contracts_config.diamond_proxy_addr), diff --git a/core/node/consensus/src/registry/abi.rs b/core/node/consensus/src/registry/abi.rs index 57c65b10ce5..d9e2996effe 100644 --- a/core/node/consensus/src/registry/abi.rs +++ b/core/node/consensus/src/registry/abi.rs @@ -20,7 +20,7 @@ impl AsRef for ConsensusRegistry { impl ConsensusRegistry { const FILE: &'static str = - "contracts/l2-contracts/artifacts-zk/contracts/ConsensusRegistry.sol/ConsensusRegistry.json"; + "contracts/l2-contracts/zkout/ConsensusRegistry.sol/ConsensusRegistry.json"; /// Loads bytecode of the contract. #[cfg(test)] diff --git a/core/node/eth_watch/Cargo.toml b/core/node/eth_watch/Cargo.toml index 62014f92f27..3446b9153c3 100644 --- a/core/node/eth_watch/Cargo.toml +++ b/core/node/eth_watch/Cargo.toml @@ -19,6 +19,7 @@ zksync_system_constants.workspace = true zksync_eth_client.workspace = true zksync_shared_metrics.workspace = true zksync_mini_merkle_tree.workspace = true +zksync_config.workspace = true zksync_utils.workspace = true zksync_web3_decl.workspace = true diff --git a/core/node/eth_watch/src/client.rs b/core/node/eth_watch/src/client.rs index 65f805f3cf4..46bfb95b78d 100644 --- a/core/node/eth_watch/src/client.rs +++ b/core/node/eth_watch/src/client.rs @@ -1,8 +1,9 @@ -use std::{fmt, sync::Arc}; +use std::{collections::HashMap, fmt, sync::Arc}; use anyhow::Context; use zksync_contracts::{ - getters_facet_contract, l2_message_root, state_transition_manager_contract, verifier_contract, + bytecode_supplier_contract, getters_facet_contract, l2_message_root, + state_transition_manager_contract, verifier_contract, }; use zksync_eth_client::{ clients::{DynClient, L1}, @@ -12,9 +13,11 @@ use zksync_eth_client::{ use zksync_system_constants::L2_MESSAGE_ROOT_ADDRESS; use zksync_types::{ api::{ChainAggProof, Log}, - ethabi::Contract, - web3::{BlockId, BlockNumber, Filter, FilterBuilder}, - Address, L1BatchNumber, L2ChainId, SLChainId, H256, U256, U64, + ethabi::{decode, Contract, ParamType}, + tokens::TokenMetadata, + web3::{BlockId, BlockNumber, CallRequest, Filter, FilterBuilder}, + Address, L1BatchNumber, L2ChainId, SLChainId, H256, SHARED_BRIDGE_ETHER_TOKEN_ADDRESS, U256, + U64, }; use zksync_web3_decl::{ client::{Network, L2}, @@ -50,6 +53,13 @@ pub trait EthClient: 'static + fmt::Debug + Send + Sync { packed_version: H256, ) -> EnrichedClientResult>>; + async fn get_published_preimages( + &self, + hashes: Vec, + ) -> EnrichedClientResult>>>; + + async fn get_base_token_metadata(&self) -> Result; + /// Returns ID of the chain. async fn chain_id(&self) -> EnrichedClientResult; @@ -63,6 +73,8 @@ pub trait EthClient: 'static + fmt::Debug + Send + Sync { ) -> Result; } +// This constant is used for reading auxilary events +const LOOK_BACK_BLOCK_RANGE: u64 = 1_000_000; pub const RETRY_LIMIT: usize = 5; const TOO_MANY_RESULTS_INFURA: &str = "query returned more than"; const TOO_MANY_RESULTS_ALCHEMY: &str = "response size exceeded"; @@ -77,6 +89,8 @@ pub struct EthHttpQueryClient { diamond_proxy_addr: Address, governance_address: Address, new_upgrade_cut_data_signature: H256, + bytecode_published_signature: H256, + bytecode_supplier_addr: Option
, // Only present for post-shared bridge chains. state_transition_manager_address: Option
, chain_admin_address: Option
, @@ -93,6 +107,7 @@ where pub fn new( client: Box>, diamond_proxy_addr: Address, + bytecode_supplier_addr: Option
, state_transition_manager_address: Option
, chain_admin_address: Option
, governance_address: Address, @@ -109,11 +124,17 @@ where state_transition_manager_address, chain_admin_address, governance_address, + bytecode_supplier_addr, new_upgrade_cut_data_signature: state_transition_manager_contract() .event("NewUpgradeCutData") .context("NewUpgradeCutData event is missing in ABI") .unwrap() .signature(), + bytecode_published_signature: bytecode_supplier_contract() + .event("BytecodePublished") + .context("BytecodePublished event is missing in ABI") + .unwrap() + .signature(), verifier_contract_abi: verifier_contract(), getters_facet_contract_abi: getters_facet_contract(), message_root_abi: l2_message_root(), @@ -261,8 +282,6 @@ where &self, packed_version: H256, ) -> EnrichedClientResult>> { - const LOOK_BACK_BLOCK_RANGE: u64 = 1_000_000; - let Some(state_transition_manager_address) = self.state_transition_manager_address else { return Ok(None); }; @@ -284,6 +303,43 @@ where Ok(logs.into_iter().next().map(|log| log.data.0)) } + async fn get_published_preimages( + &self, + hashes: Vec, + ) -> EnrichedClientResult>>> { + let Some(bytecode_supplier_addr) = self.bytecode_supplier_addr else { + return Ok(vec![None; hashes.len()]); + }; + + let to_block = self.client.block_number().await?; + let from_block = to_block.saturating_sub((LOOK_BACK_BLOCK_RANGE - 1).into()); + + let logs = self + .get_events_inner( + from_block.into(), + to_block.into(), + Some(vec![self.bytecode_published_signature]), + Some(hashes.clone()), + Some(vec![bytecode_supplier_addr]), + RETRY_LIMIT, + ) + .await?; + + let mut preimages = HashMap::new(); + for log in logs { + let hash = log.topics[1]; + let preimage = decode(&[ParamType::Bytes], &log.data.0).expect("Invalid encoding"); + assert_eq!(preimage.len(), 1); + let preimage = preimage[0].clone().into_bytes().unwrap(); + preimages.insert(hash, preimage); + } + + Ok(hashes + .into_iter() + .map(|hash| preimages.get(&hash).cloned()) + .collect()) + } + async fn get_events( &self, from: BlockNumber, @@ -351,6 +407,53 @@ where .call(&self.client) .await } + + async fn get_base_token_metadata(&self) -> Result { + let base_token_addr = CallFunctionArgs::new("getBaseToken", ()) + .for_contract(self.diamond_proxy_addr, &self.getters_facet_contract_abi) + .call(&self.client) + .await + .map(|x: Address| x)?; + + if base_token_addr == SHARED_BRIDGE_ETHER_TOKEN_ADDRESS { + return Ok(TokenMetadata { + name: String::from("Ether"), + symbol: String::from("ETH"), + decimals: 18, + }); + } + + let selectors: [[u8; 4]; 3] = [ + zksync_types::ethabi::short_signature("name", &[]), + zksync_types::ethabi::short_signature("symbol", &[]), + zksync_types::ethabi::short_signature("decimals", &[]), + ]; + let types: [ParamType; 3] = [ParamType::String, ParamType::String, ParamType::Uint(32)]; + + let mut decoded_result = vec![]; + for (selector, param_type) in selectors.into_iter().zip(types.into_iter()) { + let request = CallRequest { + to: Some(base_token_addr), + data: Some(selector.into()), + ..Default::default() + }; + let result = self.client.call_contract_function(request, None).await?; + // Base tokens are expected to support erc20 metadata + let mut token = zksync_types::ethabi::decode(&[param_type], &result.0) + .expect("base token does not support erc20 metadata"); + decoded_result.push(token.pop().unwrap()); + } + + Ok(TokenMetadata { + name: decoded_result[0].to_string(), + symbol: decoded_result[1].to_string(), + decimals: decoded_result[2] + .clone() + .into_uint() + .expect("decimals not supported") + .as_u32() as u8, + }) + } } /// Encapsulates `eth_getLogs` calls. @@ -490,4 +593,15 @@ impl EthClient for L2EthClientW { ) -> Result { self.0.get_chain_root(block_number, l2_chain_id).await } + + async fn get_base_token_metadata(&self) -> Result { + self.0.get_base_token_metadata().await + } + + async fn get_published_preimages( + &self, + hashes: Vec, + ) -> EnrichedClientResult>>> { + self.0.get_published_preimages(hashes).await + } } diff --git a/core/node/eth_watch/src/event_processors/decentralized_upgrades.rs b/core/node/eth_watch/src/event_processors/decentralized_upgrades.rs index 3f4b0f3cf5a..64fa15cd705 100644 --- a/core/node/eth_watch/src/event_processors/decentralized_upgrades.rs +++ b/core/node/eth_watch/src/event_processors/decentralized_upgrades.rs @@ -3,8 +3,9 @@ use std::sync::Arc; use anyhow::Context as _; use zksync_dal::{eth_watcher_dal::EventType, Connection, Core, CoreDal, DalError}; use zksync_types::{ - api::Log, ethabi::Contract, protocol_version::ProtocolSemanticVersion, ProtocolUpgrade, H256, - U256, + abi::ZkChainSpecificUpgradeData, api::Log, ethabi::Contract, + protocol_upgrade::ProtocolUpgradePreimageOracle, protocol_version::ProtocolSemanticVersion, + ProtocolUpgrade, H256, U256, }; use crate::{ @@ -19,14 +20,18 @@ pub struct DecentralizedUpgradesEventProcessor { /// Last protocol version seen. Used to skip events for already known upgrade proposals. last_seen_protocol_version: ProtocolSemanticVersion, update_upgrade_timestamp_signature: H256, + chain_specific_data: Option, sl_client: Arc, + l1_client: Arc, } impl DecentralizedUpgradesEventProcessor { pub fn new( last_seen_protocol_version: ProtocolSemanticVersion, chain_admin_contract: &Contract, + chain_specific_data: Option, sl_client: Arc, + l1_client: Arc, ) -> Self { Self { last_seen_protocol_version, @@ -35,11 +40,33 @@ impl DecentralizedUpgradesEventProcessor { .context("UpdateUpgradeTimestamp event is missing in ABI") .unwrap() .signature(), + chain_specific_data, sl_client, + l1_client, } } } +#[async_trait::async_trait] +impl ProtocolUpgradePreimageOracle for &dyn EthClient { + async fn get_protocol_upgrade_preimages( + &self, + hashes: Vec, + ) -> anyhow::Result>> { + let preimages = self.get_published_preimages(hashes.clone()).await?; + + let mut result = vec![]; + for (i, preimage) in preimages.into_iter().enumerate() { + let preimage = preimage.with_context(|| { + format!("Protocol upgrade preimage for {:#?} is missing", hashes[i]) + })?; + result.push(preimage); + } + + Ok(result) + } +} + #[async_trait::async_trait] impl EventProcessor for DecentralizedUpgradesEventProcessor { async fn process_events( @@ -63,7 +90,12 @@ impl EventProcessor for DecentralizedUpgradesEventProcessor { let upgrade = ProtocolUpgrade { timestamp, - ..ProtocolUpgrade::try_from_diamond_cut(&diamond_cut)? + ..ProtocolUpgrade::try_from_diamond_cut( + &diamond_cut, + self.l1_client.as_ref(), + self.chain_specific_data.clone(), + ) + .await? }; // Scheduler VK is not present in proposal event. It is hard coded in verifier contract. let scheduler_vk_hash = if let Some(address) = upgrade.verifier_address { diff --git a/core/node/eth_watch/src/lib.rs b/core/node/eth_watch/src/lib.rs index 908ff4da37f..ff3aa44b7a9 100644 --- a/core/node/eth_watch/src/lib.rs +++ b/core/node/eth_watch/src/lib.rs @@ -6,12 +6,14 @@ use std::{sync::Arc, time::Duration}; use anyhow::Context as _; use tokio::sync::watch; +use zksync_config::ContractsConfig; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal, DalError}; use zksync_mini_merkle_tree::MiniMerkleTree; use zksync_system_constants::PRIORITY_EXPIRATION; use zksync_types::{ - ethabi::Contract, protocol_version::ProtocolSemanticVersion, - web3::BlockNumber as Web3BlockNumber, L1BatchNumber, L2ChainId, PriorityOpId, + abi::ZkChainSpecificUpgradeData, ethabi::Contract, protocol_version::ProtocolSemanticVersion, + tokens::TokenMetadata, web3::BlockNumber as Web3BlockNumber, L1BatchNumber, L2ChainId, + PriorityOpId, }; pub use self::client::{EthClient, EthHttpQueryClient, L2EthClient}; @@ -56,6 +58,7 @@ impl EthWatch { sl_l2_client: Option>, pool: ConnectionPool, poll_interval: Duration, + contracts_config: &ContractsConfig, chain_id: L2ChainId, ) -> anyhow::Result { let mut storage = pool.connection_tagged("eth_watch").await?; @@ -76,7 +79,9 @@ impl EthWatch { let decentralized_upgrades_processor = DecentralizedUpgradesEventProcessor::new( state.last_seen_protocol_version, chain_admin_contract, + get_chain_specific_upgrade_params(&l1_client, contracts_config).await?, sl_client.clone(), + l1_client.clone(), ); let mut event_processors: Vec> = vec![ Box::new(priority_ops_processor), @@ -241,3 +246,19 @@ impl EthWatch { Ok(()) } } + +async fn get_chain_specific_upgrade_params( + l1_client: &Arc, + contracts_config: &ContractsConfig, +) -> anyhow::Result> { + let TokenMetadata { name, symbol, .. } = l1_client.get_base_token_metadata().await?; + + Ok(ZkChainSpecificUpgradeData::from_partial_components( + contracts_config.base_token_asset_id, + contracts_config.l2_legacy_shared_bridge_addr, + contracts_config.predeployed_l2_wrapped_base_token_address, + contracts_config.base_token_addr, + Some(name), + Some(symbol), + )) +} diff --git a/core/node/eth_watch/src/tests/client.rs b/core/node/eth_watch/src/tests/client.rs index dbf9ca6f984..89912ce1ba8 100644 --- a/core/node/eth_watch/src/tests/client.rs +++ b/core/node/eth_watch/src/tests/client.rs @@ -6,12 +6,11 @@ use zksync_contracts::{ }; use zksync_eth_client::{ContractCallError, EnrichedClientResult}; use zksync_types::{ - abi, - abi::ProposedUpgrade, + abi::{self, ProposedUpgrade}, api::{ChainAggProof, Log}, - ethabi, - ethabi::Token, + ethabi::{self, Token}, l1::L1Tx, + tokens::TokenMetadata, web3::{contract::Tokenizable, BlockNumber}, Address, L1BatchNumber, L2ChainId, ProtocolUpgrade, SLChainId, Transaction, H256, U256, U64, }; @@ -272,6 +271,21 @@ impl EthClient for MockEthClient { ) -> Result { unimplemented!() } + + async fn get_published_preimages( + &self, + hashes: Vec, + ) -> EnrichedClientResult>>> { + Ok(vec![]) + } + + async fn get_base_token_metadata(&self) -> Result { + Ok(TokenMetadata { + name: "ETH".to_string(), + symbol: "Ether".to_string(), + decimals: 18, + }) + } } #[async_trait::async_trait] @@ -428,9 +442,7 @@ fn upgrade_timestamp_log(eth_block: u64) -> Log { } fn upgrade_into_diamond_cut(upgrade: ProtocolUpgrade) -> Token { - let abi::Transaction::L1 { - tx, factory_deps, .. - } = upgrade + let abi::Transaction::L1 { tx, .. } = upgrade .tx .map(|tx| Transaction::from(tx).try_into().unwrap()) .unwrap_or(abi::Transaction::L1 { @@ -443,7 +455,6 @@ fn upgrade_into_diamond_cut(upgrade: ProtocolUpgrade) -> Token { }; ProposedUpgrade { l2_protocol_upgrade_tx: tx, - factory_deps, bootloader_hash: upgrade.bootloader_code_hash.unwrap_or_default().into(), default_account_hash: upgrade.default_account_code_hash.unwrap_or_default().into(), verifier: upgrade.verifier_address.unwrap_or_default(), diff --git a/core/node/eth_watch/src/tests/mod.rs b/core/node/eth_watch/src/tests/mod.rs index 786c8577a2e..aced9129eb3 100644 --- a/core/node/eth_watch/src/tests/mod.rs +++ b/core/node/eth_watch/src/tests/mod.rs @@ -1,5 +1,6 @@ use std::convert::TryInto; +use zksync_config::ContractsConfig; use zksync_contracts::chain_admin_contract; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_types::{ @@ -104,6 +105,7 @@ async fn create_test_watcher( sl_l2_client, connection_pool, std::time::Duration::from_nanos(1), + &ContractsConfig::for_tests(), L2ChainId::default(), ) .await @@ -210,6 +212,7 @@ async fn test_normal_operation_upgrade_timestamp() { None, connection_pool.clone(), std::time::Duration::from_nanos(1), + &ContractsConfig::for_tests(), L2ChainId::default(), ) .await diff --git a/core/node/node_framework/src/implementations/layers/eth_watch.rs b/core/node/node_framework/src/implementations/layers/eth_watch.rs index 97c054b7fe6..ff5a574fd53 100644 --- a/core/node/node_framework/src/implementations/layers/eth_watch.rs +++ b/core/node/node_framework/src/implementations/layers/eth_watch.rs @@ -1,7 +1,13 @@ +use futures::TryFutureExt; use zksync_config::{configs::gateway::GatewayChainConfig, ContractsConfig, EthWatchConfig}; use zksync_contracts::chain_admin_contract; +use zksync_eth_client::EthInterface; use zksync_eth_watch::{EthHttpQueryClient, EthWatch, L2EthClient}; -use zksync_types::{settlement::SettlementMode, L2ChainId}; +use zksync_types::{ + abi::ZkChainSpecificUpgradeData, ethabi::ParamType, settlement::SettlementMode, + web3::CallRequest, Address, L2ChainId, SHARED_BRIDGE_ETHER_TOKEN_ADDRESS, +}; +use zksync_web3_decl::client::{DynClient, L1}; use crate::{ implementations::resources::{ @@ -72,6 +78,7 @@ impl WiringLayer for EthWatchLayer { async fn wire(self, input: Self::Input) -> Result { let main_pool = input.master_pool.get().await?; let client = input.eth_client.0; + let sl_diamond_proxy_addr = if self.settlement_mode.is_gateway() { self.gateway_contracts_config .clone() @@ -94,6 +101,11 @@ impl WiringLayer for EthWatchLayer { self.contracts_config.diamond_proxy_addr, self.contracts_config .ecosystem_contracts + .as_ref() + .and_then(|a| a.l1_bytecodes_supplier_addr), + self.contracts_config + .ecosystem_contracts + .as_ref() .map(|a| a.state_transition_proxy_addr), self.contracts_config.chain_admin_addr, self.contracts_config.governance_addr, @@ -106,6 +118,7 @@ impl WiringLayer for EthWatchLayer { Some(Box::new(EthHttpQueryClient::new( gateway_client, contracts_config.diamond_proxy_addr, + None, Some(contracts_config.state_transition_proxy_addr), contracts_config.chain_admin_addr, contracts_config.governance_addr, @@ -121,6 +134,7 @@ impl WiringLayer for EthWatchLayer { sl_l2_client, main_pool, self.eth_watch_config.poll_interval(), + &self.contracts_config, self.chain_id, ) .await?; diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index dfddd36aba7..8ec4753c4bd 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -22,7 +22,9 @@ use zksync_types::{ }; // TODO (SMA-1206): use seconds instead of milliseconds. use zksync_utils::time::millis_since_epoch; -use zksync_vm_executor::storage::L1BatchParamsProvider; +use zksync_vm_executor::storage::{ + get_base_system_contracts_hashes_by_version_id, L1BatchParamsProvider, +}; use crate::{ io::{ @@ -349,18 +351,15 @@ impl StateKeeperIO for MempoolIO { protocol_version: ProtocolVersionId, _cursor: &IoCursor, ) -> anyhow::Result { - self.pool - .connection_tagged("state_keeper") - .await? - .protocol_versions_dal() - .load_base_system_contracts_by_version_id(protocol_version as u16) - .await - .context("failed loading base system contracts")? - .with_context(|| { - format!( - "no base system contracts persisted for protocol version {protocol_version:?}" - ) - }) + get_base_system_contracts_hashes_by_version_id( + &mut self.pool.connection_tagged("state_keeper").await?, + protocol_version as u16, + ) + .await + .context("failed loading base system contracts")? + .with_context(|| { + format!("no base system contracts persisted for protocol version {protocol_version:?}") + }) } async fn load_batch_version_id( diff --git a/core/tests/ts-integration/tests/l2-erc20.test.ts b/core/tests/ts-integration/tests/l2-erc20.test.ts index f1c89b1c05f..8cef2340314 100644 --- a/core/tests/ts-integration/tests/l2-erc20.test.ts +++ b/core/tests/ts-integration/tests/l2-erc20.test.ts @@ -35,11 +35,11 @@ describe('L2 native ERC20 contract checks', () => { l2Wallet = new Wallet(alice.privateKey, l2Provider); l1Wallet = new Wallet(alice.privateKey, l1Provider); const L2_NATIVE_TOKEN_VAULT_ADDRESS = '0x0000000000000000000000000000000000010004'; - const ARTIFACTS_PATH = '../../../contracts/l1-contracts/artifacts/contracts/'; - const l2NtvInterface = readContract(`${ARTIFACTS_PATH}/bridge/ntv`, 'L2NativeTokenVault').abi; + const ARTIFACTS_PATH = '../../../contracts/l1-contracts/out'; + const l2NtvInterface = readContract(`${ARTIFACTS_PATH}`, 'L2NativeTokenVault').abi; const l2NativeTokenVault = new ethers.Contract(L2_NATIVE_TOKEN_VAULT_ADDRESS, l2NtvInterface, l2Wallet); - const l1AssetRouterInterface = readContract(`${ARTIFACTS_PATH}/bridge/asset-router`, 'L1AssetRouter').abi; - const l1NativeTokenVaultInterface = readContract(`${ARTIFACTS_PATH}/bridge/ntv`, 'L1NativeTokenVault').abi; + const l1AssetRouterInterface = readContract(`${ARTIFACTS_PATH}`, 'L1AssetRouter').abi; + const l1NativeTokenVaultInterface = readContract(`${ARTIFACTS_PATH}`, 'L1NativeTokenVault').abi; const l1AssetRouter = new ethers.Contract(await assetRouter.getAddress(), l1AssetRouterInterface, l1Wallet); l1NativeTokenVault = new ethers.Contract( await l1AssetRouter.nativeTokenVault(), @@ -51,10 +51,7 @@ describe('L2 native ERC20 contract checks', () => { baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; - const ZkSyncERC20 = await readContract( - '../../../contracts/l1-contracts/artifacts-zk/contracts/dev-contracts', - 'TestnetERC20Token' - ); + const ZkSyncERC20 = await readContract('../../../contracts/l1-contracts/zkout', 'TestnetERC20Token'); aliceErc20 = await deployContract(alice, ZkSyncERC20, ['ZKsync', 'ZK', 18]); const l2TokenAddress = await aliceErc20.getAddress(); diff --git a/core/tests/ts-integration/tests/system.test.ts b/core/tests/ts-integration/tests/system.test.ts index b1508cccfaf..0ea769b1012 100644 --- a/core/tests/ts-integration/tests/system.test.ts +++ b/core/tests/ts-integration/tests/system.test.ts @@ -378,7 +378,7 @@ describe('System behavior checks', () => { const BOOTLOADER_UTILS = new ethers.Interface( require(`${ testMaster.environment().pathToHome - }/contracts/system-contracts/artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json`).abi + }/contracts/system-contracts/zkout/BootloaderUtilities.sol/BootloaderUtilities.json`).abi ); return new ethers.Contract(BOOTLOADER_UTILS_ADDRESS, BOOTLOADER_UTILS, alice); diff --git a/core/tests/upgrade-test/tests/utils.ts b/core/tests/upgrade-test/tests/utils.ts index 2972f8411f5..93f5b9bb1ee 100644 --- a/core/tests/upgrade-test/tests/utils.ts +++ b/core/tests/upgrade-test/tests/utils.ts @@ -116,14 +116,13 @@ export function initContracts(pathToHome: string, zkStack: boolean): Contracts { require(`${L1_CONTRACTS_FOLDER}/governance/ChainAdmin.sol/ChainAdmin.json`).abi ), l2ForceDeployUpgraderAbi: new ethers.Interface( - require(`${pathToHome}/contracts/l2-contracts/artifacts-zk/contracts/ForceDeployUpgrader.sol/ForceDeployUpgrader.json`).abi + require(`${pathToHome}/contracts/l2-contracts/zkout/ForceDeployUpgrader.sol/ForceDeployUpgrader.json`).abi ), complexUpgraderAbi: new ethers.Interface( - require(`${pathToHome}/contracts/system-contracts/artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json`).abi + require(`${pathToHome}/contracts/system-contracts/zkout/ComplexUpgrader.sol/ComplexUpgrader.json`).abi ), - counterBytecode: - require(`${pathToHome}/core/tests/ts-integration/artifacts-zk/contracts/counter/counter.sol/Counter.json`) - .deployedBytecode, + counterBytecode: require(`${pathToHome}/core/tests/ts-integration/zkout/counter.sol/Counter.json`) + .deployedBytecode, stateTransitonManager: new ethers.Interface( require(`${L1_CONTRACTS_FOLDER}/state-transition/StateTransitionManager.sol/StateTransitionManager.json`).abi ) diff --git a/etc/env/file_based/genesis.yaml b/etc/env/file_based/genesis.yaml index 212c17c2bf4..30fbe68766a 100644 --- a/etc/env/file_based/genesis.yaml +++ b/etc/env/file_based/genesis.yaml @@ -1,8 +1,9 @@ -genesis_root: 0x526a5d3e384ff95a976283c79a976e0a2fb749e4631233f29d3765201efd937d -genesis_batch_commitment: 0xb9794246425fd654cf6a4c2e9adfdd48aaaf97bf3b8ba6bdc88e1d141bcfa5b3 -genesis_rollup_leaf_index: 64 -default_aa_hash: 0x0100055d3993e14104994ca4d8cfa91beb9b544ee86894b45708b4824d832ff2 -bootloader_hash: 0x010008c753336bc8d1ddca235602b9f31d346412b2d463cd342899f7bfb73baf +genesis_root: 0x7317a25f528d9922db110ddab8c88b275ccfe6a7bc94e9da265ff905bb9d3471 +genesis_rollup_leaf_index: 68 +genesis_batch_commitment: 0xfdace4ecadb2286204ba1d52592ac82d2fac0cae02f2490930bc9dd4945af254 +genesis_protocol_version: 25 +default_aa_hash: 0x01000523dc43ef12a998843b5c95cefd77288333888bf3a5e7fc729b7e12b536 +bootloader_hash: 0x010008e5c007f9cf449b3cb3cac0fd49806aa98540d0b123f4cc75501f0682a4 l1_chain_id: 9 l2_chain_id: 270 fee_account: '0x0000000000000000000000000000000000000001' diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 46feff624f1..a65c2a047f6 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -8591,6 +8591,7 @@ name = "zksync_types" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "bigdecimal", "blake2 0.10.6", "chrono", diff --git a/yarn.lock b/yarn.lock index f6ccd261ef1..2929cfb4676 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11338,6 +11338,10 @@ yocto-queue@^1.0.0: version "6.12.1" resolved "https://github.com/zksync-sdk/zksync-ethers#aa834387686ff8c04e41d1675b98f91d6c01847b" +"zksync-ethers-gw@https://github.com/zksync-sdk/zksync-ethers#kl/gateway-support": + version "6.12.1" + resolved "https://github.com/zksync-sdk/zksync-ethers#aa834387686ff8c04e41d1675b98f91d6c01847b" + zksync-ethers@5.8.0-beta.5: version "5.8.0-beta.5" resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-5.8.0-beta.5.tgz#4f70193a86bd1e41b25b0aa5aa32f6d41d52f7c6" diff --git a/zkstack_cli/Cargo.lock b/zkstack_cli/Cargo.lock index 1427939f4ef..c74e01a0ae1 100644 --- a/zkstack_cli/Cargo.lock +++ b/zkstack_cli/Cargo.lock @@ -7165,6 +7165,7 @@ dependencies = [ "zksync_consensus_crypto", "zksync_consensus_roles", "zksync_consensus_utils", + "zksync_eth_client", "zksync_protobuf", "zksync_protobuf_build", "zksync_protobuf_config", @@ -7315,6 +7316,34 @@ dependencies = [ "zksync_utils", ] +[[package]] +name = "zksync_eth_client" +version = "0.1.0" +dependencies = [ + "async-trait", + "jsonrpsee", + "rlp", + "thiserror", + "tracing", + "vise", + "zksync_config", + "zksync_contracts", + "zksync_eth_signer", + "zksync_types", + "zksync_web3_decl", +] + +[[package]] +name = "zksync_eth_signer" +version = "0.1.0" +dependencies = [ + "async-trait", + "rlp", + "thiserror", + "zksync_basic_types", + "zksync_crypto_primitives", +] + [[package]] name = "zksync_mini_merkle_tree" version = "0.1.0" @@ -7397,6 +7426,7 @@ name = "zksync_types" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "bigdecimal", "blake2", "chrono", diff --git a/zkstack_cli/Cargo.toml b/zkstack_cli/Cargo.toml index b89ef9e62b3..5101dbccbed 100644 --- a/zkstack_cli/Cargo.toml +++ b/zkstack_cli/Cargo.toml @@ -39,6 +39,7 @@ zksync_protobuf = "=0.5.0" zksync_protobuf_build = "=0.5.0" zksync_types = { path = "../core/lib/types" } zksync_web3_decl = { path = "../core/lib/web3_decl" } +zksync_eth_client = { path = "../core/lib/eth_client" } # External dependencies anyhow = "1.0.82" diff --git a/zkstack_cli/crates/common/src/contracts.rs b/zkstack_cli/crates/common/src/contracts.rs index 0f771bb9dad..ff93ed4dd0f 100644 --- a/zkstack_cli/crates/common/src/contracts.rs +++ b/zkstack_cli/crates/common/src/contracts.rs @@ -12,7 +12,7 @@ pub fn build_test_contracts(shell: Shell, link_to_code: PathBuf) -> anyhow::Resu pub fn build_l1_contracts(shell: Shell, link_to_code: PathBuf) -> anyhow::Result<()> { let _dir_guard = shell.push_dir(link_to_code.join("contracts/l1-contracts")); - Ok(Cmd::new(cmd!(shell, "yarn build")).run()?) + Ok(Cmd::new(cmd!(shell, "yarn build:foundry")).run()?) } pub fn build_l1_da_contracts(shell: Shell, link_to_code: PathBuf) -> anyhow::Result<()> { @@ -27,7 +27,7 @@ pub fn build_l2_contracts(shell: Shell, link_to_code: PathBuf) -> anyhow::Result // "forge build --zksync --zk-enable-eravm-extensions" // )) // .run()?) - Cmd::new(cmd!(shell, "yarn build")).run()?; + Cmd::new(cmd!(shell, "yarn build:foundry")).run()?; Ok(()) } @@ -35,18 +35,5 @@ pub fn build_system_contracts(shell: Shell, link_to_code: PathBuf) -> anyhow::Re let _dir_guard = shell.push_dir(link_to_code.join("contracts/system-contracts")); // Do not update era-contract's lockfile to avoid dirty submodule Cmd::new(cmd!(shell, "yarn install --frozen-lockfile")).run()?; - Cmd::new(cmd!(shell, "yarn build")).run()?; - Ok(()) - // Cmd::new(cmd!(shell, "yarn preprocess:system-contracts")).run()?; - // Cmd::new(cmd!( - // shell, - // "forge build --zksync --zk-enable-eravm-extensions" - // )) - // .run()?; - // Cmd::new(cmd!(shell, "yarn preprocess:bootloader")).run()?; - // Ok(Cmd::new(cmd!( - // shell, - // "forge build --zksync --zk-enable-eravm-extensions" - // )) - // .run()?) + Ok(Cmd::new(cmd!(shell, "yarn build:foundry")).run()?) } diff --git a/zkstack_cli/crates/common/src/hardhat.rs b/zkstack_cli/crates/common/src/hardhat.rs deleted file mode 100644 index e15e94be5ad..00000000000 --- a/zkstack_cli/crates/common/src/hardhat.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::path::Path; - -use xshell::{cmd, Shell}; - -use crate::cmd::Cmd; - -pub fn build_l2_contracts(shell: &Shell, link_to_code: &Path) -> anyhow::Result<()> { - let _dir_guard = shell.push_dir(link_to_code.join("contracts")); - Ok(Cmd::new(cmd!(shell, "yarn l2 build")).run()?) -} - -/// Builds L1 contracts using hardhat. This is a temporary measure, mainly needed to -/// compile the contracts with zksolc (for some reason doing it via foundry took too much time). -pub fn build_l1_contracts(shell: &Shell, link_to_code: &Path) -> anyhow::Result<()> { - let _dir_guard = shell.push_dir(link_to_code.join("contracts")); - Ok(Cmd::new(cmd!(shell, "yarn l1 build")).run()?) -} diff --git a/zkstack_cli/crates/common/src/lib.rs b/zkstack_cli/crates/common/src/lib.rs index 91804bfe070..ebf70d95f58 100644 --- a/zkstack_cli/crates/common/src/lib.rs +++ b/zkstack_cli/crates/common/src/lib.rs @@ -12,7 +12,6 @@ pub mod external_node; pub mod files; pub mod forge; pub mod git; -pub mod hardhat; pub mod server; pub mod version; pub mod wallets; diff --git a/zkstack_cli/crates/config/src/consts.rs b/zkstack_cli/crates/config/src/consts.rs index c4895b333c7..298a725fb1c 100644 --- a/zkstack_cli/crates/config/src/consts.rs +++ b/zkstack_cli/crates/config/src/consts.rs @@ -1,3 +1,6 @@ +use ethers::abi::Address; +use zksync_basic_types::U256; + /// Name of the main configuration file pub(crate) const CONFIG_NAME: &str = "ZkStack.yaml"; /// Name of the wallets file @@ -29,7 +32,7 @@ pub const ZKSYNC_ERA_GIT_REPO: &str = "https://github.com/matter-labs/zksync-era /// Name of the docker-compose file inside zksync repository pub const DOCKER_COMPOSE_FILE: &str = "docker-compose.yml"; /// Path to the config file with mnemonic for localhost wallets -pub(crate) const CONFIGS_PATH: &str = "etc/env/file_based"; +pub const CONFIGS_PATH: &str = "etc/env/file_based"; /// Path to the docker-compose file for grafana pub const ERA_OBSERVABILITY_COMPOSE_FILE: &str = "era-observability/docker-compose.yml"; /// Path to era observability repository @@ -84,3 +87,27 @@ pub(crate) const ERA_CHAIN_ID: u32 = 270; pub(crate) const TEST_CONFIG_PATH: &str = "etc/test_config/constant/eth.json"; pub(crate) const BASE_PATH: &str = "m/44'/60'/0'"; + +pub(crate) fn apply_l1_to_l2_alias(address: Address) -> Address { + let addr_as_u256 = address_to_u256(&address); + let offset = U256::from_str_radix("1111000000000000000000000000000000001111", 16).unwrap(); + + let addr_with_offset = addr_as_u256 + offset; + + u256_to_account_address(&addr_with_offset) +} + +/// Converts `U256` value into the Address +fn u256_to_account_address(value: &U256) -> Address { + let mut bytes = [0u8; 32]; + value.to_big_endian(&mut bytes); + + Address::from_slice(&bytes[12..]) +} + +fn address_to_u256(value: &Address) -> U256 { + let mut bytes = [0u8; 32]; + bytes[12..].copy_from_slice(value.as_bytes()); + + U256::from_big_endian(&bytes) +} diff --git a/zkstack_cli/crates/config/src/contracts.rs b/zkstack_cli/crates/config/src/contracts.rs index 0213636c437..b8d85523924 100644 --- a/zkstack_cli/crates/config/src/contracts.rs +++ b/zkstack_cli/crates/config/src/contracts.rs @@ -24,8 +24,10 @@ pub struct ContractsConfig { pub l1: L1Contracts, pub l2: L2Contracts, // TODO: maybe move these guys to L1 - pub user_facing_bridgehub: Address, - pub user_facing_diamond_proxy: Address, + // Option is to support legacy protocol versions + pub user_facing_bridgehub: Option
, + // Option is to support legacy protocol versions + pub user_facing_diamond_proxy: Option
, #[serde(flatten)] pub other: serde_json::Value, } @@ -42,10 +44,12 @@ impl ContractsConfig { .deployed_addresses .bridges .shared_bridge_proxy_addr; - self.bridges.l1_nullifier_addr = deploy_l1_output - .deployed_addresses - .bridges - .l1_nullifier_proxy_addr; + self.bridges.l1_nullifier_addr = Some( + deploy_l1_output + .deployed_addresses + .bridges + .l1_nullifier_proxy_addr, + ); self.ecosystem_contracts.bridgehub_proxy_addr = deploy_l1_output .deployed_addresses .bridgehub @@ -57,14 +61,26 @@ impl ContractsConfig { self.ecosystem_contracts.transparent_proxy_admin_addr = deploy_l1_output .deployed_addresses .transparent_proxy_admin_addr; - self.ecosystem_contracts.stm_deployment_tracker_proxy_addr = deploy_l1_output - .deployed_addresses - .bridgehub - .ctm_deployment_tracker_proxy_addr; - self.ecosystem_contracts.force_deployments_data = deploy_l1_output - .contracts_config - .force_deployments_data - .clone(); + self.ecosystem_contracts.l1_bytecodes_supplier_addr = Some( + deploy_l1_output + .deployed_addresses + .state_transition + .bytecodes_supplier_addr, + ); + self.ecosystem_contracts.stm_deployment_tracker_proxy_addr = Some( + deploy_l1_output + .deployed_addresses + .bridgehub + .ctm_deployment_tracker_proxy_addr, + ); + self.ecosystem_contracts.force_deployments_data = Some( + deploy_l1_output + .contracts_config + .force_deployments_data + .clone(), + ); + self.ecosystem_contracts.expected_rollup_l2_da_validator = + Some(deploy_l1_output.expected_rollup_l2_da_validator_addr); self.l1.default_upgrade_addr = deploy_l1_output .deployed_addresses .state_transition @@ -78,7 +94,7 @@ impl ContractsConfig { self.ecosystem_contracts.validator_timelock_addr = deploy_l1_output.deployed_addresses.validator_timelock_addr; self.ecosystem_contracts.native_token_vault_addr = - deploy_l1_output.deployed_addresses.native_token_vault_addr; + Some(deploy_l1_output.deployed_addresses.native_token_vault_addr); self.l1.verifier_addr = deploy_l1_output .deployed_addresses .state_transition @@ -88,22 +104,30 @@ impl ContractsConfig { self.ecosystem_contracts .diamond_cut_data .clone_from(&deploy_l1_output.contracts_config.diamond_cut_data); - self.l1.rollup_l1_da_validator_addr = deploy_l1_output - .deployed_addresses - .rollup_l1_da_validator_addr; - self.l1.validium_l1_da_validator_addr = deploy_l1_output - .deployed_addresses - .validium_l1_da_validator_addr; + self.l1.rollup_l1_da_validator_addr = Some( + deploy_l1_output + .deployed_addresses + .rollup_l1_da_validator_addr, + ); + self.l1.validium_l1_da_validator_addr = Some( + deploy_l1_output + .deployed_addresses + .validium_l1_da_validator_addr, + ); self.l1.chain_admin_addr = deploy_l1_output.deployed_addresses.chain_admin; - self.user_facing_bridgehub = deploy_l1_output - .deployed_addresses - .bridgehub - .bridgehub_proxy_addr; - self.user_facing_diamond_proxy = deploy_l1_output - .deployed_addresses - .state_transition - .diamond_proxy_addr; + self.user_facing_bridgehub = Some( + deploy_l1_output + .deployed_addresses + .bridgehub + .bridgehub_proxy_addr, + ); + self.user_facing_diamond_proxy = Some( + deploy_l1_output + .deployed_addresses + .state_transition + .diamond_proxy_addr, + ); } pub fn set_chain_contracts(&mut self, register_chain_output: &RegisterChainOutput) { @@ -111,12 +135,16 @@ impl ContractsConfig { self.l1.governance_addr = register_chain_output.governance_addr; self.l1.chain_admin_addr = register_chain_output.chain_admin_addr; self.l1.access_control_restriction_addr = - register_chain_output.access_control_restriction_addr; - self.l1.chain_proxy_admin_addr = register_chain_output.chain_proxy_admin_addr; + Some(register_chain_output.access_control_restriction_addr); + self.l1.chain_proxy_admin_addr = Some(register_chain_output.chain_proxy_admin_addr); self.l2.legacy_shared_bridge_addr = - Some(register_chain_output.l2_legacy_shared_bridge_addr); + if register_chain_output.l2_legacy_shared_bridge_addr != Address::zero() { + Some(register_chain_output.l2_legacy_shared_bridge_addr) + } else { + None + }; - self.user_facing_diamond_proxy = register_chain_output.diamond_proxy_addr; + self.user_facing_diamond_proxy = Some(register_chain_output.diamond_proxy_addr); } pub fn set_l2_shared_bridge( @@ -125,13 +153,13 @@ impl ContractsConfig { ) -> anyhow::Result<()> { self.bridges.shared.l2_address = Some(L2_ASSET_ROUTER_ADDRESS); self.bridges.erc20.l2_address = Some(L2_ASSET_ROUTER_ADDRESS); - self.l2.l2_native_token_vault_proxy_addr = L2_NATIVE_TOKEN_VAULT_ADDRESS; - self.l2.da_validator_addr = initialize_bridges_output.l2_da_validator_address; + self.l2.l2_native_token_vault_proxy_addr = Some(L2_NATIVE_TOKEN_VAULT_ADDRESS); + self.l2.da_validator_addr = Some(initialize_bridges_output.l2_da_validator_address); Ok(()) } pub fn set_transaction_filterer(&mut self, transaction_filterer_addr: Address) { - self.l1.transaction_filterer_addr = transaction_filterer_addr; + self.l1.transaction_filterer_addr = Some(transaction_filterer_addr); } pub fn set_consensus_registry( @@ -167,11 +195,18 @@ pub struct EcosystemContracts { pub bridgehub_proxy_addr: Address, pub state_transition_proxy_addr: Address, pub transparent_proxy_admin_addr: Address, - pub stm_deployment_tracker_proxy_addr: Address, + // `Option` to be able to parse configs from previous protocol version + pub stm_deployment_tracker_proxy_addr: Option
, pub validator_timelock_addr: Address, pub diamond_cut_data: String, - pub force_deployments_data: String, - pub native_token_vault_addr: Address, + // `Option` to be able to parse configs from previous protocol version + pub force_deployments_data: Option, + // `Option` to be able to parse configs from previous protocol version + pub native_token_vault_addr: Option
, + // `Option` to be able to parse configs from previous protocol version + pub l1_bytecodes_supplier_addr: Option
, + + pub expected_rollup_l2_da_validator: Option
, } impl ZkStackConfig for EcosystemContracts {} @@ -180,7 +215,7 @@ impl ZkStackConfig for EcosystemContracts {} pub struct BridgesContracts { pub erc20: BridgeContractsDefinition, pub shared: BridgeContractsDefinition, - pub l1_nullifier_addr: Address, + pub l1_nullifier_addr: Option
, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -197,24 +232,34 @@ pub struct L1Contracts { pub governance_addr: Address, #[serde(default)] pub chain_admin_addr: Address, - pub access_control_restriction_addr: Address, - pub chain_proxy_admin_addr: Address, + // Option to be able to parse old configs + pub access_control_restriction_addr: Option
, + // Option to be able to parse old configs + pub chain_proxy_admin_addr: Option
, pub multicall3_addr: Address, pub verifier_addr: Address, pub validator_timelock_addr: Address, pub base_token_addr: Address, - pub rollup_l1_da_validator_addr: Address, - pub validium_l1_da_validator_addr: Address, - pub transaction_filterer_addr: Address, + // `Option` to be able to parse configs from previous protocol version + pub base_token_asset_id: Option, + // `Option` to be able to parse configs from previous protocol version + pub rollup_l1_da_validator_addr: Option
, + // `Option` to be able to parse configs from previous protocol version + pub validium_l1_da_validator_addr: Option
, + // `Option` to be able to parse configs from previous protocol version + pub transaction_filterer_addr: Option
, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct L2Contracts { pub testnet_paymaster_addr: Address, pub default_l2_upgrader: Address, - pub da_validator_addr: Address, - pub l2_native_token_vault_proxy_addr: Address, + // `Option` to be able to parse configs from previous protocol version + pub da_validator_addr: Option
, + // `Option` to be able to parse configs from previous protocol version + pub l2_native_token_vault_proxy_addr: Option
, + // `Option` to be able to parse configs from previous protocol version + pub legacy_shared_bridge_addr: Option
, pub consensus_registry: Option
, pub multicall3: Option
, - pub legacy_shared_bridge_addr: Option
, } diff --git a/zkstack_cli/crates/config/src/forge_interface/deploy_ecosystem/output.rs b/zkstack_cli/crates/config/src/forge_interface/deploy_ecosystem/output.rs index 31f0ae2ddaa..40691701df1 100644 --- a/zkstack_cli/crates/config/src/forge_interface/deploy_ecosystem/output.rs +++ b/zkstack_cli/crates/config/src/forge_interface/deploy_ecosystem/output.rs @@ -19,6 +19,7 @@ pub struct DeployL1Output { pub owner_address: Address, pub contracts_config: DeployL1ContractsConfigOutput, pub deployed_addresses: DeployL1DeployedAddressesOutput, + pub expected_rollup_l2_da_validator_addr: Address, } #[derive(Debug, Deserialize, Serialize, Clone)] @@ -34,6 +35,7 @@ pub struct DeployL1DeployedAddressesOutput { pub state_transition: L1StateTransitionOutput, pub rollup_l1_da_validator_addr: Address, pub validium_l1_da_validator_addr: Address, + pub l1_rollup_da_manager: Address, pub native_token_vault_addr: Address, } @@ -78,6 +80,7 @@ pub struct L1StateTransitionOutput { pub genesis_upgrade_addr: Address, pub default_upgrade_addr: Address, pub diamond_proxy_addr: Address, + pub bytecodes_supplier_addr: Address, } #[derive(Debug, Deserialize, Serialize, Clone)] diff --git a/zkstack_cli/crates/config/src/forge_interface/deploy_gateway_ctm/input.rs b/zkstack_cli/crates/config/src/forge_interface/deploy_gateway_ctm/input.rs index bcc747d797c..5335398f781 100644 --- a/zkstack_cli/crates/config/src/forge_interface/deploy_gateway_ctm/input.rs +++ b/zkstack_cli/crates/config/src/forge_interface/deploy_gateway_ctm/input.rs @@ -16,7 +16,9 @@ pub struct DeployGatewayCTMInput { native_token_vault_addr: Address, chain_type_manager_proxy_addr: Address, shared_bridge_proxy_addr: Address, + governance: Address, + base_token: Address, chain_chain_id: U256, era_chain_id: U256, @@ -47,6 +49,8 @@ pub struct DeployGatewayCTMInput { latest_protocol_version: U256, force_deployments_data: String, + + expected_rollup_l2_da_validator: Address, } impl ZkStackConfig for DeployGatewayCTMInput {} @@ -63,14 +67,20 @@ impl DeployGatewayCTMInput { bridgehub_proxy_addr: contracts_config.ecosystem_contracts.bridgehub_proxy_addr, ctm_deployment_tracker_proxy_addr: contracts_config .ecosystem_contracts - .stm_deployment_tracker_proxy_addr, - native_token_vault_addr: contracts_config.ecosystem_contracts.native_token_vault_addr, + .stm_deployment_tracker_proxy_addr + .expect("stm_deployment_tracker_proxy_addr"), + native_token_vault_addr: contracts_config + .ecosystem_contracts + .native_token_vault_addr + .expect("native_token_vault_addr"), chain_type_manager_proxy_addr: contracts_config .ecosystem_contracts .state_transition_proxy_addr, shared_bridge_proxy_addr: contracts_config.bridges.shared.l1_address, governance: contracts_config.l1.governance_addr, + base_token: contracts_config.l1.base_token_addr, + chain_chain_id: U256::from(chain_config.chain_id.0), era_chain_id: U256::from(ecosystem_config.era_chain_id.0), l1_chain_id: U256::from(ecosystem_config.l1_network.chain_id()), @@ -107,10 +117,16 @@ impl DeployGatewayCTMInput { latest_protocol_version: genesis_config.protocol_version.unwrap().pack(), + expected_rollup_l2_da_validator: contracts_config + .ecosystem_contracts + .expected_rollup_l2_da_validator + .unwrap(), + force_deployments_data: contracts_config .ecosystem_contracts .force_deployments_data - .clone(), + .clone() + .expect("force_deployments_data"), } } } diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/input.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/input.rs new file mode 100644 index 00000000000..6a526af4945 --- /dev/null +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/input.rs @@ -0,0 +1,50 @@ +use ethers::types::Address; +use serde::{Deserialize, Serialize}; +use types::L1BatchCommitmentMode; +use zksync_basic_types::L2ChainId; + +use crate::{traits::ZkStackConfig, ChainConfig}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayChainUpgradeInput { + // This should be the address that controls the current `ChainAdmin` + // contract + pub owner_address: Address, + pub chain: GatewayChainUpgradeChain, +} +impl ZkStackConfig for GatewayChainUpgradeInput {} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayChainUpgradeChain { + pub chain_id: L2ChainId, + pub diamond_proxy_address: Address, + pub validium_mode: bool, + pub permanent_rollup: bool, +} + +impl GatewayChainUpgradeInput { + pub fn new(current_chain_config: &ChainConfig) -> Self { + let contracts_config = current_chain_config.get_contracts_config().unwrap(); + + let validum = current_chain_config + .get_genesis_config() + .unwrap() + .l1_batch_commit_data_generator_mode + == L1BatchCommitmentMode::Validium; + + Self { + owner_address: current_chain_config + .get_wallets_config() + .unwrap() + .governor + .address, + chain: GatewayChainUpgradeChain { + chain_id: current_chain_config.chain_id, + diamond_proxy_address: contracts_config.l1.diamond_proxy_addr, + validium_mode: validum, + // TODO(EVM-860): we assume that all rollup chains want to forever remain this way + permanent_rollup: !validum, + }, + } + } +} diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/mod.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/mod.rs new file mode 100644 index 00000000000..7d1a54844d0 --- /dev/null +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/mod.rs @@ -0,0 +1,2 @@ +pub mod input; +pub mod output; diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/output.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/output.rs new file mode 100644 index 00000000000..94b6d25a52b --- /dev/null +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_chain_upgrade/output.rs @@ -0,0 +1,13 @@ +use ethers::types::Address; +use serde::{Deserialize, Serialize}; + +use crate::traits::ZkStackConfig; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayChainUpgradeOutput { + // This should be the address that controls the current `ChainAdmin` + // contract + pub chain_admin_addr: Address, + pub access_control_restriction: Address, +} +impl ZkStackConfig for GatewayChainUpgradeOutput {} diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/input.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/input.rs new file mode 100644 index 00000000000..205d2e506c4 --- /dev/null +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/input.rs @@ -0,0 +1,131 @@ +use ethers::types::{Address, H256}; +use serde::{Deserialize, Serialize}; +use zksync_basic_types::L2ChainId; + +use crate::{ + apply_l1_to_l2_alias, forge_interface::deploy_ecosystem::input::InitialDeploymentConfig, + traits::ZkStackConfig, ContractsConfig, GenesisConfig, WalletsConfig, +}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeInput { + pub era_chain_id: L2ChainId, + pub owner_address: Address, + pub testnet_verifier: bool, + pub contracts: GatewayUpgradeContractsConfig, + pub tokens: GatewayUpgradeTokensConfig, +} + +impl ZkStackConfig for GatewayEcosystemUpgradeInput {} + +impl GatewayEcosystemUpgradeInput { + pub fn new( + new_genesis_config: &GenesisConfig, + current_contracts_config: &ContractsConfig, + // It is expected to not change between the versions + initial_deployment_config: &InitialDeploymentConfig, + wallets_config: &WalletsConfig, + era_chain_id: L2ChainId, + era_diamond_proxy: Address, + testnet_verifier: bool, + ) -> Self { + let aliased_governance_address = + apply_l1_to_l2_alias(current_contracts_config.l1.governance_addr); + + Self { + era_chain_id, + testnet_verifier, + owner_address: current_contracts_config.l1.governance_addr, + contracts: GatewayUpgradeContractsConfig { + create2_factory_addr: initial_deployment_config.create2_factory_addr, + create2_factory_salt: initial_deployment_config.create2_factory_salt, + // TODO verify correctnesss + governance_security_council_address: wallets_config.governor.address, + governance_min_delay: initial_deployment_config.governance_min_delay, + max_number_of_chains: initial_deployment_config.max_number_of_chains, + diamond_init_batch_overhead_l1_gas: initial_deployment_config + .diamond_init_batch_overhead_l1_gas, + diamond_init_max_l2_gas_per_batch: initial_deployment_config + .diamond_init_max_l2_gas_per_batch, + diamond_init_max_pubdata_per_batch: initial_deployment_config + .diamond_init_max_pubdata_per_batch, + diamond_init_minimal_l2_gas_price: initial_deployment_config + .diamond_init_minimal_l2_gas_price, + bootloader_hash: new_genesis_config.bootloader_hash.unwrap(), + default_aa_hash: new_genesis_config.default_aa_hash.unwrap(), + diamond_init_priority_tx_max_pubdata: initial_deployment_config + .diamond_init_priority_tx_max_pubdata, + diamond_init_pubdata_pricing_mode: initial_deployment_config + .diamond_init_pubdata_pricing_mode, + // These values are not optional in genesis config with file based configuration + genesis_batch_commitment: new_genesis_config.genesis_commitment.unwrap(), + genesis_rollup_leaf_index: new_genesis_config.rollup_last_leaf_index.unwrap(), + genesis_root: new_genesis_config.genesis_root_hash.unwrap(), + recursion_circuits_set_vks_hash: H256::zero(), + recursion_leaf_level_vk_hash: H256::zero(), + recursion_node_level_vk_hash: H256::zero(), + priority_tx_max_gas_limit: initial_deployment_config.priority_tx_max_gas_limit, + validator_timelock_execution_delay: initial_deployment_config + .validator_timelock_execution_delay, + + bridgehub_proxy_address: current_contracts_config + .ecosystem_contracts + .bridgehub_proxy_addr, + old_shared_bridge_proxy_address: current_contracts_config.bridges.shared.l1_address, + state_transition_manager_address: current_contracts_config + .ecosystem_contracts + .state_transition_proxy_addr, + transparent_proxy_admin: current_contracts_config + .ecosystem_contracts + .transparent_proxy_admin_addr, + era_diamond_proxy, + legacy_erc20_bridge_address: current_contracts_config.bridges.erc20.l1_address, + old_validator_timelock: current_contracts_config + .ecosystem_contracts + .validator_timelock_addr, + }, + tokens: GatewayUpgradeTokensConfig { + token_weth_address: initial_deployment_config.token_weth_address, + }, + } + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayUpgradeContractsConfig { + pub governance_security_council_address: Address, + pub governance_min_delay: u64, + pub max_number_of_chains: u64, + pub create2_factory_salt: H256, + #[serde(skip_serializing_if = "Option::is_none")] + pub create2_factory_addr: Option
, + pub validator_timelock_execution_delay: u64, + pub genesis_root: H256, + pub genesis_rollup_leaf_index: u64, + pub genesis_batch_commitment: H256, + pub recursion_node_level_vk_hash: H256, + pub recursion_leaf_level_vk_hash: H256, + pub recursion_circuits_set_vks_hash: H256, + pub priority_tx_max_gas_limit: u64, + pub diamond_init_pubdata_pricing_mode: u64, + pub diamond_init_batch_overhead_l1_gas: u64, + pub diamond_init_max_pubdata_per_batch: u64, + pub diamond_init_max_l2_gas_per_batch: u64, + pub diamond_init_priority_tx_max_pubdata: u64, + pub diamond_init_minimal_l2_gas_price: u64, + pub bootloader_hash: H256, + pub default_aa_hash: H256, + + pub bridgehub_proxy_address: Address, + pub old_shared_bridge_proxy_address: Address, + pub state_transition_manager_address: Address, + pub transparent_proxy_admin: Address, + pub era_diamond_proxy: Address, + pub legacy_erc20_bridge_address: Address, + pub old_validator_timelock: Address, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayUpgradeTokensConfig { + pub token_weth_address: Address, +} diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/mod.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/mod.rs new file mode 100644 index 00000000000..7d1a54844d0 --- /dev/null +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/mod.rs @@ -0,0 +1,2 @@ +pub mod input; +pub mod output; diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/output.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/output.rs new file mode 100644 index 00000000000..76aca7f4143 --- /dev/null +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_ecosystem_upgrade/output.rs @@ -0,0 +1,93 @@ +use ethers::types::{Address, H256}; +use serde::{Deserialize, Serialize}; +use zksync_basic_types::web3::Bytes; + +use crate::traits::{FileConfigWithDefaultName, ZkStackConfig}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeOutput { + pub create2_factory_addr: Address, + pub create2_factory_salt: H256, + pub deployer_addr: Address, + pub era_chain_id: u32, + pub l1_chain_id: u32, + pub owner_address: Address, + pub chain_upgrade_diamond_cut: Bytes, + pub governance_stage1_calls: Bytes, + pub governance_stage2_calls: Bytes, + + pub contracts_config: GatewayEcosystemUpgradeContractsOutput, + pub deployed_addresses: GatewayEcosystemUpgradeDeployedAddresses, +} + +impl FileConfigWithDefaultName for GatewayEcosystemUpgradeOutput { + const FILE_NAME: &'static str = "gateway_ecosystem_upgrade_output.yaml"; +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeContractsOutput { + // TODO: do we even need this field? + pub diamond_cut_data: Bytes, + + pub diamond_init_batch_overhead_l1_gas: u64, + pub diamond_init_max_l2_gas_per_batch: u64, + pub diamond_init_max_pubdata_per_batch: u64, + pub diamond_init_minimal_l2_gas_price: u64, + pub diamond_init_priority_tx_max_pubdata: u64, + pub expected_rollup_l2_da_validator: Address, + pub expected_validium_l2_da_validator: Address, + + // Probably gonna need it to add new chains + pub force_deployments_data: Bytes, + + pub priority_tx_max_gas_limit: u64, + + pub recursion_circuits_set_vks_hash: H256, + pub recursion_leaf_level_vk_hash: H256, + pub recursion_node_level_vk_hash: H256, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeDeployedAddresses { + pub native_token_vault_addr: Address, + pub rollup_l1_da_validator_addr: Address, + pub validator_timelock_addr: Address, + pub validium_l1_da_validator_addr: Address, + pub l1_bytecodes_supplier_addr: Address, + + pub bridgehub: GatewayEcosystemUpgradeBridgehub, + pub bridges: GatewayEcosystemUpgradeBridges, + pub state_transition: GatewayEcosystemUpgradeStateTransition, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeBridgehub { + pub bridgehub_implementation_addr: Address, + pub ctm_deployment_tracker_implementation_addr: Address, + pub ctm_deployment_tracker_proxy_addr: Address, + pub message_root_implementation_addr: Address, + pub message_root_proxy_addr: Address, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeBridges { + pub erc20_bridge_implementation_addr: Address, + pub l1_nullifier_implementation_addr: Address, + pub shared_bridge_implementation_addr: Address, + pub shared_bridge_proxy_addr: Address, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct GatewayEcosystemUpgradeStateTransition { + pub admin_facet_addr: Address, + pub default_upgrade_addr: Address, + pub diamond_init_addr: Address, + pub executor_facet_addr: Address, + pub genesis_upgrade_addr: Address, + pub getters_facet_addr: Address, + pub mailbox_facet_addr: Address, + pub state_transition_implementation_addr: Address, + pub verifier_addr: Address, +} + +impl ZkStackConfig for GatewayEcosystemUpgradeOutput {} diff --git a/zkstack_cli/crates/config/src/forge_interface/gateway_preparation/input.rs b/zkstack_cli/crates/config/src/forge_interface/gateway_preparation/input.rs index a958915fd9b..2038f412551 100644 --- a/zkstack_cli/crates/config/src/forge_interface/gateway_preparation/input.rs +++ b/zkstack_cli/crates/config/src/forge_interface/gateway_preparation/input.rs @@ -37,17 +37,27 @@ impl GatewayPreparationConfig { chain_chain_id: chain_config.chain_id.0, ctm_deployment_tracker_proxy_addr: contracts .ecosystem_contracts - .stm_deployment_tracker_proxy_addr, + .stm_deployment_tracker_proxy_addr + .expect("stm_deployment_tracker_proxy_addr"), chain_type_manager_proxy_addr: contracts .ecosystem_contracts .state_transition_proxy_addr, shared_bridge_proxy_addr: contracts.bridges.shared.l1_address, governance: ecosystem_contracts_config.l1.governance_addr, gateway_diamond_cut_data: gateway_config.diamond_cut_data.clone(), - chain_proxy_admin: chain_contracts_config.l1.chain_proxy_admin_addr, + chain_proxy_admin: chain_contracts_config + .l1 + .chain_proxy_admin_addr + .expect("chain_proxy_admin_addr"), chain_admin: chain_contracts_config.l1.chain_admin_addr, - access_control_restriction: chain_contracts_config.l1.access_control_restriction_addr, - l1_nullifier_proxy_addr: chain_contracts_config.bridges.l1_nullifier_addr, + access_control_restriction: chain_contracts_config + .l1 + .access_control_restriction_addr + .expect("access_control_restriction_addr"), + l1_nullifier_proxy_addr: chain_contracts_config + .bridges + .l1_nullifier_addr + .expect("l1_nullifier_addr"), l1_diamond_cut_data: hex::decode( ecosystem_contracts_config .ecosystem_contracts diff --git a/zkstack_cli/crates/config/src/forge_interface/mod.rs b/zkstack_cli/crates/config/src/forge_interface/mod.rs index 1959ee4c3de..e1faa6980ec 100644 --- a/zkstack_cli/crates/config/src/forge_interface/mod.rs +++ b/zkstack_cli/crates/config/src/forge_interface/mod.rs @@ -2,6 +2,8 @@ pub mod accept_ownership; pub mod deploy_ecosystem; pub mod deploy_gateway_ctm; pub mod deploy_l2_contracts; +pub mod gateway_chain_upgrade; +pub mod gateway_ecosystem_upgrade; pub mod gateway_preparation; pub mod paymaster; pub mod register_chain; diff --git a/zkstack_cli/crates/config/src/forge_interface/register_chain/input.rs b/zkstack_cli/crates/config/src/forge_interface/register_chain/input.rs index 8689bb496c6..4b1fd6120a5 100644 --- a/zkstack_cli/crates/config/src/forge_interface/register_chain/input.rs +++ b/zkstack_cli/crates/config/src/forge_interface/register_chain/input.rs @@ -70,7 +70,8 @@ impl RegisterChainL1Config { force_deployments_data: contracts .ecosystem_contracts .force_deployments_data - .clone(), + .clone() + .expect("force_deployment_data"), }, deployed_addresses: DeployedAddresses { state_transition: StateTransition { @@ -83,10 +84,16 @@ impl RegisterChainL1Config { }, bridges: Bridges { shared_bridge_proxy_addr: contracts.bridges.shared.l1_address, - l1_nullifier_proxy_addr: contracts.bridges.l1_nullifier_addr, + l1_nullifier_proxy_addr: contracts + .bridges + .l1_nullifier_addr + .expect("l1_nullifier_addr"), }, validator_timelock_addr: contracts.ecosystem_contracts.validator_timelock_addr, - native_token_vault_addr: contracts.ecosystem_contracts.native_token_vault_addr, + native_token_vault_addr: contracts + .ecosystem_contracts + .native_token_vault_addr + .expect("native_token_vault_addr"), }, chain: ChainL1Config { chain_chain_id: chain_config.chain_id, diff --git a/zkstack_cli/crates/config/src/forge_interface/script_params.rs b/zkstack_cli/crates/config/src/forge_interface/script_params.rs index f05b1abfb37..eb780358a04 100644 --- a/zkstack_cli/crates/config/src/forge_interface/script_params.rs +++ b/zkstack_cli/crates/config/src/forge_interface/script_params.rs @@ -79,3 +79,21 @@ pub const GATEWAY_PREPARATION: ForgeScriptParams = ForgeScriptParams { output: "script-out/output-gateway-preparation-l1.toml", script_path: "deploy-scripts/GatewayPreparation.s.sol", }; + +pub const GATEWAY_UPGRADE_ECOSYSTEM_PARAMS: ForgeScriptParams = ForgeScriptParams { + input: "script-config/gateway-upgrade-ecosystem.toml", + output: "script-out/gateway-upgrade-ecosystem.toml", + script_path: "deploy-scripts/upgrade/EcosystemUpgrade.s.sol", +}; + +pub const GATEWAY_UPGRADE_CHAIN_PARAMS: ForgeScriptParams = ForgeScriptParams { + input: "script-config/gateway-upgrade-chain.toml", + output: "script-out/gateway-upgrade-chain.toml", + script_path: "deploy-scripts/upgrade/ChainUpgrade.s.sol", +}; + +pub const FINALIZE_UPGRADE_SCRIPT_PARAMS: ForgeScriptParams = ForgeScriptParams { + input: "script-config/gateway-finalize-upgrade.toml", + output: "script-out/gateway-finalize-upgrade.toml", + script_path: "deploy-scripts/upgrade/FinalizeUpgrade.s.sol", +}; diff --git a/zkstack_cli/crates/zkstack/Cargo.toml b/zkstack_cli/crates/zkstack/Cargo.toml index 0a66036854e..1a02b4cf7a8 100644 --- a/zkstack_cli/crates/zkstack/Cargo.toml +++ b/zkstack_cli/crates/zkstack/Cargo.toml @@ -46,6 +46,7 @@ zksync_protobuf_config.workspace = true zksync_types.workspace = true zksync_web3_decl.workspace = true zksync_system_constants.workspace = true +zksync_eth_client.workspace = true prost.workspace = true reqwest = "0.12.8" diff --git a/zkstack_cli/crates/zkstack/completion/_zkstack.zsh b/zkstack_cli/crates/zkstack/completion/_zkstack.zsh index c5c8987d85b..5cdfad7e628 100644 --- a/zkstack_cli/crates/zkstack/completion/_zkstack.zsh +++ b/zkstack_cli/crates/zkstack/completion/_zkstack.zsh @@ -171,6 +171,27 @@ _arguments "${_arguments_options[@]}" : \ '--help[Print help]' \ && ret=0 ;; +(gateway-upgrade) +_arguments "${_arguments_options[@]}" : \ +'--verify=[Verify deployed contracts]' \ +'--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--ecosystem-upgrade-stage=[]:ECOSYSTEM_UPGRADE_STAGE:(no-governance-prepare governance-stage1 governance-stage2 no-governance-stage2)' \ +'--ecosystem-contracts-path=[Path to ecosystem contracts]:ECOSYSTEM_CONTRACTS_PATH:_files' \ +'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ +'--resume[]' \ +'--zksync[]' \ +'-v[Verbose mode]' \ +'--verbose[Verbose mode]' \ +'--ignore-prerequisites[Ignores prerequisites checks]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +&& ret=0 +;; (help) _arguments "${_arguments_options[@]}" : \ ":: :_zkstack__ecosystem__help_commands" \ @@ -203,6 +224,10 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ && ret=0 ;; +(gateway-upgrade) +_arguments "${_arguments_options[@]}" : \ +&& ret=0 +;; (help) _arguments "${_arguments_options[@]}" : \ && ret=0 @@ -662,6 +687,25 @@ _arguments "${_arguments_options[@]}" : \ '--help[Print help (see more with '\''--help'\'')]' \ && ret=0 ;; +(gateway-upgrade) +_arguments "${_arguments_options[@]}" : \ +'--verify=[Verify deployed contracts]' \ +'--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ +'--resume[]' \ +'--zksync[]' \ +'-v[Verbose mode]' \ +'--verbose[Verbose mode]' \ +'--ignore-prerequisites[Ignores prerequisites checks]' \ +'-h[Print help (see more with '\''--help'\'')]' \ +'--help[Print help (see more with '\''--help'\'')]' \ +':chain_upgrade_stage:(adapt-config prepare-stage1 schedule-stage1 finalize-stage1 finalize-stage2 keep-up-stage2)' \ +&& ret=0 +;; (help) _arguments "${_arguments_options[@]}" : \ ":: :_zkstack__chain__help_commands" \ @@ -774,6 +818,10 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ && ret=0 ;; +(gateway-upgrade) +_arguments "${_arguments_options[@]}" : \ +&& ret=0 +;; (help) _arguments "${_arguments_options[@]}" : \ && ret=0 @@ -2502,6 +2550,10 @@ _arguments "${_arguments_options[@]}" : \ (setup-observability) _arguments "${_arguments_options[@]}" : \ && ret=0 +;; +(gateway-upgrade) +_arguments "${_arguments_options[@]}" : \ +&& ret=0 ;; esac ;; @@ -2618,6 +2670,10 @@ _arguments "${_arguments_options[@]}" : \ (migrate-from-gateway) _arguments "${_arguments_options[@]}" : \ && ret=0 +;; +(gateway-upgrade) +_arguments "${_arguments_options[@]}" : \ +&& ret=0 ;; esac ;; @@ -3105,6 +3161,7 @@ _zkstack__chain_commands() { 'convert-to-gateway:Prepare chain to be an eligible gateway' \ 'migrate-to-gateway:Migrate chain to gateway' \ 'migrate-from-gateway:Migrate chain from gateway' \ +'gateway-upgrade:Upgrade to the protocol version that supports Gateway' \ 'help:Print this message or the help of the given subcommand(s)' \ ) _describe -t commands 'zkstack chain commands' commands "$@" @@ -3154,6 +3211,11 @@ _zkstack__chain__deploy-upgrader_commands() { local commands; commands=() _describe -t commands 'zkstack chain deploy-upgrader commands' commands "$@" } +(( $+functions[_zkstack__chain__gateway-upgrade_commands] )) || +_zkstack__chain__gateway-upgrade_commands() { + local commands; commands=() + _describe -t commands 'zkstack chain gateway-upgrade commands' commands "$@" +} (( $+functions[_zkstack__chain__genesis_commands] )) || _zkstack__chain__genesis_commands() { local commands; commands=( @@ -3216,6 +3278,7 @@ _zkstack__chain__help_commands() { 'convert-to-gateway:Prepare chain to be an eligible gateway' \ 'migrate-to-gateway:Migrate chain to gateway' \ 'migrate-from-gateway:Migrate chain from gateway' \ +'gateway-upgrade:Upgrade to the protocol version that supports Gateway' \ 'help:Print this message or the help of the given subcommand(s)' \ ) _describe -t commands 'zkstack chain help commands' commands "$@" @@ -3265,6 +3328,11 @@ _zkstack__chain__help__deploy-upgrader_commands() { local commands; commands=() _describe -t commands 'zkstack chain help deploy-upgrader commands' commands "$@" } +(( $+functions[_zkstack__chain__help__gateway-upgrade_commands] )) || +_zkstack__chain__help__gateway-upgrade_commands() { + local commands; commands=() + _describe -t commands 'zkstack chain help gateway-upgrade commands' commands "$@" +} (( $+functions[_zkstack__chain__help__genesis_commands] )) || _zkstack__chain__help__genesis_commands() { local commands; commands=( @@ -4270,6 +4338,7 @@ _zkstack__ecosystem_commands() { 'init:Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' \ 'change-default-chain:Change the default chain' \ 'setup-observability:Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' \ +'gateway-upgrade:Gateway version upgrade' \ 'help:Print this message or the help of the given subcommand(s)' \ ) _describe -t commands 'zkstack ecosystem commands' commands "$@" @@ -4289,6 +4358,11 @@ _zkstack__ecosystem__create_commands() { local commands; commands=() _describe -t commands 'zkstack ecosystem create commands' commands "$@" } +(( $+functions[_zkstack__ecosystem__gateway-upgrade_commands] )) || +_zkstack__ecosystem__gateway-upgrade_commands() { + local commands; commands=() + _describe -t commands 'zkstack ecosystem gateway-upgrade commands' commands "$@" +} (( $+functions[_zkstack__ecosystem__help_commands] )) || _zkstack__ecosystem__help_commands() { local commands; commands=( @@ -4297,6 +4371,7 @@ _zkstack__ecosystem__help_commands() { 'init:Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' \ 'change-default-chain:Change the default chain' \ 'setup-observability:Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' \ +'gateway-upgrade:Gateway version upgrade' \ 'help:Print this message or the help of the given subcommand(s)' \ ) _describe -t commands 'zkstack ecosystem help commands' commands "$@" @@ -4316,6 +4391,11 @@ _zkstack__ecosystem__help__create_commands() { local commands; commands=() _describe -t commands 'zkstack ecosystem help create commands' commands "$@" } +(( $+functions[_zkstack__ecosystem__help__gateway-upgrade_commands] )) || +_zkstack__ecosystem__help__gateway-upgrade_commands() { + local commands; commands=() + _describe -t commands 'zkstack ecosystem help gateway-upgrade commands' commands "$@" +} (( $+functions[_zkstack__ecosystem__help__help_commands] )) || _zkstack__ecosystem__help__help_commands() { local commands; commands=() @@ -4496,6 +4576,7 @@ _zkstack__help__chain_commands() { 'convert-to-gateway:Prepare chain to be an eligible gateway' \ 'migrate-to-gateway:Migrate chain to gateway' \ 'migrate-from-gateway:Migrate chain from gateway' \ +'gateway-upgrade:Upgrade to the protocol version that supports Gateway' \ ) _describe -t commands 'zkstack help chain commands' commands "$@" } @@ -4544,6 +4625,11 @@ _zkstack__help__chain__deploy-upgrader_commands() { local commands; commands=() _describe -t commands 'zkstack help chain deploy-upgrader commands' commands "$@" } +(( $+functions[_zkstack__help__chain__gateway-upgrade_commands] )) || +_zkstack__help__chain__gateway-upgrade_commands() { + local commands; commands=() + _describe -t commands 'zkstack help chain gateway-upgrade commands' commands "$@" +} (( $+functions[_zkstack__help__chain__genesis_commands] )) || _zkstack__help__chain__genesis_commands() { local commands; commands=( @@ -4907,6 +4993,7 @@ _zkstack__help__ecosystem_commands() { 'init:Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' \ 'change-default-chain:Change the default chain' \ 'setup-observability:Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' \ +'gateway-upgrade:Gateway version upgrade' \ ) _describe -t commands 'zkstack help ecosystem commands' commands "$@" } @@ -4925,6 +5012,11 @@ _zkstack__help__ecosystem__create_commands() { local commands; commands=() _describe -t commands 'zkstack help ecosystem create commands' commands "$@" } +(( $+functions[_zkstack__help__ecosystem__gateway-upgrade_commands] )) || +_zkstack__help__ecosystem__gateway-upgrade_commands() { + local commands; commands=() + _describe -t commands 'zkstack help ecosystem gateway-upgrade commands' commands "$@" +} (( $+functions[_zkstack__help__ecosystem__init_commands] )) || _zkstack__help__ecosystem__init_commands() { local commands; commands=() diff --git a/zkstack_cli/crates/zkstack/completion/zkstack.fish b/zkstack_cli/crates/zkstack/completion/zkstack.fish index 9f449192003..46bec1c2118 100644 --- a/zkstack_cli/crates/zkstack/completion/zkstack.fish +++ b/zkstack_cli/crates/zkstack/completion/zkstack.fish @@ -50,16 +50,17 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand autocomplete" -l chain - complete -c zkstack -n "__fish_zkstack_using_subcommand autocomplete" -s v -l verbose -d 'Verbose mode' complete -c zkstack -n "__fish_zkstack_using_subcommand autocomplete" -l ignore-prerequisites -d 'Ignores prerequisites checks' complete -c zkstack -n "__fish_zkstack_using_subcommand autocomplete" -s h -l help -d 'Print help' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -l chain -d 'Chain to use' -r -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -s v -l verbose -d 'Verbose mode' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -l ignore-prerequisites -d 'Ignores prerequisites checks' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -s h -l help -d 'Print help' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -f -a "create" -d 'Create a new ecosystem and chain, setting necessary configurations for later initialization' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -f -a "build-transactions" -d 'Create transactions to build ecosystem contracts' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -f -a "init" -d 'Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -f -a "change-default-chain" -d 'Change the default chain' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -f -a "setup-observability" -d 'Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' -complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -l chain -d 'Chain to use' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -s v -l verbose -d 'Verbose mode' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -l ignore-prerequisites -d 'Ignores prerequisites checks' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -s h -l help -d 'Print help' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "create" -d 'Create a new ecosystem and chain, setting necessary configurations for later initialization' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "build-transactions" -d 'Create transactions to build ecosystem contracts' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "init" -d 'Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "change-default-chain" -d 'Change the default chain' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "setup-observability" -d 'Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "gateway-upgrade" -d 'Gateway version upgrade' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and not __fish_seen_subcommand_from create build-transactions init change-default-chain setup-observability gateway-upgrade help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l ecosystem-name -r complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l l1-network -d 'L1 Network' -r -f -a "{localhost\t'',sepolia\t'',holesky\t'',mainnet\t''}" complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from create" -l link-to-code -d 'Code link' -r -f -a "(__fish_complete_directories)" @@ -129,33 +130,49 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_se complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from setup-observability" -s v -l verbose -d 'Verbose mode' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from setup-observability" -l ignore-prerequisites -d 'Ignores prerequisites checks' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from setup-observability" -s h -l help -d 'Print help' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l verify -d 'Verify deployed contracts' -r -f -a "{true\t'',false\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l verifier -d 'Verifier to use' -r -f -a "{etherscan\t'',sourcify\t'',blockscout\t'',oklink\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l verifier-url -d 'Verifier URL, if using a custom provider' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l verifier-api-key -d 'Verifier API key' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -s a -l additional-args -d 'List of additional arguments that can be passed through the CLI' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l ecosystem-upgrade-stage -r -f -a "{no-governance-prepare\t'',governance-stage1\t'',governance-stage2\t'',no-governance-stage2\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l ecosystem-contracts-path -d 'Path to ecosystem contracts' -r -F +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l l1-rpc-url -d 'L1 RPC URL' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l chain -d 'Chain to use' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l resume +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l zksync +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -s v -l verbose -d 'Verbose mode' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -l ignore-prerequisites -d 'Ignores prerequisites checks' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from gateway-upgrade" -s h -l help -d 'Print help (see more with \'--help\')' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "create" -d 'Create a new ecosystem and chain, setting necessary configurations for later initialization' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "build-transactions" -d 'Create transactions to build ecosystem contracts' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "init" -d 'Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "change-default-chain" -d 'Change the default chain' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "setup-observability" -d 'Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' +complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "gateway-upgrade" -d 'Gateway version upgrade' complete -c zkstack -n "__fish_zkstack_using_subcommand ecosystem; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -l chain -d 'Chain to use' -r -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -s v -l verbose -d 'Verbose mode' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -l ignore-prerequisites -d 'Ignores prerequisites checks' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -s h -l help -d 'Print help' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "create" -d 'Create a new chain, setting the necessary configurations for later initialization' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "build-transactions" -d 'Create unsigned transactions for chain deployment' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "init" -d 'Initialize chain, deploying necessary contracts and performing on-chain operations' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "genesis" -d 'Run server genesis' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "register-chain" -d 'Register a new chain on L1 (executed by L1 governor). This command deploys and configures Governance, ChainAdmin, and DiamondProxy contracts, registers chain with BridgeHub and sets pending admin for DiamondProxy. Note: After completion, L2 governor can accept ownership by running `accept-chain-ownership`' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "deploy-l2-contracts" -d 'Deploy all L2 contracts (executed by L1 governor)' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "accept-chain-ownership" -d 'Accept ownership of L2 chain (executed by L2 governor). This command should be run after `register-chain` to accept ownership of newly created DiamondProxy contract' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "initialize-bridges" -d 'Initialize bridges on L2' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "deploy-consensus-registry" -d 'Deploy L2 consensus registry' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "deploy-multicall3" -d 'Deploy L2 multicall3' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "deploy-upgrader" -d 'Deploy Default Upgrader' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "deploy-paymaster" -d 'Deploy paymaster smart contract' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "update-token-multiplier-setter" -d 'Update Token Multiplier Setter address on L1' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "convert-to-gateway" -d 'Prepare chain to be an eligible gateway' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "migrate-to-gateway" -d 'Migrate chain to gateway' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "migrate-from-gateway" -d 'Migrate chain from gateway' -complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -l chain -d 'Chain to use' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -s v -l verbose -d 'Verbose mode' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -l ignore-prerequisites -d 'Ignores prerequisites checks' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -s h -l help -d 'Print help' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "create" -d 'Create a new chain, setting the necessary configurations for later initialization' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "build-transactions" -d 'Create unsigned transactions for chain deployment' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "init" -d 'Initialize chain, deploying necessary contracts and performing on-chain operations' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "genesis" -d 'Run server genesis' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "register-chain" -d 'Register a new chain on L1 (executed by L1 governor). This command deploys and configures Governance, ChainAdmin, and DiamondProxy contracts, registers chain with BridgeHub and sets pending admin for DiamondProxy. Note: After completion, L2 governor can accept ownership by running `accept-chain-ownership`' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "deploy-l2-contracts" -d 'Deploy all L2 contracts (executed by L1 governor)' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "accept-chain-ownership" -d 'Accept ownership of L2 chain (executed by L2 governor). This command should be run after `register-chain` to accept ownership of newly created DiamondProxy contract' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "initialize-bridges" -d 'Initialize bridges on L2' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "deploy-consensus-registry" -d 'Deploy L2 consensus registry' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "deploy-multicall3" -d 'Deploy L2 multicall3' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "deploy-upgrader" -d 'Deploy Default Upgrader' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "deploy-paymaster" -d 'Deploy paymaster smart contract' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "update-token-multiplier-setter" -d 'Update Token Multiplier Setter address on L1' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "convert-to-gateway" -d 'Prepare chain to be an eligible gateway' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "migrate-to-gateway" -d 'Migrate chain to gateway' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "migrate-from-gateway" -d 'Migrate chain from gateway' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "gateway-upgrade" -d 'Upgrade to the protocol version that supports Gateway' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and not __fish_seen_subcommand_from create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l chain-name -r complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l chain-id -d 'Chain ID' -r complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from create" -l prover-mode -d 'Prover options' -r -f -a "{no-proofs\t'',gpu\t''}" @@ -353,6 +370,17 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_s complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from migrate-from-gateway" -s v -l verbose -d 'Verbose mode' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from migrate-from-gateway" -l ignore-prerequisites -d 'Ignores prerequisites checks' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from migrate-from-gateway" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l verify -d 'Verify deployed contracts' -r -f -a "{true\t'',false\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l verifier -d 'Verifier to use' -r -f -a "{etherscan\t'',sourcify\t'',blockscout\t'',oklink\t''}" +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l verifier-url -d 'Verifier URL, if using a custom provider' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l verifier-api-key -d 'Verifier API key' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -s a -l additional-args -d 'List of additional arguments that can be passed through the CLI' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l chain -d 'Chain to use' -r +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l resume +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l zksync +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -s v -l verbose -d 'Verbose mode' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -l ignore-prerequisites -d 'Ignores prerequisites checks' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from gateway-upgrade" -s h -l help -d 'Print help (see more with \'--help\')' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "create" -d 'Create a new chain, setting the necessary configurations for later initialization' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "build-transactions" -d 'Create unsigned transactions for chain deployment' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "init" -d 'Initialize chain, deploying necessary contracts and performing on-chain operations' @@ -369,6 +397,7 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_s complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "convert-to-gateway" -d 'Prepare chain to be an eligible gateway' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "migrate-to-gateway" -d 'Migrate chain to gateway' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "migrate-from-gateway" -d 'Migrate chain from gateway' +complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "gateway-upgrade" -d 'Upgrade to the protocol version that supports Gateway' complete -c zkstack -n "__fish_zkstack_using_subcommand chain; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' complete -c zkstack -n "__fish_zkstack_using_subcommand dev; and not __fish_seen_subcommand_from database test clean snapshot lint fmt prover contracts config-writer send-transactions status generate-genesis help" -l chain -d 'Chain to use' -r complete -c zkstack -n "__fish_zkstack_using_subcommand dev; and not __fish_seen_subcommand_from database test clean snapshot lint fmt prover contracts config-writer send-transactions status generate-genesis help" -s v -l verbose -d 'Verbose mode' @@ -722,6 +751,7 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_su complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from ecosystem" -f -a "init" -d 'Initialize ecosystem and chain, deploying necessary contracts and performing on-chain operations' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from ecosystem" -f -a "change-default-chain" -d 'Change the default chain' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from ecosystem" -f -a "setup-observability" -d 'Setup observability for the ecosystem, downloading Grafana dashboards from the era-observability repo' +complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from ecosystem" -f -a "gateway-upgrade" -d 'Gateway version upgrade' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "create" -d 'Create a new chain, setting the necessary configurations for later initialization' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "build-transactions" -d 'Create unsigned transactions for chain deployment' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "init" -d 'Initialize chain, deploying necessary contracts and performing on-chain operations' @@ -738,6 +768,7 @@ complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_su complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "convert-to-gateway" -d 'Prepare chain to be an eligible gateway' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "migrate-to-gateway" -d 'Migrate chain to gateway' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "migrate-from-gateway" -d 'Migrate chain from gateway' +complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from chain" -f -a "gateway-upgrade" -d 'Upgrade to the protocol version that supports Gateway' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from dev" -f -a "database" -d 'Database related commands' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from dev" -f -a "test" -d 'Run tests' complete -c zkstack -n "__fish_zkstack_using_subcommand help; and __fish_seen_subcommand_from dev" -f -a "clean" -d 'Clean artifacts' diff --git a/zkstack_cli/crates/zkstack/completion/zkstack.sh b/zkstack_cli/crates/zkstack/completion/zkstack.sh index 57294750ca4..ef4330e0ffd 100644 --- a/zkstack_cli/crates/zkstack/completion/zkstack.sh +++ b/zkstack_cli/crates/zkstack/completion/zkstack.sh @@ -84,6 +84,9 @@ _zkstack() { zkstack__chain,deploy-upgrader) cmd="zkstack__chain__deploy__upgrader" ;; + zkstack__chain,gateway-upgrade) + cmd="zkstack__chain__gateway__upgrade" + ;; zkstack__chain,genesis) cmd="zkstack__chain__genesis" ;; @@ -153,6 +156,9 @@ _zkstack() { zkstack__chain__help,deploy-upgrader) cmd="zkstack__chain__help__deploy__upgrader" ;; + zkstack__chain__help,gateway-upgrade) + cmd="zkstack__chain__help__gateway__upgrade" + ;; zkstack__chain__help,genesis) cmd="zkstack__chain__help__genesis" ;; @@ -624,6 +630,9 @@ _zkstack() { zkstack__ecosystem,create) cmd="zkstack__ecosystem__create" ;; + zkstack__ecosystem,gateway-upgrade) + cmd="zkstack__ecosystem__gateway__upgrade" + ;; zkstack__ecosystem,help) cmd="zkstack__ecosystem__help" ;; @@ -642,6 +651,9 @@ _zkstack() { zkstack__ecosystem__help,create) cmd="zkstack__ecosystem__help__create" ;; + zkstack__ecosystem__help,gateway-upgrade) + cmd="zkstack__ecosystem__help__gateway__upgrade" + ;; zkstack__ecosystem__help,help) cmd="zkstack__ecosystem__help__help" ;; @@ -771,6 +783,9 @@ _zkstack() { zkstack__help__chain,deploy-upgrader) cmd="zkstack__help__chain__deploy__upgrader" ;; + zkstack__help__chain,gateway-upgrade) + cmd="zkstack__help__chain__gateway__upgrade" + ;; zkstack__help__chain,genesis) cmd="zkstack__help__chain__genesis" ;; @@ -945,6 +960,9 @@ _zkstack() { zkstack__help__ecosystem,create) cmd="zkstack__help__ecosystem__create" ;; + zkstack__help__ecosystem,gateway-upgrade) + cmd="zkstack__help__ecosystem__gateway__upgrade" + ;; zkstack__help__ecosystem,init) cmd="zkstack__help__ecosystem__init" ;; @@ -1075,7 +1093,7 @@ _zkstack() { return 0 ;; zkstack__chain) - opts="-v -h --verbose --chain --ignore-prerequisites --help create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" + opts="-v -h --verbose --chain --ignore-prerequisites --help create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1513,6 +1531,48 @@ _zkstack() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zkstack__chain__gateway__upgrade) + opts="-a -v -h --verify --verifier --verifier-url --verifier-api-key --resume --zksync --additional-args --verbose --chain --ignore-prerequisites --help adapt-config prepare-stage1 schedule-stage1 finalize-stage1 finalize-stage2 keep-up-stage2" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --verify) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; + --verifier) + COMPREPLY=($(compgen -W "etherscan sourcify blockscout oklink" -- "${cur}")) + return 0 + ;; + --verifier-url) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --verifier-api-key) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --additional-args) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -a) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --chain) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zkstack__chain__genesis) opts="-d -d -v -h --server-db-url --server-db-name --dev --dont-drop --verbose --chain --ignore-prerequisites --help init-database server help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then @@ -1640,7 +1700,7 @@ _zkstack() { return 0 ;; zkstack__chain__help) - opts="create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway help" + opts="create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1779,6 +1839,20 @@ _zkstack() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zkstack__chain__help__gateway__upgrade) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zkstack__chain__help__genesis) opts="init-database server" if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then @@ -4760,7 +4834,7 @@ _zkstack() { return 0 ;; zkstack__ecosystem) - opts="-v -h --verbose --chain --ignore-prerequisites --help create build-transactions init change-default-chain setup-observability help" + opts="-v -h --verbose --chain --ignore-prerequisites --help create build-transactions init change-default-chain setup-observability gateway-upgrade help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4945,8 +5019,62 @@ _zkstack() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zkstack__ecosystem__gateway__upgrade) + opts="-a -v -h --verify --verifier --verifier-url --verifier-api-key --resume --zksync --additional-args --ecosystem-upgrade-stage --ecosystem-contracts-path --l1-rpc-url --verbose --chain --ignore-prerequisites --help" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + --verify) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; + --verifier) + COMPREPLY=($(compgen -W "etherscan sourcify blockscout oklink" -- "${cur}")) + return 0 + ;; + --verifier-url) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --verifier-api-key) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --additional-args) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -a) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --ecosystem-upgrade-stage) + COMPREPLY=($(compgen -W "no-governance-prepare governance-stage1 governance-stage2 no-governance-stage2" -- "${cur}")) + return 0 + ;; + --ecosystem-contracts-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --l1-rpc-url) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --chain) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zkstack__ecosystem__help) - opts="create build-transactions init change-default-chain setup-observability help" + opts="create build-transactions init change-default-chain setup-observability gateway-upgrade help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -5001,6 +5129,20 @@ _zkstack() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zkstack__ecosystem__help__gateway__upgrade) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zkstack__ecosystem__help__help) opts="" if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then @@ -5480,7 +5622,7 @@ _zkstack() { return 0 ;; zkstack__help__chain) - opts="create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway" + opts="create build-transactions init genesis register-chain deploy-l2-contracts accept-chain-ownership initialize-bridges deploy-consensus-registry deploy-multicall3 deploy-upgrader deploy-paymaster update-token-multiplier-setter convert-to-gateway migrate-to-gateway migrate-from-gateway gateway-upgrade" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -5619,6 +5761,20 @@ _zkstack() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zkstack__help__chain__gateway__upgrade) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zkstack__help__chain__genesis) opts="init-database server" if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then @@ -6446,7 +6602,7 @@ _zkstack() { return 0 ;; zkstack__help__ecosystem) - opts="create build-transactions init change-default-chain setup-observability" + opts="create build-transactions init change-default-chain setup-observability gateway-upgrade" if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -6501,6 +6657,20 @@ _zkstack() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 ;; + zkstack__help__ecosystem__gateway__upgrade) + opts="" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; zkstack__help__ecosystem__init) opts="" if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then diff --git a/zkstack_cli/crates/zkstack/src/accept_ownership.rs b/zkstack_cli/crates/zkstack/src/accept_ownership.rs index e1655921345..4d8d28330db 100644 --- a/zkstack_cli/crates/zkstack/src/accept_ownership.rs +++ b/zkstack_cli/crates/zkstack/src/accept_ownership.rs @@ -1,12 +1,21 @@ +use anyhow::Context; use common::{ forge::{Forge, ForgeScript, ForgeScriptArgs}, spinner::Spinner, wallets::Wallet, }; -use config::{forge_interface::script_params::ACCEPT_GOVERNANCE_SCRIPT_PARAMS, EcosystemConfig}; -use ethers::{abi::parse_abi, contract::BaseContract, types::Address}; +use config::{ + forge_interface::script_params::ACCEPT_GOVERNANCE_SCRIPT_PARAMS, ChainConfig, ContractsConfig, + EcosystemConfig, +}; +use ethers::{ + abi::{parse_abi, Token}, + contract::BaseContract, + types::Address, +}; use lazy_static::lazy_static; use xshell::Shell; +use zksync_types::U256; use crate::{ messages::MSG_ACCEPTING_GOVERNANCE_SPINNER, @@ -18,7 +27,12 @@ lazy_static! { parse_abi(&[ "function governanceAcceptOwner(address governor, address target) public", "function chainAdminAcceptAdmin(address admin, address target) public", - "function setDAValidatorPair(address chainAdmin, address target, address l1DaValidator, address l2DaValidator) public" + "function setDAValidatorPair(address chainAdmin, address target, address l1DaValidator, address l2DaValidator) public", + "function makePermanentRollup(address chainAdmin, address target) public", + "function governanceExecuteCalls(bytes calldata callsToExecute, address target) public", + "function adminExecuteUpgrade(bytes memory diamondCut, address adminAddr, address accessControlRestriction, address chainDiamondProxy)", + "function adminScheduleUpgrade(address adminAddr, address accessControlRestriction, uint256 newProtocolVersion, uint256 timestamp)", + "function updateValidator(address adminAddr,address accessControlRestriction,address validatorTimelock,uint256 chainId,address validatorAddress,bool addValidator) public" ]) .unwrap(), ); @@ -124,6 +138,213 @@ pub async fn set_da_validator_pair( accept_ownership(shell, governor, forge).await } +#[allow(clippy::too_many_arguments)] +pub async fn make_permanent_rollup( + shell: &Shell, + ecosystem_config: &EcosystemConfig, + chain_admin_addr: Address, + governor: &Wallet, + diamond_proxy_address: Address, + forge_args: &ForgeScriptArgs, + l1_rpc_url: String, +) -> anyhow::Result<()> { + // resume doesn't properly work here. + let mut forge_args = forge_args.clone(); + forge_args.resume = false; + + let calldata = ACCEPT_ADMIN + .encode( + "makePermanentRollup", + (chain_admin_addr, diamond_proxy_address), + ) + .unwrap(); + let foundry_contracts_path = ecosystem_config.path_to_l1_foundry(); + let forge = Forge::new(&foundry_contracts_path) + .script( + &ACCEPT_GOVERNANCE_SCRIPT_PARAMS.script(), + forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_broadcast() + .with_calldata(&calldata); + accept_ownership(shell, governor, forge).await +} + +#[allow(clippy::too_many_arguments)] +pub async fn governance_execute_calls( + shell: &Shell, + ecosystem_config: &EcosystemConfig, + governor: &Wallet, + encoded_calls: Vec, + forge_args: &ForgeScriptArgs, + l1_rpc_url: String, +) -> anyhow::Result<()> { + // resume doesn't properly work here. + let mut forge_args = forge_args.clone(); + forge_args.resume = false; + + let governance_address = ecosystem_config.get_contracts_config()?.l1.governance_addr; + + let calldata = ACCEPT_ADMIN + .encode( + "governanceExecuteCalls", + (Token::Bytes(encoded_calls), governance_address), + ) + .unwrap(); + let foundry_contracts_path = ecosystem_config.path_to_l1_foundry(); + let forge = Forge::new(&foundry_contracts_path) + .script( + &ACCEPT_GOVERNANCE_SCRIPT_PARAMS.script(), + forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_broadcast() + .with_calldata(&calldata); + accept_ownership(shell, governor, forge).await +} + +#[allow(clippy::too_many_arguments)] +pub async fn admin_execute_upgrade( + shell: &Shell, + ecosystem_config: &EcosystemConfig, + chain_contracts_config: &ContractsConfig, + governor: &Wallet, + upgrade_diamond_cut: Vec, + forge_args: &ForgeScriptArgs, + l1_rpc_url: String, +) -> anyhow::Result<()> { + // resume doesn't properly work here. + let mut forge_args = forge_args.clone(); + forge_args.resume = false; + + let admin_addr = chain_contracts_config.l1.chain_admin_addr; + let access_control_restriction = chain_contracts_config + .l1 + .access_control_restriction_addr + .context("no access_control_restriction_addr")?; + let diamond_proxy = chain_contracts_config.l1.diamond_proxy_addr; + + let calldata = ACCEPT_ADMIN + .encode( + "adminExecuteUpgrade", + ( + Token::Bytes(upgrade_diamond_cut), + admin_addr, + access_control_restriction, + diamond_proxy, + ), + ) + .unwrap(); + let foundry_contracts_path = ecosystem_config.path_to_l1_foundry(); + let forge = Forge::new(&foundry_contracts_path) + .script( + &ACCEPT_GOVERNANCE_SCRIPT_PARAMS.script(), + forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_broadcast() + .with_calldata(&calldata); + accept_ownership(shell, governor, forge).await +} + +#[allow(clippy::too_many_arguments)] +pub async fn admin_schedule_upgrade( + shell: &Shell, + ecosystem_config: &EcosystemConfig, + chain_contracts_config: &ContractsConfig, + new_protocol_version: U256, + timestamp: U256, + governor: &Wallet, + forge_args: &ForgeScriptArgs, + l1_rpc_url: String, +) -> anyhow::Result<()> { + // resume doesn't properly work here. + let mut forge_args = forge_args.clone(); + forge_args.resume = false; + + let admin_addr = chain_contracts_config.l1.chain_admin_addr; + let access_control_restriction = chain_contracts_config + .l1 + .access_control_restriction_addr + .context("no access_control_restriction_addr")?; + + let calldata = ACCEPT_ADMIN + .encode( + "adminScheduleUpgrade", + ( + admin_addr, + access_control_restriction, + new_protocol_version, + timestamp, + ), + ) + .unwrap(); + let foundry_contracts_path = ecosystem_config.path_to_l1_foundry(); + let forge = Forge::new(&foundry_contracts_path) + .script( + &ACCEPT_GOVERNANCE_SCRIPT_PARAMS.script(), + forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_broadcast() + .with_calldata(&calldata); + accept_ownership(shell, governor, forge).await +} + +#[allow(clippy::too_many_arguments)] +pub async fn admin_update_validator( + shell: &Shell, + ecosystem_config: &EcosystemConfig, + chain_config: &ChainConfig, + validator_timelock: Address, + validator: Address, + add_validator: bool, + governor: &Wallet, + forge_args: &ForgeScriptArgs, + l1_rpc_url: String, +) -> anyhow::Result<()> { + // resume doesn't properly work here. + let mut forge_args = forge_args.clone(); + forge_args.resume = false; + + let chain_contracts_config = chain_config.get_contracts_config()?; + + let admin_addr = chain_contracts_config.l1.chain_admin_addr; + let access_control_restriction = chain_contracts_config + .l1 + .access_control_restriction_addr + .context("no access_control_restriction_addr")?; + + let calldata = ACCEPT_ADMIN + .encode( + "updateValidator", + ( + admin_addr, + access_control_restriction, + validator_timelock, + chain_config.chain_id.as_u64(), + validator, + add_validator, + ), + ) + .unwrap(); + let foundry_contracts_path = ecosystem_config.path_to_l1_foundry(); + let forge = Forge::new(&foundry_contracts_path) + .script( + &ACCEPT_GOVERNANCE_SCRIPT_PARAMS.script(), + forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_broadcast() + .with_calldata(&calldata); + accept_ownership(shell, governor, forge).await +} + async fn accept_ownership( shell: &Shell, governor: &Wallet, diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/convert_to_gateway.rs b/zkstack_cli/crates/zkstack/src/commands/chain/convert_to_gateway.rs index fd5b7f5414f..e3637d3b834 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/convert_to_gateway.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/convert_to_gateway.rs @@ -36,6 +36,14 @@ lazy_static! { ]) .unwrap(), ); + + static ref DEPLOY_GATEWAY_CTM_INTERFACE: BaseContract = BaseContract::from( + parse_abi(&[ + "function prepareAddresses() public", + "function deployCTM() public", + ]) + .unwrap(), + ); } pub async fn run(args: ForgeScriptArgs, shell: &Shell) -> anyhow::Result<()> { @@ -55,7 +63,7 @@ pub async fn run(args: ForgeScriptArgs, shell: &Shell) -> anyhow::Result<()> { let chain_genesis_config = chain_config.get_genesis_config()?; // Firstly, deploying gateway contracts - let gateway_config = deploy_gateway_ctm( + let gateway_config = calculate_gateway_ctm( shell, args.clone(), &ecosystem_config, @@ -87,25 +95,39 @@ pub async fn run(args: ForgeScriptArgs, shell: &Shell) -> anyhow::Result<()> { let output = call_script( shell, - args, + args.clone(), &GATEWAY_PREPARATION_INTERFACE .encode("deployAndSetGatewayTransactionFilterer", ()) .unwrap(), &ecosystem_config, &chain_config, &chain_config.get_wallets_config()?.governor, - l1_url, + l1_url.clone(), ) .await?; chain_contracts_config.set_transaction_filterer(output.gateway_transaction_filterer_proxy); + // We could've deployed the CTM at the beginning however, to be closer to how the actual upgrade + // looks like we'll do it as the last step + + deploy_gateway_ctm( + shell, + args, + &ecosystem_config, + &chain_config, + &chain_genesis_config, + &ecosystem_config.get_initial_deployment_config().unwrap(), + l1_url, + ) + .await?; + chain_contracts_config.save_with_base_path(shell, chain_config.configs)?; Ok(()) } -async fn deploy_gateway_ctm( +async fn calculate_gateway_ctm( shell: &Shell, forge_args: ForgeScriptArgs, config: &EcosystemConfig, @@ -126,10 +148,15 @@ async fn deploy_gateway_ctm( ); deploy_config.save(shell, deploy_config_path)?; + let calldata = DEPLOY_GATEWAY_CTM_INTERFACE + .encode("deployCTM", ()) + .unwrap(); + let mut forge = Forge::new(&config.path_to_l1_foundry()) .script(&DEPLOY_GATEWAY_CTM.script(), forge_args.clone()) .with_ffi() .with_rpc_url(l1_rpc_url) + .with_calldata(&calldata) .with_broadcast(); // Governor private key should not be needed for this script @@ -147,6 +174,46 @@ async fn deploy_gateway_ctm( Ok(gateway_config) } +async fn deploy_gateway_ctm( + shell: &Shell, + forge_args: ForgeScriptArgs, + config: &EcosystemConfig, + chain_config: &ChainConfig, + chain_genesis_config: &GenesisConfig, + initial_deployemnt_config: &InitialDeploymentConfig, + l1_rpc_url: String, +) -> anyhow::Result<()> { + let contracts_config = chain_config.get_contracts_config()?; + let deploy_config_path = DEPLOY_GATEWAY_CTM.input(&config.link_to_code); + + let deploy_config = DeployGatewayCTMInput::new( + chain_config, + config, + chain_genesis_config, + &contracts_config, + initial_deployemnt_config, + ); + deploy_config.save(shell, deploy_config_path)?; + + let calldata = DEPLOY_GATEWAY_CTM_INTERFACE + .encode("prepareAddresses", ()) + .unwrap(); + + let mut forge = Forge::new(&config.path_to_l1_foundry()) + .script(&DEPLOY_GATEWAY_CTM.script(), forge_args.clone()) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_calldata(&calldata) + .with_broadcast(); + + // Governor private key should not be needed for this script + forge = fill_forge_private_key(forge, config.get_wallets()?.deployer.as_ref())?; + check_the_balance(&forge).await?; + forge.run(shell)?; + + Ok(()) +} + async fn gateway_governance_whitelisting( shell: &Shell, forge_args: ForgeScriptArgs, diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/deploy_l2_contracts.rs b/zkstack_cli/crates/zkstack/src/commands/chain/deploy_l2_contracts.rs index 578069546f9..192a384d8e3 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/deploy_l2_contracts.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/deploy_l2_contracts.rs @@ -3,8 +3,8 @@ use std::path::Path; use anyhow::Context; use common::{ // contracts::build_l2_contracts, + contracts::build_l2_contracts, forge::{Forge, ForgeScriptArgs}, - hardhat::build_l2_contracts, spinner::Spinner, }; use config::{ @@ -122,7 +122,7 @@ async fn build_and_deploy( signature: Option<&str>, mut update_config: impl FnMut(&Shell, &Path) -> anyhow::Result<()>, ) -> anyhow::Result<()> { - build_l2_contracts(shell, &ecosystem_config.link_to_code)?; + build_l2_contracts(shell.clone(), ecosystem_config.link_to_code.clone())?; call_forge(shell, chain_config, ecosystem_config, forge_args, signature).await?; update_config( shell, diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/gateway_upgrade.rs b/zkstack_cli/crates/zkstack/src/commands/chain/gateway_upgrade.rs new file mode 100644 index 00000000000..9b06e001aa3 --- /dev/null +++ b/zkstack_cli/crates/zkstack/src/commands/chain/gateway_upgrade.rs @@ -0,0 +1,467 @@ +use anyhow::Context; +use clap::{Parser, ValueEnum}; +use common::{ + config::global_config, + forge::{Forge, ForgeScriptArgs}, +}; +use config::{ + forge_interface::{ + gateway_chain_upgrade::{ + input::GatewayChainUpgradeInput, output::GatewayChainUpgradeOutput, + }, + gateway_ecosystem_upgrade::output::GatewayEcosystemUpgradeOutput, + script_params::GATEWAY_UPGRADE_CHAIN_PARAMS, + }, + traits::{ReadConfig, ReadConfigWithBasePath, SaveConfig, SaveConfigWithBasePath}, + ChainConfig, EcosystemConfig, +}; +use ethers::{ + abi::{decode, encode, parse_abi, ParamType}, + contract::BaseContract, + utils::hex, +}; +use lazy_static::lazy_static; +use serde::{Deserialize, Serialize}; +use strum::EnumIter; +use types::L1BatchCommitmentMode; +use xshell::Shell; +use zksync_basic_types::{H256, U256}; +use zksync_eth_client::EthInterface; +use zksync_types::{ + web3::{keccak256, CallRequest}, + Address, L2_NATIVE_TOKEN_VAULT_ADDRESS, +}; +use zksync_web3_decl::client::{Client, L1}; + +use crate::{ + accept_ownership::{ + admin_execute_upgrade, admin_schedule_upgrade, admin_update_validator, + set_da_validator_pair, + }, + messages::{MSG_CHAIN_NOT_INITIALIZED, MSG_L1_SECRETS_MUST_BE_PRESENTED}, + utils::forge::fill_forge_private_key, +}; + +lazy_static! { + static ref ZK_CHAIN: BaseContract = + BaseContract::from(parse_abi(&["function getPriorityTreeStartIndex() public",]).unwrap(),); +} + +#[derive( + Debug, Serialize, Deserialize, Clone, Copy, ValueEnum, EnumIter, strum::Display, PartialEq, Eq, +)] +pub enum GatewayChainUpgradeStage { + // some config paaram + AdaptConfig, + + // Does not require admin, still needs to be done to update configs, etc + PrepareStage1, + + // Used to schedule an upgrade. + ScheduleStage1, + + // Should be executed after Stage1 of the governance upgrade + FinalizeStage1, + + // Mainly about changing configs + FinalizeStage2, + + // For tests in case a chain missed the correct window for the upgrade + // and needs to execute after Stage2 + KeepUpStage2, +} + +#[derive(Debug, Serialize, Deserialize, Parser)] +pub struct GatewayUpgradeArgs { + /// All ethereum environment related arguments + #[clap(flatten)] + #[serde(flatten)] + pub forge_args: ForgeScriptArgs, + + chain_upgrade_stage: GatewayChainUpgradeStage, +} + +// TODO: use a different script here (i.e. make it have a different file) +lazy_static! { + static ref GATEWAY_PREPARATION_INTERFACE: BaseContract = BaseContract::from( + parse_abi(&[ + "function startMigrateChainFromGateway(address chainAdmin,address accessControlRestriction,uint256 chainId) public", + "function finishMigrateChainFromGateway(uint256 migratingChainId,uint256 gatewayChainId,uint256 l2BatchNumber,uint256 l2MessageIndex,uint16 l2TxNumberInBatch,bytes memory message,bytes32[] memory merkleProof) public", + ]) + .unwrap(), + ); +} + +pub async fn run(args: GatewayUpgradeArgs, shell: &Shell) -> anyhow::Result<()> { + let ecosystem_config = EcosystemConfig::from_file(shell)?; + + let chain_name = global_config().chain_name.clone(); + let chain_config = ecosystem_config + .load_chain(chain_name) + .context(MSG_CHAIN_NOT_INITIALIZED)?; + + let l1_url = chain_config + .get_secrets_config()? + .l1 + .context(MSG_L1_SECRETS_MUST_BE_PRESENTED)? + .l1_rpc_url + .expose_str() + .to_string(); + + match args.chain_upgrade_stage { + GatewayChainUpgradeStage::AdaptConfig => adapt_config(shell, chain_config).await, + GatewayChainUpgradeStage::PrepareStage1 => { + prepare_stage1(shell, args, ecosystem_config, chain_config, l1_url).await + } + GatewayChainUpgradeStage::ScheduleStage1 => { + schedule_stage1(shell, args, ecosystem_config, chain_config, l1_url).await + } + GatewayChainUpgradeStage::FinalizeStage1 => { + finalize_stage1(shell, args, ecosystem_config, chain_config, l1_url).await + } + GatewayChainUpgradeStage::FinalizeStage2 => { + finalize_stage2(shell, ecosystem_config, chain_config).await + } + GatewayChainUpgradeStage::KeepUpStage2 => { + panic!("Not supported"); + } + } +} + +pub fn encode_ntv_asset_id(l1_chain_id: U256, addr: Address) -> H256 { + let encoded_data = encode(&[ + ethers::abi::Token::Uint(l1_chain_id), + ethers::abi::Token::Address(L2_NATIVE_TOKEN_VAULT_ADDRESS), + ethers::abi::Token::Address(addr), + ]); + + H256(keccak256(&encoded_data)) +} + +async fn adapt_config(shell: &Shell, chain_config: ChainConfig) -> anyhow::Result<()> { + println!("Adapting config"); + let mut contracts_config = chain_config.get_contracts_config()?; + let genesis_config = chain_config.get_genesis_config()?; + + contracts_config.l2.legacy_shared_bridge_addr = contracts_config.bridges.shared.l2_address; + contracts_config.l1.base_token_asset_id = Some(encode_ntv_asset_id( + genesis_config.l1_chain_id.0.into(), + contracts_config.l1.base_token_addr, + )); + + contracts_config.save_with_base_path(shell, &chain_config.configs)?; + println!("Done"); + + Ok(()) +} + +async fn prepare_stage1( + shell: &Shell, + args: GatewayUpgradeArgs, + ecosystem_config: EcosystemConfig, + chain_config: ChainConfig, + l1_url: String, +) -> anyhow::Result<()> { + let chain_upgrade_config_path = + GATEWAY_UPGRADE_CHAIN_PARAMS.input(&ecosystem_config.link_to_code); + + let gateway_upgrade_input = GatewayChainUpgradeInput::new(&chain_config); + gateway_upgrade_input.save(shell, chain_upgrade_config_path.clone())?; + + let mut forge = Forge::new(&ecosystem_config.path_to_l1_foundry()) + .script( + &GATEWAY_UPGRADE_CHAIN_PARAMS.script(), + args.forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_url) + .with_slow() + .with_broadcast(); + + forge = fill_forge_private_key(forge, Some(&chain_config.get_wallets_config()?.governor))?; + + println!("Preparing the chain for the upgrade!"); + + forge.run(shell)?; + + println!("done!"); + + let chain_output = GatewayChainUpgradeOutput::read( + shell, + GATEWAY_UPGRADE_CHAIN_PARAMS.output(&ecosystem_config.link_to_code), + )?; + + let gateway_ecosystem_preparation_output = + GatewayEcosystemUpgradeOutput::read_with_base_path(shell, ecosystem_config.config)?; + + // No need to save it, we have enough for now + + let mut contracts_config = chain_config.get_contracts_config()?; + + contracts_config.user_facing_bridgehub = + Some(contracts_config.ecosystem_contracts.bridgehub_proxy_addr); + contracts_config.user_facing_diamond_proxy = Some(contracts_config.l1.diamond_proxy_addr); + contracts_config + .ecosystem_contracts + .stm_deployment_tracker_proxy_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .bridgehub + .ctm_deployment_tracker_proxy_addr, + ); + // This is force deployment data for creating new contracts, not really relevant here tbh, + contracts_config.ecosystem_contracts.force_deployments_data = Some(hex::encode( + &gateway_ecosystem_preparation_output + .contracts_config + .force_deployments_data + .0, + )); + contracts_config.ecosystem_contracts.native_token_vault_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .native_token_vault_addr, + ); + contracts_config + .ecosystem_contracts + .l1_bytecodes_supplier_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .l1_bytecodes_supplier_addr, + ); + contracts_config.l1.access_control_restriction_addr = + Some(chain_output.access_control_restriction); + contracts_config.l1.chain_admin_addr = chain_output.chain_admin_addr; + + contracts_config.l1.rollup_l1_da_validator_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .rollup_l1_da_validator_addr, + ); + contracts_config.l1.validium_l1_da_validator_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .validium_l1_da_validator_addr, + ); + + let validum = chain_config + .get_genesis_config()? + .l1_batch_commit_data_generator_mode + == L1BatchCommitmentMode::Validium; + + // We do not use chain output because IMHO we should delete it altogether from there + contracts_config.l2.da_validator_addr = if !validum { + Some( + gateway_ecosystem_preparation_output + .contracts_config + .expected_rollup_l2_da_validator, + ) + } else { + Some( + gateway_ecosystem_preparation_output + .contracts_config + .expected_validium_l2_da_validator, + ) + }; + contracts_config.l2.l2_native_token_vault_proxy_addr = Some(L2_NATIVE_TOKEN_VAULT_ADDRESS); + contracts_config.l2.legacy_shared_bridge_addr = contracts_config.bridges.shared.l2_address; + + contracts_config.save_with_base_path(shell, chain_config.configs)?; + + Ok(()) +} + +async fn schedule_stage1( + shell: &Shell, + args: GatewayUpgradeArgs, + ecosystem_config: EcosystemConfig, + chain_config: ChainConfig, + l1_url: String, +) -> anyhow::Result<()> { + println!("Schedule stage1 of the upgrade!!"); + + admin_schedule_upgrade( + shell, + &ecosystem_config, + &chain_config.get_contracts_config()?, + // For now it is hardcoded both in scripts and here + U256::from(0x1900000000_u64), + // We only do instant upgrades for now + U256::zero(), + &chain_config.get_wallets_config()?.governor, + &args.forge_args, + l1_url.clone(), + ) + .await?; + + println!("done!"); + + Ok(()) +} + +async fn finalize_stage1( + shell: &Shell, + args: GatewayUpgradeArgs, + ecosystem_config: EcosystemConfig, + chain_config: ChainConfig, + l1_url: String, +) -> anyhow::Result<()> { + println!("Finalizing stage1 of chain upgrade!"); + + let mut geneal_config = chain_config.get_general_config()?; + let genesis_config = chain_config.get_genesis_config()?; + let mut contracts_config = chain_config.get_contracts_config()?; + let secrets_config = chain_config.get_secrets_config()?; + let gateway_ecosystem_preparation_output = + GatewayEcosystemUpgradeOutput::read_with_base_path(shell, &ecosystem_config.config)?; + + let old_validator_timelock = contracts_config.l1.validator_timelock_addr; + let new_validator_timelock = gateway_ecosystem_preparation_output + .deployed_addresses + .validator_timelock_addr; + + let validators = [ + chain_config.get_wallets_config()?.operator.address, + chain_config.get_wallets_config()?.blob_operator.address, + ]; + + println!("Setting new validators!"); + for val in validators { + admin_update_validator( + shell, + &ecosystem_config, + &chain_config, + old_validator_timelock, + val, + false, + &chain_config.get_wallets_config()?.governor, + &args.forge_args, + l1_url.clone(), + ) + .await?; + + admin_update_validator( + shell, + &ecosystem_config, + &chain_config, + new_validator_timelock, + val, + true, + &chain_config.get_wallets_config()?.governor, + &args.forge_args, + l1_url.clone(), + ) + .await?; + } + + println!("Setting new validators done!"); + + contracts_config.l1.validator_timelock_addr = gateway_ecosystem_preparation_output + .deployed_addresses + .validator_timelock_addr; + + admin_execute_upgrade( + shell, + &ecosystem_config, + &chain_config.get_contracts_config()?, + &chain_config.get_wallets_config()?.governor, + gateway_ecosystem_preparation_output + .chain_upgrade_diamond_cut + .0, + &args.forge_args, + l1_url.clone(), + ) + .await?; + + let l1_da_validator_contract = if chain_config + .get_genesis_config()? + .l1_batch_commit_data_generator_mode + == L1BatchCommitmentMode::Rollup + { + ecosystem_config + .get_contracts_config()? + .l1 + .rollup_l1_da_validator_addr + } else { + ecosystem_config + .get_contracts_config()? + .l1 + .validium_l1_da_validator_addr + } + .context("l1 da validator")?; + + set_da_validator_pair( + shell, + &ecosystem_config, + contracts_config.l1.chain_admin_addr, + &chain_config.get_wallets_config()?.governor, + contracts_config.l1.diamond_proxy_addr, + l1_da_validator_contract, + contracts_config + .l2 + .da_validator_addr + .context("l2_da_validator_addr")?, + &args.forge_args, + l1_url, + ) + .await?; + + let client = Box::new( + Client::::http(secrets_config.l1.clone().context("l1 secrets")?.l1_rpc_url) + .context("Client::new()")? + .for_network(genesis_config.l1_chain_id.into()) + .build(), + ); + let request = CallRequest { + to: Some(contracts_config.l1.diamond_proxy_addr), + data: Some( + zksync_types::ethabi::short_signature("getPriorityTreeStartIndex", &[]) + .to_vec() + .into(), + ), + ..Default::default() + }; + let result = client.call_contract_function(request, None).await?; + + let priority_tree_start_index = decode(&[ParamType::Uint(32)], &result.0)? + .pop() + .unwrap() + .into_uint() + .unwrap(); + + geneal_config + .eth + .as_mut() + .context("general_config_eth")? + .sender + .as_mut() + .context("eth sender")? + .priority_tree_start_index = Some(priority_tree_start_index.as_usize()); + + contracts_config.save_with_base_path(shell, &chain_config.configs)?; + geneal_config.save_with_base_path(shell, &chain_config.configs)?; + + println!("done!"); + + Ok(()) +} + +async fn finalize_stage2( + shell: &Shell, + ecosystem_config: EcosystemConfig, + chain_config: ChainConfig, +) -> anyhow::Result<()> { + println!("Finalizing stage2 for the chain! (just updating configs)"); + + let ecosystem_config = ecosystem_config.get_contracts_config()?; + + let mut contracts_config = chain_config.get_contracts_config()?; + contracts_config.bridges.l1_nullifier_addr = Some(contracts_config.bridges.shared.l1_address); + contracts_config.bridges.shared.l1_address = ecosystem_config.bridges.shared.l1_address; + contracts_config.bridges.shared.l2_address = + Some(zksync_system_constants::L2_ASSET_ROUTER_ADDRESS); + contracts_config.save_with_base_path(shell, &chain_config.configs)?; + + println!("done!"); + + Ok(()) +} diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs b/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs index 31c5c681e7d..36c9f4bc40b 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/init/configs.rs @@ -11,6 +11,7 @@ use crate::{ commands::{ chain::{ args::init::configs::{InitConfigsArgs, InitConfigsArgsFinal}, + gateway_upgrade::encode_ntv_asset_id, genesis, }, portal::update_portal_config, @@ -90,6 +91,10 @@ pub async fn init_configs( contracts_config.l1.governance_addr = Address::zero(); contracts_config.l1.chain_admin_addr = Address::zero(); contracts_config.l1.base_token_addr = chain_config.base_token.address; + contracts_config.l1.base_token_asset_id = Some(encode_ntv_asset_id( + genesis_config.l1_chain_id.0.into(), + contracts_config.l1.base_token_addr, + )); contracts_config.save_with_base_path(shell, &chain_config.configs)?; // Initialize secrets config diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/init/mod.rs b/zkstack_cli/crates/zkstack/src/commands/chain/init/mod.rs index 8157a131815..03f1e26186d 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/init/mod.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/init/mod.rs @@ -6,7 +6,7 @@ use types::{BaseToken, L1BatchCommitmentMode}; use xshell::Shell; use crate::{ - accept_ownership::{accept_admin, set_da_validator_pair}, + accept_ownership::{accept_admin, make_permanent_rollup, set_da_validator_pair}, commands::chain::{ args::init::{ configs::{InitConfigsArgs, InitConfigsArgsFinal}, @@ -125,7 +125,10 @@ pub async fn init( shell, ecosystem_config, &chain_config.get_wallets_config()?.governor, - chain_contracts.l1.access_control_restriction_addr, + chain_contracts + .l1 + .access_control_restriction_addr + .context("chain_contracts.l1.access_control_restriction_addr")?, chain_contracts.l1.diamond_proxy_addr, chain_config .get_wallets_config() @@ -167,14 +170,32 @@ pub async fn init( contracts_config.l1.chain_admin_addr, &chain_config.get_wallets_config()?.governor, contracts_config.l1.diamond_proxy_addr, - l1_da_validator_addr, - contracts_config.l2.da_validator_addr, + l1_da_validator_addr.context("l1_da_validator_addr")?, + contracts_config + .l2 + .da_validator_addr + .context("da_validator_addr")?, &init_args.forge_args.clone(), init_args.l1_rpc_url.clone(), ) .await?; spinner.finish(); + if !validium_mode { + println!("Making permanent rollup!"); + make_permanent_rollup( + shell, + ecosystem_config, + contracts_config.l1.chain_admin_addr, + &chain_config.get_wallets_config()?.governor, + contracts_config.l1.diamond_proxy_addr, + &init_args.forge_args.clone(), + init_args.l1_rpc_url.clone(), + ) + .await?; + println!("Done"); + } + // Setup legacy bridge - shouldn't be used for new chains (run by L1 Governor) if let Some(true) = chain_config.legacy_bridge { setup_legacy_bridge( diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/migrate_from_gateway.rs b/zkstack_cli/crates/zkstack/src/commands/chain/migrate_from_gateway.rs index dca212778fa..a5d7cbba8ce 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/migrate_from_gateway.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/migrate_from_gateway.rs @@ -113,7 +113,7 @@ pub async fn run(args: MigrateFromGatewayArgs, shell: &Shell) -> anyhow::Result< "startMigrateChainFromGateway", ( chain_admin_addr, - chain_access_control_restriction, + chain_access_control_restriction.context("chain_access_control_restriction")?, U256::from(chain_config.chain_id.0), ), ) diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/migrate_to_gateway.rs b/zkstack_cli/crates/zkstack/src/commands/chain/migrate_to_gateway.rs index fd2a78e35da..5de821770a5 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/migrate_to_gateway.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/migrate_to_gateway.rs @@ -104,8 +104,10 @@ pub async fn run(args: MigrateToGatewayArgs, shell: &Shell) -> anyhow::Result<() let chain_contracts_config = chain_config.get_contracts_config().unwrap(); let chain_admin_addr = chain_contracts_config.l1.chain_admin_addr; - let chain_access_control_restriction = - chain_contracts_config.l1.access_control_restriction_addr; + let chain_access_control_restriction = chain_contracts_config + .l1 + .access_control_restriction_addr + .context("chain_access_control_restriction")?; println!("Whitelisting the chains' addresseses..."); call_script( @@ -118,7 +120,8 @@ pub async fn run(args: MigrateToGatewayArgs, shell: &Shell) -> anyhow::Result<() gateway_chain_config .get_contracts_config()? .l1 - .transaction_filterer_addr, + .transaction_filterer_addr + .context("transaction_filterer_addr")?, vec![ chain_config.get_wallets_config()?.governor.address, chain_config.get_contracts_config()?.l1.chain_admin_addr, @@ -213,7 +216,10 @@ pub async fn run(args: MigrateToGatewayArgs, shell: &Shell) -> anyhow::Result<() chain_access_control_restriction, U256::from(chain_config.chain_id.0), gateway_da_validator_address, - chain_contracts_config.l2.da_validator_addr, + chain_contracts_config + .l2 + .da_validator_addr + .context("da_validator_addr")?, new_diamond_proxy_address, ), ) diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/mod.rs b/zkstack_cli/crates/zkstack/src/commands/chain/mod.rs index 4846ac5e891..94a65b9138c 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/mod.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/mod.rs @@ -3,6 +3,7 @@ use args::build_transactions::BuildTransactionsArgs; pub(crate) use args::create::ChainCreateArgsFinal; use clap::{command, Subcommand}; pub(crate) use create::create_chain_inner; +use gateway_upgrade::GatewayUpgradeArgs; use migrate_from_gateway::MigrateFromGatewayArgs; use migrate_to_gateway::MigrateToGatewayArgs; use xshell::Shell; @@ -20,6 +21,7 @@ mod convert_to_gateway; mod create; pub mod deploy_l2_contracts; pub mod deploy_paymaster; +pub mod gateway_upgrade; pub mod genesis; pub mod init; mod migrate_from_gateway; @@ -75,6 +77,8 @@ pub enum ChainCommands { MigrateToGateway(MigrateToGatewayArgs), /// Migrate chain from gateway MigrateFromGateway(MigrateFromGatewayArgs), + /// Upgrade to the protocol version that supports Gateway + GatewayUpgrade(GatewayUpgradeArgs), } pub(crate) async fn run(shell: &Shell, args: ChainCommands) -> anyhow::Result<()> { @@ -107,5 +111,6 @@ pub(crate) async fn run(shell: &Shell, args: ChainCommands) -> anyhow::Result<() ChainCommands::ConvertToGateway(args) => convert_to_gateway::run(args, shell).await, ChainCommands::MigrateToGateway(args) => migrate_to_gateway::run(args, shell).await, ChainCommands::MigrateFromGateway(args) => migrate_from_gateway::run(args, shell).await, + ChainCommands::GatewayUpgrade(args) => gateway_upgrade::run(args, shell).await, } } diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/set_token_multiplier_setter.rs b/zkstack_cli/crates/zkstack/src/commands/chain/set_token_multiplier_setter.rs index d9d8994af87..dcce57e5ca0 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/set_token_multiplier_setter.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/set_token_multiplier_setter.rs @@ -54,7 +54,10 @@ pub async fn run(args: ForgeScriptArgs, shell: &Shell) -> anyhow::Result<()> { shell, &ecosystem_config, &chain_config.get_wallets_config()?.governor, - contracts_config.l1.access_control_restriction_addr, + contracts_config + .l1 + .access_control_restriction_addr + .context("access_control_restriction_addr")?, contracts_config.l1.diamond_proxy_addr, token_multiplier_setter_address, &args.clone(), diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/gateway_upgrade.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/gateway_upgrade.rs new file mode 100644 index 00000000000..593c1bc3f06 --- /dev/null +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/gateway_upgrade.rs @@ -0,0 +1,88 @@ +use std::path::PathBuf; + +use clap::{Parser, ValueEnum}; +use common::{forge::ForgeScriptArgs, Prompt}; +use serde::{Deserialize, Serialize}; +use strum::EnumIter; +use types::L1Network; +use url::Url; + +use crate::{ + defaults::LOCAL_RPC_URL, + messages::{MSG_L1_RPC_URL_HELP, MSG_L1_RPC_URL_INVALID_ERR, MSG_L1_RPC_URL_PROMPT}, +}; + +#[derive( + Debug, Serialize, Deserialize, Clone, Copy, ValueEnum, EnumIter, strum::Display, PartialEq, Eq, +)] +pub enum GatewayUpgradeStage { + // Deploy contracts + init everything the governance will need to approve the upgrade + NoGovernancePrepare, + // Governance will execute stage 1 of the upgrade, which appends + // a new protocol version and all chains involved must upgrade + GovernanceStage1, + // Governance will execute stage 2 of the upgrade. It is CRUCIAL + // to have it done only after protocol deadline has passed. + GovernanceStage2, + // Finish finalizing tokens, chains, etc + NoGovernanceStage2, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Parser)] +pub struct GatewayUpgradeArgs { + #[clap(flatten)] + #[serde(flatten)] + pub forge_args: ForgeScriptArgs, + #[clap(long, value_enum)] + ecosystem_upgrade_stage: GatewayUpgradeStage, + /// Path to ecosystem contracts + #[clap(long)] + pub ecosystem_contracts_path: Option, + #[clap(long, help = MSG_L1_RPC_URL_HELP)] + pub l1_rpc_url: Option, +} + +impl GatewayUpgradeArgs { + pub fn fill_values_with_prompt( + self, + l1_network: L1Network, + dev: bool, + ) -> GatewayUpgradeArgsFinal { + let l1_rpc_url = self.l1_rpc_url.unwrap_or_else(|| { + let mut prompt = Prompt::new(MSG_L1_RPC_URL_PROMPT); + if dev { + return LOCAL_RPC_URL.to_string(); + } + if l1_network == L1Network::Localhost { + prompt = prompt.default(LOCAL_RPC_URL); + } + prompt + .validate_with(|val: &String| -> Result<(), String> { + Url::parse(val) + .map(|_| ()) + .map_err(|_| MSG_L1_RPC_URL_INVALID_ERR.to_string()) + }) + .ask() + }); + GatewayUpgradeArgsFinal { + forge_args: self.forge_args, + ecosystem_upgrade_stage: self.ecosystem_upgrade_stage, + ecosystem_contracts_path: self.ecosystem_contracts_path, + l1_rpc_url, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, Parser)] +pub struct GatewayUpgradeArgsFinal { + #[clap(flatten)] + #[serde(flatten)] + pub forge_args: ForgeScriptArgs, + #[clap(long, value_enum)] + pub ecosystem_upgrade_stage: GatewayUpgradeStage, + /// Path to ecosystem contracts + #[clap(long)] + pub ecosystem_contracts_path: Option, + #[clap(long, help = MSG_L1_RPC_URL_HELP)] + pub l1_rpc_url: String, +} diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/mod.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/mod.rs index c25eebda3d6..9ee2deacdb1 100644 --- a/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/mod.rs +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/args/mod.rs @@ -1,4 +1,5 @@ pub mod build_transactions; pub mod change_default; pub mod create; +pub mod gateway_upgrade; pub mod init; diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/gateway_upgrade.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/gateway_upgrade.rs new file mode 100644 index 00000000000..5acd979100c --- /dev/null +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/gateway_upgrade.rs @@ -0,0 +1,347 @@ +use anyhow::Context; +use common::{forge::Forge, git, spinner::Spinner}; +use config::{ + forge_interface::{ + gateway_ecosystem_upgrade::{ + input::GatewayEcosystemUpgradeInput, output::GatewayEcosystemUpgradeOutput, + }, + script_params::{FINALIZE_UPGRADE_SCRIPT_PARAMS, GATEWAY_UPGRADE_ECOSYSTEM_PARAMS}, + }, + traits::{ReadConfig, ReadConfigWithBasePath, SaveConfig, SaveConfigWithBasePath}, + EcosystemConfig, GenesisConfig, CONFIGS_PATH, +}; +use ethers::{abi::parse_abi, contract::BaseContract, utils::hex}; +use lazy_static::lazy_static; +use types::ProverMode; +use xshell::Shell; +use zksync_types::{H160, L2_NATIVE_TOKEN_VAULT_ADDRESS, SHARED_BRIDGE_ETHER_TOKEN_ADDRESS, U256}; + +use super::args::gateway_upgrade::{GatewayUpgradeArgs, GatewayUpgradeArgsFinal}; +use crate::{ + accept_ownership::governance_execute_calls, + commands::ecosystem::args::gateway_upgrade::GatewayUpgradeStage, + messages::MSG_INTALLING_DEPS_SPINNER, utils::forge::fill_forge_private_key, +}; + +pub async fn run(args: GatewayUpgradeArgs, shell: &Shell) -> anyhow::Result<()> { + println!("Running ecosystem gateway upgrade args"); + + let ecosystem_config = EcosystemConfig::from_file(shell)?; + git::submodule_update(shell, ecosystem_config.link_to_code.clone())?; + + let mut final_ecosystem_args = args.fill_values_with_prompt(ecosystem_config.l1_network, true); + + match final_ecosystem_args.ecosystem_upgrade_stage { + GatewayUpgradeStage::NoGovernancePrepare => { + no_governance_prepare(&mut final_ecosystem_args, shell, &ecosystem_config).await?; + } + GatewayUpgradeStage::GovernanceStage1 => { + governance_stage_1(&mut final_ecosystem_args, shell, &ecosystem_config).await?; + } + GatewayUpgradeStage::GovernanceStage2 => { + governance_stage_2(&mut final_ecosystem_args, shell, &ecosystem_config).await?; + } + GatewayUpgradeStage::NoGovernanceStage2 => { + no_governance_stage_2(&mut final_ecosystem_args, shell, &ecosystem_config).await?; + } + } + + Ok(()) +} + +async fn no_governance_prepare( + init_args: &mut GatewayUpgradeArgsFinal, + shell: &Shell, + ecosystem_config: &EcosystemConfig, +) -> anyhow::Result<()> { + let spinner = Spinner::new(MSG_INTALLING_DEPS_SPINNER); + spinner.finish(); + + let forge_args = init_args.forge_args.clone(); + let l1_rpc_url = init_args.l1_rpc_url.clone(); + + let new_genesis_config = GenesisConfig::read_with_base_path(shell, CONFIGS_PATH)?; + let current_contracts_config = ecosystem_config.get_contracts_config()?; + let initial_deployment_config = ecosystem_config.get_initial_deployment_config()?; + let wallets_config = ecosystem_config.get_wallets()?; + + let ecosystem_upgrade_config_path = + GATEWAY_UPGRADE_ECOSYSTEM_PARAMS.input(&ecosystem_config.link_to_code); + + let era_config = ecosystem_config + .load_chain(Some("era".to_string())) + .context("No era")?; + + // FIXME: we will have to force this in production environment + // assert_eq!(era_config.chain_id, ecosystem_config.era_chain_id); + + let gateway_upgrade_input = GatewayEcosystemUpgradeInput::new( + &new_genesis_config, + ¤t_contracts_config, + &initial_deployment_config, + &wallets_config, + ecosystem_config.era_chain_id, + // FIXME: provide correct era diamond proxy + era_config.get_contracts_config()?.l1.diamond_proxy_addr, + ecosystem_config.prover_version == ProverMode::NoProofs, + ); + gateway_upgrade_input.save(shell, ecosystem_upgrade_config_path.clone())?; + + let mut forge = Forge::new(&ecosystem_config.path_to_l1_foundry()) + .script( + &GATEWAY_UPGRADE_ECOSYSTEM_PARAMS.script(), + forge_args.clone(), + ) + .with_ffi() + .with_rpc_url(l1_rpc_url) + .with_slow() + .with_broadcast(); + + forge = fill_forge_private_key(forge, ecosystem_config.get_wallets()?.deployer.as_ref())?; + + println!("Preparing the ecosystem for the upgrade!"); + + forge.run(shell)?; + + println!("done!"); + + let output = GatewayEcosystemUpgradeOutput::read( + shell, + GATEWAY_UPGRADE_ECOSYSTEM_PARAMS.output(&ecosystem_config.link_to_code), + )?; + output.save_with_base_path(shell, &ecosystem_config.config)?; + + Ok(()) +} + +// Governance has approved the proposal, now it will insert the new protocol version into our STM (CTM) +async fn governance_stage_1( + init_args: &mut GatewayUpgradeArgsFinal, + shell: &Shell, + ecosystem_config: &EcosystemConfig, +) -> anyhow::Result<()> { + println!("Executing governance stage 1!"); + + let previous_output = GatewayEcosystemUpgradeOutput::read( + shell, + GATEWAY_UPGRADE_ECOSYSTEM_PARAMS.output(&ecosystem_config.link_to_code), + )?; + previous_output.save_with_base_path(shell, &ecosystem_config.config)?; + + // These are ABI-encoded + let stage1_calls = previous_output.governance_stage1_calls; + + governance_execute_calls( + shell, + ecosystem_config, + &ecosystem_config.get_wallets()?.governor, + stage1_calls.0, + &init_args.forge_args.clone(), + init_args.l1_rpc_url.clone(), + ) + .await?; + + let gateway_ecosystem_preparation_output = + GatewayEcosystemUpgradeOutput::read_with_base_path(shell, &ecosystem_config.config)?; + + let mut contracts_config = ecosystem_config.get_contracts_config()?; + + contracts_config.user_facing_bridgehub = + Some(contracts_config.ecosystem_contracts.bridgehub_proxy_addr); + contracts_config.user_facing_diamond_proxy = Some(contracts_config.l1.diamond_proxy_addr); + contracts_config + .ecosystem_contracts + .stm_deployment_tracker_proxy_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .bridgehub + .ctm_deployment_tracker_proxy_addr, + ); + // This is force deployment data for creating new contracts, not really relevant here tbh, + contracts_config.ecosystem_contracts.force_deployments_data = Some(hex::encode( + &gateway_ecosystem_preparation_output + .contracts_config + .force_deployments_data + .0, + )); + contracts_config.ecosystem_contracts.native_token_vault_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .native_token_vault_addr, + ); + contracts_config + .ecosystem_contracts + .l1_bytecodes_supplier_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .l1_bytecodes_supplier_addr, + ); + + contracts_config.l1.rollup_l1_da_validator_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .rollup_l1_da_validator_addr, + ); + contracts_config.l1.validium_l1_da_validator_addr = Some( + gateway_ecosystem_preparation_output + .deployed_addresses + .validium_l1_da_validator_addr, + ); + + // This value is meaningless for the ecosystem, but we'll populate it for consistency + contracts_config.l2.da_validator_addr = Some(H160::zero()); + contracts_config.l2.l2_native_token_vault_proxy_addr = Some(L2_NATIVE_TOKEN_VAULT_ADDRESS); + contracts_config.l2.legacy_shared_bridge_addr = contracts_config.bridges.shared.l2_address; + + contracts_config.save_with_base_path(shell, &ecosystem_config.config)?; + + Ok(()) +} + +// Governance has approved the proposal, now it will insert the new protocol version into our STM (CTM) +async fn governance_stage_2( + init_args: &mut GatewayUpgradeArgsFinal, + shell: &Shell, + ecosystem_config: &EcosystemConfig, +) -> anyhow::Result<()> { + println!("Executing governance stage 2!"); + + let previous_output = + GatewayEcosystemUpgradeOutput::read_with_base_path(shell, &ecosystem_config.config)?; + + // These are ABI-encoded + let stage2_calls = previous_output.governance_stage2_calls; + + governance_execute_calls( + shell, + ecosystem_config, + &ecosystem_config.get_wallets()?.governor, + stage2_calls.0, + &init_args.forge_args.clone(), + init_args.l1_rpc_url.clone(), + ) + .await?; + + let mut contracts_config = ecosystem_config.get_contracts_config()?; + contracts_config.bridges.shared.l1_address = previous_output + .deployed_addresses + .bridges + .shared_bridge_proxy_addr; + + contracts_config.save_with_base_path(shell, &ecosystem_config.config)?; + println!("Stage2 finalized!"); + + Ok(()) +} + +lazy_static! { + static ref FINALIZE_UPGRADE: BaseContract = BaseContract::from( + parse_abi(&[ + "function initChains(address bridgehub, uint256[] chains) public", + "function initTokens(address l1NativeTokenVault, address[] tokens, uint256[] chains) public", + ]) + .unwrap(), + ); +} + +// Governance has approved the proposal, now it will insert the new protocol version into our STM (CTM) +async fn no_governance_stage_2( + init_args: &mut GatewayUpgradeArgsFinal, + shell: &Shell, + ecosystem_config: &EcosystemConfig, +) -> anyhow::Result<()> { + let contracts_config = ecosystem_config.get_contracts_config()?; + let wallets = ecosystem_config.get_wallets()?; + let deployer_private_key = wallets + .deployer + .context("deployer_wallet")? + .private_key_h256() + .context("deployer_priuvate_key")?; + + println!("Finalizing stage2 of the upgrade!"); + + let chains: Vec<_> = ecosystem_config + .list_of_chains() + .into_iter() + .map(|name| { + ecosystem_config + .load_chain(Some(name)) + .expect("Invalid chain") + }) + .collect(); + + let chain_ids: Vec<_> = chains + .into_iter() + .map(|c| ethers::abi::Token::Uint(U256::from(c.chain_id.as_u64()))) + .collect(); + let mut tokens: Vec<_> = ecosystem_config + .get_erc20_tokens() + .into_iter() + .map(|t| ethers::abi::Token::Address(t.address)) + .collect(); + let tokens_no_eth = tokens.clone(); + tokens.push(ethers::abi::Token::Address( + SHARED_BRIDGE_ETHER_TOKEN_ADDRESS, + )); + + // Resume for accept admin doesn't work properly. Foundry assumes that if signature of the function is the same, + // than it's the same call, but because we are calling this function multiple times during the init process, + // code assumes that doing only once is enough, but actually we need to accept admin multiple times + let mut forge_args = init_args.forge_args.clone(); + forge_args.resume = false; + + let init_chains_calldata = FINALIZE_UPGRADE + .encode( + "initChains", + ( + ethers::abi::Token::Address( + contracts_config.ecosystem_contracts.bridgehub_proxy_addr, + ), + ethers::abi::Token::Array(chain_ids.clone()), + ), + ) + .unwrap(); + let init_tokens_calldata = FINALIZE_UPGRADE + .encode( + "initTokens", + ( + ethers::abi::Token::Address( + contracts_config + .ecosystem_contracts + .native_token_vault_addr + .context("native_token_vault_addr")?, + ), + ethers::abi::Token::Array(tokens), + ethers::abi::Token::Array(chain_ids), + ), + ) + .unwrap(); + + println!("Initiing chains!"); + let foundry_contracts_path = ecosystem_config.path_to_l1_foundry(); + let forge = Forge::new(&foundry_contracts_path) + .script(&FINALIZE_UPGRADE_SCRIPT_PARAMS.script(), forge_args.clone()) + .with_ffi() + .with_rpc_url(init_args.l1_rpc_url.clone()) + .with_broadcast() + .with_calldata(&init_chains_calldata) + .with_private_key(deployer_private_key); + + forge.run(shell)?; + + println!("Initiing tokens!"); + + let forge = Forge::new(&foundry_contracts_path) + .script(&FINALIZE_UPGRADE_SCRIPT_PARAMS.script(), forge_args.clone()) + .with_ffi() + .with_rpc_url(init_args.l1_rpc_url.clone()) + .with_broadcast() + .with_calldata(&init_tokens_calldata) + .with_private_key(deployer_private_key); + + forge.run(shell)?; + + println!("Done!"); + + Ok(()) +} diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/init.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/init.rs index b823344f9b3..b240fb42d0c 100644 --- a/zkstack_cli/crates/zkstack/src/commands/ecosystem/init.rs +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/init.rs @@ -3,11 +3,9 @@ use std::{path::PathBuf, str::FromStr}; use anyhow::Context; use common::{ config::global_config, - contracts::build_system_contracts, + contracts::{build_l1_contracts, build_l2_contracts, build_system_contracts}, forge::{Forge, ForgeScriptArgs}, - git, - hardhat::{build_l1_contracts, build_l2_contracts}, - logger, + git, logger, spinner::Spinner, Prompt, }; @@ -117,9 +115,9 @@ async fn init_ecosystem( install_yarn_dependencies(shell, &ecosystem_config.link_to_code)?; if !init_args.skip_contract_compilation_override { build_da_contracts(shell, &ecosystem_config.link_to_code)?; - build_l1_contracts(shell, &ecosystem_config.link_to_code)?; + build_l1_contracts(shell.clone(), ecosystem_config.link_to_code.clone())?; build_system_contracts(shell.clone(), ecosystem_config.link_to_code.clone())?; - build_l2_contracts(shell, &ecosystem_config.link_to_code)?; + build_l2_contracts(shell.clone(), ecosystem_config.link_to_code.clone())?; } spinner.finish(); @@ -335,7 +333,8 @@ async fn deploy_ecosystem_inner( &config.get_wallets()?.governor, contracts_config .ecosystem_contracts - .stm_deployment_tracker_proxy_addr, + .stm_deployment_tracker_proxy_addr + .context("stm_deployment_tracker_proxy_addr")?, &forge_args, l1_rpc_url.clone(), ) @@ -382,8 +381,8 @@ async fn init_chains( deploy_paymaster, l1_rpc_url: Some(final_init_args.ecosystem.l1_rpc_url.clone()), no_port_reallocation: final_init_args.no_port_reallocation, - dev: final_init_args.dev, skip_submodules_checkout: final_init_args.skip_submodules_checkout, + dev: final_init_args.dev, }; let final_chain_init_args = chain_init_args.fill_values_with_prompt(&chain_config); diff --git a/zkstack_cli/crates/zkstack/src/commands/ecosystem/mod.rs b/zkstack_cli/crates/zkstack/src/commands/ecosystem/mod.rs index 3f4aa7565e1..d22ae109100 100644 --- a/zkstack_cli/crates/zkstack/src/commands/ecosystem/mod.rs +++ b/zkstack_cli/crates/zkstack/src/commands/ecosystem/mod.rs @@ -1,4 +1,4 @@ -use args::build_transactions::BuildTransactionsArgs; +use args::{build_transactions::BuildTransactionsArgs, gateway_upgrade::GatewayUpgradeArgs}; use clap::Subcommand; use xshell::Shell; @@ -12,6 +12,7 @@ mod change_default; mod common; mod create; pub mod create_configs; +mod gateway_upgrade; pub(crate) mod init; pub(crate) mod setup_observability; mod utils; @@ -34,6 +35,8 @@ pub enum EcosystemCommands { /// downloading Grafana dashboards from the era-observability repo #[command(alias = "obs")] SetupObservability, + /// Gateway version upgrade + GatewayUpgrade(GatewayUpgradeArgs), } pub(crate) async fn run(shell: &Shell, args: EcosystemCommands) -> anyhow::Result<()> { @@ -43,5 +46,6 @@ pub(crate) async fn run(shell: &Shell, args: EcosystemCommands) -> anyhow::Resul EcosystemCommands::Init(args) => init::run(args, shell).await, EcosystemCommands::ChangeDefaultChain(args) => change_default::run(args, shell), EcosystemCommands::SetupObservability => setup_observability::run(shell), + EcosystemCommands::GatewayUpgrade(args) => gateway_upgrade::run(args, shell).await, } }