Overview
UserRegistry is an upgradeable version of PermissionedRegistry designed for user-owned registries. It implements the UUPS (Universal Upgradeable Proxy Standard) pattern, allowing the registry implementation to be upgraded while preserving state. This contract is typically deployed via the VerifiableFactory and used for user-controlled namespaces within ENS v2.Key Features
- All PermissionedRegistry functionality
- UUPS upgradeable pattern
- Role-based upgrade authorization
- Initialization pattern for proxy deployment
- Secure upgrade controls
Contract Information
Inherits:Initializable, PermissionedRegistry, UUPSUpgradeable
Deployment: Via VerifiableFactory as a proxy
Interface ID: Includes UUPSUpgradeable interface (0x52d1902d)
Constructor
HCA factory for hierarchical contract address equivalence checking
Metadata provider for token URIs (set immutably)
initialize() function on the proxy.
Initialization
initialize
Initializes the UserRegistry proxy with an admin and roles.The address that will receive admin privileges and upgrade rights. Cannot be address(0).
Bitmap of roles to grant to the admin on the root resource. Should include
ROLE_UPGRADE and ROLE_UPGRADE_ADMIN for upgrade capabilities.- Can only be called once (initializer modifier)
- Admin address must not be address(0)
Upgrade Functions
upgradeToAndCall
Upgrades the proxy to a new implementation (inherited from UUPSUpgradeable).The address of the new implementation contract
Optional calldata to execute after upgrade (typically empty)
ROLE_UPGRADE on the root resource.
Example:
Authorization Check
The upgrade authorization is enforced by the internal_authorizeUpgrade function:
ROLE_UPGRADE on the root resource can upgrade the contract.
Inherited Functionality
UserRegistry inherits all functionality from PermissionedRegistry:Registration Functions
register()- Register new namesunregister()- Delete namesrenew()- Extend expiration
Configuration Functions
setSubregistry()- Set subregistrysetResolver()- Set resolversetParent()- Set parent registry
Access Control Functions
grantRoles()- Grant rolesrevokeRoles()- Revoke rolesroles()- Query roleshasRoles()- Check roles
Query Functions
getSubregistry()- Get subregistrygetResolver()- Get resolvergetParent()- Get parentgetExpiry()- Get expirationgetStatus()- Get registration statusgetState()- Get complete stategetResource()- Get resource IDgetTokenId()- Get token IDownerOf()- Get ownerlatestOwnerOf()- Get latest owner
Deployment Pattern
Standard Deployment
Verifiable Deployment
The VerifiableFactory ensures:- Deterministic addresses based on salt
- Verifiable deployment via CREATE2
- Proper initialization in one transaction
Upgrade Safety
Authorization
Only accounts withROLE_UPGRADE can upgrade:
Admin Management
Upgrade admins can grant/revoke upgrade rights:Storage Safety
UUPS proxies store the implementation address in a standard slot:- Maintain storage layout compatibility
- Not remove or reorder existing storage variables
- Only append new storage variables
Interface Support
supportsInterface
Extends PermissionedRegistry interface support:IPermissionedRegistry(0xafff3a63)IStandardRegistry(0xb844ab6c)IRegistry(0x51f67f40)IEnhancedAccessControlIERC1155SingletonIERC165(0x01ffc9a7)UUPSUpgradeable(0x52d1902d)
Events
Inherits all events from PermissionedRegistry. UUPS upgrades emit:Upgraded
Role Requirements
Recommended Initial Roles
For a user-controlled registry:For Subregistry Owners
When registering a name with a subregistry:Security Considerations
Initialization
- Implementation contract must call
_disableInitializers()in constructor - Proxies must call
initialize()exactly once - Admin address must be carefully chosen (cannot be changed easily)
Upgrade Path
- Only upgrade to audited implementations
- Test upgrades on testnet first
- Verify storage layout compatibility
- Consider upgrade delay/timelock for production
Role Management
- Initial admin should secure
ROLE_UPGRADE_ADMIN - Consider multi-sig for upgrade privileges
- Regularly audit role assignments
- Use events to monitor role changes
Example Usage
Deploy and Configure
Upgrade Example
Differences from PermissionedRegistry
| Feature | PermissionedRegistry | UserRegistry |
|---|---|---|
| Upgradeability | Not upgradeable | UUPS upgradeable |
| Deployment | Direct deployment | Proxy pattern |
| Initialization | Constructor | initialize() function |
| Upgrade control | N/A | Role-based (ROLE_UPGRADE) |
| Use case | Base implementation | User-owned registries |
Notes
- UserRegistry is designed for proxy deployment, not direct deployment
- The implementation contract cannot be initialized or used directly
- All storage is in the proxy, not the implementation
- Upgrade authorization is enforced at the contract level
- The metadata provider is set in the constructor and cannot be changed