Skip to content

Commit

Permalink
add size limit checks for Sierra and CASM programs
Browse files Browse the repository at this point in the history
  • Loading branch information
DelevoXDG committed Dec 19, 2024
1 parent f23fe58 commit 59e7f74
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
6 changes: 5 additions & 1 deletion scarb/src/compiler/compilers/starknet_contract/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use tracing::{debug, trace, trace_span};

use super::contract_selector::ContractSelector;
use crate::compiler::compilers::starknet_contract::contract_selector::GLOB_PATH_SELECTOR;
use crate::compiler::compilers::starknet_contract::validations::check_allowed_libfuncs;
use crate::compiler::compilers::starknet_contract::validations::{check_allowed_libfuncs, check_sierra_size_limits, check_casm_size_limits};
use crate::compiler::compilers::{ensure_gas_enabled, ArtifactsWriter};
use crate::compiler::helpers::{build_compiler_config, collect_main_crate_ids};
use crate::compiler::{CairoCompilationUnit, CompilationUnitAttributes, Compiler};
Expand Down Expand Up @@ -113,6 +113,8 @@ impl Compiler for StarknetContractCompiler {

check_allowed_libfuncs(&props, &contracts, &classes, db, &unit, ws)?;

check_sierra_size_limits(&classes, ws);

let casm_classes: Vec<Option<CasmContractClass>> = if props.casm {
let span = trace_span!("compile_sierra");
let _guard = span.enter();
Expand All @@ -135,6 +137,8 @@ impl Compiler for StarknetContractCompiler {
classes.iter().map(|_| None).collect()
};

check_casm_size_limits(&casm_classes, ws);

let target_name = &unit.main_component().target_name();

let writer = ArtifactsWriter::new(target_name.clone(), target_dir, props);
Expand Down
51 changes: 51 additions & 0 deletions scarb/src/compiler/compilers/starknet_contract/validations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ use cairo_lang_starknet_classes::allowed_libfuncs::{
AllowedLibfuncsError, ListSelector, BUILTIN_EXPERIMENTAL_LIBFUNCS_LIST,
};
use cairo_lang_starknet_classes::contract_class::ContractClass;
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
use cairo_lang_utils::Upcast;
use indoc::{formatdoc, writedoc};
use std::fmt::Write;
use std::iter::zip;
use tracing::debug;

const AUTO_WITHDRAW_GAS_FLAG: &str = "add_withdraw_gas";
const MAX_SIERRA_PROGRAM_FELTS: usize = 81290;
const MAX_CASM_PROGRAM_FELTS: usize = 81290;
const MAX_CONTRACT_CLASS_BYTES: usize = 4089446;
const MAX_COMPILED_CONTRACT_CLASS_BYTES: usize = 4089446;

pub fn ensure_gas_enabled(db: &mut RootDatabase) -> anyhow::Result<()> {
let flag = FlagId::new(db.as_files_group_mut(), AUTO_WITHDRAW_GAS_FLAG);
Expand Down Expand Up @@ -117,3 +122,49 @@ pub fn check_allowed_libfuncs(

Ok(())
}

pub fn check_sierra_size_limits(
classes: &[ContractClass],
ws: &Workspace<'_>,
) {
for class in classes {
let sierra_felts = class.sierra_program.to_vec().len();
if sierra_felts > MAX_SIERRA_PROGRAM_FELTS {
ws.config().ui().warn(formatdoc! {r#"
Sierra program exceeds maximum byte-code size:
{MAX_SIERRA_PROGRAM_FELTS} felts allowed on Starknet. Actual size: {sierra_felts} felts.
"#});
}

let class_size = serde_json::to_vec(class).unwrap().len();
if class_size > MAX_CONTRACT_CLASS_BYTES {
ws.config().ui().warn(formatdoc! {r#"
Contract class size exceeds maximum allowed size:
{MAX_CONTRACT_CLASS_BYTES} bytes allowed on Starknet. Actual size: {class_size} bytes.
"#});
}
}
}

pub fn check_casm_size_limits(
casm_classes: &[Option<CasmContractClass>],
ws: &Workspace<'_>,
) {
for casm_class in casm_classes.iter().flatten() {
let casm_felts = casm_class.bytecode.len();
if casm_felts > MAX_CASM_PROGRAM_FELTS {
ws.config().ui().warn(formatdoc! {r#"
CASM program exceeds maximum byte-code size:
{MAX_CASM_PROGRAM_FELTS} felts allowed on Starknet. Actual size: {casm_felts} felts.
"#});
}

let compiled_class_size = serde_json::to_vec(casm_class).unwrap().len();
if compiled_class_size > MAX_COMPILED_CONTRACT_CLASS_BYTES {
ws.config().ui().warn(formatdoc! {r#"
Compiled contract class size exceeds maximum allowed size:
{MAX_COMPILED_CONTRACT_CLASS_BYTES} bytes allowed on Starknet. Actual size: {compiled_class_size} bytes.
"#});
}
}
}

0 comments on commit 59e7f74

Please sign in to comment.