{"record":{"id":"27160a7238200243","repo":"nautechsystems/nautilus_trader","slug":"poolmanager-address-should-be-set-in-logs","errorCode":null,"errorMessage":"PoolManager address should be set in logs","messagePattern":"PoolManager address should be set in logs","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/exchanges/parsing/uniswap_v4/initialize.rs","lineNumber":81,"sourceCode":"/// ```\n///\n/// # Errors\n///\n/// Returns an error if the log parsing fails or if the event data is invalid.\n///\n/// # Panics\n///\n/// Panics if the log address is not set.\npub fn parse_initialize_event_hypersync(log: HypersyncLog) -> anyhow::Result<PoolCreatedEvent> {\n    validate_event_signature_hash(\"InitializeEvent\", INITIALIZE_EVENT_SIGNATURE_HASH, &log)?;\n\n    let block_number = extract_block_number(&log)?;\n\n    // The pool address for V4 is the PoolManager contract address (the event emitter)\n    let pool_manager_address = Address::from_slice(\n        log.address\n            .clone()\n            .expect(\"PoolManager address should be set in logs\")\n            .as_ref(),\n    );\n\n    // Extract currency0 and currency1 from topics\n    // topics[0] = event signature\n    // topics[1] = poolId (bytes32)\n    // topics[2] = currency0 (indexed)\n    // topics[3] = currency1 (indexed)\n    let topics = &log.topics;\n    if topics.len() < 4 {\n        anyhow::bail!(\n            \"Initialize event missing topics: expected 4, was {}\",\n            topics.len()\n        );\n    }\n\n    // Extract Pool ID from topics[1] - this is the unique identifier for V4 pools\n    let pool_id_bytes = topics[1]","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/exchanges/parsing/uniswap_v4/initialize.rs#L63-L99","documentation":"In `parse_initialize_event_hypersync` (Uniswap V4), the pool is identified by the PoolManager contract that emitted the Initialize event, read from `log.address` via `.expect(\"PoolManager address should be set in logs\")`. On-chain logs always carry the emitter address, so `None` means the input log is missing its emitter — an input-contract violation the parser treats as a hard panic. Unlike V3, the pool address here is the contract address itself, so this field is mandatory for building the `PoolIdentifier`.","triggerScenarios":"Calling `parse_initialize_event_hypersync` with a `HyperSyncLog` whose `address` is `None`, e.g. a fixture built without `address` or log data that lost the emitter during deserialization/conversion.","commonSituations":"Test logs for V4 Initialize events built via default construction omitting the PoolManager address; adapting logs from another indexer into the hypersync log type; a hypersync client schema change making the address field optional.","solutions":["Populate `log.address` with the PoolManager contract address before parsing.","If converting logs from another source, ensure the emitter address is copied into the hypersync log.","In your own code, unwrap the Option with a proper error message instead of relying on the panic.","Verify the hypersync client version still fills the log address field on deserialization."],"exampleFix":"// before\nlet pool_manager_address = Address::from_slice(\n    log.address.clone().expect(\"PoolManager address should be set in logs\").as_ref(),\n);\n// after\nlet emitter = log.address.clone().ok_or_else(|| anyhow::anyhow!(\"initialize log missing PoolManager address\"))?;\nlet pool_manager_address = Address::from_slice(emitter.as_ref());","handlingStrategy":"validation","validationCode":"fn require_pool_manager(log: &HyperSyncLog) -> Result<Address, String> {\n    log.address.clone().ok_or_else(|| \"V4 initialize log missing PoolManager address\".to_string())\n}","typeGuard":"fn has_pool_manager(log: &HyperSyncLog) -> bool {\n    log.address.is_some()\n}","tryCatchPattern":"// Propagate as error before parsing\nlet pool_manager = require_pool_manager(&log)?;","preventionTips":["Always set log.address to the PoolManager address in V4 fixtures.","Centralize hypersync log construction so the emitter is a mandatory parameter.","Assert fixture completeness in tests before exercising the parser."],"tags":["panic","rust","hypersync","uniswap-v4","missing-field"],"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"}