nautechsystems/nautilus_trader · error

Missing tickLower in topic2 when parsing collect event

Error message

Missing tickLower in topic2 when parsing collect event

What it means

This error is raised by parse_collect_event_hypersync when a Uniswap V3 Collect event log fetched via HyperSync has no topic at index 2. The Collect event encodes tickLower as an indexed int24 in topic2, so without it the position's lower tick boundary cannot be recovered and parsing must abort.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/collect.rs:69

///
/// # Panics
///
/// Panics if the contract address is not set in the log.
pub fn parse_collect_event_hypersync(
    dex: SharedDex,
    log: &HypersyncLog,
) -> anyhow::Result<CollectEvent> {
    validate_event_signature_hash("Collect", COLLECT_EVENT_SIGNATURE_HASH, log)?;

    let owner = extract_address_from_topic(log, 1, "owner")?;

    // Extract int24 tickLower from topic2 (stored as a 32-byte padded value)
    let tick_lower = match log.topics.get(2).and_then(|t| t.as_ref()) {
        Some(topic) => {
            let tick_lower_bytes: [u8; 32] = topic.as_ref().try_into()?;
            i32::from_be_bytes(tick_lower_bytes[28..32].try_into()?)
        }
        None => anyhow::bail!("Missing tickLower in topic2 when parsing collect event"),
    };

    // Extract int24 tickUpper from topic3 (stored as a 32-byte padded value)
    let tick_upper = match log.topics.get(3).and_then(|t| t.as_ref()) {
        Some(topic) => {
            let tick_upper_bytes: [u8; 32] = topic.as_ref().try_into()?;
            i32::from_be_bytes(tick_upper_bytes[28..32].try_into()?)
        }
        None => anyhow::bail!("Missing tickUpper in topic3 when parsing collect event"),
    };

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

        // Validate if data contains 3 parameters of 32 bytes each
        if data_bytes.len() < 3 * 32 {
            anyhow::bail!("Collect event data is too short");
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the log's topic0 matches the Collect event signature before calling parse_collect_event_hypersync
  2. Check log.topics.len() >= 4 and that each slot is Some before parsing
  3. Ensure the HyperSync query/request is scoped to the UniswapV3Pool Collect event ABI
  4. Log the raw topics array to confirm which event was actually delivered

Example fix

// before
let event = parse_collect_event_hypersync(&dex, &log)?;
// after
if log.topics.len() < 4 || log.topics[0].as_deref() != Some(&COLLECT_TOPIC0) {
    return Ok(None); // skip non-Collect logs
}
let event = parse_collect_event_hypersync(&dex, &log)?;
Defensive patterns

Strategy: validation

Validate before calling

const COLLECT_TOPIC0: [u8; 32] = <Collect as SolEvent>::SIGNATURE_HASH;
fn has_collect_topics(log: &Log) -> bool {
    log.topics.len() >= 4
        && log.topics[0].as_deref() == Some(&COLLECT_TOPIC0)
        && log.topics.iter().skip(1).all(|t| t.is_some())
}
// if !has_collect_topics(&log) { skip or re-fetch }

Type guard

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

Try / catch

match parse_collect_event_hypersync(&dex, &log) {
    Ok(event) => handle(event),
    Err(e) if e.to_string().contains("Missing tickLower") => {
        tracing::warn!("Collect log missing topic2, skipping: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing a log whose topics array has fewer than 3 entries, a log for a different event with only 2 indexed parameters, or a malformed HyperSync response where topics[2] is null.

Common situations: Subscribing with an over-broad topic0 filter that matches non-Collect events; upstream provider delivering truncated topic arrays; testing with hand-crafted logs missing indexed fields.

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/4e456a9ad982ca41. Report an issue: GitHub.