@@ -303,31 +303,48 @@ use crate::transaction::test_utils::proof_facts_as_cairo_array;
303303 false ,
304304 true ;
305305 "Exclude l1 data gas: query" ) ]
306+ /// Tests the `get_execution_info` syscall by invoking `test_get_execution_info` across multiple
307+ /// contract implementations and transaction variants.
308+ ///
309+ /// Contracts covered:
310+ /// - `TestContract` (Cairo 1): uses `get_execution_info_v3_syscall()`, expects V3 `TxInfo`.
311+ /// - `SierraExecutionInfoV1Contract` (Cairo 1): uses `get_execution_info_syscall()`, expects V1
312+ /// `TxInfo`.
313+ /// - `LegacyTestContract` (Cairo 0, compiler v2.1.0): uses `get_execution_info()`, expects V1
314+ /// `TxInfo`.
315+ ///
316+ /// The test matrix varies execution mode (`Validate` vs `Execute`), tx version (V1 vs V3),
317+ /// query mode, and special account behaviors (v1-bound / data-gas / high-tip).
318+ /// In `Validate`, block info fields are rounded/zeroed; in `Execute`, they are populated normally.
319+
306320fn test_get_execution_info (
307321 test_contract : FeatureContract ,
308322 execution_mode : ExecutionMode ,
309- mut version : TransactionVersion ,
323+ version : TransactionVersion ,
310324 only_query : bool ,
311325 v1_bound_account : bool ,
312326 // Whether the tip is larger than `v1_bound_accounts_max_tip`.
313327 high_tip : bool ,
314328 exclude_l1_data_gas : bool ,
315329) {
316330 let mut test_contract_data: FeatureContractData = test_contract. into ( ) ;
331+
332+ // Override class hash for special account types that affect execution info behavior.
317333 if v1_bound_account {
318334 assert ! (
319335 !exclude_l1_data_gas,
320336 "Unable to set both exclude_l1_data_gas and v1_bound_account."
321337 ) ;
322- let optional_class_hash =
323- VersionedConstants :: latest_constants ( ) . os_constants . v1_bound_accounts_cairo1 . first ( ) ;
324- test_contract_data. class_hash =
325- * optional_class_hash. expect ( "No v1 bound accounts found in versioned constants." ) ;
338+ test_contract_data. class_hash = * VersionedConstants :: latest_constants ( )
339+ . os_constants
340+ . v1_bound_accounts_cairo1
341+ . first ( )
342+ . expect ( "No v1 bound accounts found in versioned constants." ) ;
326343 } else if exclude_l1_data_gas {
327344 test_contract_data. class_hash =
328345 * VersionedConstants :: latest_constants ( ) . os_constants . data_gas_accounts . first ( ) . unwrap ( ) ;
329346 }
330- // Set the erc20 version to be the same as the test contract version.
347+
331348 let erc20_version = test_contract. cairo_version ( ) ;
332349 let state = & mut test_state_inner (
333350 & ChainInfo :: create_for_testing ( ) ,
@@ -336,6 +353,8 @@ fn test_get_execution_info(
336353 & HashVersion :: V2 ,
337354 erc20_version,
338355 ) ;
356+
357+ // Build expected block info.
339358 let expected_block_info = match execution_mode {
340359 ExecutionMode :: Validate => [
341360 // Rounded block number.
@@ -351,56 +370,15 @@ fn test_get_execution_info(
351370 ] ,
352371 } ;
353372
373+ // Build transaction fields.
354374 let test_contract_address = test_contract. get_instance_address ( 0 ) ;
355-
356- // Transaction tip.
357- let tip = Tip ( VersionedConstants :: latest_constants ( ) . os_constants . v1_bound_accounts_max_tip . 0
358- + if high_tip { 1 } else { 0 } ) ;
359- let expected_tip = if version == TransactionVersion :: THREE { tip } else { Tip ( 0 ) } ;
360-
361375 let tx_hash = tx_hash ! ( 1991 ) ;
362-
363- let ( expected_unsupported_fields, expected_signature) = match test_contract {
364- FeatureContract :: LegacyTestContract => {
365- // Read and parse file content.
366- let raw_contract: serde_json:: Value =
367- serde_json:: from_str ( & test_contract. get_raw_class ( ) ) . expect ( "Error parsing JSON" ) ;
368- // Verify version.
369- if let Some ( compiler_version) = raw_contract[ "compiler_version" ] . as_str ( ) {
370- assert_eq ! ( compiler_version, "2.1.0" ) ;
371- } else {
372- panic ! ( "'compiler_version' not found or not a valid string in JSON." ) ;
373- } ;
374- ( vec ! [ ] , vec ! [ ] )
375- }
376- #[ cfg( feature = "cairo_native" ) ]
377- FeatureContract :: SierraExecutionInfoV1Contract ( RunnableCairo1 :: Native ) => ( vec ! [ ] , vec ! [ ] ) ,
378- _ => {
379- (
380- vec ! [
381- expected_tip. into( ) , // Tip.
382- Felt :: ZERO , // Paymaster data.
383- Felt :: ZERO , // Nonce DA.
384- Felt :: ZERO , // Fee DA.
385- Felt :: ZERO , // Account data.
386- ] ,
387- vec ! [ tx_hash. 0 ] ,
388- )
389- }
390- } ;
391-
392- let mut expected_version = if v1_bound_account && !high_tip { 1 . into ( ) } else { version. 0 } ;
393- if only_query {
394- let simulate_version_base = * QUERY_VERSION_BASE ;
395- let query_version = simulate_version_base + version. 0 ;
396- version = TransactionVersion ( query_version) ;
397- expected_version += simulate_version_base;
398- }
399-
400- let max_fee = Fee ( 42 ) ;
376+ let max_fee = if version == TransactionVersion :: ONE { Fee ( 42 ) } else { Fee ( 0 ) } ;
401377 let nonce = nonce ! ( 3_u16 ) ;
402378 let sender_address = test_contract_address;
403- let signature = TransactionSignature ( Arc :: new ( expected_signature) ) ;
379+ let tip = Tip ( VersionedConstants :: latest_constants ( ) . os_constants . v1_bound_accounts_max_tip . 0
380+ + if high_tip { 1 } else { 0 } ) ;
381+ let expected_tip = if version == TransactionVersion :: THREE { tip } else { Tip ( 0 ) } ;
404382
405383 let resource_bounds =
406384 ResourceBounds { max_amount : GasAmount ( 13 ) , max_price_per_unit : GasPrice ( 61 ) } ;
@@ -410,116 +388,125 @@ fn test_get_execution_info(
410388 l1_data_gas : resource_bounds,
411389 } ) ;
412390
413- let expected_resource_bounds: Vec < Felt > = match ( test_contract, version) {
414- ( FeatureContract :: LegacyTestContract , _) => vec ! [ ] ,
391+ // Sanity check: verify legacy contract has expected compiler version.
392+ if matches ! ( test_contract, FeatureContract :: LegacyTestContract ) {
393+ let raw_contract: serde_json:: Value =
394+ serde_json:: from_str ( & test_contract. get_raw_class ( ) ) . expect ( "Error parsing JSON" ) ;
395+ let compiler_version = raw_contract[ "compiler_version" ]
396+ . as_str ( )
397+ . expect ( "'compiler_version' not found or not a valid string in JSON." ) ;
398+ assert_eq ! ( compiler_version, "2.1.0" ) ;
399+ }
400+
401+ let expected_signature = match test_contract {
402+ FeatureContract :: LegacyTestContract => vec ! [ ] ,
415403 #[ cfg( feature = "cairo_native" ) ]
416- ( FeatureContract :: SierraExecutionInfoV1Contract ( RunnableCairo1 :: Native ) , _) => vec ! [ ] ,
417- ( _, version) if version == TransactionVersion :: ONE => vec ! [
418- felt!( 0_u16 ) , // Length of resource bounds array.
419- ] ,
420- ( _, _) => {
421- vec ! [ felt!( if exclude_l1_data_gas { 2_u8 } else { 3_u8 } ) ] // Length of resource bounds array.
422- . into_iter ( )
423- . chain (
424- valid_resource_bounds_as_felts ( & all_resource_bounds, exclude_l1_data_gas)
425- . unwrap ( )
426- . into_iter ( )
427- . flat_map ( |bounds| bounds. flatten ( ) ) ,
428- )
429- . collect ( )
430- }
404+ FeatureContract :: SierraExecutionInfoV1Contract ( RunnableCairo1 :: Native ) => vec ! [ ] ,
405+ FeatureContract :: TestContract ( _) => vec ! [ tx_hash. 0 ] ,
406+ _ => panic ! ( "Unsupported contract for this test." ) ,
431407 } ;
408+ let signature = TransactionSignature ( Arc :: new ( expected_signature) ) ;
432409
433- // Only transaction V3 supports non-trivial proof facts.
434- // TODO(Meshi): Make sure we do not change the version or the transaction.
435- let proof_facts = if version == TransactionVersion :: ONE {
436- ProofFacts :: default ( )
437- } else {
410+ let mut expected_version = if v1_bound_account && !high_tip { 1 . into ( ) } else { version. 0 } ;
411+ if only_query {
412+ expected_version += * QUERY_VERSION_BASE ;
413+ }
414+
415+ // Only V3 transactions support non-trivial proof facts.
416+ let proof_facts = if version == TransactionVersion :: THREE {
438417 ProofFacts :: snos_proof_facts_for_testing ( )
418+ } else {
419+ ProofFacts :: default ( )
439420 } ;
440421
441- let expected_tx_info: Vec < Felt > ;
442- let tx_info: TransactionInfo ;
443- if version == TransactionVersion :: ONE {
444- expected_tx_info = vec ! [
445- expected_version, // Transaction version.
446- * sender_address. 0 . key( ) , // Account address.
447- felt!( max_fee. 0 ) , // Max fee.
448- Felt :: ZERO , // Signature.
449- tx_hash. 0 , // Transaction hash.
450- felt!( & * CHAIN_ID_FOR_TESTS . as_hex( ) ) , // Chain ID.
451- nonce. 0 , // Nonce.
452- ] ;
422+ // Build transaction info object.
423+ let common_fields = CommonAccountFields {
424+ transaction_hash : tx_hash,
425+ version,
426+ signature,
427+ nonce,
428+ sender_address,
429+ only_query,
430+ } ;
453431
454- tx_info = TransactionInfo :: Deprecated ( DeprecatedTransactionInfo {
455- common_fields : CommonAccountFields {
456- transaction_hash : tx_hash,
457- version : TransactionVersion :: ONE ,
458- signature,
459- nonce,
460- sender_address,
461- only_query,
462- } ,
463- max_fee,
464- } ) ;
432+ let tx_info = if version == TransactionVersion :: ONE {
433+ TransactionInfo :: Deprecated ( DeprecatedTransactionInfo { common_fields, max_fee } )
465434 } else {
466- expected_tx_info = vec ! [
467- expected_version, // Transaction version.
468- * sender_address. 0 . key( ) , // Account address.
469- Felt :: ZERO , // Max fee.
470- Felt :: ZERO , // Signature.
471- tx_hash. 0 , // Transaction hash.
472- felt!( & * CHAIN_ID_FOR_TESTS . as_hex( ) ) , // Chain ID.
473- nonce. 0 , // Nonce.
474- ] ;
475-
476- tx_info = TransactionInfo :: Current ( CurrentTransactionInfo {
477- common_fields : CommonAccountFields {
478- transaction_hash : tx_hash,
479- version : TransactionVersion :: THREE ,
480- signature,
481- nonce,
482- sender_address,
483- only_query,
484- } ,
435+ TransactionInfo :: Current ( CurrentTransactionInfo {
436+ common_fields,
485437 resource_bounds : all_resource_bounds,
486438 tip,
487439 nonce_data_availability_mode : DataAvailabilityMode :: L1 ,
488440 fee_data_availability_mode : DataAvailabilityMode :: L1 ,
489441 paymaster_data : PaymasterData :: default ( ) ,
490442 account_deployment_data : AccountDeploymentData :: default ( ) ,
491443 proof_facts : proof_facts. clone ( ) ,
492- } ) ;
493- }
444+ } )
445+ } ;
494446
447+ // Build expected calldata to pass to the contract's test_get_execution_info entry point.
448+ // The contract will compare the syscall results with the expected values.
495449 let entry_point_selector = selector_from_name ( "test_get_execution_info" ) ;
450+
496451 let expected_call_info = vec ! [
497- felt!( 0_u16 ) , // Caller address.
498- * test_contract_address. 0 . key( ) , // Storage address.
499- entry_point_selector. 0 , // Entry point selector.
452+ felt!( 0_u16 ) , // Caller address.
453+ * test_contract_address. 0 . key( ) ,
454+ entry_point_selector. 0 ,
500455 ] ;
501456
502- let expected_proof_facts = proof_facts_as_cairo_array ( proof_facts) ;
503- let mut calldata = vec ! [
504- expected_block_info. to_vec( ) ,
505- expected_call_info,
506- expected_tx_info,
507- expected_resource_bounds. into_iter( ) . chain( expected_unsupported_fields) . collect( ) ,
457+ // TxInfo fields (shared between V1 and V3).
458+ let expected_tx_info = vec ! [
459+ expected_version,
460+ * sender_address. 0 . key( ) ,
461+ felt!( max_fee. 0 ) ,
462+ Felt :: ZERO , // Signature
463+ tx_hash. 0 ,
464+ felt!( & * CHAIN_ID_FOR_TESTS . as_hex( ) ) ,
465+ nonce. 0 ,
508466 ] ;
509467
510- // Only `TestContract` was updated to call the `get_execution_info_v3` that includes
511- // `proof_facts`. The other contracts continue to call `get_execution_info_v1`, so their
512- // calldata layout must remain unchanged.
468+ let mut calldata = vec ! [ expected_block_info. to_vec( ) , expected_call_info, expected_tx_info] ;
469+
470+ // TestContract uses get_execution_info_v3 which includes additional V3 fields.
471+ // The LegacyTestContract and SierraExecutionInfoV1Contract use get_execution_info_v1 and don't
472+ // expect these fields.
513473 if matches ! ( test_contract, FeatureContract :: TestContract ( _) ) {
514- calldata. push ( expected_proof_facts) ;
474+ let expected_resource_bounds: Vec < Felt > = if version == TransactionVersion :: ONE {
475+ vec ! [ felt!( 0_u16 ) ] // Empty resource bounds for V1.
476+ } else {
477+ let num_resources = if exclude_l1_data_gas { 2_u8 } else { 3_u8 } ;
478+ std:: iter:: once ( felt ! ( num_resources) )
479+ . chain (
480+ valid_resource_bounds_as_felts ( & all_resource_bounds, exclude_l1_data_gas)
481+ . unwrap ( )
482+ . into_iter ( )
483+ . flat_map ( |bounds| bounds. flatten ( ) ) ,
484+ )
485+ . collect ( )
486+ } ;
487+
488+ let expected_unsupported_fields = vec ! [
489+ expected_tip. into( ) ,
490+ Felt :: ZERO , // Paymaster data.
491+ Felt :: ZERO , // Nonce DA mode.
492+ Felt :: ZERO , // Fee DA mode.
493+ Felt :: ZERO , // Account deployment data.
494+ ] ;
495+
496+ calldata. push (
497+ expected_resource_bounds. into_iter ( ) . chain ( expected_unsupported_fields) . collect ( ) ,
498+ ) ;
499+ calldata. push ( proof_facts_as_cairo_array ( proof_facts) ) ;
515500 }
516501
502+ // Execute and verify.
517503 let entry_point_call = CallEntryPoint {
518504 entry_point_selector,
519505 code_address : None ,
520506 calldata : Calldata ( calldata. concat ( ) . into ( ) ) ,
521507 ..trivial_external_entry_point_with_address ( test_contract_address)
522508 } ;
509+
523510 let result = entry_point_call. execute_directly_given_tx_info (
524511 state,
525512 tx_info,
0 commit comments