{"record":{"id":"8db83dba90fdec09","repo":"nautechsystems/nautilus_trader","slug":"missing-fee-in-topic3-when-parsing-pool-created-ev","errorCode":null,"errorMessage":"Missing fee in topic3 when parsing pool created event","messagePattern":"Missing fee in topic3 when parsing pool created event","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/pool_created.rs","lineNumber":49,"sourceCode":"    \"783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b7118\";\n\n/// Parses a pool creation event from a HyperSync log.\n///\n/// # Errors\n///\n/// Returns an error if the log parsing fails or if the event data is invalid.\npub fn parse_pool_created_event_hypersync(log: HypersyncLog) -> anyhow::Result<PoolCreatedEvent> {\n    validate_event_signature_hash(\"PoolCreatedEvent\", POOL_CREATED_EVENT_SIGNATURE_HASH, &log)?;\n\n    let block_number = extract_block_number(&log)?;\n\n    let token = extract_address_from_topic(&log, 1, \"token0\")?;\n    let token1 = extract_address_from_topic(&log, 2, \"token1\")?;\n\n    let fee = if let Some(topic) = log.topics.get(3).and_then(|t| t.as_ref()) {\n        U256::from_be_slice(topic.as_ref()).as_limbs()[0] as u32\n    } else {\n        anyhow::bail!(\"Missing fee in topic3 when parsing pool created event\");\n    };\n\n    if let Some(data) = log.data {\n        // Data contains: [tick_spacing (32 bytes), pool_address (32 bytes)]\n        let data_bytes = data.as_ref();\n\n        // Extract tick_spacing (first 32 bytes)\n        let tick_spacing_bytes: [u8; 32] = data_bytes[0..32].try_into()?;\n        let tick_spacing = u32::from_be_bytes(tick_spacing_bytes[28..32].try_into()?);\n\n        // Extract pool_address (next 32 bytes)\n        let pool_address_bytes: [u8; 32] = data_bytes[32..64].try_into()?;\n        let pool_address = Address::from_slice(&pool_address_bytes[12..32]);\n\n        Ok(PoolCreatedEvent::new(\n            block_number,\n            token,\n            token1,","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/pool_created.rs#L31-L67","documentation":"parse_pool_created_event_hypersync requires topic3 of the PoolCreated event because the fee uint24 is indexed there. When the hypersync log carries fewer than 4 topics, the library cannot recover the fee tier and bails rather than guessing a default.","triggerScenarios":"Calling parse_pool_created_event_hypersync with a log that has fewer than 4 topics — typically because the source address is not actually a Uniswap V3 factory, or the subscription filter matched a non-PoolCreated event signature.","commonSituations":"Wide hypersync queries (topic0 omitted or broad) that pull in unrelated factory events; decoding logs from a V2-style factory or a fork that emits PoolCreated with unindexed fee (fee in data instead of topic3).","solutions":["Filter hypersync queries by the exact PoolCreated topic0 and require 4 indexed topics","Check topics.len() >= 4 in the caller before invoking the parser and skip non-matching logs","Confirm the source contract is the canonical Uniswap V3 factory for the target chain","If decoding a fork whose fee is not indexed, parse fee from the data section instead of topic3"],"exampleFix":"// before\nlet fee = if let Some(topic) = log.topics.get(3).and_then(|t| t.as_ref()) {\n    U256::from_be_slice(topic.as_ref()).as_limbs()[0] as u32\n} else {\n    anyhow::bail!(\"Missing fee in topic3 when parsing pool created event\");\n};\n// after\nif log.topics.len() < 4 {\n    tracing::debug!(\"skipping log: not a canonical PoolCreated event (topics < 4)\");\n    return Ok(None); // or continue\n}\nlet fee = U256::from_be_slice(log.topics[3].as_ref()).as_limbs()[0] as u32;","handlingStrategy":"validation","validationCode":"fn has_pool_created_topics(log: &HypersyncLog) -> bool {\n    log.topics.len() >= 4 && log.topics[0].as_ref() == POOL_CREATED_TOPIC0\n}\nif !has_pool_created_topics(&log) { skip_or_log(); }","typeGuard":null,"tryCatchPattern":"match parse_pool_created_event_hypersync(&log, &factory) {\n    Ok(ev) => handle(ev),\n    Err(e) => { tracing::debug!(%e, \"pool-created log skipped\"); Ok(None) }\n}","preventionTips":["Always include the exact PoolCreated topic0 in hypersync topic filters","Require 4 indexed topics in the subscription","Verify chain-specific factory addresses","Treat topic3-fee presence as a V3-canonicality check"],"tags":["blockchain","uniswap-v3","event-parsing","missing-field"],"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"}