@@ -8,12 +8,15 @@ use anyhow::Result;
88use cairo_lang_starknet_classes:: casm_contract_class:: CasmContractClass ;
99use cairo_lang_starknet_classes:: contract_class:: ContractClass ;
1010use dojo_utils:: { Declarer , Deployer , Invoker , LabeledClass , TransactionResult , TxnConfig } ;
11- use starknet:: accounts:: { Account , SingleOwnerAccount } ;
11+ use starknet:: accounts:: { Account , ConnectedAccount , SingleOwnerAccount } ;
1212use starknet:: core:: crypto:: compute_hash_on_elements;
13- use starknet:: core:: types:: { contract:: SierraClass , Call , Felt , FlattenedSierraClass } ;
13+ use starknet:: core:: types:: {
14+ contract:: SierraClass , BlockId , BlockTag , Call , Felt , FlattenedSierraClass ,
15+ MaybePreConfirmedBlockWithTxHashes ,
16+ } ;
1417use starknet:: macros:: { selector, short_string} ;
1518use starknet:: providers:: jsonrpc:: HttpTransport ;
16- use starknet:: providers:: JsonRpcClient ;
19+ use starknet:: providers:: { JsonRpcClient , Provider } ;
1720use starknet:: signers:: LocalWallet ;
1821use starknet_api:: contract_class:: compiled_class_hash:: { HashVersion , HashableCompiledClass } ;
1922use std:: { fs, path:: Path } ;
@@ -32,8 +35,9 @@ pub async fn declare_contract(
3235) -> Result < ( Felt , TransactionResult ) > {
3336 let txn_config = TxnConfig :: default ( ) ;
3437
38+ let use_blake2s = chain_uses_blake2s_casm_hash ( account. provider ( ) ) . await ?;
3539 let mut declarer = Declarer :: new ( account, txn_config) ;
36- let class = prepare_class ( contract_path, true ) ?;
40+ let class = prepare_class ( contract_path, use_blake2s ) ?;
3741 let labeled = LabeledClass {
3842 label : class. label . clone ( ) ,
3943 casm_class_hash : class. casm_class_hash ,
@@ -66,8 +70,9 @@ pub async fn declare_contract_from_bytes(
6670) -> Result < ( Felt , TransactionResult ) > {
6771 let txn_config = TxnConfig :: default ( ) ;
6872
73+ let use_blake2s = chain_uses_blake2s_casm_hash ( account. provider ( ) ) . await ?;
6974 let mut declarer = Declarer :: new ( account, txn_config) ;
70- let class = prepare_class_from_bytes ( contract_bytes, true , contract_name. to_string ( ) ) ?;
75+ let class = prepare_class_from_bytes ( contract_bytes, use_blake2s , contract_name. to_string ( ) ) ?;
7176 let labeled = LabeledClass {
7277 label : class. label . clone ( ) ,
7378 casm_class_hash : class. casm_class_hash ,
@@ -292,6 +297,36 @@ fn casm_class_hash_from_bytes(data: &[u8], use_blake2s: bool) -> Result<Felt> {
292297 Ok ( Felt :: from_bytes_be ( & hash. 0 . to_bytes_be ( ) ) )
293298}
294299
300+ /// Returns whether the settlement chain expects the Blake2s-based compiled
301+ /// class hash for `declare` transactions.
302+ ///
303+ /// Starknet v0.14.1 switched the canonical compiled class hash from Poseidon
304+ /// to Blake2s and rejects declares using the old algorithm; earlier versions
305+ /// still expect Poseidon. The decision is sourced from the chain's
306+ /// `starknet_version` on the latest block header so it auto-adapts when the
307+ /// settlement chain upgrades.
308+ async fn chain_uses_blake2s_casm_hash < P : Provider > ( provider : & P ) -> Result < bool > {
309+ let block = provider
310+ . get_block_with_tx_hashes ( BlockId :: Tag ( BlockTag :: Latest ) )
311+ . await ?;
312+ let version_str = match block {
313+ MaybePreConfirmedBlockWithTxHashes :: Block ( b) => b. starknet_version ,
314+ MaybePreConfirmedBlockWithTxHashes :: PreConfirmedBlock ( b) => b. starknet_version ,
315+ } ;
316+ Ok ( version_at_least_v0_14_1 ( & version_str) )
317+ }
318+
319+ /// Parses `MAJOR.MINOR.PATCH[.BUILD]` and returns true if it is at least
320+ /// `0.14.1`. Strings that don't have at least three numeric components fall
321+ /// back to `false` so the caller uses the legacy Poseidon hash.
322+ fn version_at_least_v0_14_1 ( version : & str ) -> bool {
323+ let parts: Vec < u64 > = version. split ( '.' ) . map ( |s| s. parse ( ) . unwrap_or ( 0 ) ) . collect ( ) ;
324+ match parts. as_slice ( ) {
325+ [ major, minor, patch, ..] => ( * major, * minor, * patch) >= ( 0 , 14 , 1 ) ,
326+ _ => false ,
327+ }
328+ }
329+
295330#[ cfg( test) ]
296331mod test {
297332 use super :: * ;
@@ -319,4 +354,22 @@ mod test {
319354
320355 assert_eq ! ( computed, expected) ;
321356 }
357+
358+ #[ test]
359+ fn version_comparison_picks_blake2s_for_0_14_1_and_above ( ) {
360+ assert ! ( version_at_least_v0_14_1( "0.14.1" ) ) ;
361+ assert ! ( version_at_least_v0_14_1( "0.14.2" ) ) ;
362+ assert ! ( version_at_least_v0_14_1( "0.15.0" ) ) ;
363+ assert ! ( version_at_least_v0_14_1( "1.0.0" ) ) ;
364+ assert ! ( version_at_least_v0_14_1( "0.14.1.0" ) ) ;
365+ }
366+
367+ #[ test]
368+ fn version_comparison_picks_poseidon_for_pre_0_14_1 ( ) {
369+ assert ! ( !version_at_least_v0_14_1( "0.13.4" ) ) ;
370+ assert ! ( !version_at_least_v0_14_1( "0.14.0" ) ) ;
371+ assert ! ( !version_at_least_v0_14_1( "0.13.2" ) ) ;
372+ assert ! ( !version_at_least_v0_14_1( "" ) ) ;
373+ assert ! ( !version_at_least_v0_14_1( "not-a-version" ) ) ;
374+ }
322375}
0 commit comments