async fn build_and_deploy(
    shell: &Shell,
    chain_config: &ChainConfig,
    ecosystem_config: &EcosystemConfig,
    forge_args: ForgeScriptArgs,
    signature: Option<&str>,
    mut update_config: impl FnMut(&Shell, &Path) -> anyhow::Result<()>,
    with_broadcast: bool,
) -> anyhow::Result<()> {
    build_l2_contracts(shell.clone(), ecosystem_config.link_to_code.clone())?;
    call_forge(
        shell,
        chain_config,
        ecosystem_config,
        forge_args,
        signature,
        with_broadcast,
    )
    .await?;
    update_config(
        shell,
        &DEPLOY_L2_CONTRACTS_SCRIPT_PARAMS.output(&chain_config.path_to_l1_foundry()),
    )?;
    Ok(())
}
Build the L2 contracts, deploy one or all of them with `forge`, then update the config
by reading one or all outputs written by the deploy scripts.
zkstack_cli/crates/zkstack/src/commands/chain/deploy_l2_contracts.rs