@@ -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| {
@@ -142,3 +153,56 @@ mod tests {
142153 )
143154 }
144155}
156+
157+ struct PythonJsonFormatter ;
158+
159+ impl Formatter for PythonJsonFormatter {
160+ fn begin_array_value < W > ( & mut self , writer : & mut W , first : bool ) -> io:: Result < ( ) >
161+ where
162+ W : ?Sized + io:: Write ,
163+ {
164+ if first {
165+ Ok ( ( ) )
166+ } else {
167+ writer. write_all ( b", " )
168+ }
169+ }
170+
171+ fn begin_object_key < W > ( & mut self , writer : & mut W , first : bool ) -> io:: Result < ( ) >
172+ where
173+ W : ?Sized + io:: Write ,
174+ {
175+ if first {
176+ Ok ( ( ) )
177+ } else {
178+ writer. write_all ( b", " )
179+ }
180+ }
181+
182+ fn begin_object_value < W > ( & mut self , writer : & mut W ) -> io:: Result < ( ) >
183+ where
184+ W : ?Sized + io:: Write ,
185+ {
186+ writer. write_all ( b": " )
187+ }
188+
189+ fn write_string_fragment < W > ( & mut self , writer : & mut W , fragment : & str ) -> io:: Result < ( ) >
190+ where
191+ W : ?Sized + io:: Write ,
192+ {
193+ let mut buf = [ 0 , 0 ] ;
194+
195+ for c in fragment. chars ( ) {
196+ if c. is_ascii ( ) {
197+ writer. write_all ( & [ c as u8 ] ) ?;
198+ } else {
199+ let buf = c. encode_utf16 ( & mut buf) ;
200+ for i in buf {
201+ write ! ( writer, r"\u{i:04x}" ) ?;
202+ }
203+ }
204+ }
205+
206+ Ok ( ( ) )
207+ }
208+ }
0 commit comments