Skip to content

Commit 19ca512

Browse files
authored
feat(zk_toolbox): Add zks contracts (#2781)
## What ❔ Add zks contracts. Builds contracts
1 parent b82dfa4 commit 19ca512

File tree

5 files changed

+165
-4
lines changed

5 files changed

+165
-4
lines changed

zk_toolbox/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ Create a snapshot of the current chain:
320320
zks snapshot create
321321
```
322322

323+
### Contracts
324+
325+
Build contracts:
326+
327+
```bash
328+
zks contracts
329+
```
330+
323331
### Format
324332

325333
Format code:
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use std::path::PathBuf;
2+
3+
use clap::{Parser, ValueEnum};
4+
use common::{cmd::Cmd, logger, spinner::Spinner};
5+
use config::EcosystemConfig;
6+
use strum::EnumIter;
7+
use xshell::{cmd, Shell};
8+
9+
use crate::messages::{
10+
MSG_BUILDING_CONTRACTS, MSG_BUILDING_CONTRACTS_SUCCESS, MSG_BUILDING_L1_CONTRACTS_SPINNER,
11+
MSG_BUILDING_L2_CONTRACTS_SPINNER, MSG_BUILDING_SYSTEM_CONTRACTS_SPINNER,
12+
MSG_BUILD_L1_CONTRACTS_HELP, MSG_BUILD_L2_CONTRACTS_HELP, MSG_BUILD_SYSTEM_CONTRACTS_HELP,
13+
MSG_CONTRACTS_DEPS_SPINNER, MSG_NOTHING_TO_BUILD_MSG,
14+
};
15+
16+
#[derive(Debug, Parser)]
17+
pub struct ContractsArgs {
18+
#[clap(long, alias = "l1", help = MSG_BUILD_L1_CONTRACTS_HELP, default_missing_value = "true", num_args = 0..=1)]
19+
pub l1_contracts: Option<bool>,
20+
#[clap(long, alias = "l2", help = MSG_BUILD_L2_CONTRACTS_HELP, default_missing_value = "true", num_args = 0..=1)]
21+
pub l2_contracts: Option<bool>,
22+
#[clap(long, alias = "sc", help = MSG_BUILD_SYSTEM_CONTRACTS_HELP, default_missing_value = "true", num_args = 0..=1)]
23+
pub system_contracts: Option<bool>,
24+
}
25+
26+
impl ContractsArgs {
27+
fn contracts(&self) -> Vec<ContractType> {
28+
if self.l1_contracts.is_none()
29+
&& self.l2_contracts.is_none()
30+
&& self.system_contracts.is_none()
31+
{
32+
return vec![
33+
ContractType::L1,
34+
ContractType::L2,
35+
ContractType::SystemContracts,
36+
];
37+
}
38+
39+
let mut contracts = vec![];
40+
41+
if self.l1_contracts.unwrap_or(false) {
42+
contracts.push(ContractType::L1);
43+
}
44+
if self.l2_contracts.unwrap_or(false) {
45+
contracts.push(ContractType::L2);
46+
}
47+
if self.system_contracts.unwrap_or(false) {
48+
contracts.push(ContractType::SystemContracts);
49+
}
50+
51+
contracts
52+
}
53+
}
54+
55+
#[derive(Debug, ValueEnum, EnumIter, strum::Display, PartialEq, Eq, Clone, Copy)]
56+
#[strum(serialize_all = "lowercase")]
57+
pub enum ContractType {
58+
L1,
59+
L2,
60+
SystemContracts,
61+
}
62+
63+
#[derive(Debug)]
64+
struct ContractBuilder {
65+
dir: PathBuf,
66+
cmd: String,
67+
msg: String,
68+
}
69+
70+
impl ContractBuilder {
71+
fn new(ecosystem: &EcosystemConfig, contract_type: ContractType) -> Self {
72+
match contract_type {
73+
ContractType::L1 => Self {
74+
dir: ecosystem.path_to_foundry(),
75+
cmd: "forge build".to_string(),
76+
msg: MSG_BUILDING_L1_CONTRACTS_SPINNER.to_string(),
77+
},
78+
ContractType::L2 => Self {
79+
dir: ecosystem.link_to_code.clone(),
80+
cmd: "yarn l2-contracts build".to_string(),
81+
msg: MSG_BUILDING_L2_CONTRACTS_SPINNER.to_string(),
82+
},
83+
ContractType::SystemContracts => Self {
84+
dir: ecosystem.link_to_code.join("contracts"),
85+
cmd: "yarn sc build".to_string(),
86+
msg: MSG_BUILDING_SYSTEM_CONTRACTS_SPINNER.to_string(),
87+
},
88+
}
89+
}
90+
91+
fn build(&self, shell: &Shell) -> anyhow::Result<()> {
92+
let spinner = Spinner::new(&self.msg);
93+
let _dir_guard = shell.push_dir(&self.dir);
94+
95+
let mut args = self.cmd.split_whitespace().collect::<Vec<_>>();
96+
let command = args.remove(0); // It's safe to unwrap here because we know that the vec is not empty
97+
let mut cmd = cmd!(shell, "{command}");
98+
99+
for arg in args {
100+
cmd = cmd.arg(arg);
101+
}
102+
103+
Cmd::new(cmd).run()?;
104+
105+
spinner.finish();
106+
Ok(())
107+
}
108+
}
109+
110+
pub fn run(shell: &Shell, args: ContractsArgs) -> anyhow::Result<()> {
111+
let contracts = args.contracts();
112+
if contracts.is_empty() {
113+
logger::outro(MSG_NOTHING_TO_BUILD_MSG);
114+
return Ok(());
115+
}
116+
117+
logger::info(MSG_BUILDING_CONTRACTS);
118+
119+
let ecosystem = EcosystemConfig::from_file(shell)?;
120+
let link_to_code = ecosystem.link_to_code.clone();
121+
122+
let spinner = Spinner::new(MSG_CONTRACTS_DEPS_SPINNER);
123+
let _dir_guard = shell.push_dir(&link_to_code);
124+
Cmd::new(cmd!(shell, "yarn install")).run()?;
125+
spinner.finish();
126+
127+
contracts
128+
.iter()
129+
.map(|contract| ContractBuilder::new(&ecosystem, *contract))
130+
.try_for_each(|builder| builder.build(shell))?;
131+
132+
logger::outro(MSG_BUILDING_CONTRACTS_SUCCESS);
133+
134+
Ok(())
135+
}

zk_toolbox/crates/zk_supervisor/src/commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod clean;
2+
pub mod contracts;
23
pub mod database;
34
pub mod fmt;
45
pub mod lint;

zk_toolbox/crates/zk_supervisor/src/main.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clap::{Parser, Subcommand};
22
use commands::{
3-
database::DatabaseCommands, lint::LintArgs, snapshot::SnapshotCommands, test::TestCommands,
3+
contracts::ContractsArgs, database::DatabaseCommands, lint::LintArgs,
4+
snapshot::SnapshotCommands, test::TestCommands,
45
};
56
use common::{
67
check_general_prerequisites,
@@ -10,9 +11,9 @@ use common::{
1011
};
1112
use config::EcosystemConfig;
1213
use messages::{
13-
msg_global_chain_does_not_exist, MSG_PROVER_VERSION_ABOUT, MSG_SUBCOMMAND_CLEAN,
14-
MSG_SUBCOMMAND_DATABASE_ABOUT, MSG_SUBCOMMAND_FMT_ABOUT, MSG_SUBCOMMAND_LINT_ABOUT,
15-
MSG_SUBCOMMAND_SNAPSHOTS_CREATOR_ABOUT, MSG_SUBCOMMAND_TESTS_ABOUT,
14+
msg_global_chain_does_not_exist, MSG_CONTRACTS_ABOUT, MSG_PROVER_VERSION_ABOUT,
15+
MSG_SUBCOMMAND_CLEAN, MSG_SUBCOMMAND_DATABASE_ABOUT, MSG_SUBCOMMAND_FMT_ABOUT,
16+
MSG_SUBCOMMAND_LINT_ABOUT, MSG_SUBCOMMAND_SNAPSHOTS_CREATOR_ABOUT, MSG_SUBCOMMAND_TESTS_ABOUT,
1617
};
1718
use xshell::Shell;
1819

@@ -49,6 +50,8 @@ enum SupervisorSubcommands {
4950
Markdown,
5051
#[command(about = MSG_PROVER_VERSION_ABOUT)]
5152
ProverVersion,
53+
#[command(about = MSG_CONTRACTS_ABOUT)]
54+
Contracts(ContractsArgs),
5255
}
5356

5457
#[derive(Parser, Debug)]
@@ -106,6 +109,7 @@ async fn run_subcommand(args: Supervisor, shell: &Shell) -> anyhow::Result<()> {
106109
SupervisorSubcommands::Lint(args) => commands::lint::run(shell, args)?,
107110
SupervisorSubcommands::Fmt(args) => commands::fmt::run(shell.clone(), args).await?,
108111
SupervisorSubcommands::ProverVersion => commands::prover_version::run(shell).await?,
112+
SupervisorSubcommands::Contracts(args) => commands::contracts::run(shell, args)?,
109113
}
110114
Ok(())
111115
}

zk_toolbox/crates/zk_supervisor/src/messages.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub(super) const MSG_SUBCOMMAND_DATABASE_ABOUT: &str = "Database related command
1313
pub(super) const MSG_SUBCOMMAND_TESTS_ABOUT: &str = "Run tests";
1414
pub(super) const MSG_SUBCOMMAND_CLEAN: &str = "Clean artifacts";
1515
pub(super) const MSG_SUBCOMMAND_LINT_ABOUT: &str = "Lint code";
16+
pub(super) const MSG_CONTRACTS_ABOUT: &str = "Build contracts";
1617

1718
pub(super) const MSG_SUBCOMMAND_FMT_ABOUT: &str = "Format code";
1819

@@ -104,6 +105,18 @@ pub(super) const MSG_PROVER_TEST_SUCCESS: &str = "Prover tests ran successfully"
104105
pub(super) const MSG_POSTGRES_CONFIG_NOT_FOUND_ERR: &str = "Postgres config not found";
105106
pub(super) const MSG_RESETTING_TEST_DATABASES: &str = "Resetting test databases";
106107

108+
// Contract building related messages
109+
pub(super) const MSG_NOTHING_TO_BUILD_MSG: &str = "Nothing to build!";
110+
pub(super) const MSG_BUILDING_CONTRACTS: &str = "Building contracts";
111+
pub(super) const MSG_CONTRACTS_DEPS_SPINNER: &str = "Installing dependencies..";
112+
pub(super) const MSG_BUILDING_L2_CONTRACTS_SPINNER: &str = "Building L2 contracts..";
113+
pub(super) const MSG_BUILDING_L1_CONTRACTS_SPINNER: &str = "Building L1 contracts..";
114+
pub(super) const MSG_BUILDING_SYSTEM_CONTRACTS_SPINNER: &str = "Building system contracts..";
115+
pub(super) const MSG_BUILDING_CONTRACTS_SUCCESS: &str = "Contracts built successfully";
116+
pub(super) const MSG_BUILD_L1_CONTRACTS_HELP: &str = "Build L1 contracts";
117+
pub(super) const MSG_BUILD_L2_CONTRACTS_HELP: &str = "Build L2 contracts";
118+
pub(super) const MSG_BUILD_SYSTEM_CONTRACTS_HELP: &str = "Build system contracts";
119+
107120
// Integration tests related messages
108121
pub(super) fn msg_integration_tests_run(external_node: bool) -> String {
109122
let base = "Running integration tests";

0 commit comments

Comments
 (0)