nautechsystems/nautilus_trader · error
Missing currency0 topic
Error message
Missing currency0 topic
What it means
parse_initialize_event_hypersync for Uniswap V4 throws this when topics[2] is absent, since currency0 (the first token address) is stored as an indexed topic on the V4 Initialize event. Without currency0 the pool's currency pair cannot be constructed and the event is unusable. The library fails fast instead of emitting a pool with a missing currency.
Source
Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v4/initialize.rs:108
let topics = &log.topics;
if topics.len() < 4 {
anyhow::bail!(
"Initialize event missing topics: expected 4, was {}",
topics.len()
);
}
// Extract Pool ID from topics[1] - this is the unique identifier for V4 pools
let pool_id_bytes = topics[1]
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Missing poolId topic"))?
.as_ref();
let pool_identifier = Ustr::from(&hex::encode_prefixed(pool_id_bytes));
let currency0 = Address::from_slice(
topics[2]
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Missing currency0 topic"))?
.as_ref()
.get(12..32)
.ok_or_else(|| anyhow::anyhow!("Invalid currency0 topic length"))?,
);
let currency1 = Address::from_slice(
topics[3]
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Missing currency1 topic"))?
.as_ref()
.get(12..32)
.ok_or_else(|| anyhow::anyhow!("Invalid currency1 topic length"))?,
);
if let Some(data) = log.data {
let data_bytes = data.as_ref();
// Validate minimum data length (5 fields × 32 bytes = 160 bytes)View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm the log has 4 topics: signature, poolId, currency0, currency1 (canonical V4 Initialize).
- Guard topics.len() >= 3 && topics[2].is_some() before parsing and skip/skip-log otherwise.
- Verify V3 logs are not being fed to the V4 parser.
- Correct test fixtures to include both currency topics.
Defensive patterns
Strategy: validation
Validate before calling
if log.topics.len() < 3 || log.topics[2].is_none() {
// skip: v4 Initialize requires currency0 as topics[2]
return Ok(None);
} Type guard
fn has_currency0_topic(log: &Log) -> bool {
log.topics.len() >= 3 && log.topics[2].is_some()
} Try / catch
match parse_initialize_event_hypersync(&log) {
Ok(event) => handle(event),
Err(e) if e.to_string().contains("Missing currency0 topic") => {
tracing::warn!("v4 initialize log without currency0; skipping");
}
Err(e) => return Err(e),
} Prevention
- Check topics count and presence of topics[2]/topics[3] before parsing.
- Confirm the emitting contract is the canonical V4 PoolManager.
- Avoid hand-built fixtures omitting indexed currency topics.
- Validate log shape at the ingestion boundary.
When it happens
Trigger: Calling parse_initialize_event_hypersync (v4) with a log that has fewer than 3 topics or topics[2] = None — typically a malformed/non-standard Initialize log or an incomplete test fixture.
Common situations: Forked V4 contracts omitting indexed currency parameters; hand-built test logs with only signature and poolId topics; provider payloads delivering null topic slots; routing V3 Initialize logs (different topic count/layout) into the V4 parser.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Missing poolId topic
- Invalid currency0 topic length
- Missing data in burn event log
- Missing data in collect event log
- Missing data in initialize event log
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1794cdd48507a690.
Report an issue: GitHub.