nautechsystems/nautilus_trader · error

Contract address should be set in logs

Error message

Contract address should be set in logs

What it means

parse_collect_event_hypersync expects log.address to be Some: the emitting contract address is converted into the PoolIdentifier of the CollectEvent. The expect() panics on address-less logs, which the library considers malformed input since every on-chain event log must name its emitting contract.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/collect.rs:98

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

        // Validate if data contains 3 parameters of 32 bytes each
        if data_bytes.len() < 3 * 32 {
            anyhow::bail!("Collect event data is too short");
        }

        // Decode the data using the CollectEventData struct
        let decoded = match <CollectEventData as SolType>::abi_decode(data_bytes) {
            Ok(decoded) => decoded,
            Err(e) => anyhow::bail!("Failed to decode collect 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(CollectEvent::new(
            dex,
            pool_identifier,
            extract_block_number(log)?,
            extract_transaction_hash(log)?,
            extract_transaction_index(log)?,
            extract_log_index(log)?,
            owner,
            decoded.recipient,
            tick_lower,
            tick_upper,
            decoded.amount0,
            decoded.amount1,
        ))
    } else {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the Hypersync query includes the log address field.
  2. Validate/skip logs with missing addresses before calling the parser.
  3. Replace the expect with ok_or(...)? to surface a recoverable error.

Example fix

// before
let pool_address = Address::from_slice(
    log.address.clone().expect("Contract address should be set in logs").as_ref(),
);
// after
let raw_address = log.address.as_ref()
    .ok_or_else(|| anyhow::anyhow!("missing contract address in collect log"))?;
let pool_address = Address::from_slice(raw_address.as_ref());
Defensive patterns

Strategy: validation

Validate before calling

if log.address.is_none() {
    log::warn!("skipping collect log without contract address");
    return Ok(());
}
let event = parse_collect_event_hypersync(dex.clone(), &log)?;

Type guard

fn has_address(log: &HypersyncLog) -> bool {
    log.address.is_some()
}

Try / catch

match parse_collect_event_hypersync(dex, &log) {
    Ok(event) => handle(event),
    Err(e) => log::error!("failed to parse collect log: {e:#}"),
}
// Note: missing address panics via expect(); pre-check log.address before calling.

Prevention

When it happens

Trigger: Calling parse_collect_event_hypersync with a HypersyncLog whose address is None, e.g. when the Hypersync query did not project the address field or a synthetic test log omitted it.

Common situations: Misconfigured Hypersync column selection; schema drift in the Hypersync API making address optional; fixtures for tests built without address.

Related errors


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