@@ -278,7 +278,15 @@ impl AutomaticTopUpTask {
278278 chain_id
279279 ) ;
280280
281- match self . check_native_from_address_balance ( provider, from_address, native_config) . await {
281+ match self
282+ . check_native_from_address_balance (
283+ provider,
284+ from_address,
285+ native_config,
286+ addresses_needing_top_up. len ( ) ,
287+ )
288+ . await
289+ {
282290 Ok ( sufficient) => {
283291 if !sufficient {
284292 warn ! (
@@ -376,7 +384,15 @@ impl AutomaticTopUpTask {
376384 chain_id
377385 ) ;
378386
379- match self . check_erc20_from_address_balance ( provider, from_address, token_config) . await {
387+ match self
388+ . check_erc20_from_address_balance (
389+ provider,
390+ from_address,
391+ token_config,
392+ addresses_needing_top_up. len ( ) ,
393+ )
394+ . await
395+ {
380396 Ok ( sufficient) => {
381397 if !sufficient {
382398 warn ! (
@@ -649,6 +665,7 @@ impl AutomaticTopUpTask {
649665 provider : & EvmProvider ,
650666 from_address : & EvmAddress ,
651667 native_config : & NativeTokenConfig ,
668+ total_relayers_to_top_up : usize ,
652669 ) -> Result < bool , String > {
653670 let balance = provider
654671 . rpc_client ( )
@@ -659,12 +676,13 @@ impl AutomaticTopUpTask {
659676 info ! ( "From address {} has balance: {} ETH" , from_address, format_wei_to_eth( & balance) ) ;
660677
661678 let estimated_gas_cost =
662- self . estimate_transaction_cost ( provider) . await . unwrap_or_else ( |e| {
679+ self . estimate_native_transaction_cost ( provider) . await . unwrap_or_else ( |e| {
663680 warn ! ( "Failed to estimate gas cost: {}. Using default estimate." , e) ;
664681 U256 :: from ( 21000u64 ) * U256 :: from ( 20_000_000_000u64 )
665682 } ) ;
666683
667- let min_required_balance = native_config. top_up_amount + estimated_gas_cost;
684+ let min_required_balance = ( native_config. top_up_amount + estimated_gas_cost)
685+ * U256 :: from ( total_relayers_to_top_up) ;
668686
669687 info ! (
670688 "From address {} requires {} ETH (top-up: {} ETH + gas: {} ETH)" ,
@@ -676,12 +694,13 @@ impl AutomaticTopUpTask {
676694
677695 if balance < min_required_balance {
678696 warn ! (
679- "From address {} balance ({} ETH) is insufficient for top-up transaction. Required: {} ETH (top-up: {} ETH + gas: {} ETH)" ,
697+ "From address {} balance ({} ETH) is insufficient for top-up transaction. Required: {} ETH (top-up: {} ETH + gas: {} ETH) for {} ETH transfers " ,
680698 from_address,
681699 format_wei_to_eth( & balance) ,
682700 format_wei_to_eth( & min_required_balance) ,
683701 format_wei_to_eth( & native_config. top_up_amount) ,
684- format_wei_to_eth( & estimated_gas_cost)
702+ format_wei_to_eth( & estimated_gas_cost) ,
703+ total_relayers_to_top_up
685704 ) ;
686705 return Ok ( false ) ;
687706 }
@@ -690,7 +709,10 @@ impl AutomaticTopUpTask {
690709 }
691710
692711 /// Estimates the gas cost for a standard transfer transaction.
693- async fn estimate_transaction_cost ( & self , provider : & EvmProvider ) -> Result < U256 , String > {
712+ async fn estimate_native_transaction_cost (
713+ & self ,
714+ provider : & EvmProvider ,
715+ ) -> Result < U256 , String > {
694716 let gas_price = provider
695717 . rpc_client ( )
696718 . get_gas_price ( )
@@ -710,6 +732,31 @@ impl AutomaticTopUpTask {
710732 Ok ( total_cost)
711733 }
712734
735+ /// Estimates the gas cost for an ERC-20 transfer transaction.
736+ async fn estimate_erc20_transaction_cost (
737+ & self ,
738+ provider : & EvmProvider ,
739+ ) -> Result < U256 , String > {
740+ let gas_price = provider
741+ . rpc_client ( )
742+ . get_gas_price ( )
743+ . await
744+ . map_err ( |e| format ! ( "Failed to get gas price: {}" , e) ) ?;
745+
746+ // ERC-20 transfers typically use around 65,000 gas
747+ let gas_limit = U256 :: from ( 65000u64 ) ;
748+ let total_cost = U256 :: from ( gas_price) * gas_limit;
749+
750+ info ! (
751+ "Estimated ERC-20 transaction cost: {} ETH (gas price: {} gwei, limit: {})" ,
752+ format_wei_to_eth( & total_cost) ,
753+ U256 :: from( gas_price) / U256 :: from( GWEI_TO_WEI ) ,
754+ gas_limit
755+ ) ;
756+
757+ Ok ( total_cost)
758+ }
759+
713760 /// Finds the EVM provider for a specific chain ID.
714761 fn get_provider_for_chain ( & self , chain_id : & ChainId ) -> Option < & EvmProvider > {
715762 self . providers . iter ( ) . find ( |p| & p. chain_id == chain_id)
@@ -760,37 +807,70 @@ impl AutomaticTopUpTask {
760807 provider : & EvmProvider ,
761808 from_address : & EvmAddress ,
762809 token_config : & Erc20TokenConfig ,
810+ total_relayers_to_top_up : usize ,
763811 ) -> Result < bool , String > {
764- let balance =
765- self . get_erc20_balance ( provider, & token_config. address , from_address)
766- . await
767- . map_err ( |e| format ! ( "Failed to get from_address ERC-20 token balance: {}" , e) ) ?;
812+ let token_balance = self
813+ . get_erc20_balance ( provider, & token_config. address , from_address)
814+ . await
815+ . map_err ( |e| format ! ( "Failed to get from_address ERC-20 token balance: {}" , e) ) ?;
768816
769817 info ! (
770818 "From address {} has ERC-20 token balance: {} for token {}" ,
771819 from_address,
772- format_token_amount( & balance , token_config. decimals) ,
820+ format_token_amount( & token_balance , token_config. decimals) ,
773821 token_config. address
774822 ) ;
775823
776- // For ERC-20 tokens, we don't need gas estimation as gas is paid in native tokens
777- // We just need to ensure sufficient token balance for the top-up amount
778- let min_required_balance = token_config. top_up_amount ;
824+ let native_balance =
825+ provider. rpc_client ( ) . get_balance ( ( * from_address) . into ( ) ) . await . map_err ( |e| {
826+ format ! ( "Failed to get from_address native balance for gas check: {}" , e)
827+ } ) ?;
779828
780829 info ! (
781- "From address {} requires {} tokens for token {} " ,
830+ "From address {} has native balance: {} ETH for gas " ,
782831 from_address,
783- format_token_amount( & min_required_balance, token_config. decimals) ,
784- token_config. address
832+ format_wei_to_eth( & native_balance)
785833 ) ;
786834
787- if balance < min_required_balance {
835+ let estimated_gas_cost =
836+ self . estimate_erc20_transaction_cost ( provider) . await . unwrap_or_else ( |e| {
837+ warn ! ( "Failed to estimate ERC-20 gas cost: {}. Using default estimate." , e) ;
838+ // ERC-20 transfer typically uses 65,000 gas
839+ U256 :: from ( 65000u64 ) * U256 :: from ( 20_000_000_000u64 )
840+ } ) ;
841+
842+ let total_gas_required = estimated_gas_cost * U256 :: from ( total_relayers_to_top_up) ;
843+
844+ let total_tokens_required =
845+ token_config. top_up_amount * U256 :: from ( total_relayers_to_top_up) ;
846+
847+ info ! (
848+ "From address {} requires {} ETH for gas and {} tokens for {} top-ups" ,
849+ from_address,
850+ format_wei_to_eth( & total_gas_required) ,
851+ format_token_amount( & total_tokens_required, token_config. decimals) ,
852+ total_relayers_to_top_up
853+ ) ;
854+
855+ if native_balance < total_gas_required {
788856 warn ! (
789- "From address {} token balance ({}) is insufficient for top-up transaction . Required: {} for token {} " ,
857+ "From address {} native balance ({} ETH ) is insufficient for gas costs . Required: {} ETH for {} ERC-20 transactions " ,
790858 from_address,
791- format_token_amount( & balance, token_config. decimals) ,
792- format_token_amount( & min_required_balance, token_config. decimals) ,
793- token_config. address
859+ format_wei_to_eth( & native_balance) ,
860+ format_wei_to_eth( & total_gas_required) ,
861+ total_relayers_to_top_up
862+ ) ;
863+ return Ok ( false ) ;
864+ }
865+
866+ if token_balance < total_tokens_required {
867+ warn ! (
868+ "From address {} token balance ({}) is insufficient for top-up transactions. Required: {} for token {} for {} ERC-20 transactions" ,
869+ from_address,
870+ format_token_amount( & token_balance, token_config. decimals) ,
871+ format_token_amount( & total_tokens_required, token_config. decimals) ,
872+ token_config. address,
873+ total_relayers_to_top_up
794874 ) ;
795875 return Ok ( false ) ;
796876 }
0 commit comments