Overview
The Registry Datastore is not a separate contract but rather the internal storage architecture used by PermissionedRegistry. It manages the persistent state for all registered names through an efficient mapping-based structure.Storage Architecture
Entry Structure
Each registered name is stored as anEntry struct, which contains all the metadata and state for that name:
Enhanced Access Control Version IDIncremented each time the name is unregistered or burned. This ensures that access control resources are invalidated when a name expires and is re-registered, preventing old permissions from carrying over.
Token Version IDIncremented whenever:
- The name is unregistered/burned
- Roles are granted or revoked (triggers token regeneration)
Subregistry ContractThe registry contract that manages subdomains for this name. For example, if this entry represents “alice.eth”, the subregistry would handle names like “sub.alice.eth”.Set to
address(0) if no subregistry exists.Expiration TimestampUnix timestamp when the registration expires. After this time:
- The name becomes AVAILABLE
- Queries return address(0) for owner, resolver, and subregistry
- The name can be re-registered
Resolver ContractThe contract responsible for resolving records (addresses, text records, etc.) for this name.Set to
address(0) if no resolver is configured.Storage Mapping
Entries are stored in a mapping from storage ID to Entry:- Efficient lookups using any form of ID (labelhash, token ID, or resource ID)
- Version information to be stored separately in the Entry
- Consistent storage location regardless of token/resource version
Parent Registry Information
The datastore also maintains the canonical location of the registry in the ENS hierarchy:The parent registry contract. For example, the parent of a 2LD registry like “alice.eth” would be the ETH registry.
The label of this registry in the parent. For example, “alice” if this is the “alice.eth” registry.
ID System
The registry uses three types of IDs that can be converted between each other:Labelhash
The base identifier, computed as:Token ID
The ERC1155 token identifier, which includes the token version:- Roles are granted or revoked
- The name is burned and re-registered
Resource ID
The Enhanced Access Control resource identifier:- Include the EAC version instead of token version
- Automatically increment for expired names (even before re-registration)
- Used for all access control checks
Version Management
When Versions Change
eacVersionId increments when:- Name is unregistered via
unregister() - Name is burned and re-registered via
register()
- Name is unregistered
- Name is burned and re-registered
- Roles are granted to any account
- Roles are revoked from any account
Token Regeneration
When roles change, the token is regenerated:- Burns the old token
- Increments the version
- Mints a new token with the same owner
- Emits
TokenRegeneratedevent
State Queries
The datastore supports querying state with any type of ID:Direct Entry Access
Status Determination
- Expiry time: Past expiry → AVAILABLE
- Owner: No owner → RESERVED, has owner → REGISTERED
Expiry Checking
Data Lifecycle
Registration (AVAILABLE → REGISTERED)
Reservation (AVAILABLE → RESERVED)
Conversion (RESERVED → REGISTERED)
Unregistration (REGISTERED/RESERVED → AVAILABLE)
Renewal (REGISTERED/RESERVED → REGISTERED/RESERVED)
Storage Efficiency
Packed Storage
The Entry struct is designed for efficient storage packing:Version Bits
Versions use the upper bits of the 256-bit ID:- Single mapping for all entries
- Efficient version extraction
- No additional storage for version tracking
Access Patterns
Common Queries
Get current state:Notes
- All storage is internal to PermissionedRegistry
- The datastore has no external interface
- Version management is automatic and transparent to users
- Storage IDs are normalized to version 0 for consistent access
- Expired entries are not deleted, just marked as expired
- Re-registration of expired names reuses the same storage slot