nautechsystems/nautilus_trader · error · anyhow::Error

Failed converting gas limit to u64

Error message

Failed converting gas limit to u64

What it means

calculate_fee_from_gas computes the fee as gas_price * gas_limit using Decimal arithmetic, then converts the gas limit back to u64 for the cosmrs Fee. If the Decimal gas limit cannot be represented as u64 (e.g. it is negative, fractional, or exceeds u64::MAX), the conversion fails and this error is returned.

Source

Thrown at crates/adapters/dydx/src/grpc/builder.rs:96

        if let Some(gas) = gas_used {
            self.calculate_fee_from_gas(gas)
        } else {
            Ok(Self::default_fee())
        }
    }

    /// Calculate fee from gas usage.
    fn calculate_fee_from_gas(&self, gas_used: u64) -> Result<Fee, anyhow::Error> {
        let gas_multiplier = Decimal::try_from(GAS_MULTIPLIER)?;
        let gas_limit = Decimal::from(gas_used) * gas_multiplier;

        // Gas price for dYdX (typically 0.025 adydx per gas)
        let gas_price = Decimal::new(25, 3); // 0.025
        let amount = (gas_price * gas_limit).ceil();

        let gas_limit_u64 = gas_limit
            .to_u64()
            .ok_or_else(|| anyhow::anyhow!("Failed converting gas limit to u64"))?;

        let amount_u128 = amount
            .to_u128()
            .ok_or_else(|| anyhow::anyhow!("Failed converting gas cost to u128"))?;

        Ok(Fee::from_amount_and_gas(
            Coin {
                amount: amount_u128,
                denom: self
                    .fee_denom
                    .parse()
                    .map_err(|e| anyhow::anyhow!("Invalid fee denom: {e}"))?,
            },
            gas_limit_u64,
        ))
    }

    /// Get default fee (zero fee).

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the gas limit passed to calculate_fee is a non-negative whole number Decimal within u64 range (practically <= ~1.8e19, real txs use far less).
  2. Sanity-clamp the gas estimate before calling: if gas_limit <= 0 or > a sane ceiling, fix the estimation source.
  3. Check where the gas value originates (simulation response vs hardcoded default) and correct unit conversion there.
  4. If a fractional gas value comes from averaging estimates, round it (e.g. .ceil()/.round()) before calling.

Example fix

// before
let gas_limit = Decimal::new(-5, 0); // negative -> conversion fails
// after
let gas_limit = Decimal::from(2_000_000u64); // valid whole-number gas limit
Defensive patterns

Strategy: validation

Validate before calling

fn valid_gas_limit(g: Decimal) -> bool {
    g.is_sign_positive() && g.fract().is_zero() && g <= Decimal::from(u64::MAX)
}

Try / catch

let fee = client.calculate_fee(instrument_id, gas_limit)
    .map_err(|e| {
        if e.to_string().contains("gas limit to u64") {
            // clamp/fix gas estimate at the source
        }
        e
    })?;

Prevention

When it happens

Trigger: Calling calculate_fee (-> calculate_fee_from_gas) with a gas_limit Decimal that is negative, non-integer, or greater than 2^64-1.

Common situations: A misconfigured or corrupted gas estimate (e.g. gas limit parsed from an API response with unexpected units); passing a fractional Decimal like 0.5; an upstream simulation returning an absurdly large gas figure.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/9c62656ab4763ffe. Report an issue: GitHub.