@@ -196,7 +196,7 @@ pub async fn submit_tx_with_backoff<T: Middleware + NonceManaged + 'static>(
196196
197197#[ allow( clippy:: large_enum_variant) ]
198198pub enum SubmitTxError < T : Middleware + NonceManaged + ' static > {
199- GasUsageEstimateError ( ContractError < T > ) ,
199+ GasUsageEstimateError ( TypedTransaction , ContractError < T > ) ,
200200 GasLimitExceeded { estimate : U256 , limit : U256 } ,
201201 GasPriceEstimateError ( <T as Middleware >:: Error ) ,
202202 SubmissionError ( TypedTransaction , <T as Middleware >:: Error ) ,
@@ -211,8 +211,8 @@ where
211211{
212212 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
213213 match self {
214- SubmitTxError :: GasUsageEstimateError ( e) => {
215- write ! ( f, "Error estimating gas for reveal: {e:?}" )
214+ SubmitTxError :: GasUsageEstimateError ( tx , e) => {
215+ write ! ( f, "Error estimating gas for reveal: Tx:{tx:?}, Error: {e:?}" )
216216 }
217217 SubmitTxError :: GasLimitExceeded { estimate, limit } => write ! (
218218 f,
@@ -247,7 +247,16 @@ pub async fn submit_tx<T: Middleware + NonceManaged + 'static>(
247247 // A value of 100 submits the tx with the same fee as the estimate.
248248 fee_estimate_multiplier_pct : u64 ,
249249) -> Result < TransactionReceipt , backoff:: Error < SubmitTxError < T > > > {
250+ // Estimate the gas *before* filling the transaction. Filling the transaction increments the nonce of the
251+ // provider. If we can't send the transaction (because the gas estimation fails), then the nonce will be
252+ // out of sync with the one on-chain, causing subsequent transactions to fail.
253+ let gas: U256 = call. estimate_gas ( ) . await . map_err ( |e| {
254+ backoff:: Error :: transient ( SubmitTxError :: GasUsageEstimateError ( call. tx . clone ( ) , e) )
255+ } ) ?;
256+
250257 let mut transaction = call. tx . clone ( ) ;
258+ // Setting the gas here avoids a redundant call to estimate_gas within the Provider's fill_transaction method.
259+ transaction. set_gas ( gas) ;
251260
252261 // manually fill the tx with the gas price info, so we can log the details in case of error
253262 client
@@ -258,6 +267,7 @@ pub async fn submit_tx<T: Middleware + NonceManaged + 'static>(
258267 if let Some ( e) = e. as_error_response ( ) {
259268 if let Some ( e) = e. as_revert_data ( ) {
260269 return backoff:: Error :: transient ( SubmitTxError :: GasUsageEstimateError (
270+ transaction. clone ( ) ,
261271 ContractError :: Revert ( e. clone ( ) ) ,
262272 ) ) ;
263273 }
0 commit comments