nautechsystems/nautilus_trader · error
Contract address should be set in logs
Error message
Contract address should be set in logs
What it means
In `parse_swap_event_hypersync`, the swap log's `address` field is `Option<Address>` and is unwrapped with `.expect("Contract address should be set in logs")` to derive the pool identifier. Since every on-chain EVM log is emitted by a contract and therefore has an address, a `None` value signals that the input log is malformed or was built without the emitter address — the parser treats that as an unrecoverable input-contract violation and panics. It is not related to decoding the swap amounts or topics.
Source
Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/swap.rs:80
if let Some(data) = &log.data {
let data_bytes = data.as_ref();
// Validate if data contains 5 parameters of 32 bytes each
if data_bytes.len() < 5 * 32 {
anyhow::bail!("Swap event data is too short");
}
// Decode the data using the SwapEventData struct
let decoded = match <SwapEventData as SolType>::abi_decode(data_bytes) {
Ok(decoded) => decoded,
Err(e) => anyhow::bail!("Failed to decode swap event data: {e}"),
};
let _ = decoded.amount0;
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(SwapEvent::new(
dex,
pool_identifier,
extract_block_number(log)?,
extract_transaction_hash(log)?,
extract_transaction_index(log)?,
extract_log_index(log)?,
sender,
recipient,
decoded.amount0,
decoded.amount1,
decoded.sqrt_price_x96,
decoded.liquidity,
decoded.tick.as_i32(),
))View on GitHub (pinned to 18893faf8b)
Solutions
- Set `log.address` to the emitting Uniswap V3 pool contract address before calling the parser.
- If logs are converted from another source, copy the emitter address into the `address` field of the hypersync log.
- Handle the Option explicitly in your own code and surface an error rather than hitting the panic.
- Confirm the hypersync client version/schema still deserializes the log address field.
Example fix
// before
let pool_address = Address::from_slice(
log.address.clone().expect("Contract address should be set in logs").as_ref(),
);
// after
let emitter = log.address.clone().ok_or_else(|| anyhow::anyhow!("swap log missing contract address"))?;
let pool_address = Address::from_slice(emitter.as_ref()); Defensive patterns
Strategy: validation
Validate before calling
fn require_emitter(log: &HyperSyncLog) -> Result<Address, String> {
log.address.clone().ok_or_else(|| "swap log missing emitter address".to_string())
} Type guard
fn log_has_emitter(log: &HyperSyncLog) -> bool {
log.address.is_some()
} Try / catch
// Unwrap via ok_or_else and propagate, not expect let emitter = require_emitter(&log)?;
Prevention
- When converting logs from other data sources, map the emitter field in one shared adapter function.
- Unit-test the conversion layer to assert address round-trips.
- Pin hypersync-client versions and review changelogs for log schema changes.
When it happens
Trigger: Invoking `parse_swap_event_hypersync` with a `HyperSyncLog` where `address` is `None` — e.g. a test fixture constructed without `address`, or log data deserialized through a path that leaves the emitter address unset.
Common situations: Hand-written swap log fixtures in tests missing the `address` field; adapting logs from an RPC/other indexer into the hypersync log type and forgetting the emitter; a library upgrade changing the log struct so `address` became optional and defaults to `None`.
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/474dc6a504448ecc.
Report an issue: GitHub.