nautechsystems/nautilus_trader · error

Missing currency0 topic

Error message

Missing currency0 topic

What it means

parse_initialize_event_hypersync for Uniswap V4 throws this when topics[2] is absent, since currency0 (the first token address) is stored as an indexed topic on the V4 Initialize event. Without currency0 the pool's currency pair cannot be constructed and the event is unusable. The library fails fast instead of emitting a pool with a missing currency.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v4/initialize.rs:108

    let topics = &log.topics;
    if topics.len() < 4 {
        anyhow::bail!(
            "Initialize event missing topics: expected 4, was {}",
            topics.len()
        );
    }

    // Extract Pool ID from topics[1] - this is the unique identifier for V4 pools
    let pool_id_bytes = topics[1]
        .as_ref()
        .ok_or_else(|| anyhow::anyhow!("Missing poolId topic"))?
        .as_ref();
    let pool_identifier = Ustr::from(&hex::encode_prefixed(pool_id_bytes));

    let currency0 = Address::from_slice(
        topics[2]
            .as_ref()
            .ok_or_else(|| anyhow::anyhow!("Missing currency0 topic"))?
            .as_ref()
            .get(12..32)
            .ok_or_else(|| anyhow::anyhow!("Invalid currency0 topic length"))?,
    );

    let currency1 = Address::from_slice(
        topics[3]
            .as_ref()
            .ok_or_else(|| anyhow::anyhow!("Missing currency1 topic"))?
            .as_ref()
            .get(12..32)
            .ok_or_else(|| anyhow::anyhow!("Invalid currency1 topic length"))?,
    );

    if let Some(data) = log.data {
        let data_bytes = data.as_ref();

        // Validate minimum data length (5 fields × 32 bytes = 160 bytes)

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the log has 4 topics: signature, poolId, currency0, currency1 (canonical V4 Initialize).
  2. Guard topics.len() >= 3 && topics[2].is_some() before parsing and skip/skip-log otherwise.
  3. Verify V3 logs are not being fed to the V4 parser.
  4. Correct test fixtures to include both currency topics.
Defensive patterns

Strategy: validation

Validate before calling

if log.topics.len() < 3 || log.topics[2].is_none() {
    // skip: v4 Initialize requires currency0 as topics[2]
    return Ok(None);
}

Type guard

fn has_currency0_topic(log: &Log) -> bool {
    log.topics.len() >= 3 && log.topics[2].is_some()
}

Try / catch

match parse_initialize_event_hypersync(&log) {
    Ok(event) => handle(event),
    Err(e) if e.to_string().contains("Missing currency0 topic") => {
        tracing::warn!("v4 initialize log without currency0; skipping");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling parse_initialize_event_hypersync (v4) with a log that has fewer than 3 topics or topics[2] = None — typically a malformed/non-standard Initialize log or an incomplete test fixture.

Common situations: Forked V4 contracts omitting indexed currency parameters; hand-built test logs with only signature and poolId topics; provider payloads delivering null topic slots; routing V3 Initialize logs (different topic count/layout) into the V4 parser.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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