@@ -6837,6 +6837,12 @@ fn get_valid_nft_addr_to_withdraw(
68376837pub enum EthGasDetailsErr {
68386838 #[ display( fmt = "Invalid fee policy: {}" , _0) ]
68396839 InvalidFeePolicy ( String ) ,
6840+ #[ display(
6841+ fmt = "Amount {} is too low. Required minimum is {} to cover fees." ,
6842+ amount,
6843+ threshold
6844+ ) ]
6845+ AmountTooLow { amount : BigDecimal , threshold : BigDecimal } ,
68406846 #[ from_stringify( "NumConversError" ) ]
68416847 #[ display( fmt = "Internal error: {}" , _0) ]
68426848 Internal ( String ) ,
@@ -6919,7 +6925,11 @@ async fn get_eth_gas_details_from_withdraw_fee(
69196925
69206926 // covering edge case by deducting the standard transfer fee when we want to max withdraw ETH
69216927 let eth_value_for_estimate = if fungible_max && eth_coin. coin_type == EthCoinType :: Eth {
6922- eth_value - calc_total_fee ( U256 :: from ( eth_coin. gas_limit . eth_send_coins ) , & pay_for_gas_option) . map_mm_err ( ) ?
6928+ let estimated_fee =
6929+ calc_total_fee ( U256 :: from ( eth_coin. gas_limit . eth_send_coins ) , & pay_for_gas_option) . map_mm_err ( ) ?;
6930+ // Defaulting to zero is safe; if the balance is indeed too low, the `estimate_gas` call below
6931+ // will fail, and we will catch and handle that error gracefully.
6932+ eth_value. checked_sub ( estimated_fee) . unwrap_or_default ( )
69236933 } else {
69246934 eth_value
69256935 } ;
@@ -6939,9 +6949,25 @@ async fn get_eth_gas_details_from_withdraw_fee(
69396949 max_fee_per_gas,
69406950 ..CallRequest :: default ( )
69416951 } ;
6942- // TODO Note if the wallet's balance is insufficient to withdraw, then `estimate_gas` may fail with the `Exception` error.
6943- // TODO Ideally we should determine the case when we have the insufficient balance and return `WithdrawError::NotSufficientBalance`.
6944- let gas_limit = eth_coin. estimate_gas_wrapper ( estimate_gas_req) . compat ( ) . await ?;
6952+ let gas_limit = match eth_coin. estimate_gas_wrapper ( estimate_gas_req) . compat ( ) . await {
6953+ Ok ( gas_limit) => gas_limit,
6954+ Err ( e) => {
6955+ let error_str = e. to_string ( ) . to_lowercase ( ) ;
6956+ if error_str. contains ( "insufficient funds" ) || error_str. contains ( "exceeds allowance" ) {
6957+ let standard_tx_fee =
6958+ calc_total_fee ( U256 :: from ( eth_coin. gas_limit . eth_send_coins ) , & pay_for_gas_option) . map_mm_err ( ) ?;
6959+ let threshold = u256_to_big_decimal ( standard_tx_fee, eth_coin. decimals ) . map_mm_err ( ) ?;
6960+ let amount = u256_to_big_decimal ( eth_value, eth_coin. decimals ) . map_mm_err ( ) ?;
6961+
6962+ return MmError :: err ( EthGasDetailsErr :: AmountTooLow { amount, threshold } ) ;
6963+ }
6964+ // This can be a transport error or a non-standard insufficient funds error.
6965+ // In the latter case,
6966+ // we can add to the above error handling of insufficient funds on a case-by-case basis.
6967+ return MmError :: err ( EthGasDetailsErr :: Transport ( e. to_string ( ) ) ) ;
6968+ } ,
6969+ } ;
6970+
69456971 Ok ( ( gas_limit, pay_for_gas_option) )
69466972}
69476973
0 commit comments