@@ -12,30 +12,108 @@ pub struct ContractInfoChangeList {
1212 pub nonce_change_list : BlockList ,
1313}
1414
15+ /// The type of event that triggered the class change.
16+ #[ derive( Debug , Default , PartialEq , Eq ) ]
17+ #[ cfg_attr( test, derive( :: arbitrary:: Arbitrary ) ) ]
18+ pub enum ContractClassChangeType {
19+ /// The contract was deployed with the given class hash.
20+ #[ default]
21+ Deployed ,
22+ /// The class change is made using the `replace_class` syscall.
23+ Replaced ,
24+ }
25+
1526#[ derive( Debug , Default , PartialEq , Eq ) ]
1627#[ cfg_attr( test, derive( :: arbitrary:: Arbitrary ) ) ]
1728pub struct ContractClassChange {
29+ /// The type of class change.
30+ pub r#type : ContractClassChangeType ,
31+ /// The address of the contract whose class has changed.
1832 pub contract_address : ContractAddress ,
1933 /// The updated class hash of `contract_address`.
2034 pub class_hash : ClassHash ,
2135}
2236
37+ impl ContractClassChange {
38+ /// Creates a new `ContractClassChange` instance representing a deployed contract.
39+ pub fn deployed ( contract_address : ContractAddress , class_hash : ClassHash ) -> Self {
40+ Self { r#type : ContractClassChangeType :: Deployed , contract_address, class_hash }
41+ }
42+
43+ /// Creates a new `ContractClassChange` instance representing a replaced class
44+ pub fn replaced ( contract_address : ContractAddress , new_class_hash : ClassHash ) -> Self {
45+ Self {
46+ r#type : ContractClassChangeType :: Replaced ,
47+ contract_address,
48+ class_hash : new_class_hash,
49+ }
50+ }
51+
52+ fn decompress_current ( bytes : & [ u8 ] ) -> Result < Self , CodecError > {
53+ let r#type = ContractClassChangeType :: decompress ( & bytes[ 0 ..1 ] ) ?;
54+ let contract_address = ContractAddress :: decode ( & bytes[ 1 ..33 ] ) ?;
55+ let class_hash = ClassHash :: decompress ( & bytes[ 33 ..] ) ?;
56+ Ok ( Self { r#type, contract_address, class_hash } )
57+ }
58+
59+ /// Backward compatibility purposes.
60+ ///
61+ /// For old format, ContractClassChangeType::Deployed type is assumed.
62+ #[ cold]
63+ fn decompress_legacy ( bytes : & [ u8 ] ) -> Result < Self , CodecError > {
64+ let contract_address = ContractAddress :: decode ( & bytes[ 0 ..32 ] ) ?;
65+ let class_hash = ClassHash :: decompress ( & bytes[ 32 ..] ) ?;
66+ Ok ( Self { r#type : ContractClassChangeType :: Deployed , contract_address, class_hash } )
67+ }
68+ }
69+
70+ impl Compress for ContractClassChangeType {
71+ type Compressed = Vec < u8 > ;
72+ fn compress ( self ) -> Result < Self :: Compressed , CodecError > {
73+ let byte: u8 = match self {
74+ ContractClassChangeType :: Deployed => 0 ,
75+ ContractClassChangeType :: Replaced => 1 ,
76+ } ;
77+ Ok ( vec ! [ byte] )
78+ }
79+ }
80+
81+ impl Decompress for ContractClassChangeType {
82+ fn decompress < B : AsRef < [ u8 ] > > ( bytes : B ) -> Result < Self , CodecError > {
83+ let bytes = bytes. as_ref ( ) ;
84+ if bytes. is_empty ( ) {
85+ return Err ( CodecError :: Decompress ( "can't decompress empty bytes" . to_string ( ) ) ) ;
86+ }
87+
88+ match bytes[ 0 ] {
89+ 0 => Ok ( ContractClassChangeType :: Deployed ) ,
90+ 1 => Ok ( ContractClassChangeType :: Replaced ) ,
91+ _ => Err ( CodecError :: Decompress ( "unknown ContractClassChangeType variant" . to_string ( ) ) ) ,
92+ }
93+ }
94+ }
95+
2396impl Compress for ContractClassChange {
2497 type Compressed = Vec < u8 > ;
98+
2599 fn compress ( self ) -> Result < Self :: Compressed , CodecError > {
26100 let mut buf = Vec :: new ( ) ;
27- buf. extend_from_slice ( self . contract_address . encode ( ) . as_ref ( ) ) ;
28- buf. extend_from_slice ( self . class_hash . compress ( ) ?. as_ref ( ) ) ;
101+ buf. extend ( self . r#type . compress ( ) ?) ;
102+ buf. extend ( self . contract_address . encode ( ) ) ;
103+ buf. extend ( self . class_hash . compress ( ) ?) ;
29104 Ok ( buf)
30105 }
31106}
32107
33108impl Decompress for ContractClassChange {
34109 fn decompress < B : AsRef < [ u8 ] > > ( bytes : B ) -> Result < Self , crate :: error:: CodecError > {
35110 let bytes = bytes. as_ref ( ) ;
36- let contract_address = ContractAddress :: decode ( & bytes[ 0 ..32 ] ) ?;
37- let class_hash = ClassHash :: decompress ( & bytes[ 32 ..] ) ?;
38- Ok ( Self { contract_address, class_hash } )
111+
112+ if let Ok ( result) = Self :: decompress_current ( bytes) {
113+ return Ok ( result) ;
114+ }
115+
116+ ContractClassChange :: decompress_legacy ( bytes)
39117 }
40118}
41119
0 commit comments