{"record":{"id":"4e456a9ad982ca41","repo":"nautechsystems/nautilus_trader","slug":"missing-ticklower-in-topic2-when-parsing-collect-e","errorCode":null,"errorMessage":"Missing tickLower in topic2 when parsing collect event","messagePattern":"Missing tickLower in topic2 when parsing collect event","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/collect.rs","lineNumber":69,"sourceCode":"///\n/// # Panics\n///\n/// Panics if the contract address is not set in the log.\npub fn parse_collect_event_hypersync(\n    dex: SharedDex,\n    log: &HypersyncLog,\n) -> anyhow::Result<CollectEvent> {\n    validate_event_signature_hash(\"Collect\", COLLECT_EVENT_SIGNATURE_HASH, log)?;\n\n    let owner = extract_address_from_topic(log, 1, \"owner\")?;\n\n    // Extract int24 tickLower from topic2 (stored as a 32-byte padded value)\n    let tick_lower = match log.topics.get(2).and_then(|t| t.as_ref()) {\n        Some(topic) => {\n            let tick_lower_bytes: [u8; 32] = topic.as_ref().try_into()?;\n            i32::from_be_bytes(tick_lower_bytes[28..32].try_into()?)\n        }\n        None => anyhow::bail!(\"Missing tickLower in topic2 when parsing collect event\"),\n    };\n\n    // Extract int24 tickUpper from topic3 (stored as a 32-byte padded value)\n    let tick_upper = match log.topics.get(3).and_then(|t| t.as_ref()) {\n        Some(topic) => {\n            let tick_upper_bytes: [u8; 32] = topic.as_ref().try_into()?;\n            i32::from_be_bytes(tick_upper_bytes[28..32].try_into()?)\n        }\n        None => anyhow::bail!(\"Missing tickUpper in topic3 when parsing collect event\"),\n    };\n\n    if let Some(data) = &log.data {\n        let data_bytes = data.as_ref();\n\n        // Validate if data contains 3 parameters of 32 bytes each\n        if data_bytes.len() < 3 * 32 {\n            anyhow::bail!(\"Collect event data is too short\");\n        }","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/collect.rs#L51-L87","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the log's topic0 matches the Collect event signature before calling parse_collect_event_hypersync","Check log.topics.len() >= 4 and that each slot is Some before parsing","Ensure the HyperSync query/request is scoped to the UniswapV3Pool Collect event ABI","Log the raw topics array to confirm which event was actually delivered"],"exampleFix":"// before\nlet event = parse_collect_event_hypersync(&dex, &log)?;\n// after\nif log.topics.len() < 4 || log.topics[0].as_deref() != Some(&COLLECT_TOPIC0) {\n    return Ok(None); // skip non-Collect logs\n}\nlet event = parse_collect_event_hypersync(&dex, &log)?;","handlingStrategy":"validation","validationCode":"const COLLECT_TOPIC0: [u8; 32] = <Collect as SolEvent>::SIGNATURE_HASH;\nfn has_collect_topics(log: &Log) -> bool {\n    log.topics.len() >= 4\n        && log.topics[0].as_deref() == Some(&COLLECT_TOPIC0)\n        && log.topics.iter().skip(1).all(|t| t.is_some())\n}\n// if !has_collect_topics(&log) { skip or re-fetch }","typeGuard":"fn is_collect_log(log: &Log) -> bool {\n    log.topics.len() >= 4 && log.topics[0].is_some() && log.topics[2].is_some()\n}","tryCatchPattern":"match parse_collect_event_hypersync(&dex, &log) {\n    Ok(event) => handle(event),\n    Err(e) if e.to_string().contains(\"Missing tickLower\") => {\n        tracing::warn!(\"Collect log missing topic2, skipping: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always filter HyperSync/RPC queries by the exact Collect event topic0","Validate topic count and presence before invoking parsers","Write a round-trip test that encodes a Collect event and parses it back","Pin the pool ABI version your adapter expects"],"tags":["blockchain","uniswap-v3","event-parsing","missing-topic"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}