@@ -7,7 +7,9 @@ use starknet_api::deprecated_contract_class::EntryPoint;
7
7
pub use starknet_contract_class:: to_cairo_runner_program;
8
8
use starknet_contract_class:: AbiType ;
9
9
use starknet_contract_class:: { ContractEntryPoint , EntryPointType } ;
10
- use std:: { collections:: HashMap , fs:: File , io:: BufReader , path:: PathBuf } ;
10
+ use std:: collections:: HashMap ;
11
+ use std:: io:: { BufReader , Read } ;
12
+ use std:: path:: { Path , PathBuf } ;
11
13
12
14
// -------------------------------
13
15
// Contract Class
@@ -33,12 +35,10 @@ impl ContractClass {
33
35
abi : Option < AbiType > ,
34
36
) -> Result < Self , ContractClassError > {
35
37
for entry_points in entry_points_by_type. values ( ) {
36
- let mut index = 1 ;
37
- while let Some ( entry_point) = entry_points. get ( index) {
38
- if entry_point. selector ( ) > entry_points[ index - 1 ] . selector ( ) {
38
+ for i in 1 ..entry_points. len ( ) {
39
+ if entry_points[ i - 1 ] . selector ( ) > entry_points[ i] . selector ( ) {
39
40
return Err ( ContractClassError :: EntrypointError ( entry_points. clone ( ) ) ) ;
40
41
}
41
- index += 1 ;
42
42
}
43
43
}
44
44
@@ -49,21 +49,29 @@ impl ContractClass {
49
49
abi,
50
50
} )
51
51
}
52
+
53
+ pub fn new_from_path < F > ( path : F ) -> Result < Self , ProgramError >
54
+ where
55
+ F : AsRef < Path > ,
56
+ {
57
+ Self :: try_from ( std:: fs:: read_to_string ( path) ?. as_str ( ) )
58
+ }
52
59
}
53
60
54
61
// -------------------------------
55
62
// From traits
56
63
// -------------------------------
57
- impl TryFrom < starknet_api:: deprecated_contract_class:: ContractClass > for ContractClass {
64
+
65
+ impl TryFrom < & str > for ContractClass {
58
66
type Error = ProgramError ;
59
67
60
- fn try_from (
61
- contract_class : starknet_api:: deprecated_contract_class:: ContractClass ,
62
- ) -> Result < Self , Self :: Error > {
68
+ fn try_from ( s : & str ) -> Result < Self , ProgramError > {
69
+ let contract_class: starknet_api:: deprecated_contract_class:: ContractClass =
70
+ serde_json :: from_str ( s ) ? ;
63
71
let program = to_cairo_runner_program ( & contract_class. program ) ?;
64
72
let entry_points_by_type =
65
73
convert_entry_points ( contract_class. clone ( ) . entry_points_by_type ) ;
66
- let program_json = serde_json:: to_value ( & contract_class ) ?;
74
+ let program_json = serde_json:: from_str ( s ) ?;
67
75
Ok ( ContractClass {
68
76
program_json,
69
77
program,
@@ -73,58 +81,52 @@ impl TryFrom<starknet_api::deprecated_contract_class::ContractClass> for Contrac
73
81
}
74
82
}
75
83
76
- // -------------------
77
- // Helper Functions
78
- // -------------------
79
-
80
- impl TryFrom < & str > for ContractClass {
84
+ impl TryFrom < & Path > for ContractClass {
81
85
type Error = ProgramError ;
82
86
83
- fn try_from ( s : & str ) -> Result < Self , ProgramError > {
84
- let raw_contract_class: starknet_api:: deprecated_contract_class:: ContractClass =
85
- serde_json:: from_str ( s) ?;
86
- ContractClass :: try_from ( raw_contract_class)
87
+ fn try_from ( path : & Path ) -> Result < Self , Self :: Error > {
88
+ Self :: new_from_path ( path)
87
89
}
88
90
}
89
91
90
92
impl TryFrom < PathBuf > for ContractClass {
91
93
type Error = ProgramError ;
92
94
93
95
fn try_from ( path : PathBuf ) -> Result < Self , Self :: Error > {
94
- ContractClass :: try_from ( & path)
96
+ Self :: new_from_path ( path)
95
97
}
96
98
}
97
99
98
100
impl TryFrom < & PathBuf > for ContractClass {
99
101
type Error = ProgramError ;
100
102
101
103
fn try_from ( path : & PathBuf ) -> Result < Self , Self :: Error > {
102
- let file = File :: open ( path) ?;
103
- let reader = BufReader :: new ( file) ;
104
- let raw_contract_class: starknet_api:: deprecated_contract_class:: ContractClass =
105
- serde_json:: from_reader ( reader) ?;
106
- ContractClass :: try_from ( raw_contract_class)
104
+ Self :: new_from_path ( path)
107
105
}
108
106
}
109
107
110
108
impl < T : std:: io:: Read > TryFrom < BufReader < T > > for ContractClass {
111
109
type Error = ProgramError ;
112
110
113
- fn try_from ( reader : BufReader < T > ) -> Result < Self , Self :: Error > {
114
- let raw_contract_class : starknet_api :: deprecated_contract_class :: ContractClass =
115
- serde_json :: from_reader ( reader) ?;
116
- ContractClass :: try_from ( raw_contract_class )
111
+ fn try_from ( mut reader : BufReader < T > ) -> Result < Self , Self :: Error > {
112
+ let mut s = String :: new ( ) ;
113
+ reader. read_to_string ( & mut s ) ?;
114
+ Self :: try_from ( s . as_str ( ) )
117
115
}
118
116
}
119
117
118
+ // -------------------
119
+ // Helper Functions
120
+ // -------------------
121
+
120
122
fn convert_entry_points (
121
123
entry_points : HashMap < starknet_api:: deprecated_contract_class:: EntryPointType , Vec < EntryPoint > > ,
122
124
) -> HashMap < EntryPointType , Vec < ContractEntryPoint > > {
123
125
let mut converted_entries: HashMap < EntryPointType , Vec < ContractEntryPoint > > = HashMap :: new ( ) ;
124
- for ( entry_type, vec ) in entry_points {
126
+ for ( entry_type, entry_points ) in entry_points {
125
127
let en_type = entry_type. into ( ) ;
126
128
127
- let contracts_entry_points = vec
129
+ let contracts_entry_points = entry_points
128
130
. into_iter ( )
129
131
. map ( |e| {
130
132
let selector = Felt252 :: from_bytes_be ( e. selector . 0 . bytes ( ) ) ;
@@ -141,20 +143,20 @@ fn convert_entry_points(
141
143
142
144
#[ cfg( test) ]
143
145
mod tests {
146
+ use crate :: core:: contract_address:: compute_deprecated_class_hash;
147
+
144
148
use super :: * ;
145
149
use cairo_vm:: {
146
150
felt:: { felt_str, PRIME_STR } ,
147
151
serde:: deserialize_program:: BuiltinName ,
148
152
} ;
149
- use std:: io:: Read ;
153
+ use starknet_contract_class:: ParsedContractClass ;
154
+ use std:: { fs, str:: FromStr } ;
150
155
151
156
#[ test]
152
157
fn deserialize_contract_class ( ) {
153
- let mut serialized = String :: new ( ) ;
154
-
155
158
// This specific contract compiles with --no_debug_info
156
- File :: open ( PathBuf :: from ( "starknet_programs/AccountPreset.json" ) )
157
- . and_then ( |mut f| f. read_to_string ( & mut serialized) )
159
+ let serialized = fs:: read_to_string ( "starknet_programs/AccountPreset.json" )
158
160
. expect ( "should be able to read file" ) ;
159
161
160
162
let res = ContractClass :: try_from ( serialized. as_str ( ) ) ;
@@ -201,4 +203,112 @@ mod tests {
201
203
) ]
202
204
) ;
203
205
}
206
+
207
+ #[ test]
208
+ fn test_contract_class_new_equals_raw_instantiation ( ) {
209
+ let contract_str = fs:: read_to_string ( "starknet_programs/raw_contract_classes/0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad.json" ) . unwrap ( ) ;
210
+
211
+ let parsed_contract_class = ParsedContractClass :: try_from ( contract_str. as_str ( ) ) . unwrap ( ) ;
212
+ let contract_class = ContractClass {
213
+ program_json : serde_json:: Value :: from_str ( & contract_str) . unwrap ( ) ,
214
+ program : parsed_contract_class. program . clone ( ) ,
215
+ entry_points_by_type : parsed_contract_class. entry_points_by_type . clone ( ) ,
216
+ abi : parsed_contract_class. abi . clone ( ) ,
217
+ } ;
218
+
219
+ let contract_class_new = ContractClass :: new (
220
+ serde_json:: Value :: from_str ( & contract_str) . unwrap ( ) ,
221
+ parsed_contract_class. program ,
222
+ parsed_contract_class. entry_points_by_type ,
223
+ parsed_contract_class. abi ,
224
+ )
225
+ . unwrap ( ) ;
226
+
227
+ assert_eq ! ( contract_class, contract_class_new) ;
228
+ }
229
+
230
+ #[ test]
231
+ fn test_compute_class_hash_0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad_try_from (
232
+ ) {
233
+ let contract_str = fs:: read_to_string ( "starknet_programs/raw_contract_classes/0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad.json" ) . unwrap ( ) ;
234
+
235
+ let contract_class = ContractClass :: try_from ( contract_str. as_str ( ) ) . unwrap ( ) ;
236
+
237
+ assert_eq ! (
238
+ compute_deprecated_class_hash( & contract_class) . unwrap( ) ,
239
+ felt_str!(
240
+ "4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad" ,
241
+ 16
242
+ )
243
+ ) ;
244
+ }
245
+
246
+ #[ test]
247
+ fn test_new_equals_try_from ( ) {
248
+ let contract_str = fs:: read_to_string ( "starknet_programs/raw_contract_classes/0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad.json" ) . unwrap ( ) ;
249
+
250
+ let parsed_contract_class = ParsedContractClass :: try_from ( contract_str. as_str ( ) ) . unwrap ( ) ;
251
+
252
+ let contract_class_new = ContractClass :: new (
253
+ serde_json:: Value :: from_str ( & contract_str) . unwrap ( ) ,
254
+ parsed_contract_class. program ,
255
+ parsed_contract_class. entry_points_by_type ,
256
+ parsed_contract_class. abi ,
257
+ )
258
+ . unwrap ( ) ;
259
+
260
+ let contract_class = ContractClass :: try_from ( contract_str. as_str ( ) ) . unwrap ( ) ;
261
+
262
+ assert_eq ! ( contract_class. abi, contract_class_new. abi) ;
263
+ assert_eq ! ( contract_class. program, contract_class_new. program) ;
264
+ assert_eq ! ( contract_class. program_json, contract_class_new. program_json) ;
265
+ assert_eq ! (
266
+ contract_class. entry_points_by_type,
267
+ contract_class_new. entry_points_by_type
268
+ ) ;
269
+ }
270
+
271
+ #[ test]
272
+ fn test_compute_class_hash_0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad_new (
273
+ ) {
274
+ let contract_str = fs:: read_to_string ( "starknet_programs/raw_contract_classes/0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad.json" ) . unwrap ( ) ;
275
+
276
+ let parsed_contract_class = ParsedContractClass :: try_from ( contract_str. as_str ( ) ) . unwrap ( ) ;
277
+ let contract_class = ContractClass :: new (
278
+ serde_json:: Value :: from_str ( & contract_str) . unwrap ( ) ,
279
+ parsed_contract_class. program ,
280
+ parsed_contract_class. entry_points_by_type ,
281
+ parsed_contract_class. abi ,
282
+ )
283
+ . unwrap ( ) ;
284
+
285
+ assert_eq ! (
286
+ compute_deprecated_class_hash( & contract_class) . unwrap( ) ,
287
+ felt_str!(
288
+ "4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad" ,
289
+ 16
290
+ )
291
+ ) ;
292
+ }
293
+
294
+ #[ test]
295
+ fn test_compute_class_hash_0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad ( ) {
296
+ let contract_str = fs:: read_to_string ( "starknet_programs/raw_contract_classes/0x4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad.json" ) . unwrap ( ) ;
297
+
298
+ let parsed_contract_class = ParsedContractClass :: try_from ( contract_str. as_str ( ) ) . unwrap ( ) ;
299
+ let contract_class = ContractClass {
300
+ program_json : serde_json:: Value :: from_str ( & contract_str) . unwrap ( ) ,
301
+ program : parsed_contract_class. program ,
302
+ entry_points_by_type : parsed_contract_class. entry_points_by_type ,
303
+ abi : parsed_contract_class. abi ,
304
+ } ;
305
+
306
+ assert_eq ! (
307
+ compute_deprecated_class_hash( & contract_class) . unwrap( ) ,
308
+ felt_str!(
309
+ "4479c3b883b34f1eafa5065418225d78a11ee7957c371e1b285e4b77afc6dad" ,
310
+ 16
311
+ )
312
+ ) ;
313
+ }
204
314
}
0 commit comments