Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* Fix bug affecting cairo1 programs with input and System builtin [#2207](https://github.com/lambdaclass/cairo-vm/pull/2207)

* fix: Added `cairo_1_test_contracts` and `cairo_2_test_contracts` as dependencies for `test-extensive_hints` target [#2201](https://github.com/lambdaclass/cairo-vm/pull/2201)

* breaking: Store constants in Hint Data [#2191](https://github.com/lambdaclass/cairo-vm/pull/2191)
Expand Down
49 changes: 25 additions & 24 deletions cairo1-run/src/cairo_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ use num_bigint::{BigInt, Sign};
use num_traits::{cast::ToPrimitive, Zero};
use std::{collections::HashMap, iter::Peekable};

// Necessary memory gaps for the values created on the entry code of each implicit builtin
const SEGMENT_ARENA_GAPS: usize = 4;
const GAS_BUILTIN_GAPS: usize = 1;
const SYSTEM_BUILTIN_GAPS: usize = 1;

/// Representation of a cairo argument
/// Can consist of a single Felt or an array of Felts
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -469,20 +474,13 @@ fn load_arguments(
cairo_run_config: &Cairo1RunConfig,
main_func: &Function,
) -> Result<(), Error> {
let got_gas_builtin = main_func
.signature
.param_types
.iter()
.any(|ty| ty.debug_name.as_ref().is_some_and(|n| n == "GasBuiltin"));
let got_gas_builtin = got_implicit_builtin(&main_func.signature.param_types, "GasBuiltin");
if cairo_run_config.args.is_empty() && !got_gas_builtin {
// Nothing to be done
return Ok(());
}
let got_segment_arena = main_func
.signature
.param_types
.iter()
.any(|ty| ty.debug_name.as_ref().is_some_and(|n| n == "SegmentArena"));
let got_segment_arena = got_implicit_builtin(&main_func.signature.param_types, "SegmentArena");
let got_system_builtin = got_implicit_builtin(&main_func.signature.param_types, "System");
// This AP correction represents the memory slots taken up by the values created by `create_entry_code`:
// These include:
// * The builtin bases (not including output)
Expand All @@ -497,10 +495,13 @@ fn load_arguments(
ap_offset += runner.get_program().builtins_len() - 1;
}
if got_segment_arena {
ap_offset += 4;
ap_offset += SEGMENT_ARENA_GAPS;
}
if got_gas_builtin {
ap_offset += 1;
ap_offset += GAS_BUILTIN_GAPS;
}
if got_system_builtin {
ap_offset += SYSTEM_BUILTIN_GAPS;
}
for arg in cairo_run_config.args {
match arg {
Expand Down Expand Up @@ -547,16 +548,9 @@ fn create_entry_code(
) -> Result<(CasmContext, Vec<BuiltinName>), Error> {
let copy_to_output_builtin = config.copy_to_output();
let signature = &func.signature;
let got_segment_arena = signature.param_types.iter().any(|ty| {
get_info(sierra_program_registry, ty)
.map(|x| x.long_id.generic_id == SegmentArenaType::ID)
.unwrap_or_default()
});
let got_gas_builtin = signature.param_types.iter().any(|ty| {
get_info(sierra_program_registry, ty)
.map(|x| x.long_id.generic_id == GasBuiltinType::ID)
.unwrap_or_default()
});
let got_segment_arena = got_implicit_builtin(&signature.param_types, "SegmentArena");
let got_gas_builtin = got_implicit_builtin(&signature.param_types, "GasBuiltin");
let got_system_builtin = got_implicit_builtin(&signature.param_types, "System");
// The builtins in the formatting expected by the runner.
let (builtins, builtin_offset) =
get_function_builtins(&signature.param_types, copy_to_output_builtin);
Expand Down Expand Up @@ -738,10 +732,12 @@ fn create_entry_code(
// We lost the output_ptr var after re-scoping, so we need to create it again
// The last instruction will write the last output ptr so we can find it in [ap - 1]
let output_ptr = ctx.add_var(CellExpression::Deref(deref!([ap - 1])));
// len(builtins - output) + len(builtins) + if segment_arena: segment_arena_ptr + info_ptr + 0 + (segment_arena_ptr + 3) + (gas_builtin)
// len(builtins - output) + len(builtins) + if segment_arena: segment_arena_ptr +
// info_ptr + 0 + (segment_arena_ptr + 3) + (gas_builtin) + (system_builtin)
let offset = (2 * builtins.len() - 1
+ 4 * got_segment_arena as usize
+ got_gas_builtin as usize) as i16;
+ got_gas_builtin as usize
+ got_system_builtin as usize) as i16;
let array_start_ptr = ctx.add_var(CellExpression::Deref(deref!([fp + offset])));
let array_end_ptr = ctx.add_var(CellExpression::Deref(deref!([fp + offset + 1])));
casm_build_extend! {ctx,
Expand Down Expand Up @@ -1008,6 +1004,11 @@ fn check_only_array_felt_return_type(
_ => false,
}
}
fn got_implicit_builtin(param_types: &[ConcreteTypeId], builtin_name: &str) -> bool {
param_types
.iter()
.any(|ty| ty.debug_name.as_ref().is_some_and(|n| n == builtin_name))
}
Comment on lines +1007 to +1011
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use BuiltinName here instead of a &str, just to be safe. You can convert a ty.debug_name with BuiltinName::from(s)

Copy link
Contributor Author

@DiegoCivi DiegoCivi Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to implement it but there is no BuiltinName variant for the gas builtin or system builtin


fn is_panic_result(return_type_id: Option<&ConcreteTypeId>) -> bool {
return_type_id
Expand Down
21 changes: 21 additions & 0 deletions cairo1-run/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,27 @@ mod tests {
None,
None
)]
#[case(
"with_input/implicit_system_builtin.cairo",
"[1 2]",
"[1 2]",
Some("[1 2]"),
Some("[1 2]")
)]
#[case(
"with_input/implicit_gas_builtin.cairo",
"[1 2]",
"[1 2]",
Some("[1 2]"),
Some("[1 2]")
)]
#[case(
"with_input/system_segment_gas.cairo",
"[1 2]",
"[1 2]",
Some("[1 2]"),
Some("[1 2]")
)]
fn test_run_program(
#[case] program: &str,
#[case] expected_output: &str,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main(input: Array<felt252>) -> Array<felt252> {
core::internal::require_implicit::<GasBuiltin>();
input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main(input: Array<felt252>) -> Array<felt252> {
core::internal::require_implicit::<System>();
input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main(input:Array<felt252>) -> Array<felt252> {
core::internal::require_implicit::<System>();
let _elements: Felt252Dict<Nullable<Span<u8>>> = Default::default();
input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main(input: Array<felt252>) -> Array<felt252> {
core::internal::require_implicit::<GasBuiltin>();
input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main(input: Array<felt252>) -> Array<felt252> {
core::internal::require_implicit::<System>();
input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main(input:Array<felt252>) -> Array<felt252> {
core::internal::require_implicit::<System>();
let _elements: Felt252Dict<Nullable<Span<u8>>> = Default::default();
input
}
Loading