@@ -103,29 +103,14 @@ corresponds to the sender, or let foundry automatically detect it by not specify
103103 Ok ( ( ) )
104104}
105105
106- /// Ensures the transaction is either a contract deployment or a recipient address is specified
107- pub async fn resolve_tx_kind < P : Provider < T , AnyNetwork > , T : Transport + Clone > (
108- provider : & P ,
109- code : & Option < String > ,
110- to : & Option < NameOrAddress > ,
111- ) -> Result < TxKind > {
112- if code. is_some ( ) {
113- Ok ( TxKind :: Create )
114- } else if let Some ( to) = to {
115- Ok ( TxKind :: Call ( to. resolve ( provider) . await ?) )
116- } else {
117- eyre:: bail!( "Must specify a recipient address or contract code to deploy" ) ;
118- }
119- }
120-
121106/// Initial state.
122107#[ derive( Debug ) ]
123108pub struct InitState ;
124109
125110/// State with known [TxKind].
126111#[ derive( Debug ) ]
127- pub struct TxKindState {
128- kind : TxKind ,
112+ pub struct ToState {
113+ to : Option < Address > ,
129114}
130115
131116/// State with known input for the transaction.
@@ -211,22 +196,23 @@ where
211196 }
212197
213198 /// Sets [TxKind] for this builder and changes state to [TxKindState].
214- pub fn with_tx_kind ( self , kind : TxKind ) -> CastTxBuilder < T , P , TxKindState > {
215- CastTxBuilder {
199+ pub async fn with_to ( self , to : Option < NameOrAddress > ) -> Result < CastTxBuilder < T , P , ToState > > {
200+ let to = if let Some ( to) = to { Some ( to. resolve ( & self . provider ) . await ?) } else { None } ;
201+ Ok ( CastTxBuilder {
216202 provider : self . provider ,
217203 tx : self . tx ,
218204 legacy : self . legacy ,
219205 blob : self . blob ,
220206 chain : self . chain ,
221207 etherscan_api_key : self . etherscan_api_key ,
222208 auth : self . auth ,
223- state : TxKindState { kind } ,
209+ state : ToState { to } ,
224210 _t : self . _t ,
225- }
211+ } )
226212 }
227213}
228214
229- impl < T , P > CastTxBuilder < T , P , TxKindState >
215+ impl < T , P > CastTxBuilder < T , P , ToState >
230216where
231217 P : Provider < T , AnyNetwork > ,
232218 T : Transport + Clone ,
@@ -244,7 +230,7 @@ where
244230 parse_function_args (
245231 & sig,
246232 args,
247- self . state . kind . to ( ) . cloned ( ) ,
233+ self . state . to ,
248234 self . chain ,
249235 & self . provider ,
250236 self . etherscan_api_key . as_deref ( ) ,
@@ -254,14 +240,24 @@ where
254240 ( Vec :: new ( ) , None )
255241 } ;
256242
257- let input = if let Some ( code) = code {
243+ let input = if let Some ( code) = & code {
258244 let mut code = hex:: decode ( code) ?;
259245 code. append ( & mut args) ;
260246 code
261247 } else {
262248 args
263249 } ;
264250
251+ if self . state . to . is_none ( ) && code. is_none ( ) {
252+ let has_value = self . tx . value . map_or ( false , |v| !v. is_zero ( ) ) ;
253+ let has_auth = self . auth . is_some ( ) ;
254+ // We only allow user to omit the recipient address if transaction is an EIP-7702 tx
255+ // without a value.
256+ if !has_auth || has_value {
257+ eyre:: bail!( "Must specify a recipient address or contract code to deploy" ) ;
258+ }
259+ }
260+
265261 Ok ( CastTxBuilder {
266262 provider : self . provider ,
267263 tx : self . tx ,
@@ -270,7 +266,7 @@ where
270266 chain : self . chain ,
271267 etherscan_api_key : self . etherscan_api_key ,
272268 auth : self . auth ,
273- state : InputState { kind : self . state . kind , input, func } ,
269+ state : InputState { kind : self . state . to . into ( ) , input, func } ,
274270 _t : self . _t ,
275271 } )
276272 }
0 commit comments