Hats Protocol
Hats Protocol provides the on-chain role hierarchy that decides who may do what in a garden. Gardeners submit work, evaluators attest assessments, and stewards approve work. Roles stack, so stewards can also do what the roles below them do, and the garden's owner can do all of it. Because hats are tokens, the EAS resolvers check them directly at write time, and because each garden's hats form a tree, its whole authority structure is inspectable at once.
How it flows
Stewards and the garden's owner grant and revoke roles through the Hats module. A grant reaches down the tree: the owner role brings the steward and gardener hats with it, and the steward role brings the evaluator and gardener hats. A revoke does not: it removes the one hat it names, so taking someone out of a garden means revoking each hat they hold.
One role can also be self-served: while a garden has open joining on, anyone who is not yet a
member can call joinGarden on the garden account and receives the gardener hat. A steward or the
owner turns that on or off with setOpenJoining and can limit it with setMaxGardeners. That
limit counts successful joinGarden calls, not current members: a gardener hat granted at mint or
by a steward does not count toward it, and revoking a hat does not free a place.
One more caller can write the tree. The module accepts a call that comes from the garden account itself, and the account executes what the holder of the garden's token tells it to. So whoever holds the token can grant and revoke roles through the account without wearing a hat, which is why handing a garden over means moving the token and the hats together. Everything else only reads the tree.
Where it lives in the code
| Layer | Source |
|---|---|
| Module | packages/contracts/src/modules/Hats.sol |
| Open joining | packages/contracts/src/accounts/Garden.sol (joinGarden, setOpenJoining, setMaxGardeners) |
| Role helpers | packages/shared/src/utils/blockchain/garden-roles.ts |
| Persona mapping | The ontology, which binds each persona to its hat |
A gotcha worth knowing early
Hats has no on-chain wearer enumeration, and revoking a hat is a transfer. Never build a guard on hat supply; when you need "who wears this hat", the answer comes from the Hats subgraph, not a contract call.
Checked-in deployment projection
| Network | Status | Recorded components |
|---|---|---|
Sepolia Testnet (11155111) | Deployed | hatsModule |
Arbitrum One (42161) | Deployed | hatsModule |
Networks without recorded components are omitted; per-network state lives in the deployment status projection.
Indexer boundary
Configured indexer contracts: HatsModule.
A deployment artifact does not by itself prove product activation, live indexing, or partner-service health. This projection regenerates from checked-in artifacts via node scripts/docs/generate.mjs.
Working with it locally
The fork mode (bun run dev -- fork) runs a local fork of
Arbitrum One, so the Hats contract and every existing garden tree are available locally without
real gas.
Canonical upstream docs
- Hats for developers for the concepts: hats, trees, wearers, eligibility.
- The Hats SDK, built on viem like this repo.
- The subgraph for wearer queries.
- Supported chains for official addresses.
- app.hatsprotocol.xyz to view a garden's tree.
Next steps
- EAS shows where these roles are checked: in the resolvers, at the moment a record is written.
- Tokenbound Accounts covers the garden account that wears the tree.
- Anatomy of a Work Submission puts the roles to work in one real flow.