Context
ADR-0035 gates decoders on contract identity, but some protocols have no usable factory namespace: comet shares Balancer-v1 ("POOL", ...) topics across deployments, and some contracts are never announced by a factory. Any pubnet contract can emit a colliding shape and inject trades under our source attribution.
Decision
§1 Mechanisms. Extends ADR-0035. Three sanctioned gate mechanisms, all built on contractid.Registry. Per-source declarations are in internal/pipeline/gated_registry.go.
- Factory-descended. Seeded from
protocol_contractsplus hard-coded factory IDs, and live creation events register new children (blend, soroswap, sushiswap_v3, phoenix pools, aquarius via the router'sadd_poolevents). Aquarius also carries an in-code seed for history. - Curated set with a declared factory.
WithSeed(curatedSet)plusWithFactories, for children a factory does not announce or whose creation events are untrusted: phoenix stake contracts (the pool deploys them) and defindex (the create body's addresses are attacker-controlled, so it never admits a child). - Curated only. No factory namespace and no creation event: comet (one mainnet pool,
comet.MainnetGatedSet), blend_emitter and upshift. The in-code set is the whole trust root, and nothing discovers contracts at runtime. A new pool needs a code change, or an operatorseed-protocol-contracts -source <name>for the warm table. The WASM-hash gate once proposed for comet was not built.wasm-drift(internal/ops/chops/wasm_drift.go) only checks and alerts on drift; it never admits a contract.
All three fail closed. An unlisted contract's events are not attributed and show as Claim 2a recognition gaps (ADR-0033), so a missing one is visible.
The boot warm (GatedRegistryOptions) seeds every source's CuratedSet into its registry. On the indexer path it also reconciles the set into protocol_contracts with provenance factory_id = "curated", so the declared trust root reaches the roster and the explorer. seed-protocol-contracts is still the operator step for factory-anchored sources.
§2 Rollout per source. Seed, gate Matches(), wire the gate and reconcile-catalogue entry, re-derive history from the lake (projector-replay), then one compute-completeness -ch cycle returns complete=true. Gate code must not deploy before its seed exists. Where the seed comes from a factory walk, run seed-protocol-contracts once the lake covers the factory.
§3 Enumerating a curated set. Take every emitter the lake shows for the protocol and classify each against independent proofs: first event inside a factory create transaction, address in a factory create event body, live WASM hash the team publishes, listing in the team's own registry. A contract with no proof is excluded and flagged, never seeded. A proof that is weak alone (a create-body address) must not admit a contract by itself.
Invariant
- A gated decoder's
Matches()requires a registered contract, or a factory for creation events.internal/pipeline/lockstep_ast_test.goandTestApplyGatedOptions_EveryGatedSourceAdmitsARegistryOnlyContractfail CI on a missed wiring edit. - A curated-only entry declares a non-empty trust root (
TestGatedSources_curatedOnlyDeclaresTrustRoot). - The boot warm seeds
CuratedSetinto every registry it builds, and the indexer reconciles it intoprotocol_contracts(internal/pipeline/gated_registry_curated_test.go). - A claim that creation events predate the lake is made only with a ledger number and a query behind it.
Consequences
- The injection vector closes source by source, each with seed rows, gated decoder tests, a re-derive and a green verdict.
- An incomplete curated set shows as
complete=falsewith named contracts, never as silently attributed foreign trades. - Curated sets are code and review-gated like any code change.
- Phoenix pools moved from curated to factory-descended once its
createevents were found in the lake (from ledger 51,572,026).
Evidence
internal/pipeline/gated_registry.go, internal/pipeline/gated_registry_curated_test.go, internal/contractid/registry.go, docs/protocols/aquarius.md, docs/protocols/defindex.md, docs/operations/wasm-audits/comet.md.