Skip to navigation

DID Registry Smart Contract

View as Markdown

The DID Registry is the core on-chain contract that stores DID registrations, document hashes, and lifecycle state on the ADI blockchain.

Contract Address

NetworkAddress
ADI Mainnet0x... (TBD)
ADI Testnet0x5FbDB2315678afecb367f032d93F642f64180aa3
Local DevnetDeployed via forge script

Interface

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface IDIDRegistry {
struct DIDRecord {
address owner;
bytes32 documentHash;
string storageUri;
uint256 versionId;
uint256 created;
uint256 updated;
bool deactivated;
uint256 nonce;
}
event DIDRegistered(string indexed did, address indexed owner, bytes32 documentHash);
event DIDUpdated(string indexed did, bytes32 newDocumentHash, uint256 versionId);
event DIDDeactivated(string indexed did);
event DIDOwnerChanged(string indexed did, address indexed newOwner);
function registerDID(
string calldata did,
bytes32 documentHash,
string calldata storageUri
) external;
function resolveDID(string calldata did) external view returns (DIDRecord memory);
function updateDID(
string calldata did,
bytes32 newDocumentHash,
string calldata newStorageUri
) external;
function deactivateDID(string calldata did) external;
function changeOwner(string calldata did, address newOwner) external;
function getNonce(string calldata did) external view returns (uint256);
function isActive(string calldata did) external view returns (bool);
}

Key Functions

registerDID

Registers a new DID on the blockchain.

function registerDID(
string calldata did,
bytes32 documentHash,
string calldata storageUri
) external;
ParameterTypeDescription
didstringThe full DID string (e.g., did:adi:3f7a...)
documentHashbytes32SHA-256 hash of the DID Document
storageUristringIPFS URI for the full DID Document

Requirements:

  • DID must not already exist
  • msg.sender becomes the owner
  • Emits DIDRegistered event

resolveDID

Returns the on-chain record for a DID.

function resolveDID(string calldata did) external view returns (DIDRecord memory);

Returns: Full DIDRecord struct including document hash, storage URI, version, and status.

updateDID

Updates the DID Document hash and storage URI.

function updateDID(
string calldata did,
bytes32 newDocumentHash,
string calldata newStorageUri
) external;

Requirements:

  • msg.sender must be the DID owner
  • DID must not be deactivated
  • Increments versionId
  • Emits DIDUpdated event

deactivateDID

Permanently deactivates a DID.

function deactivateDID(string calldata did) external;

Requirements:

  • msg.sender must be the DID owner
  • DID must not already be deactivated
  • Sets deactivated = true
  • Emits DIDDeactivated event

Interaction Examples

Register a DID (ethers.js)

import { ethers } from 'ethers';
const registry = new ethers.Contract(DID_REGISTRY_ADDRESS, DID_REGISTRY_ABI, signer);
const did = 'did:adi:3f7a9b2e1c4d5f6a8b0c2d4e6f8a0b2c...';
const documentHash = ethers.keccak256(ethers.toUtf8Bytes(JSON.stringify(didDocument)));
const storageUri = 'ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco';
const tx = await registry.registerDID(did, documentHash, storageUri);
await tx.wait();
console.log('DID registered:', tx.hash);

Resolve a DID

const record = await registry.resolveDID('did:adi:3f7a9b2e1c4d...');
console.log('Owner:', record.owner);
console.log('Document hash:', record.documentHash);
console.log('Storage URI:', record.storageUri);
console.log('Version:', record.versionId.toString());
console.log('Active:', !record.deactivated);

Gas Costs

OperationEstimated GasEstimated Cost (ADI)
registerDID~150,000~0.003 ADI
resolveDID0 (view)Free
updateDID~80,000~0.0016 ADI
deactivateDID~50,000~0.001 ADI
changeOwner~45,000~0.0009 ADI

Security Considerations

  • Only the DID owner can update or deactivate their DID
  • Deactivation is permanent and irreversible
  • The contract uses a nonce-based replay protection
  • All state changes emit events for off-chain indexing
  • The contract is upgradeable via a proxy pattern for bug fixes