Search projects, hackathons, sponsors and tech

    ← All projects

    Hank0

    ENS names as trading permissions for a Uniswap v4 permissioned pool holding a tokenized stock

    Demo

    About

    In September 2026 the SEC's Innovation Exemption defined a Tokenized Securities Venue as doing two things: running AMM pools for permissioned participants, and setting the standards for who may access them. Uniswap v4 permissioned pools cover the first. The second is left to the venue, and the interface Uniswap gives you is one function returning a flag for an address. Hanko answers that function with ENSv2. A cleared investor holds a name under let's say swap.tnvda.eth or lp.tnvda.eth, and the shape of the name is the permission. Every swap and every liquidity deposit resolves it live. Because it's ENS, three things come free. Names expire, so access lapses on its own. They're registered without the transfer role, so clearance can't be sold to a wallet the venue never cleared. And an investor can open names for their own trading bots / AI Agents inside their own registry without asking the venue. Revoke the investor and every bot under them stops in the same transaction, because a child of a lapsed name has nothing left to resolve through. Everything on the site is read from Sepolia.

    How it's made

    The checker is a Solidity contract implementing Uniswap's IAllowlistChecker. checkAllowlist(account, token) turns the address into a lowercase hex label, looks it up in two ENSv2 UserRegistries, and returns the bytes2 flags (0x0001 swap, 0x0002 liquidity). If no direct name resolves, it tries agent delegation: the label is looked up in an index registry whose entries point at an investor's own registry through the resolver field, then walks back up to check the investor's name is still alive. Putting the pointer in ENS rather than a mapping means expiry and revocation semantics are inherited, not reimplemented. Each investor gets a UserRegistry proxy from ENS's VerifiableFactory, and names are granted with EnhancedAccessControl roles that deliberately exclude transfer. The pool is a real v4 permissioned pool on Sepolia: PermissionsAdapter wrapping a mock tNVDA, PermissionedHooks, PermissionedPositionManager. Two things cost us time and are worth writing down. UniversalRouter v2.1.2 is the default entry in Uniswap's deployment file and it cannot do permissioned swaps; you need v2.2. And the adapter has to be registered as a wrapper on the PoolManager itself, not just the router, which is only documented in Uniswap's own integration tests. 67 Foundry tests, most of them forked against live Sepolia so the ENS and Uniswap contracts under test are the real deployed ones. Frontend is Next.js reading state directly over viem, with the audit trail pulled from event logs.