nautechsystems/nautilus_trader · error
PoolManager address should be set in logs
Error message
PoolManager address should be set in logs
What it means
In `parse_initialize_event_hypersync` (Uniswap V4), the pool is identified by the PoolManager contract that emitted the Initialize event, read from `log.address` via `.expect("PoolManager address should be set in logs")`. On-chain logs always carry the emitter address, so `None` means the input log is missing its emitter — an input-contract violation the parser treats as a hard panic. Unlike V3, the pool address here is the contract address itself, so this field is mandatory for building the `PoolIdentifier`.
Source
Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v4/initialize.rs:81
/// ```
///
/// # Errors
///
/// Returns an error if the log parsing fails or if the event data is invalid.
///
/// # Panics
///
/// Panics if the log address is not set.
pub fn parse_initialize_event_hypersync(log: HypersyncLog) -> anyhow::Result<PoolCreatedEvent> {
validate_event_signature_hash("InitializeEvent", INITIALIZE_EVENT_SIGNATURE_HASH, &log)?;
let block_number = extract_block_number(&log)?;
// The pool address for V4 is the PoolManager contract address (the event emitter)
let pool_manager_address = Address::from_slice(
log.address
.clone()
.expect("PoolManager address should be set in logs")
.as_ref(),
);
// Extract currency0 and currency1 from topics
// topics[0] = event signature
// topics[1] = poolId (bytes32)
// topics[2] = currency0 (indexed)
// topics[3] = currency1 (indexed)
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]View on GitHub (pinned to 18893faf8b)
Solutions
- Populate `log.address` with the PoolManager contract address before parsing.
- If converting logs from another source, ensure the emitter address is copied into the hypersync log.
- In your own code, unwrap the Option with a proper error message instead of relying on the panic.
- Verify the hypersync client version still fills the log address field on deserialization.
Example fix
// before
let pool_manager_address = Address::from_slice(
log.address.clone().expect("PoolManager address should be set in logs").as_ref(),
);
// after
let emitter = log.address.clone().ok_or_else(|| anyhow::anyhow!("initialize log missing PoolManager address"))?;
let pool_manager_address = Address::from_slice(emitter.as_ref()); Defensive patterns
Strategy: validation
Validate before calling
fn require_pool_manager(log: &HyperSyncLog) -> Result<Address, String> {
log.address.clone().ok_or_else(|| "V4 initialize log missing PoolManager address".to_string())
} Type guard
fn has_pool_manager(log: &HyperSyncLog) -> bool {
log.address.is_some()
} Try / catch
// Propagate as error before parsing let pool_manager = require_pool_manager(&log)?;
Prevention
- Always set log.address to the PoolManager address in V4 fixtures.
- Centralize hypersync log construction so the emitter is a mandatory parameter.
- Assert fixture completeness in tests before exercising the parser.
When it happens
Trigger: Calling `parse_initialize_event_hypersync` with a `HyperSyncLog` whose `address` is `None`, e.g. a fixture built without `address` or log data that lost the emitter during deserialization/conversion.
Common situations: Test logs for V4 Initialize events built via default construction omitting the PoolManager address; adapting logs from another indexer into the hypersync log type; a hypersync client schema change making the address field optional.
Related errors
- Contract address should be set in logs
- Contract address should be set in logs
- Contract address should be set in logs
- Contract address should be set in logs
- Contract address should be set in logs
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/27160a7238200243.
Report an issue: GitHub.