nautechsystems/nautilus_trader · error

Failed to decode SetFeeProtocol event data: {e}

Error message

Failed to decode SetFeeProtocol event data: {e}

What it means

After the length check passes, the Hypersync parser decodes the raw bytes as `SetFeeProtocolEventData` using alloy's `SolType::abi_decode`; any decoding failure (wrong ABI shape, non-integer bytes, unexpected layout) is wrapped with this message including the underlying error. It means the data payload is 128+ bytes but does not conform to the expected SetFeeProtocol ABI (two uint8 fee fields in 32-byte words).

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/fee_protocol_update.rs:72

    dex: SharedDex,
    log: &HypersyncLog,
) -> anyhow::Result<FeeProtocolUpdateEvent> {
    validate_event_signature_hash(
        "SetFeeProtocolEvent",
        FEE_PROTOCOL_UPDATE_EVENT_SIGNATURE_HASH,
        log,
    )?;

    if let Some(data) = &log.data {
        let data_bytes = data.as_ref();

        if data_bytes.len() < 4 * 32 {
            anyhow::bail!("SetFeeProtocol event data is too short");
        }

        let decoded = match <SetFeeProtocolEventData as SolType>::abi_decode(data_bytes) {
            Ok(decoded) => decoded,
            Err(e) => anyhow::bail!("Failed to decode SetFeeProtocol event data: {e}"),
        };

        let pool_address = Address::from_slice(
            log.address
                .clone()
                .expect("Contract address should be set in logs")
                .as_ref(),
        );
        let pool_identifier = PoolIdentifier::Address(Ustr::from(&pool_address.to_string()));

        Ok(FeeProtocolUpdateEvent::new(
            dex,
            pool_identifier,
            extract_block_number(log)?,
            extract_transaction_hash(log)?,
            extract_transaction_index(log)?,
            extract_log_index(log)?,
            decoded.fee_protocol0_new,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the log's topic0 equals the canonical SetFeeProtocol event selector before decoding.
  2. Regenerate `SetFeeProtocolEventData` (sol! macro) from the exact ABI of the deployed PancakeSwap V3 pool/factory contracts.
  3. Log `hex::encode(data_bytes)` alongside the error to inspect the actual payload and identify the emitting contract.
  4. Skip non-conforming logs (return Ok(None)) instead of failing the whole ingestion batch.

Example fix

// before
let decoded = match <SetFeeProtocolEventData as SolType>::abi_decode(data_bytes) {
    Ok(d) => d,
    Err(e) => anyhow::bail!("Failed to decode SetFeeProtocol event data: {e}"),
};
// after
if log.topic0() != SET_FEE_PROTOCOL_TOPIC {
    return Ok(None);
}
let decoded = <SetFeeProtocolEventData as SolType>::abi_decode(data_bytes)
    .with_context(|| format!("SetFeeProtocol decode failed, data={}", hex::encode(data_bytes)))?;
Defensive patterns

Strategy: try-catch

Validate before calling

if log.topic0.as_deref() != Some(SET_FEE_PROTOCOL_TOPIC) {
    return Ok(None);
}
if log.data.as_ref().map(|d| d.as_ref().len()).unwrap_or(0) < 128 {
    return Ok(None);
}

Type guard

fn is_set_fee_protocol_topic(log: &HyperSyncLog) -> bool {
    log.topic0.as_deref() == Some(keccak256("SetFeeProtocol(uint8,uint8)").to_string().as_str())
}

Try / catch

let decoded = <SetFeeProtocolEventData as SolType>::abi_decode(data_bytes)
    .map(Some)
    .or_else(|e| {
        tracing::warn!("SetFeeProtocol decode failed ({e}); data={}", hex::encode(data_bytes));
        Ok::<_, anyhow::Error>(None)
    })?;

Prevention

When it happens

Trigger: Feeding `parse_fee_protocol_update_event_hypersync` a log whose data decodes differently than expected — e.g. a log from a different event that shares length characteristics, a contract with a modified SetFeeProtocol signature, or trailing extra fields that alloy's strict decoder rejects.

Common situations: See trigger scenarios.

Understand the failure class

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/9c05e09a48884f6a. Report an issue: GitHub.