Many protocols deploy contracts at runtime: Uniswap’s factory spins up a pool per pair, a Safe factory
deploys a proxy per wallet. You can’t list those addresses at init - they don’t exist yet. A
factory tells nuthatch to discover them as they’re created and index each child automatically.
The shape
A factory is a template (the child’s ABI + events) plus a factory rule (which event on the parent announces a new child, and which field holds its address):
[[templates]]
name = "pool"
abi = "abis/uniswap-v3-pool.json"
# filter = "topic0" # optional backfill-strategy override for templates with very many children
[[factories]]
# When `factory` emits PoolCreated, the child in the `pool` param is indexed as a `pool`.
watch = "factory" # the ALIAS of a [[contracts]] entry (or another template, for nesting)
event = "PoolCreated"
child_param = "pool" # the event param holding the new child's address
template = "pool" # which [[templates]] to apply to the child
# start = 12369621 # optional: only honour discoveries at or after this block
When the parent emits PoolCreated, nuthatch registers the address in that event’s pool param as a new
pool child and decodes its events - every event the template’s ABI defines - from discovery onward.
One table, many children
All children of a template share one set of tables - pool__swap, pool__mint, pool__burn - no matter
how many pools exist. The implicit address column tells you which child each row
came from:
SELECT address AS pool, COUNT(*) AS swaps
FROM pool__swap
GROUP BY 1 ORDER BY swaps DESC;
Discovery is deterministic
Child discovery is part of the deterministic decode path: the same blocks always discover the same
children in the same order, keyed off the parent’s events. A reorg that un-emits a PoolCreated retracts
that child and its rows along with everything else - factories inherit the same reorg safety as any table
(see Reorgs).
Runaway factories are bounded
A factory that discovers a vast number of children is exactly the kind of thing that could blow the ≤2 GB per-cursor budget. Discovery is bounded and observable per nest, and in a roost one nest’s runaway factory is isolated to its own cursor - it can’t starve a co-tenant.
Next
- ABIs, events & tables - the
addresscolumn that distinguishes children - Reorgs - how discovered children roll back
- Recipes - e.g.
reservesacross all discovered pools