1- use std:: collections:: HashMap ;
1+ use std:: collections:: { HashMap , HashSet } ;
22use std:: sync:: { Arc , LazyLock } ;
33
44use blockifier:: abi:: constants:: STORED_BLOCK_HASH_BUFFER ;
55use blockifier:: blockifier_versioned_constants:: VersionedConstants ;
66use blockifier:: test_utils:: dict_state_reader:: DictStateReader ;
7+ use blockifier:: test_utils:: ALIAS_CONTRACT_ADDRESS ;
78use blockifier:: transaction:: test_utils:: ExpectedExecutionInfo ;
89use blockifier_test_utils:: cairo_versions:: { CairoVersion , RunnableCairo1 } ;
910use blockifier_test_utils:: calldata:: create_calldata;
@@ -78,6 +79,7 @@ use starknet_committer::patricia_merkle_tree::types::CompiledClassHash;
7879use starknet_core:: crypto:: ecdsa_sign;
7980use starknet_crypto:: { get_public_key, Signature } ;
8081use starknet_os:: hints:: hint_implementation:: deprecated_compiled_class:: class_hash:: compute_deprecated_class_hash;
82+ use starknet_os:: hints:: vars:: Const ;
8183use starknet_os:: io:: os_output:: MessageToL2 ;
8284use starknet_types_core:: felt:: Felt ;
8385use starknet_types_core:: hash:: { Pedersen , StarkHash } ;
@@ -91,7 +93,12 @@ use crate::special_contracts::{
9193 V1_BOUND_CAIRO1_CONTRACT_CASM ,
9294 V1_BOUND_CAIRO1_CONTRACT_SIERRA ,
9395} ;
94- use crate :: test_manager:: { TestManager , TestParameters , FUNDED_ACCOUNT_ADDRESS } ;
96+ use crate :: test_manager:: {
97+ TestManager ,
98+ TestParameters ,
99+ FUNDED_ACCOUNT_ADDRESS ,
100+ STRK_FEE_TOKEN_ADDRESS ,
101+ } ;
95102use crate :: utils:: {
96103 divide_vec_into_n_parts,
97104 get_class_hash_of_feature_contract,
@@ -1765,3 +1772,78 @@ async fn test_deprecated_tx_info() {
17651772 test_output. assert_account_balance_change ( * FUNDED_ACCOUNT_ADDRESS ) ;
17661773 test_output. assert_account_balance_change ( contract_address ! ( TEST_SEQUENCER_ADDRESS ) ) ;
17671774}
1775+
1776+ #[ rstest]
1777+ #[ tokio:: test]
1778+ async fn test_deploy_syscall ( ) {
1779+ let test_contract = FeatureContract :: TestContract ( CairoVersion :: Cairo0 ) ;
1780+ let empty_contract = FeatureContract :: Empty ( CairoVersion :: Cairo0 ) ;
1781+ let class_hash = get_class_hash_of_feature_contract ( test_contract) ;
1782+ let empty_class_hash = get_class_hash_of_feature_contract ( empty_contract) ;
1783+ // Initialize the test manager with the test contract and empty contract already declared.
1784+ // We can ignore the addresses of the deployed instances.
1785+ let ( mut test_manager, _) = TestManager :: < DictStateReader > :: new_with_default_initial_state ( [
1786+ ( test_contract, calldata ! [ Felt :: ZERO , Felt :: ZERO ] ) ,
1787+ ( empty_contract, calldata ! [ ] ) ,
1788+ ] )
1789+ . await ;
1790+
1791+ let ctor_calldata = vec ! [ Felt :: from( 1979 ) , Felt :: from( 1989 ) ] ;
1792+ let salt = ContractAddressSalt ( Felt :: from ( 12 ) ) ;
1793+
1794+ // Call deploy_contract(...).
1795+ let ( deploy_tx, deployed_test_address) = get_deploy_contract_tx_and_address_with_salt (
1796+ class_hash,
1797+ Calldata ( Arc :: new ( ctor_calldata. clone ( ) ) ) ,
1798+ test_manager. next_nonce ( * FUNDED_ACCOUNT_ADDRESS ) ,
1799+ * NON_TRIVIAL_RESOURCE_BOUNDS ,
1800+ salt,
1801+ ) ;
1802+ test_manager. add_invoke_tx ( deploy_tx, None ) ;
1803+ let expected_storage_updates = HashMap :: from ( [ (
1804+ deployed_test_address,
1805+ HashMap :: from ( [ (
1806+ StarknetStorageKey ( ctor_calldata[ 0 ] . try_into ( ) . unwrap ( ) ) ,
1807+ StarknetStorageValue ( ctor_calldata[ 1 ] ) ,
1808+ ) ] ) ,
1809+ ) ] ) ;
1810+
1811+ // Deploy a contract with no constructor using deploy syscall.
1812+ let calldata = create_calldata (
1813+ * FUNDED_ACCOUNT_ADDRESS ,
1814+ "deploy_contract" ,
1815+ & [ empty_class_hash. 0 , salt. 0 , Felt :: ZERO ] ,
1816+ ) ;
1817+ test_manager. add_funded_account_invoke ( invoke_tx_args ! { calldata } ) ;
1818+
1819+ // Run the test and verify storage changes.
1820+ let test_output =
1821+ test_manager. execute_test_with_default_block_contexts ( & TestParameters :: default ( ) ) . await ;
1822+ let perform_global_validations = true ;
1823+ test_output. perform_validations (
1824+ perform_global_validations,
1825+ Some ( & StateDiff { storage_updates : expected_storage_updates, ..Default :: default ( ) } ) ,
1826+ ) ;
1827+
1828+ // Make sure only the newly deployed contract and the fee contract have changed storage.
1829+ let block_hash_contract_address = ContractAddress (
1830+ Const :: BlockHashContractAddress . fetch_from_os_program ( ) . unwrap ( ) . try_into ( ) . unwrap ( ) ,
1831+ ) ;
1832+ let allowed_changed_addresses = HashSet :: from ( [
1833+ & deployed_test_address,
1834+ & * STRK_FEE_TOKEN_ADDRESS ,
1835+ & * ALIAS_CONTRACT_ADDRESS ,
1836+ & block_hash_contract_address,
1837+ ] ) ;
1838+ assert ! (
1839+ HashSet :: from_iter(
1840+ test_output
1841+ . decompressed_state_diff
1842+ . storage_updates
1843+ . into_keys( )
1844+ . collect:: <Vec <_>>( )
1845+ . iter( )
1846+ )
1847+ . is_subset( & allowed_changed_addresses)
1848+ ) ;
1849+ }
0 commit comments