{"record":{"id":"2184f20d2936b97a","repo":"nautechsystems/nautilus_trader","slug":"failed-to-decode-collectprotocol-event-data-e","errorCode":null,"errorMessage":"Failed to decode CollectProtocol event data: {e}","messagePattern":"Failed to decode CollectProtocol event data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/fee_protocol_collect.rs","lineNumber":77,"sourceCode":"        \"CollectProtocol\",\n        FEE_PROTOCOL_COLLECT_EVENT_SIGNATURE_HASH,\n        log,\n    )?;\n\n    let sender = extract_address_from_topic(log, 1, \"sender\")?;\n    let recipient = extract_address_from_topic(log, 2, \"recipient\")?;\n\n    if let Some(data) = &log.data {\n        let data_bytes = data.as_ref();\n\n        // Validate the data contains 2 parameters of 32 bytes each\n        if data_bytes.len() < 2 * 32 {\n            anyhow::bail!(\"CollectProtocol event data is too short\");\n        }\n\n        let decoded = match <FeeProtocolCollectEventData as SolType>::abi_decode(data_bytes) {\n            Ok(decoded) => decoded,\n            Err(e) => anyhow::bail!(\"Failed to decode CollectProtocol 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(FeeProtocolCollectEvent::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            sender,","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/fee_protocol_collect.rs#L59-L95","documentation":"Raised by parse_fee_protocol_collect_event_hypersync when FeeProtocolCollectEventData::abi_decode fails on data that passed the 64-byte length check. The alloy error is embedded, meaning the two 32-byte words do not match the expected (uint256, uint256) layout.","triggerScenarios":"Data words from a different event layout decoded as CollectProtocol; extra ABI offset/pointer encoding from dynamic fields; corrupted data bytes from upstream conversion.","commonSituations":"Custom pool contracts emitting same-topic events with different payloads; stale adapter ABI vs contract upgrade; bugs in hex-to-bytes conversion of test fixtures.","solutions":["Read the embedded error to identify which word failed to decode as uint256","Verify topic0 equals the canonical CollectProtocol signature hash","Dump data_bytes as hex and decode with cast abi-decode to compare layouts","Re-fetch logs with the correct event filter from HyperSync"],"exampleFix":"// before\nlet decoded = <FeeProtocolCollectEventData as SolType>::abi_decode(data_bytes)?;\n// after\nanyhow::ensure!(\n    log.topics[0].as_deref() == Some(&COLLECT_PROTOCOL_TOPIC0),\n    \"not CollectProtocol: {:?}\", log.topics.first()\n);\nlet decoded = <FeeProtocolCollectEventData as SolType>::abi_decode(data_bytes)?;","handlingStrategy":"try-catch","validationCode":"anyhow::ensure!(\n    log.topics[0].as_deref() == Some(&COLLECT_PROTOCOL_TOPIC0),\n    \"unexpected event for CollectProtocol parser\"\n);\nanyhow::ensure!(log.data.as_deref().map_or(false, |d| d.len() >= 64), \"missing/truncated data\");","typeGuard":"fn is_collect_protocol(log: &Log) -> bool {\n    log.topics.first().and_then(|t| t.as_deref()) == Some(&COLLECT_PROTOCOL_TOPIC0)\n        && log.data.as_deref().map_or(false, |d| d.len() >= 64)\n}","tryCatchPattern":"let decoded = <FeeProtocolCollectEventData as SolType>::abi_decode(data_bytes)\n    .with_context(|| format!(\"CollectProtocol decode failed; data={:?}\", log.data.as_deref().map(hex::encode)))?;","preventionTips":["Verify event signature before decoding","Hex-dump failing payloads for offline diagnosis","Track contract upgrades that may alter event layouts","Add decode round-trip tests for CollectProtocol fixtures"],"tags":["blockchain","uniswap-v3","fee-protocol","abi","decode-failure"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}