{"record":{"id":"b4046019262a334e","repo":"nautechsystems/nautilus_trader","slug":"setfeeprotocol-event-data-is-too-short","errorCode":null,"errorMessage":"SetFeeProtocol event data is too short","messagePattern":"SetFeeProtocol event data is too short","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/fee_protocol_update.rs","lineNumber":67,"sourceCode":"///\n/// # Panics\n///\n/// Panics if the contract address is not set in the log.\npub fn parse_fee_protocol_update_event_hypersync(\n    dex: SharedDex,\n    log: &HypersyncLog,\n) -> anyhow::Result<FeeProtocolUpdateEvent> {\n    validate_event_signature_hash(\n        \"SetFeeProtocolEvent\",\n        FEE_PROTOCOL_UPDATE_EVENT_SIGNATURE_HASH,\n        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,","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/fee_protocol_update.rs#L49-L85","documentation":"In the Hypersync parsing path for PancakeSwap V3 `SetFeeProtocol` events, the log's `data` payload is length-checked against 4 words (4 * 32 = 128 bytes) before ABI decoding; if it is shorter, the parser bails with this message. The SetFeeProtocol event data is two 32-byte words plus padding, so a shorter payload means the log is corrupt, truncated, or was not actually a SetFeeProtocol event.","triggerScenarios":"Calling `parse_fee_protocol_update_event_hypersync` with a Hypersync log whose `data` field contains fewer than 128 bytes — e.g. a mis-filtered log (wrong topic0 in the query), a zero-length/empty data field, or a truncated payload from the provider.","commonSituations":"A Hypersync query whose topic0 filter accidentally matches logs with a different data layout; logs from a forked/modified PancakeSwap V3 deployment with a different event signature; provider-side data truncation; running the parser against logs fetched without the data column populated correctly.","solutions":["Filter the Hypersync query by the exact SetFeeProtocol topic0 signature so only genuine SetFeeProtocol logs reach the parser.","Before parsing, check `log.data.as_ref().map(|d| d.len()).unwrap_or(0) >= 128` and skip logs that fail.","Verify the target contract is a stock PancakeSwap V3 pool whose SetFeeProtocol ABI matches `SetFeeProtocolEventData` (2 params, non-indexed).","Log the offending log's address/tx hash to identify the emitting contract and exclude it if it is a non-standard fork."],"exampleFix":"// before\nif let Some(data) = &log.data {\n    let decoded = <SetFeeProtocolEventData as SolType>::abi_decode(data.as_ref())?;\n// after\nif let Some(data) = &log.data {\n    if data.as_ref().len() < 4 * 32 {\n        tracing::warn!(\"skipping short SetFeeProtocol log (len={})\", data.as_ref().len());\n        return Ok(None);\n    }\n    let decoded = <SetFeeProtocolEventData as SolType>::abi_decode(data.as_ref())?;","handlingStrategy":"validation","validationCode":"// before calling parse_fee_protocol_update_event_hypersync\nlet data_len = log.data.as_ref().map(|d| d.as_ref().len()).unwrap_or(0);\nif data_len < 128 {\n    tracing::warn!(\"SetFeeProtocol log data too short: {data_len}\");\n    return Ok(None);\n}","typeGuard":"fn is_valid_set_fee_protocol_log(log: &HyperSyncLog) -> bool {\n    log.topic0.as_deref() == Some(SET_FEE_PROTOCOL_TOPIC)\n        && log.data.as_ref().map(|d| d.as_ref().len()).unwrap_or(0) >= 128\n}","tryCatchPattern":"match parse_fee_protocol_update_event_hypersync(dex, &log) {\n    Ok(ev) => store(ev),\n    Err(e) if e.to_string().contains(\"too short\") => {\n        tracing::warn!(\"skipping malformed SetFeeProtocol log\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always filter Hypersync queries by the exact SetFeeProtocol topic0 hash.","Sanity-check data length (>= 128 bytes) at the ingestion boundary.","Keep SetFeeProtocolEventData in sync with the deployed contract ABI version.","Log the offending log's tx hash/address to trace non-standard contracts."],"tags":["rust","anyhow","abi","event-parsing","pancakeswap-v3","data-length"],"backgroundTag":"schema-validation-failed","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"}