nautechsystems/nautilus_trader · error · anyhow::Error

Maximum gas cost overflow

Error message

Maximum gas cost overflow

What it means

gas_limit * max_fee_per_gas overflowed U256 while computing the worst-case gas cost before signing. Both inputs are bounded (gas limit derives from the node estimate plus a buffer capped by the configured gas_limit; max fee derives from the base fee plus buffer capped by max_fee_per_gas_wei), so an overflow implies wildly misconfigured caps rather than plausible chain values.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:1478

        let latest_block = self.http_rpc_client.latest_block().await?;
        let base_fee_per_gas_wei = latest_block.base_fee_per_gas.ok_or_else(|| {
            anyhow::anyhow!("Latest block {} has no base fee", latest_block.number)
        })?;
        let priority_fee_per_gas_wei = self.http_rpc_client.max_priority_fee_per_gas().await?;
        let (max_fee_per_gas, max_priority_fee_per_gas) = derive_fees(
            base_fee_per_gas_wei,
            priority_fee_per_gas_wei,
            self.base_fee_buffer_bps,
            u128::from(self.max_fee_per_gas_wei),
        )?;
        let gas_estimate = self
            .http_rpc_client
            .estimate_gas(&self.wallet_address, &to, value, &input)
            .await?;
        let gas_limit = derive_gas_limit(gas_estimate, self.gas_buffer_bps, self.gas_limit)?;
        let max_gas_cost = U256::from(gas_limit)
            .checked_mul(U256::from(max_fee_per_gas))
            .ok_or_else(|| anyhow::anyhow!("Maximum gas cost overflow"))?;
        let max_transaction_cost = value
            .checked_add(max_gas_cost)
            .ok_or_else(|| anyhow::anyhow!("Maximum transaction cost overflow"))?;
        let native_balance = self
            .http_rpc_client
            .get_balance_with_timeout(&self.wallet_address, None, Some(EXECUTION_RPC_TIMEOUT_SECS))
            .await?;

        if native_balance < max_transaction_cost {
            anyhow::bail!(
                "Native currency balance {native_balance} wei is below maximum transaction cost {max_transaction_cost} wei"
            );
        }

        let tx = build_eip1559_transaction(
            expected_chain_id,
            nonce,
            gas_limit,

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Sanity-check the fee config: max_fee_per_gas_wei should be a realistic gwei price scaled to wei (e.g. 100 gwei = 100 * 10**9)
  2. Bound gas_limit to the block gas limit of the target chain (typically <= 30M)
  3. Add startup validation rejecting configs whose max_fee_per_gas_wei * gas_limit could approach U256 bounds

Example fix

# before: gwei value written as if it were already scaled, near-overflowing product
config.max_fee_per_gas_wei = 10**30
config.gas_limit = 30_000_000

# after: realistic caps (100 gwei ceiling, 1M gas)
config.max_fee_per_gas_wei = 100 * 10**9
config.gas_limit = 1_000_000
assert config.max_fee_per_gas_wei * config.gas_limit < 2**128
Defensive patterns

Strategy: validation

Validate before calling

# Startup config sanity: worst-case gas cost must stay far below U256
assert config.max_fee_per_gas_wei <= 1_000 * 10**9, 'max fee above 1000 gwei is a units bug'
assert config.gas_limit <= 30_000_000, 'gas limit above a typical block limit is a units bug'
assert config.max_fee_per_gas_wei * config.gas_limit < 2**128, 'cost ceiling unrealistic'

Prevention

When it happens

Trigger: prepare_and_sign with max_fee_per_gas_wei set near u128::MAX (wrong units, e.g. wei-vs-gwei confusion) combined with a high configured gas_limit, making the product exceed 2^256.

Common situations: Configuring gas prices in wei when the value was already in gwei (10^9 factor); pasting test/sentinel values like 2^127 into the config; generated configs with unbounded defaults.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/a6184764bb3b1ce4. Report an issue: GitHub.