Factory pattern for tracking deployed contracts, best practice on Midnight?

Hey everyone :waving_hand:

I’m building a ticketing dApp where each event is its own deployed contract (using the event-tickets.compact pattern, one contract per event, no shared state between them).

On Ethereum we’d typically use a factory contract that deploys children and maintains an on-chain registry of all deployed addresses. This gives full trustless discoverability.

On Midnight I’m currently using an off-chain PostgreSQL backend as the registry — when an organizer deploys a contract, the frontend posts the contractAddress to the backend. Individual contract state (tickets issued, commitments) remains fully on-chain and trustless. Only the index lives off-chain.

My questions:

  1. Is there a recommended pattern for on-chain contract discovery on Midnight? e.g. a registry contract with a Set<Bytes<32>> of deployed addresses?

  2. Does Midnight support deploying a contract from within another contract (factory pattern)?

  3. Are there any indexer APIs or chain query tools that would let me discover all deployments of a given contract bytecode without a registry?

Happy to share the full contract if useful. Thanks!

1 Like

Great question. Here are direct answers to all three points.

1. On-Chain Contract Discovery via a Registry Contract

Yes, this is supported and is the recommended trustless approach. You write a separate Compact registry contract whose ledger holds a map or set of contract addresses. When an organizer deploys a new event contract, your frontend calls a circuit on the registry contract that inserts the new address into that map. The registry contract address itself is fixed and published once, so anyone can query it for the full list of deployed event contracts. A rough sketch in Compact:

ledger { events: Map<Bytes<32>, Boolean>; }
export circuit register_event(addr: Bytes<32>): { events.insert(addr, true); }

2. Deploying a Contract from Within Another Contract (Factory Pattern)

Midnight does not currently support deploying a contract from inside another running contract. Contract deployment is a client-side operation driven by deployContract in midnight-js. The factory pattern on Midnight is therefore split: the client code deploys each child contract, then calls a circuit on the registry contract to record the address. The registry enforces whatever invariants you want on that address, but it cannot itself trigger a deployment.

3. Indexer-Based Discovery Without a Registry

The Midnight Indexer GraphQL API does not expose a bytecode-hash query to discover all deployments of a given contract type. There is no equivalent of an EVM event log that marks every deployment. Without a registry contract or an off-chain index, you have no trustless way to enumerate sibling instances.


Verdict for Your Ticketing dApp

Your PostgreSQL approach works in practice but is a centralized trust dependency. The cleanest path is to add a lightweight registry contract that just stores the set of deployed event addresses. The off-chain backend can then remain as a cache for performance without being the source of truth. The indexer can also track the registry contract state directly so frontends can subscribe to new event registrations in real time via a GraphQL subscription on the registry contract address.

1 Like

Thanks @mzf11125 for this clear and helpful response. I’ll try to dig more and understand the Compact registry contract.