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
- Confirm the log's topic0 equals the canonical SetFeeProtocol event selector before decoding.
- Regenerate `SetFeeProtocolEventData` (sol! macro) from the exact ABI of the deployed PancakeSwap V3 pool/factory contracts.
- Log `hex::encode(data_bytes)` alongside the error to inspect the actual payload and identify the emitting contract.
- 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
- Verify topic0 before decode; never rely on data length alone.
- Regenerate ABI types via the sol! macro from the contract ABI JSON you actually index.
- Include raw data hex in decode error context for forensics.
- Skip bad logs per-record instead of failing the whole Hypersync batch.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- SetFeeProtocol event data is too short
- RPC parsing of SetFeeProtocol event is not defined in this d
- RPC parsing of CollectProtocol event is not defined in this
- Missing data in SetFeeProtocol event log
- RPC parsing of initialize event is not defined in this dex:
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9c05e09a48884f6a.
Report an issue: GitHub.