@@ -9,7 +9,10 @@ use core::str::FromStr;
99
1010use crate :: {
1111 felt:: Felt ,
12- patricia_key:: { PatriciaKey , PatriciaKeyFromFeltError , PatriciaKeyFromStrError } ,
12+ patricia_key:: {
13+ PatriciaKey , PatriciaKeyFromFeltError , PatriciaKeyFromStrError ,
14+ STORAGE_LEAF_ADDRESS_UPPER_BOUND ,
15+ } ,
1316} ;
1417
1518#[ repr( transparent) ]
@@ -31,7 +34,9 @@ impl ContractAddress {
3134 /// Lower inclusive bound
3235 pub const LOWER_BOUND : Self = Self :: ZERO ;
3336 /// Upper non-inclusive bound
34- pub const UPPER_BOUND : Self = Self ( PatriciaKey :: UPPER_BOUND ) ;
37+ ///
38+ /// For consistency with other merkle leaf bounds, [ContractAddress] is also bounded by [STORAGE_LEAF_ADDRESS_UPPER_BOUND]
39+ pub const UPPER_BOUND : Self = Self ( STORAGE_LEAF_ADDRESS_UPPER_BOUND ) ;
3540}
3641
3742impl core:: fmt:: Display for ContractAddress {
@@ -64,17 +69,67 @@ impl From<ContractAddress> for PatriciaKey {
6469 }
6570}
6671
67- impl From < PatriciaKey > for ContractAddress {
68- fn from ( value : PatriciaKey ) -> Self {
69- ContractAddress ( value)
72+ #[ derive( Debug ) ]
73+ pub enum ContractAddressFromPatriciaKeyError {
74+ OutOfBound ,
75+ }
76+
77+ impl core:: fmt:: Display for ContractAddressFromPatriciaKeyError {
78+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
79+ match self {
80+ ContractAddressFromPatriciaKeyError :: OutOfBound => write ! (
81+ f,
82+ "value out of bound, upper non-inclusive bound is {}" ,
83+ ContractAddress :: UPPER_BOUND
84+ ) ,
85+ }
86+ }
87+ }
88+
89+ #[ cfg( feature = "std" ) ]
90+ impl std:: error:: Error for ContractAddressFromPatriciaKeyError { }
91+
92+ impl TryFrom < PatriciaKey > for ContractAddress {
93+ type Error = ContractAddressFromPatriciaKeyError ;
94+
95+ fn try_from ( value : PatriciaKey ) -> Result < Self , Self :: Error > {
96+ if value >= STORAGE_LEAF_ADDRESS_UPPER_BOUND {
97+ Err ( ContractAddressFromPatriciaKeyError :: OutOfBound )
98+ } else {
99+ Ok ( ContractAddress ( value) )
100+ }
101+ }
102+ }
103+
104+ #[ derive( Debug ) ]
105+ pub enum ContractAddressFromFeltError {
106+ PatriciaKey ( PatriciaKeyFromFeltError ) ,
107+ OutOfBound ( ContractAddressFromPatriciaKeyError ) ,
108+ }
109+
110+ impl core:: fmt:: Display for ContractAddressFromFeltError {
111+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
112+ match self {
113+ ContractAddressFromFeltError :: OutOfBound ( e) => {
114+ write ! ( f, "invalid value for contract address: {e}" )
115+ }
116+ ContractAddressFromFeltError :: PatriciaKey ( e) => {
117+ write ! ( f, "invalid patricia key value: {e}" )
118+ }
119+ }
70120 }
71121}
72122
123+ #[ cfg( feature = "std" ) ]
124+ impl std:: error:: Error for ContractAddressFromFeltError { }
73125impl TryFrom < Felt > for ContractAddress {
74- type Error = PatriciaKeyFromFeltError ;
126+ type Error = ContractAddressFromFeltError ;
75127
76128 fn try_from ( value : Felt ) -> Result < Self , Self :: Error > {
77- Ok ( ContractAddress ( PatriciaKey :: try_from ( value) ?) )
129+ let pk = PatriciaKey :: try_from ( value) . map_err ( ContractAddressFromFeltError :: PatriciaKey ) ?;
130+ let ca = ContractAddress :: try_from ( pk) . map_err ( ContractAddressFromFeltError :: OutOfBound ) ?;
131+
132+ Ok ( ca)
78133 }
79134}
80135
@@ -85,19 +140,43 @@ impl Felt {
85140 }
86141}
87142
143+ #[ derive( Debug ) ]
144+ pub enum ContractAddressFromStrError {
145+ PatriciaKey ( PatriciaKeyFromStrError ) ,
146+ OutOfBound ( ContractAddressFromPatriciaKeyError ) ,
147+ }
148+
149+ impl core:: fmt:: Display for ContractAddressFromStrError {
150+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
151+ match self {
152+ ContractAddressFromStrError :: PatriciaKey ( e) => {
153+ write ! ( f, "invalid patricia key: {e}" )
154+ }
155+ ContractAddressFromStrError :: OutOfBound ( e) => {
156+ write ! ( f, "invalid value for contract address: {e}" )
157+ }
158+ }
159+ }
160+ }
161+
162+ #[ cfg( feature = "std" ) ]
163+ impl std:: error:: Error for ContractAddressFromStrError { }
164+
88165impl FromStr for ContractAddress {
89- type Err = PatriciaKeyFromStrError ;
166+ type Err = ContractAddressFromStrError ;
90167
91168 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
92- Ok ( ContractAddress ( PatriciaKey :: from_str ( s) ?) )
169+ let pk = PatriciaKey :: from_str ( s) . map_err ( ContractAddressFromStrError :: PatriciaKey ) ?;
170+ let ca = ContractAddress :: try_from ( pk) . map_err ( ContractAddressFromStrError :: OutOfBound ) ?;
171+
172+ Ok ( ca)
93173 }
94174}
95175
96176impl ContractAddress {
97177 /// Create a new [ContractAddress] from an hex encoded string without checking it is a valid value.
98178 ///
99- /// Should NEVER be used on user inputs,
100- /// as it can cause erroneous execution if dynamically initialized with bad values.
179+ /// Should NEVER be used on user inputs, as it can cause erroneous execution if dynamically initialized with bad values.
101180 /// Should mostly be used at compilation time on hardcoded static string.
102181 pub const fn from_hex_unchecked ( s : & ' static str ) -> ContractAddress {
103182 let patricia_key = PatriciaKey :: from_hex_unchecked ( s) ;
0 commit comments