{"record":{"id":"1cfd23d40c01335e","repo":"nautechsystems/nautilus_trader","slug":"contract-address-should-be-set-in-logs","errorCode":null,"errorMessage":"Contract address should be set in logs","messagePattern":"Contract address should be set in logs","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/fee_protocol_update.rs","lineNumber":78,"sourceCode":"        log,\n    )?;\n\n    if let Some(data) = &log.data {\n        let data_bytes = data.as_ref();\n\n        if data_bytes.len() < 4 * 32 {\n            anyhow::bail!(\"SetFeeProtocol event data is too short\");\n        }\n\n        let decoded = match <SetFeeProtocolEventData as SolType>::abi_decode(data_bytes) {\n            Ok(decoded) => decoded,\n            Err(e) => anyhow::bail!(\"Failed to decode SetFeeProtocol event data: {e}\"),\n        };\n\n        let pool_address = Address::from_slice(\n            log.address\n                .clone()\n                .expect(\"Contract address should be set in logs\")\n                .as_ref(),\n        );\n        let pool_identifier = PoolIdentifier::Address(Ustr::from(&pool_address.to_string()));\n\n        Ok(FeeProtocolUpdateEvent::new(\n            dex,\n            pool_identifier,\n            extract_block_number(log)?,\n            extract_transaction_hash(log)?,\n            extract_transaction_index(log)?,\n            extract_log_index(log)?,\n            decoded.fee_protocol0_new,\n            decoded.fee_protocol1_new,\n        ))\n    } else {\n        anyhow::bail!(\"Missing data in SetFeeProtocol event log\");\n    }\n}","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/fee_protocol_update.rs#L60-L96","documentation":"parse_fee_protocol_update_event_hypersync unwraps log.address with expect() because a Hypersync log for a PancakeSwap V3 SetFeeProtocol event must carry the emitting contract address, which becomes the pool identifier. If the Hypersync query returned a log row without an address, this expect panics. The doc comment on these parsers explicitly documents the panic condition.","triggerScenarios":"Calling parse_fee_protocol_update_event_hypersync with a HypersyncLog whose address field is None — i.e. a log produced by a Hypersync query that did not request/return the address field, or a hand-built test log missing address.","commonSituations":"Hypersync schema/API changes or query projections that omit log.address; constructing synthetic HypersyncLog fixtures without setting address; upstream Hypersync returning partial rows for contract-creation or malformed logs.","solutions":["Ensure the Hypersync query/request includes the log address field in its selected columns so every returned log has an address.","Guard before calling: skip or log-and-drop logs with address None instead of passing them to the parser.","In the parser, replace expect with ok_or(anyhow!(...)) to return a recoverable error for address-less logs."],"exampleFix":"// before\nlet pool_address = Address::from_slice(\n    log.address.clone().expect(\"Contract address should be set in logs\").as_ref(),\n);\n// after\nlet raw_address = log.address.as_ref()\n    .ok_or_else(|| anyhow::anyhow!(\"missing contract address in SetFeeProtocol log\"))?;\nlet pool_address = Address::from_slice(raw_address.as_ref());","handlingStrategy":"validation","validationCode":"if log.address.is_none() {\n    log::warn!(\"skipping SetFeeProtocol log without contract address\");\n    return Ok(());\n}\nlet event = parse_fee_protocol_update_event_hypersync(dex.clone(), &log)?;","typeGuard":"fn has_address(log: &HypersyncLog) -> bool {\n    log.address.is_some()\n}","tryCatchPattern":"match parse_fee_protocol_update_event_hypersync(dex, &log) {\n    Ok(event) => handle(event),\n    Err(e) => log::error!(\"failed to parse SetFeeProtocol log: {e:#}\"),\n}\n// Note: missing address panics via expect(); pre-check log.address before calling.","preventionTips":["Always include the address column in Hypersync log query projections.","Run a shared pre-parse guard (e.g. has_address) before any *_hypersync parser.","After upgrading the Hypersync client, re-verify that log.address is still populated in returned rows."],"tags":["panic","missing-field","hypersync","blockchain-logs","rust"],"backgroundTag":"null-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"}