
Fleet Naming Service
One ENSv2 registry, many doorways: hire an AI agent fleet with one tx, fire it with one.
Demo
About
FNS (Fleet Naming Service) gives AI agent fleets a single on-chain identity that many businesses can adopt and drop instantly, using ENSv2's registry-linking primitives. A vendor runs a fleet of support agents (mia, kai, rin) in one ENSv2 UserRegistry. That same registry is mounted under several names at once — support.vendor.eth, support.shopa.eth, support.shopb.eth — so mia.support.shopa.eth and mia.support.shopb.eth resolve to the SAME ERC-1155 token, not copies kept in sync. Two kill switches, owned by opposite parties: - Hire / fire: a merchant mounts the fleet with one setSubregistry transaction and unmounts it with one. - Vendor recall: the vendor unregisters one agent and every doorway for it, under every merchant, dies in the same block. The catch: mounting is permissionless, so a scammer can mount the real fleet under support.scam.eth and it resolves. FNS ships a verifier (stock viem + the real UniversalResolver) that checks membership, canonical registry, two-sided consent (the fleet's own enf.parents record must list the parent), doorway expiry, and screens the settlement address against the OFAC sanctions oracle / Intercepta. Every name gets a live verdict: GREEN (legit), RED (counterfeit mount), ORANGE (endorsed doorway, flagged counterparty) or BLACK (not a member). The Next.js app includes a playbook editor where you build the demo as a node workflow — check a name, unmount, fire an agent, counterfeit mount, dirty settlement — sign each step in your browser wallet, and watch the topology graph, agent × doorway verdict grid and on-chain timeline update live. Deployed on Sepolia.
How it's made
FNS writes no Solidity of its own — it composes the real, deployed ENSv2 contracts on Sepolia (RootRegistry, ETHRegistry, ETHRegistrar, UserRegistry, PermissionedResolver, VerifiableFactory, UniversalResolverV2, UniversalHelper). The fleet's UserRegistry and a shared PermissionedResolver are deployed as proxies through VerifiableFactory.deployProxy with CREATE2 salts; each merchant gets its own UserRegistry with a "support" label whose subregistry points at the fleet. The hacky/notable bits: - Namespace aliasing: one registry mounted at multiple setSubregistry points. We found no other project doing multi-mount. - The shared resolver's default record (DNS name 0x00) holds the whole fleet bundle — addr(60) settlement address, enf.canonical, enf.parents, ENSIP-26 agent-context and agent-endpoint[web] — so every member inherits it without its own record. - Topology fix: the resolver is attached to members only at register(), never to the parent node. That way a made-up name (bob.support.shopa.eth) returns ResolverNotFound instead of resolving through a wildcard — otherwise the verifier's "not a member" verdict would be meaningless. Stack: TypeScript + viem for setup/demo scripts (tsx), a standalone @fns/verifier package implementing checks C1–C5 (ENSIP-15 normalization, UniversalResolver resolution, registry walk from the root, UniversalHelper.findExactRegistry for canonical match). C5 screening uses the Chainalysis sanctions oracle on mainnet (keyless, real OFAC data) plus Intercepta (Web3 Antivirus) when an API key is set. Next.js 16 / React 19 app with server routes: /api/verify, /api/fleet (discovers every mount from SubregistryUpdated logs and verifies every agent × doorway at one block), and /api/actions, which plans kill-switch transactions for the browser wallet to sign — the server holds no keys. Testing: Foundry fork tests against the live ENSv2 deployment (10 passing, no mocks) and 80 vitest tests, including fork tests that run the demo scripts end-to-end.