async fn try_from_init_calldata(
        init_calldata: &[u8],
        preimage_oracle: impl ProtocolUpgradePreimageOracle,
        chain_specific: Option<ZkChainSpecificUpgradeData>,
    ) -> anyhow::Result<Self> {
        let raw_data = init_calldata.get(4..).context("need >= 4 bytes")?;
        let mut upgrade =
            abi::ProposedUpgrade::decode(raw_data).context("ProposedUpgrade::decode()")?;

        let bootloader_hash = H256(upgrade.bootloader_hash);
        let default_account_hash = H256(upgrade.default_account_hash);
        let evm_emulator_hash = H256(upgrade.evm_emulator_hash);

        let version = ProtocolSemanticVersion::try_from_packed(upgrade.new_protocol_version)
            .map_err(|err| anyhow::format_err!("Version is not supported: {err}"))?;
        let tx = if upgrade.l2_protocol_upgrade_tx.tx_type != U256::zero() {
            let factory_deps = if version.minor.is_pre_gateway() {
                upgrade.factory_deps.clone().unwrap()
            } else {
                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::<ProtocolUpgradeTx>(): {err}"))?,
            )
        } else {
            None
        };

        Ok(Self {
            version,
            bootloader_code_hash: (bootloader_hash != H256::zero()).then_some(bootloader_hash),
            default_account_code_hash: (default_account_hash != H256::zero())
                .then_some(default_account_hash),
            evm_emulator_code_hash: (evm_emulator_hash != H256::zero())
                .then_some(evm_emulator_hash),
            verifier_params: (upgrade.verifier_params != abi::VerifierParams::default())
                .then_some(upgrade.verifier_params.into()),
            verifier_address: (upgrade.verifier != Address::zero()).then_some(upgrade.verifier),
            timestamp: upgrade.upgrade_timestamp.try_into().unwrap(),
            tx,
        })
    }
`l1-contracts/contracts/state-transition/libraries/diamond.sol:DiamondCutData.initCalldata`
core/lib/types/src/protocol_upgrade.rs