Skip to content

Factory child discovery can be falsely marked complete when reusing ponder_sync cache #2271

@medariox

Description

@medariox

Version

0.16.3

Current behavior

When reusing an existing ponder_sync, factory child discovery can be skipped even though it did not run for the current factory row. This causes child-address-based handlers to silently miss events.

Expected behavior

Factory discovery should be considered complete only from actual factory interval cache (factory_log_*), not inferred from log_*.

Steps to reproduce

Minimal example

  • A parent contract emits ChildSet(address indexed child).
  • Ponder uses factory(...) with parameter: "child" and indexes child event Child:Action.
  • Cache is reused (ponder_sync) across deployments/restarts.
  • DB ends up with log_* intervals present, but factory_log_* intervals empty for the current factory row.
    • This happens with factory identity changes (most commonly range change, but also parent address set change).
  • On startup, the fallback above copies filterIntervals into factory intervals in memory.
  • Historical sync computes no missing factory intervals.
  • Child rediscovery is skipped.
  • Child:Action events are not matched because child addresses are missing/incomplete.

Link to repository

No response

Anything else?

Relevant code block:
https://github.com/ponder-sh/ponder/blob/main/packages/core/src/sync-store/index.ts#L424-L447

  if (
    filterIntervals.length > 0 &&
    factoryIntervals.length === 0 &&
    filter.fromBlock === factory.fromBlock &&
    filter.toBlock === factory.toBlock
  ) {
    for (const factoryInterval of result.get(factory)!) {
      factoryInterval.intervals = filterIntervals;
    }
  }

This block infers factory discovery completeness from normal log filter completeness.
log_* cache progress is not equivalent to factory_log_* progress.
If this inference is wrong, runtime interval planning sees no missing factory intervals and skips rediscovery, so child addresses are not (re)inserted.

Proposed fix
Remove the fallback inference block above from getIntervals().
If legacy migration compatibility is still required, gate any fallback behind an explicit migration-version check, not runtime interval inference.

Workaround
Delete affected rows from:
ponder_sync.factory_addresses
ponder_sync.intervals for both matching factory_log_* and matching log_* fragments.
Then restart/resync.


As always, thank you for maintaining Ponder. Please let me know if you need anything else to help triage the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions