@@ -13,7 +13,7 @@ use cairo_vm::types::builtin_name::BuiltinName;
1313use expect_test:: expect;
1414use rstest:: rstest;
1515use starknet_api:: abi:: abi_utils:: { get_storage_var_address, selector_from_name} ;
16- use starknet_api:: block:: { BlockNumber , BlockTimestamp } ;
16+ use starknet_api:: block:: { BlockInfo , BlockNumber , BlockTimestamp } ;
1717use starknet_api:: contract_class:: compiled_class_hash:: { HashVersion , HashableCompiledClass } ;
1818use starknet_api:: contract_class:: { ClassInfo , ContractClass } ;
1919use starknet_api:: core:: {
@@ -2007,3 +2007,149 @@ async fn test_deploy_syscall() {
20072007 . is_subset( & allowed_changed_addresses)
20082008 ) ;
20092009}
2010+
2011+ #[ rstest]
2012+ #[ tokio:: test]
2013+ async fn test_block_info ( #[ values( true , false ) ] is_cairo0 : bool ) {
2014+ let cairo_version =
2015+ if is_cairo0 { CairoVersion :: Cairo0 } else { CairoVersion :: Cairo1 ( RunnableCairo1 :: Casm ) } ;
2016+ let test_contract = FeatureContract :: BlockInfoTestContract ( cairo_version) ;
2017+ let class_hash = get_class_hash_of_feature_contract ( test_contract) ;
2018+ let is_validate = Felt :: ONE ;
2019+ let ( mut test_manager, mut nonce_manager, _) =
2020+ TestManager :: < DictStateReader > :: new_with_default_initial_state ( [ ] ) . await ;
2021+
2022+ // Prepare block info data.
2023+ let next_block_number = test_manager. initial_state . next_block_number ;
2024+ let rounded_block_number = ( next_block_number. 0 / 100 ) * 100 ;
2025+ let next_block_timestamp = BlockInfo :: create_for_testing ( ) . block_timestamp . 0 ;
2026+ let rounded_next_block_timestamp = ( next_block_timestamp / 3600 ) * 3600 ;
2027+ assert ! (
2028+ rounded_block_number != next_block_number. 0 ,
2029+ "For the test the rounded block number must be different from the next block number; both \
2030+ are {rounded_block_number}."
2031+ ) ;
2032+ assert ! (
2033+ rounded_next_block_timestamp != next_block_timestamp,
2034+ "For the test the rounded block timestamp must be different from the next block \
2035+ timestamp; both are {rounded_next_block_timestamp}."
2036+ ) ;
2037+
2038+ // Declare the block info contract.
2039+ let class_info = get_class_info_of_feature_contract ( test_contract) ;
2040+ if is_cairo0 {
2041+ let declare_args = declare_tx_args ! {
2042+ version: TransactionVersion :: ZERO ,
2043+ max_fee: Fee ( 1_000_000_000_000_000 ) ,
2044+ class_hash,
2045+ sender_address: * FUNDED_ACCOUNT_ADDRESS ,
2046+ nonce: Nonce :: default ( ) ,
2047+ } ;
2048+ let account_declare_tx = declare_tx ( declare_args) ;
2049+ let tx = DeclareTransaction :: create ( account_declare_tx, class_info, & CHAIN_ID_FOR_TESTS )
2050+ . unwrap ( ) ;
2051+ test_manager. add_cairo0_declare_tx ( tx, StarknetAPICompiledClassHash ( class_hash. 0 ) ) ;
2052+ } else {
2053+ let test_contract_sierra = test_contract. get_sierra ( ) ;
2054+ let test_contract_compiled_class_hash =
2055+ test_contract. get_compiled_class_hash ( & HashVersion :: V2 ) ;
2056+ let declare_tx_args = declare_tx_args ! {
2057+ sender_address: * FUNDED_ACCOUNT_ADDRESS ,
2058+ class_hash,
2059+ compiled_class_hash: test_contract_compiled_class_hash,
2060+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2061+ nonce: nonce_manager. next( * FUNDED_ACCOUNT_ADDRESS ) ,
2062+ } ;
2063+ let account_declare_tx = declare_tx ( declare_tx_args) ;
2064+ let declare_tx =
2065+ DeclareTransaction :: create ( account_declare_tx, class_info, & CHAIN_ID_FOR_TESTS )
2066+ . unwrap ( ) ;
2067+ test_manager. add_cairo1_declare_tx ( declare_tx. clone ( ) , & test_contract_sierra) ;
2068+ }
2069+
2070+ // Prepare to deploy: precompute the address.
2071+ let salt = Felt :: ZERO ;
2072+ let block_info_account_address = calculate_contract_address (
2073+ ContractAddressSalt ( salt) ,
2074+ class_hash,
2075+ & calldata ! [ is_validate] ,
2076+ ContractAddress :: default ( ) ,
2077+ )
2078+ . unwrap ( ) ;
2079+
2080+ // Fund the address.
2081+ let transfer_amount = 2 * NON_TRIVIAL_RESOURCE_BOUNDS . max_possible_fee ( Tip ( 0 ) ) . 0 ;
2082+ let transfer_tx_args = invoke_tx_args ! {
2083+ sender_address: * FUNDED_ACCOUNT_ADDRESS ,
2084+ nonce: nonce_manager. next( * FUNDED_ACCOUNT_ADDRESS ) ,
2085+ calldata: create_calldata(
2086+ * STRK_FEE_TOKEN_ADDRESS ,
2087+ "transfer" ,
2088+ & [ * * block_info_account_address, Felt :: from( transfer_amount) , Felt :: ZERO ]
2089+ ) ,
2090+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2091+ } ;
2092+ test_manager. add_invoke_tx_from_args ( transfer_tx_args, & CHAIN_ID_FOR_TESTS , None ) ;
2093+
2094+ // Deploy the contract using a DeployAccount transaction.
2095+ let deploy_account_tx_args = deploy_account_tx_args ! {
2096+ class_hash,
2097+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2098+ contract_address_salt: ContractAddressSalt ( Felt :: ZERO ) ,
2099+ constructor_calldata: calldata![ is_validate] ,
2100+ nonce: Nonce :: default ( ) ,
2101+ } ;
2102+ let deploy_account_tx = DeployAccountTransaction :: create (
2103+ deploy_account_tx ( deploy_account_tx_args, nonce_manager. next ( block_info_account_address) ) ,
2104+ & CHAIN_ID_FOR_TESTS ,
2105+ )
2106+ . unwrap ( ) ;
2107+ test_manager. add_deploy_account_tx ( deploy_account_tx) ;
2108+
2109+ // Test validate_declare.
2110+ let empty_contract = FeatureContract :: Empty ( CairoVersion :: Cairo1 ( RunnableCairo1 :: Casm ) ) ;
2111+ let empty_class_hash = get_class_hash_of_feature_contract ( empty_contract) ;
2112+ let empty_compiled_class_hash = empty_contract. get_compiled_class_hash ( & HashVersion :: V2 ) ;
2113+ let declare_tx_args = declare_tx_args ! {
2114+ sender_address: block_info_account_address,
2115+ class_hash: empty_class_hash,
2116+ compiled_class_hash: empty_compiled_class_hash,
2117+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2118+ nonce: nonce_manager. next( block_info_account_address) ,
2119+ } ;
2120+ let account_declare_tx = declare_tx ( declare_tx_args) ;
2121+ let class_info = get_class_info_of_feature_contract ( empty_contract) ;
2122+ let declare_tx =
2123+ DeclareTransaction :: create ( account_declare_tx, class_info, & CHAIN_ID_FOR_TESTS ) . unwrap ( ) ;
2124+ test_manager. add_cairo1_declare_tx ( declare_tx. clone ( ) , & empty_contract. get_sierra ( ) ) ;
2125+
2126+ // Test `validate` and `execute`.
2127+ let invoke_args = invoke_tx_args ! {
2128+ sender_address: block_info_account_address,
2129+ nonce: nonce_manager. next( block_info_account_address) ,
2130+ // Dummy contract address and selector, calldata length of zero.
2131+ calldata: calldata![ Felt :: ZERO , Felt :: ZERO , Felt :: ZERO ] ,
2132+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2133+ } ;
2134+ test_manager. add_invoke_tx_from_args ( invoke_args, & CHAIN_ID_FOR_TESTS , None ) ;
2135+
2136+ // Test `constructor` in execute mode.
2137+ let ctor_calldata = vec ! [ Felt :: ZERO ] ; // Not validate mode (execute mode).
2138+ let salt = Felt :: ZERO ;
2139+ let invoke_args = invoke_tx_args ! {
2140+ sender_address: * FUNDED_ACCOUNT_ADDRESS ,
2141+ nonce: nonce_manager. next( * FUNDED_ACCOUNT_ADDRESS ) ,
2142+ calldata: create_calldata(
2143+ * FUNDED_ACCOUNT_ADDRESS ,
2144+ "deploy_contract" ,
2145+ & [ class_hash. 0 , salt, ctor_calldata. len( ) . into( ) , ctor_calldata[ 0 ] ]
2146+ ) ,
2147+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2148+ } ;
2149+ test_manager. add_invoke_tx_from_args ( invoke_args, & CHAIN_ID_FOR_TESTS , None ) ;
2150+
2151+ // Run the test.
2152+ let test_output =
2153+ test_manager. execute_test_with_default_block_contexts ( & TestParameters :: default ( ) ) . await ;
2154+ test_output. perform_default_validations ( ) ;
2155+ }
0 commit comments