sui_bridge/sui_bridge_watchdog/
eth_vault_balance.rs1use crate::abi::EthERC20::EthERC20Instance;
5use crate::sui_bridge_watchdog::Observable;
6use crate::utils::EthProvider;
7use alloy::primitives::{Address as EthAddress, U256};
8use async_trait::async_trait;
9use prometheus::IntGauge;
10use tokio::time::Duration;
11use tracing::{error, info};
12
13#[derive(Debug)]
14pub enum VaultAsset {
15 WETH,
16 USDT,
17 WBTC,
18 LBTC,
19}
20
21pub struct EthereumVaultBalance {
22 coin_contract: EthERC20Instance<EthProvider>,
23 asset: VaultAsset,
24 decimals: u8,
25 vault_address: EthAddress,
26 metric: IntGauge,
27}
28
29impl EthereumVaultBalance {
30 pub async fn new(
31 provider: EthProvider,
32 vault_address: EthAddress,
33 coin_address: EthAddress, asset: VaultAsset,
35 metric: IntGauge,
36 ) -> anyhow::Result<Self> {
37 let coin_contract = EthERC20Instance::new(coin_address, provider);
38 let decimals = coin_contract
39 .decimals()
40 .call()
41 .await
42 .map_err(|e| anyhow::anyhow!("Failed to get decimals from token contract: {e}"))?;
43 Ok(Self {
44 coin_contract,
45 vault_address,
46 decimals,
47 asset,
48 metric,
49 })
50 }
51}
52
53#[async_trait]
54impl Observable for EthereumVaultBalance {
55 fn name(&self) -> &str {
56 "EthereumVaultBalance"
57 }
58 async fn observe_and_report(&self) {
59 let balance: Result<U256, alloy::contract::Error> = self
60 .coin_contract
61 .balanceOf(self.vault_address)
62 .call()
63 .await;
64 match balance {
65 Ok(balance) => {
66 let normalized_balance: U256 = match self.decimals.checked_sub(8) {
76 Some(delta) if delta > 0 => balance
79 .checked_div(U256::from(10).pow(U256::from(delta)))
80 .expect("Division by zero should be impossible here"),
81 None => {
84 let delta = 8 - self.decimals;
85 balance
86 .checked_mul(U256::from(10).pow(U256::from(delta)))
87 .expect("Integer overflow")
88 }
89 Some(_) => balance,
92 };
93 self.metric.set(normalized_balance.to::<i64>());
94
95 info!("{:?} Vault Balance: {:?}", self.asset, normalized_balance,);
96 }
97 Err(e) => {
98 error!("Error getting balance from vault: {:?}", e);
99 }
100 }
101 }
102
103 fn interval(&self) -> Duration {
104 Duration::from_secs(10)
105 }
106}