@@ -4,7 +4,10 @@ use cairo_lang_starknet::{
44 contract_class:: { ContractClass as SierraContractClass , ContractEntryPoint } ,
55} ;
66use cairo_vm:: felt:: Felt252 ;
7+ use serde:: Serialize ;
8+ use serde_json:: ser:: Formatter ;
79use starknet_crypto:: { poseidon_hash_many, FieldElement , PoseidonHasher } ;
10+ use std:: io:: { self , Cursor } ;
811
912const CONTRACT_CLASS_VERSION : & [ u8 ] = b"CONTRACT_CLASS_V0.1.0" ;
1013
@@ -60,14 +63,22 @@ pub fn compute_sierra_class_hash(
6063 hasher. update ( constructors) ;
6164
6265 // Hash abi
63- let abi = serde_json_pythonic:: to_string_pythonic (
64- & contract_class
66+ let abi = {
67+ let mut buf = Cursor :: new ( Vec :: new ( ) ) ;
68+ let mut fmt = serde_json:: Serializer :: with_formatter ( & mut buf, PythonJsonFormatter ) ;
69+
70+ contract_class
6571 . abi
6672 . as_ref ( )
6773 . ok_or ( ContractAddressError :: MissingAbi ) ?
68- . items ,
69- )
70- . map_err ( |_| ContractAddressError :: MissingAbi ) ?;
74+ . items
75+ . serialize ( & mut fmt)
76+ . map_err ( |_| ContractAddressError :: MissingAbi ) ?;
77+
78+ // Note: The following unwrap should never be triggered as long as serde_json generates
79+ // UTF-8 encoded data, which in practice means it should never panic.
80+ String :: from_utf8 ( buf. into_inner ( ) ) . unwrap ( )
81+ } ;
7182
7283 let abi_hash = FieldElement :: from_byte_slice_be ( & starknet_keccak ( abi. as_bytes ( ) ) . to_bytes_be ( ) )
7384 . map_err ( |_err| {
@@ -143,3 +154,56 @@ mod tests {
143154 )
144155 }
145156}
157+
158+ struct PythonJsonFormatter ;
159+
160+ impl Formatter for PythonJsonFormatter {
161+ fn begin_array_value < W > ( & mut self , writer : & mut W , first : bool ) -> io:: Result < ( ) >
162+ where
163+ W : ?Sized + io:: Write ,
164+ {
165+ if first {
166+ Ok ( ( ) )
167+ } else {
168+ writer. write_all ( b", " )
169+ }
170+ }
171+
172+ fn begin_object_key < W > ( & mut self , writer : & mut W , first : bool ) -> io:: Result < ( ) >
173+ where
174+ W : ?Sized + io:: Write ,
175+ {
176+ if first {
177+ Ok ( ( ) )
178+ } else {
179+ writer. write_all ( b", " )
180+ }
181+ }
182+
183+ fn begin_object_value < W > ( & mut self , writer : & mut W ) -> io:: Result < ( ) >
184+ where
185+ W : ?Sized + io:: Write ,
186+ {
187+ writer. write_all ( b": " )
188+ }
189+
190+ fn write_string_fragment < W > ( & mut self , writer : & mut W , fragment : & str ) -> io:: Result < ( ) >
191+ where
192+ W : ?Sized + io:: Write ,
193+ {
194+ let mut buf = [ 0 , 0 ] ;
195+
196+ for c in fragment. chars ( ) {
197+ if c. is_ascii ( ) {
198+ writer. write_all ( & [ c as u8 ] ) ?;
199+ } else {
200+ let buf = c. encode_utf16 ( & mut buf) ;
201+ for i in buf {
202+ write ! ( writer, r"\u{i:04x}" ) ?;
203+ }
204+ }
205+ }
206+
207+ Ok ( ( ) )
208+ }
209+ }
0 commit comments