pub async fn load_l1_batch_params(
        &self,
        storage: &mut Connection<'_, Core>,
        first_l2_block_in_batch: &FirstL2BlockInBatch,
        validation_computational_gas_limit: u32,
        chain_id: L2ChainId,
    ) -> anyhow::Result<(SystemEnv, L1BatchEnv, PubdataParams)> {
        anyhow::ensure!(
            first_l2_block_in_batch.l1_batch_number > L1BatchNumber(0),
            "Loading params for genesis L1 batch not supported"
        );
        // L1 batch timestamp is set to the timestamp of its first L2 block.
        let l1_batch_timestamp = first_l2_block_in_batch.header.timestamp;

        let prev_l1_batch_number = first_l2_block_in_batch.l1_batch_number - 1;
        tracing::info!("Getting previous L1 batch hash for batch #{prev_l1_batch_number}");
        let (prev_l1_batch_hash, prev_l1_batch_timestamp) = self
            .wait_for_l1_batch_params(storage, prev_l1_batch_number)
            .await
            .context("failed getting hash for previous L1 batch")?;
        tracing::info!("Got state root hash for previous L1 batch #{prev_l1_batch_number}: {prev_l1_batch_hash:?}");

        anyhow::ensure!(
            prev_l1_batch_timestamp < l1_batch_timestamp,
            "Invalid params for L1 batch #{}: Timestamp of previous L1 batch ({prev_l1_batch_timestamp}) >= \
             provisional L1 batch timestamp ({l1_batch_timestamp}), \
             meaning that L1 batch will be rejected by the bootloader",
            first_l2_block_in_batch.l1_batch_number
        );

        let prev_l2_block_number = first_l2_block_in_batch.header.number - 1;
        tracing::info!("Getting previous L2 block hash for L2 block #{prev_l2_block_number}");

        let prev_l2_block_hash = self.snapshot.as_ref().and_then(|snapshot| {
            (snapshot.l2_block_number == prev_l2_block_number).then_some(snapshot.l2_block_hash)
        });
        let prev_l2_block_hash = match prev_l2_block_hash {
            Some(hash) => hash,
            None => storage
                .blocks_web3_dal()
                .get_l2_block_hash(prev_l2_block_number)
                .await
                .map_err(DalError::generalize)?
                .context("previous L2 block disappeared from storage")?,
        };
        tracing::info!(
            "Got hash for previous L2 block #{prev_l2_block_number}: {prev_l2_block_hash:?}"
        );

        let contract_hashes = first_l2_block_in_batch.header.base_system_contracts_hashes;
        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,
            first_l2_block_in_batch.header.fee_account_address,
            l1_batch_timestamp,
            prev_l1_batch_hash,
            first_l2_block_in_batch.header.batch_fee_input,
            first_l2_block_in_batch.header.number,
            prev_l2_block_hash,
            base_system_contracts,
            validation_computational_gas_limit,
            first_l2_block_in_batch
                .header
                .protocol_version
                .context("`protocol_version` must be set for L2 block")?,
            first_l2_block_in_batch.header.virtual_blocks,
            chain_id,
        );

        Ok((
            system_env,
            l1_batch_env,
            first_l2_block_in_batch.header.pubdata_params,
        ))
    }
Loads VM-related L1 batch parameters for the specified batch.
core/lib/vm_executor/src/storage.rs