DIDRegistry
Overview
The DIDRegistry contract implements a decentralized identity (DID) registry following the W3C DID specification. It enables users to register, update, and manage DID Documents on-chain with support for verification methods, services, and delegated control.
Contract Details
Solidity Version
^0.8.28
License
MIT
Inheritance
Context, EIP712 (OpenZeppelin)
DID Method
did:pkh (Public Key Hash)
Purpose
The DIDRegistry contract provides a complete on-chain DID management system:
Self-Sovereign Identity: Users control their own DID documents
Delegated Control: Authorized controllers can manage DIDs on behalf of subjects
Verification Methods: Support for multiple cryptographic keys with relationship types
Services: Link external services to DID documents
Meta-Transactions: EIP-712 signatures enable gasless updates
Data Structures
VerificationMethod
Represents a cryptographic key or verification method.
id
string
Full DID URL identifier for the method
methodType
string
Cryptographic suite type
metadata
string
JSON-encoded additional properties
controller
address
Ethereum address of the controller
relationships
uint8
Bitflags indicating verification relationships
Service
Represents an external service endpoint.
id
string
Unique service identifier
serviceType
string
Type classification
serviceEndpoint
string
URL, URI, or JSON endpoint data
DIDDocument
The complete DID Document structure.
context
string[]
JSON-LD context URIs
controllers
address[]
Delegated controller addresses
alsoKnownAs
string[]
Alias identifiers
verificationMethods
VerificationMethod[]
Array of verification methods
services
Service[]
Array of service endpoints
nonce
uint256
Auto-incrementing counter for updates
Verification Relationships
Verification relationships are stored as packed bitflags in a uint8:
AUTHENTICATION
1
0x01
Key can authenticate as the DID subject
ASSERTION
2
0x02
Key can make assertions/claims
KEY_AGREEMENT
4
0x04
Key can be used for key agreement (encryption)
CAPABILITY_INVOCATION
8
0x08
Key can invoke capabilities
CAPABILITY_DELEGATION
16
0x10
Key can delegate capabilities
Examples
Authentication only
1
00001
Authentication + Assertion
3
00011
Key Agreement only
4
00100
All relationships
31
11111
State Variables
DID_TYPE
string
public constant
DID method type ("did:pkh")
AUTHENTICATION
uint8
public constant
Authentication bitflag (1)
ASSERTION
uint8
public constant
Assertion bitflag (2)
KEY_AGREEMENT
uint8
public constant
Key Agreement bitflag (4)
CAPABILITY_INVOCATION
uint8
public constant
Capability Invocation bitflag (8)
CAPABILITY_DELEGATION
uint8
public constant
Capability Delegation bitflag (16)
didDocuments
mapping(address => DIDDocument)
internal
DID document storage
Functions
Constructor
Initializes the contract with EIP-712 domain parameters.
Parameters:
name
string
Domain name (e.g., "DIDRegistry")
version
string
Domain version (e.g., "1")
Registration Functions
registerDID
Registers a new DID document for msg.sender.
Parameters:
_didDocument
DIDDocument
The DID document to register
Requirements:
Subject must not already have a registered DID (nonce == 0)
Context array must not be empty
Emits: DIDRegistered
registerDIDOf
Registers a DID on behalf of another address using their signature.
Parameters:
_didDocument
DIDDocument
The DID document to register
_didSubject
address
The address to register the DID for
_subjectSignature
bytes
EIP-712 signature from the subject
Requirements:
Signature must be from the
_didSubjectSubject must not already have a registered DID
Emits: DIDRegistered
Update Functions
updateDID
Updates an existing DID document.
Parameters:
_didDocument
DIDDocument
The updated DID document
_didSubject
address
The address whose DID to update
Requirements:
Caller must be the subject OR a listed controller
Provided nonce must match current stored nonce
Context array must not be empty
Emits: DIDUpdated
updateDIDOf
Updates a DID document using a signature from an authorized party.
Parameters:
_didDocument
DIDDocument
The updated DID document
_didSubject
address
The address whose DID to update
_signature
bytes
EIP-712 signature from subject or controller
Requirements:
Signer must be the subject OR a listed controller
Provided nonce must match current stored nonce
Emits: DIDUpdated
Query Functions
getDIDDocument
Retrieves the DID document for a given address.
Parameters:
subject
address
The DID subject address
Returns: DIDDocument struct (empty if not registered)
isController
Checks if an address is a controller for a DID.
Parameters:
subject
address
The DID subject address
account
address
The address to check
Returns: true if account is listed as a controller
Relationship Helper Functions
hasRelationship
Checks if a relationship flag is set.
Parameters:
relationships
uint8
The packed relationship bitflags
flag
uint8
The flag to check (e.g., AUTHENTICATION)
Returns: true if the flag is set
Example:
addRelationship
Adds a relationship flag.
Parameters:
relationships
uint8
Current relationship bitflags
flag
uint8
The flag to add
Returns: Updated relationship bitflags
removeRelationship
Removes a relationship flag.
Parameters:
relationships
uint8
Current relationship bitflags
flag
uint8
The flag to remove
Returns: Updated relationship bitflags
Hashing Functions
hashDIDDocument
Computes the EIP-712 struct hash for a DID document.
getTypedDataHash
Returns the complete EIP-712 typed data hash for signing.
Events
DIDRegistered
Emitted when a new DID document is registered.
DIDUpdated
Emitted when a DID document is updated.
subject
The DID subject address
updatedBy
The address that performed the update
nonce
The new nonce value after update
Errors
InvalidContext()
Context array is empty
InvalidControllers()
Controllers array validation failed
InvalidSignature()
Signature verification failed
InvalidNonce()
Provided nonce doesn't match stored nonce
Unauthorized()
Caller is not authorized to update
AlreadyRegistered()
DID already registered for this address
EIP-712 Type Definitions
VerificationMethod
Service
DIDDocument
Usage Examples
Registering a DID Document (TypeScript/Viem)
Registering on Behalf of Another User
Updating with Delegated Controller
Reading and Decoding a DID Document
W3C DID Document Mapping
The contract's structures map to W3C DID Document format:
@context
context
Array of context URIs
id
N/A (mapping key)
Derived from did:pkh:{address}
controller
controllers
Array of controller addresses
alsoKnownAs
alsoKnownAs
Alternative identifiers
verificationMethod
verificationMethods
Array of methods
authentication
relationships bitflag
Derived from bitflag
assertionMethod
relationships bitflag
Derived from bitflag
keyAgreement
relationships bitflag
Derived from bitflag
capabilityInvocation
relationships bitflag
Derived from bitflag
capabilityDelegation
relationships bitflag
Derived from bitflag
service
services
Array of services
Example: JSON-LD to Solidity Encoding
W3C JSON-LD Format:
Solidity Struct Encoding:
Security Considerations
Nonce Protection: Each update increments the nonce, preventing replay attacks
Controller Authorization: Only subject or listed controllers can update
Signature Verification: Meta-transactions verified via EIP-712 ECDSA recovery
Context Validation: Empty context arrays are rejected
Immutable Registration: DID cannot be re-registered once created
Related Contracts
Agreement: Uses DIDs for party identification
Consent: Links consent records to DID-identified suppliers
Deployment
The contract is deployed using Hardhat Ignition:
Last updated

