nautechsystems/nautilus_trader · error · anyhow::Error
Pool {instrument_id} fee {fee} exceeds uint24
Error message
Pool {instrument_id} fee {fee} exceeds uint24 What it means
The pool's fee value could not be converted to alloy's U24 type: it exceeds 16,777,215 (2^24 - 1). Uniswap V3 encodes the fee tier in the upper 24 bits of the pool address space, so any fee outside u24 cannot appear in a valid pool. This is effectively a configuration unit error, not a chain condition.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:1180
if order.order_side() != OrderSide::Sell {
anyhow::bail!(
"Unsupported order side {}; only Sell is supported",
order.order_side()
);
}
if order.is_quote_quantity() {
anyhow::bail!(
"Quote-denominated quantities are not supported; quantity must be denominated in the base token"
);
}
let fee = pool
.fee
.ok_or_else(|| anyhow::anyhow!("Pool {instrument_id} has no fee tier"))?;
let fee = U24::try_from(fee)
.map_err(|_| anyhow::anyhow!("Pool {instrument_id} fee {fee} exceeds uint24"))?;
let base_token = pool.get_base_token();
let quote_token = pool.get_quote_token();
let quote_currency = Currency::new_checked(
"e_token.symbol,
quote_token.decimals,
0,
"e_token.name,
CurrencyType::Crypto,
)?;
if !self
.transaction_limits
.allowed_token_pairs
.contains(&(base_token.address, quote_token.address))
{
anyhow::bail!(
"Token pair {} -> {} is not in the `allowed_token_pairs` allowlist",View on GitHub (pinned to 2114cf6f76)
Solutions
- Correct the fee to Uniswap V3's encoding: integer hundredths of a bip, at most 1,000,000 (100%), well under the u24 ceiling
- Validate config at load time: assert 0 < fee <= 0xFFFFFF for every configured pool
- Cross-check against the on-chain pool: read fee() from the pool contract and use exactly that value
Example fix
# before: fee authored in wei-like units, exceeds u24 pool.fee = 5_000_000_000 # Pool ... fee exceeds uint24 # after: Uniswap V3 fee encoding (0.05% = 500) pool.fee = 500 assert 0 < pool.fee <= 0xFFFFFF
Defensive patterns
Strategy: validation
Validate before calling
U24_MAX = (1 << 24) - 1
def valid_uniswap_fee(fee: int | None) -> bool:
return fee is not None and 0 < fee <= U24_MAX
for pool in configured_pools:
assert valid_uniswap_fee(pool.fee), f'{pool.instrument_id}: fee must be hundredths of a bip, <= {U24_MAX}' Type guard
def is_uniswap_v3_fee(fee: int | None) -> bool:
"""Uniswap V3 fee tiers: integer hundredths of a bip, u24-encoded."""
return isinstance(fee, int) and 0 < fee <= 0xFFFFFF Prevention
- Write fee tiers in Uniswap V3 units from day one: 100=0.01%, 500=0.05%, 3000=0.30%, 10000=1%
- Cross-check the value against the pool contract's immutable fee() before deploying config
When it happens
Trigger: submit_order where the cached pool fee was authored in the wrong units: e.g. fee entered in millionths of a percent, as a decimal fraction scaled up, or pasted from a spec sheet (values like 5_000_000_000 or 0.05*10**12).
Common situations: Copy-pasting a '0.0005' probability-style fee and multiplying by the wrong power of ten; mixing up 'fee' (bps*100) with 'tick spacing'; configuration written for a different DEX's fee units.
Related errors
- Pool {instrument_id} has no fee tier
- slippage_bps parameter {value} exceeds the u32 range
- Swap quote failed for {instrument_id}: {e}
- Maximum gas cost overflow
- Maximum transaction cost overflow
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/87f63ffc67150701.
Report an issue: GitHub.