From b87b2bcc605b83349b461e02bae5566a742195d1 Mon Sep 17 00:00:00 2001 From: Jayant Krishnamurthy Date: Wed, 17 Dec 2025 21:17:50 -0600 Subject: [PATCH] cleanup --- apps/fortuna/src/command.rs | 3 +- apps/fortuna/src/command/debug_gas.rs | 102 +++++++++++++++++++++++++ apps/fortuna/src/config.rs | 12 ++- apps/fortuna/src/config/debug_gas.rs | 16 ++++ apps/fortuna/src/main.rs | 1 + target_chains/fuel/sdk/js/package.json | 2 +- 6 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 apps/fortuna/src/command/debug_gas.rs create mode 100644 apps/fortuna/src/config/debug_gas.rs diff --git a/apps/fortuna/src/command.rs b/apps/fortuna/src/command.rs index 3d895af458..e446f4f969 100644 --- a/apps/fortuna/src/command.rs +++ b/apps/fortuna/src/command.rs @@ -1,3 +1,4 @@ +mod debug_gas; mod generate; mod get_request; mod inspect; @@ -8,7 +9,7 @@ mod setup_provider; mod withdraw_fees; pub use { - generate::generate, get_request::get_request, inspect::inspect, + debug_gas::debug_gas, generate::generate, get_request::get_request, inspect::inspect, register_provider::register_provider, request_randomness::request_randomness, run::run, setup_provider::setup_provider, withdraw_fees::withdraw_fees, }; diff --git a/apps/fortuna/src/command/debug_gas.rs b/apps/fortuna/src/command/debug_gas.rs new file mode 100644 index 0000000000..e793e7fdea --- /dev/null +++ b/apps/fortuna/src/command/debug_gas.rs @@ -0,0 +1,102 @@ +use { + crate::{ + chain::ethereum::{InstrumentedPythContract, InstrumentedSignablePythContract}, + config::{Config, DebugGasOptions}, + eth_utils::{traced_client::RpcMetrics, utils::estimate_tx_cost}, + }, + anyhow::Result, + ethers::providers::Middleware, + prometheus_client::registry::Registry, + std::sync::Arc, + tokio::{sync::RwLock, time::Duration}, +}; + +const POLL_INTERVAL: Duration = Duration::from_secs(2); + +pub async fn debug_gas(opts: &DebugGasOptions) -> Result<()> { + let config = Config::load(&opts.config.config)?; + let chain_config = config.get_chain_config(&opts.chain_id)?; + + // Create metrics registry for the instrumented contract + let metrics_registry = Arc::new(RwLock::new(Registry::default())); + let rpc_metrics = Arc::new(RpcMetrics::new(metrics_registry.clone()).await); + + // Get network_id by creating a temporary contract + let temp_contract = InstrumentedPythContract::from_config( + &chain_config, + opts.chain_id.clone(), + rpc_metrics.clone(), + )?; + let network_id = temp_contract.get_network_id().await?.as_u64(); + + // Get the keeper private key + let keeper_private_key = + config.keeper.private_key.load()?.ok_or_else(|| { + anyhow::anyhow!("Keeper private key is required for debug_gas command") + })?; + + // Instantiate InstrumentedSignablePythContract + let contract = Arc::new(InstrumentedSignablePythContract::from_config( + &chain_config, + &keeper_private_key, + opts.chain_id.clone(), + rpc_metrics, + network_id, + )?); + + tracing::info!("Starting gas price debugger for chain: {}", opts.chain_id); + tracing::info!("Watching for new blocks and calling estimate_tx_cost on each block..."); + tracing::info!("Press Ctrl+C to stop"); + + let middleware = contract.client().clone(); + let mut last_block_number: Option = None; + + loop { + // Get the latest block number + let latest_block = match middleware.get_block_number().await { + Ok(block_num) => block_num.as_u64(), + Err(e) => { + tracing::error!("Failed to get latest block number: {}", e); + tokio::time::sleep(POLL_INTERVAL).await; + continue; + } + }; + + // Check if we have a new block + if let Some(last) = last_block_number { + if latest_block <= last { + tokio::time::sleep(POLL_INTERVAL).await; + continue; + } + } + + // New block detected, estimate transaction cost + let gas_limit: u128 = chain_config.gas_limit as u128; + match estimate_tx_cost(middleware.clone(), chain_config.legacy_tx, gas_limit).await { + Ok(tx_cost) => { + let tx_cost_eth = tx_cost as f64 / 1e18; + let effective_gas_price = tx_cost / gas_limit; + let effective_gas_price_gwei = effective_gas_price as f64 / 1e9; + tracing::info!( + "Block {}: tx_cost ({} gas) = {} ETH ({} wei), effective_gas_price = {} gwei ({} wei)", + latest_block, + gas_limit, + tx_cost_eth, + tx_cost, + effective_gas_price_gwei, + effective_gas_price + ); + } + Err(e) => { + tracing::error!( + "Block {}: Failed to estimate transaction cost: {}", + latest_block, + e + ); + } + } + + last_block_number = Some(latest_block); + tokio::time::sleep(POLL_INTERVAL).await; + } +} diff --git a/apps/fortuna/src/config.rs b/apps/fortuna/src/config.rs index a7902139ff..4e944a3d92 100644 --- a/apps/fortuna/src/config.rs +++ b/apps/fortuna/src/config.rs @@ -10,12 +10,13 @@ use { std::{collections::HashMap, fs}, }; pub use { - generate::GenerateOptions, get_request::GetRequestOptions, inspect::InspectOptions, - prometheus_client::metrics::histogram::Histogram, register_provider::RegisterProviderOptions, - request_randomness::RequestRandomnessOptions, run::RunOptions, - setup_provider::SetupProviderOptions, withdraw_fees::WithdrawFeesOptions, + debug_gas::DebugGasOptions, generate::GenerateOptions, get_request::GetRequestOptions, + inspect::InspectOptions, prometheus_client::metrics::histogram::Histogram, + register_provider::RegisterProviderOptions, request_randomness::RequestRandomnessOptions, + run::RunOptions, setup_provider::SetupProviderOptions, withdraw_fees::WithdrawFeesOptions, }; +mod debug_gas; mod generate; mod get_request; mod inspect; @@ -58,6 +59,9 @@ pub enum Options { /// Withdraw any of the provider's accumulated fees from the contract. WithdrawFees(WithdrawFeesOptions), + + /// Debug gas estimation issues on a blockchain by watching blocks and calling get_gas_price. + DebugGas(DebugGasOptions), } #[derive(Args, Clone, Debug)] diff --git a/apps/fortuna/src/config/debug_gas.rs b/apps/fortuna/src/config/debug_gas.rs new file mode 100644 index 0000000000..f20e441f41 --- /dev/null +++ b/apps/fortuna/src/config/debug_gas.rs @@ -0,0 +1,16 @@ +use { + crate::{api::ChainId, config::ConfigOptions}, + clap::Args, +}; + +#[derive(Args, Clone, Debug)] +#[command(next_help_heading = "Debug Gas Options")] +#[group(id = "DebugGas")] +pub struct DebugGasOptions { + #[command(flatten)] + pub config: ConfigOptions, + + /// The chain ID to debug gas estimation for. + #[arg(long = "chain-id")] + pub chain_id: ChainId, +} diff --git a/apps/fortuna/src/main.rs b/apps/fortuna/src/main.rs index 2d3ea45edb..3d5735f6da 100644 --- a/apps/fortuna/src/main.rs +++ b/apps/fortuna/src/main.rs @@ -38,5 +38,6 @@ async fn main() -> Result<()> { config::Options::RequestRandomness(opts) => command::request_randomness(&opts).await, config::Options::Inspect(opts) => command::inspect(&opts).await, config::Options::WithdrawFees(opts) => command::withdraw_fees(&opts).await, + config::Options::DebugGas(opts) => command::debug_gas(&opts).await, } } diff --git a/target_chains/fuel/sdk/js/package.json b/target_chains/fuel/sdk/js/package.json index 5d159b210b..9fd1a3b247 100644 --- a/target_chains/fuel/sdk/js/package.json +++ b/target_chains/fuel/sdk/js/package.json @@ -99,4 +99,4 @@ "./package.json": "./package.json" }, "module": "./dist/esm/index.mjs" -} +} \ No newline at end of file