@@ -9,12 +9,12 @@ use crate::{
9
9
update_progress,
10
10
} ;
11
11
use ethers:: {
12
- prelude:: { Signer , SignerMiddleware , TxHash } ,
13
- providers:: Middleware ,
12
+ prelude:: { Provider , Signer , SignerMiddleware , TxHash } ,
13
+ providers:: { JsonRpcClient , Middleware } ,
14
14
types:: transaction:: eip2718:: TypedTransaction ,
15
15
utils:: format_units,
16
16
} ;
17
- use eyre:: ContextCompat ;
17
+ use eyre:: { ContextCompat , WrapErr } ;
18
18
use foundry_common:: { get_http_provider, RetryProvider } ;
19
19
use foundry_config:: Chain ;
20
20
use futures:: StreamExt ;
@@ -188,9 +188,9 @@ impl ScriptArgs {
188
188
}
189
189
190
190
match signer {
191
- WalletType :: Local ( signer) => broadcast ( signer, tx) . await ,
192
- WalletType :: Ledger ( signer) => broadcast ( signer, tx) . await ,
193
- WalletType :: Trezor ( signer) => broadcast ( signer, tx) . await ,
191
+ WalletType :: Local ( signer) => self . broadcast ( signer, tx) . await ,
192
+ WalletType :: Ledger ( signer) => self . broadcast ( signer, tx) . await ,
193
+ WalletType :: Trezor ( signer) => self . broadcast ( signer, tx) . await ,
194
194
}
195
195
}
196
196
@@ -277,43 +277,106 @@ impl ScriptArgs {
277
277
for mut tx in txes. into_iter ( ) {
278
278
tx. change_type ( is_legacy) ;
279
279
280
- let typed_tx = tx. typed_tx_mut ( ) ;
280
+ if !self . skip_simulation {
281
+ let typed_tx = tx. typed_tx_mut ( ) ;
281
282
282
- if has_different_gas_calc ( chain) || self . skip_simulation {
283
- typed_tx. set_gas (
284
- provider. estimate_gas ( typed_tx) . await ? * self . gas_estimate_multiplier / 100 ,
285
- ) ;
286
- }
283
+ if has_different_gas_calc ( chain) {
284
+ self . estimate_gas ( typed_tx, & provider) . await ?;
285
+ }
287
286
288
- total_gas += * typed_tx. gas ( ) . expect ( "gas is set" ) ;
287
+ total_gas += * typed_tx. gas ( ) . expect ( "gas is set" ) ;
288
+ }
289
289
290
290
new_txes. push_back ( tx) ;
291
291
}
292
292
293
- // We don't store it in the transactions, since we want the most updated value. Right before
294
- // broadcasting.
295
- let per_gas = if let Some ( gas_price) = self . with_gas_price {
296
- gas_price
297
- } else {
298
- match new_txes. front ( ) . unwrap ( ) . typed_tx ( ) {
299
- TypedTransaction :: Legacy ( _) | TypedTransaction :: Eip2930 ( _) => {
300
- provider. get_gas_price ( ) . await ?
293
+ if !self . skip_simulation {
294
+ // We don't store it in the transactions, since we want the most updated value. Right
295
+ // before broadcasting.
296
+ let per_gas = if let Some ( gas_price) = self . with_gas_price {
297
+ gas_price
298
+ } else {
299
+ match new_txes. front ( ) . unwrap ( ) . typed_tx ( ) {
300
+ TypedTransaction :: Legacy ( _) | TypedTransaction :: Eip2930 ( _) => {
301
+ provider. get_gas_price ( ) . await ?
302
+ }
303
+ TypedTransaction :: Eip1559 ( _) => provider. estimate_eip1559_fees ( None ) . await ?. 0 ,
301
304
}
302
- TypedTransaction :: Eip1559 ( _) => provider. estimate_eip1559_fees ( None ) . await ?. 0 ,
303
- }
304
- } ;
305
+ } ;
305
306
306
- println ! ( "\n ==========================" ) ;
307
- println ! ( "\n Estimated total gas used for script: {}" , total_gas) ;
308
- println ! (
309
- "\n Estimated amount required: {} ETH" ,
310
- format_units( total_gas. saturating_mul( per_gas) , 18 )
311
- . unwrap_or_else( |_| "[Could not calculate]" . to_string( ) )
312
- . trim_end_matches( '0' )
313
- ) ;
314
- println ! ( "\n ==========================" ) ;
307
+ println ! ( "\n ==========================" ) ;
308
+ println ! ( "\n Estimated total gas used for script: {}" , total_gas) ;
309
+ println ! (
310
+ "\n Estimated amount required: {} ETH" ,
311
+ format_units( total_gas. saturating_mul( per_gas) , 18 )
312
+ . unwrap_or_else( |_| "[Could not calculate]" . to_string( ) )
313
+ . trim_end_matches( '0' )
314
+ ) ;
315
+ println ! ( "\n ==========================" ) ;
316
+ }
315
317
Ok ( new_txes)
316
318
}
319
+ /// Uses the signer to submit a transaction to the network. If it fails, it tries to retrieve
320
+ /// the transaction hash that can be used on a later run with `--resume`.
321
+ async fn broadcast < T , U > (
322
+ & self ,
323
+ signer : & SignerMiddleware < T , U > ,
324
+ mut legacy_or_1559 : TypedTransaction ,
325
+ ) -> Result < TxHash , BroadcastError >
326
+ where
327
+ T : Middleware ,
328
+ U : Signer ,
329
+ {
330
+ tracing:: debug!( "sending transaction: {:?}" , legacy_or_1559) ;
331
+
332
+ // Chains which use `eth_estimateGas` are being sent sequentially and require their gas to
333
+ // be re-estimated right before broadcasting.
334
+ if has_different_gas_calc ( signer. signer ( ) . chain_id ( ) ) || self . skip_simulation {
335
+ // if already set, some RPC endpoints might simply return the gas value that is already
336
+ // set in the request and omit the estimate altogether, so we remove it here
337
+ let _ = legacy_or_1559. gas_mut ( ) . take ( ) ;
338
+
339
+ self . estimate_gas ( & mut legacy_or_1559, signer. provider ( ) ) . await ?;
340
+ }
341
+
342
+ // Signing manually so we skip `fill_transaction` and its `eth_createAccessList` request.
343
+ let signature = signer
344
+ . sign_transaction (
345
+ & legacy_or_1559,
346
+ * legacy_or_1559. from ( ) . expect ( "Tx should have a `from`." ) ,
347
+ )
348
+ . await
349
+ . map_err ( |err| BroadcastError :: Simple ( err. to_string ( ) ) ) ?;
350
+
351
+ // Submit the raw transaction
352
+ let pending = signer
353
+ . provider ( )
354
+ . send_raw_transaction ( legacy_or_1559. rlp_signed ( & signature) )
355
+ . await
356
+ . map_err ( |err| BroadcastError :: Simple ( err. to_string ( ) ) ) ?;
357
+
358
+ Ok ( pending. tx_hash ( ) )
359
+ }
360
+
361
+ async fn estimate_gas < T > (
362
+ & self ,
363
+ tx : & mut TypedTransaction ,
364
+ provider : & Provider < T > ,
365
+ ) -> Result < ( ) , BroadcastError >
366
+ where
367
+ T : JsonRpcClient ,
368
+ {
369
+ tx. set_gas (
370
+ provider
371
+ . estimate_gas ( tx)
372
+ . await
373
+ . wrap_err_with ( || format ! ( "Failed to estimate gas for tx: {}" , tx. sighash( ) ) )
374
+ . map_err ( |err| BroadcastError :: Simple ( err. to_string ( ) ) ) ? *
375
+ self . gas_estimate_multiplier /
376
+ 100 ,
377
+ ) ;
378
+ Ok ( ( ) )
379
+ }
317
380
}
318
381
319
382
#[ derive( thiserror:: Error , Debug , Clone ) ]
@@ -332,50 +395,3 @@ impl fmt::Display for BroadcastError {
332
395
}
333
396
}
334
397
}
335
-
336
- /// Uses the signer to submit a transaction to the network. If it fails, it tries to retrieve the
337
- /// transaction hash that can be used on a later run with `--resume`.
338
- async fn broadcast < T , U > (
339
- signer : & SignerMiddleware < T , U > ,
340
- mut legacy_or_1559 : TypedTransaction ,
341
- ) -> Result < TxHash , BroadcastError >
342
- where
343
- T : Middleware ,
344
- U : Signer ,
345
- {
346
- tracing:: debug!( "sending transaction: {:?}" , legacy_or_1559) ;
347
-
348
- // Chains which use `eth_estimateGas` are being sent sequentially and require their gas to be
349
- // re-estimated right before broadcasting.
350
- if has_different_gas_calc ( signer. signer ( ) . chain_id ( ) ) {
351
- // if already set, some RPC endpoints might simply return the gas value that is already set
352
- // in the request and omit the estimate altogether, so we remove it here
353
- let _ = legacy_or_1559. gas_mut ( ) . take ( ) ;
354
-
355
- legacy_or_1559. set_gas (
356
- signer
357
- . provider ( )
358
- . estimate_gas ( & legacy_or_1559)
359
- . await
360
- . map_err ( |err| BroadcastError :: Simple ( err. to_string ( ) ) ) ?,
361
- ) ;
362
- }
363
-
364
- // Signing manually so we skip `fill_transaction` and its `eth_createAccessList` request.
365
- let signature = signer
366
- . sign_transaction (
367
- & legacy_or_1559,
368
- * legacy_or_1559. from ( ) . expect ( "Tx should have a `from`." ) ,
369
- )
370
- . await
371
- . map_err ( |err| BroadcastError :: Simple ( err. to_string ( ) ) ) ?;
372
-
373
- // Submit the raw transaction
374
- let pending = signer
375
- . provider ( )
376
- . send_raw_transaction ( legacy_or_1559. rlp_signed ( & signature) )
377
- . await
378
- . map_err ( |err| BroadcastError :: Simple ( err. to_string ( ) ) ) ?;
379
-
380
- Ok ( pending. tx_hash ( ) )
381
- }
0 commit comments