Skip to content

Commit ba69956

Browse files
fix: extra checks for the auto top-up background task to make sure th… (#50)
* fix: extra checks for the auto top-up background task to make sure they have eth and tokens * update logs
1 parent bba6bcc commit ba69956

File tree

2 files changed

+104
-23
lines changed

2 files changed

+104
-23
lines changed

crates/core/src/background_tasks/automatic_top_up_task.rs

Lines changed: 103 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

documentation/rrelayer/docs/pages/changelog.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
- fix: use correct serialization function for ERC20 tokens in topup flow
1414
- fix: Rust SDK now passes API key in `x-rrelayer-api-key` header instead of `Authorization` header
15+
- fix: extra checks for the auto top-up background task to make sure they have eth and tokens
1516

1617
---
1718

0 commit comments

Comments
 (0)