Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Enhanced Access Control

Enhanced Access Control (EAC) is the permission system used throughout ENSv2. It controls who is allowed to do what - and on which names.

Think of it like a building where each room has its own set of locks: you can give someone a key to one room, or a master key that opens every room. EAC works the same way, but with ENS names and on-chain permissions.

Resources

A resource is the thing you're controlling access to. In most ENS contracts, a resource is a name - but it can be any uint256 identifier that makes sense for the contract.

For example, the ENS registry treats each name as a separate resource. Permissions you grant on alice.eth don't affect bob.eth - they're independent.

There's also a special resource called ROOT_RESOURCE (0x0) that represents the contract itself. Permissions granted on ROOT_RESOURCE apply everywhere - like a master key. If you have a role on ROOT_RESOURCE, you automatically have that role on every individual resource too.

Roles

A role represents a specific permission - for example, "can set the resolver" or "can register subnames". Each ENS contract defines the roles that are relevant to it.

Roles are always tied to a resource. Granting someone the "set resolver" role on alice.eth doesn't let them set the resolver on bob.eth. To give someone a permission across all names, grant the role on ROOT_RESOURCE instead.

Up to 15 accounts can hold the same role on the same resource, enabling shared management and delegation.

How role checks work: when a contract checks whether an account has a role on a specific name, it looks in two places - the name itself and ROOT_RESOURCE - and allows the action if the role is found in either. This is how the master key effect works.

Admin Roles

Every role has a corresponding admin role that controls who can manage it. If you hold the admin role, you can:

  • Grant the regular role to other accounts
  • Grant the admin role itself to other accounts
  • Revoke either role from other accounts

For example, the admin role for "set resolver" controls who is allowed to grant or revoke the "set resolver" permission. Admin roles follow the same resource-scoping - you can be an admin for a specific name or for all names via ROOT_RESOURCE.

Granting and Revoking

Roles are managed through four functions:

  • grantRoles / revokeRoles - manage roles on a specific resource (name)
  • grantRootRoles / revokeRootRoles - manage roles on ROOT_RESOURCE (contract-wide)

The caller must hold the admin role for every role being granted or revoked. Admin role holders can also revoke the admin role itself - including from themselves.

Contracts can hook into role changes by overriding _onRolesGranted and _onRolesRevoked to run custom logic whenever permissions change.

Bitmap Layout

Under the hood, roles are packed into a single uint256 bitmap split into two halves. Each role occupies one nybble (4 bits), giving space for up to 32 regular roles and 32 corresponding admin roles:

  255         128 127            0
  ┌──────────────┬───────────────┐
  │ Admin Roles  │ Regular Roles │
  └──────────────┴───────────────┘

A regular role at nybble index N occupies bits N*4 to N*4+3. Its admin counterpart sits at the same position in the upper half (N*4+128 to N*4+131). The same nybble-per-role layout is used for assignee counting - each nybble tracks how many accounts hold that role within a resource (which is why the maximum is 15, the largest value a 4-bit nybble can store).

Replacing Fuses

EAC replaces the one-way fuse system from the Name Wrapper. Key advantages:

  • Reversible: roles can be granted and revoked, not just permanently burned
  • Multi-account: up to 15 accounts can hold the same role per resource, enabling delegation and shared management
  • Granular scoping: permissions can be set contract-wide or per individual resource, with the two scopes composing automatically
  • Extensible: each contract defines its own roles - no fixed set of permissions baked into the protocol