Decentralized Health ID
What it does:
Creates a self-sovereign, on-chain health identity that allows individuals to prove their medical identity and credentials without exposing sensitive personal data.
Why it matters:
Eliminates fragmented patient records, reduces identity fraud, and enables seamless interoperability across hospitals, insurers, and health platforms while preserving privacy.
How it works:
-
Users create a decentralized health identity on-chain
-
Identity links to verifiable credentials (hashes only)
-
Trusted issuers attest medical or insurance credentials
-
Users selectively prove identity ownership
-
Health ID can be used across multiple healthcare contracts
-
Identity updates are auditable without revealing raw data
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title DecentralizedHealthID
* @author Nam
* @notice Self-sovereign health identity on-chain
*/
contract DecentralizedHealthID {
// -------------------- ROLES --------------------
address public admin;
mapping(address => bool) public trustedIssuers;
// -------------------- IDENTITY STRUCT --------------------
struct HealthIdentity {
bool registered;
string metadataHash; // IPFS hash / encrypted identity metadata
uint256 createdAt;
}
struct Credential {
string credentialHash;
address issuer;
uint256 issuedAt;
bool valid;
}
// user => identity
mapping(address => HealthIdentity) public identities;
// user => credentialId => Credential
mapping(address => mapping(uint256 => Credential)) public credentials;
mapping(address => uint256) public credentialCount;
// -------------------- EVENTS --------------------
event HealthIDCreated(address indexed user);
event HealthIDUpdated(address indexed user);
event IssuerAuthorized(address indexed issuer);
event CredentialIssued(
address indexed user,
uint256 indexed credentialId,
address indexed issuer
);
event CredentialRevoked(
address indexed user,
uint256 indexed credentialId
);
// -------------------- MODIFIERS --------------------
modifier onlyAdmin() {
require(msg.sender == admin, "Not admin");
_;
}
modifier onlyIssuer() {
require(trustedIssuers[msg.sender], "Not trusted issuer");
_;
}
modifier onlyUser(address _user) {
require(msg.sender == _user, "Not identity owner");
_;
}
// -------------------- CONSTRUCTOR --------------------
constructor() {
admin = msg.sender;
}
// -------------------- ISSUER MANAGEMENT --------------------
/**
* @notice Authorize a trusted credential issuer
*/
function authorizeIssuer(address _issuer)
external
onlyAdmin
{
require(_issuer != address(0), "Invalid issuer");
trustedIssuers[_issuer] = true;
emit IssuerAuthorized(_issuer);
}
// -------------------- HEALTH ID --------------------
/**
* @notice Create a decentralized health ID
*/
function createHealthID(string calldata _metadataHash)
external
{
require(!identities[msg.sender].registered, "Already registered");
identities[msg.sender] = HealthIdentity({
registered: true,
metadataHash: _metadataHash,
createdAt: block.timestamp
});
emit HealthIDCreated(msg.sender);
}
/**
* @notice Update identity metadata reference
*/
function updateHealthID(string calldata _metadataHash)
external
onlyUser(msg.sender)
{
require(identities[msg.sender].registered, "Not registered");
identities[msg.sender].metadataHash = _metadataHash;
emit HealthIDUpdated(msg.sender);
}
// -------------------- CREDENTIALS --------------------
/**
* @notice Issue a verifiable credential
*/
function issueCredential(
address _user,
string calldata _credentialHash
)
external
onlyIssuer
{
require(identities[_user].registered, "User not registered");
credentialCount[_user] += 1;
credentials[_user][credentialCount[_user]] = Credential({
credentialHash: _credentialHash,
issuer: msg.sender,
issuedAt: block.timestamp,
valid: true
});
emit CredentialIssued(
_user,
credentialCount[_user],
msg.sender
);
}
/**
* @notice Revoke a credential
*/
function revokeCredential(
address _user,
uint256 _credentialId
)
external
{
Credential storage c = credentials[_user][_credentialId];
require(
msg.sender == c.issuer || msg.sender == admin,
"Not authorized"
);
require(c.valid, "Already revoked");
c.valid = false;
emit CredentialRevoked(_user, _credentialId);
}
// -------------------- VIEW --------------------
/**
* @notice Verify a credential
*/
function verifyCredential(
address _user,
uint256 _credentialId
)
external
view
returns (
string memory credentialHash,
address issuer,
bool valid
)
{
Credential memory c = credentials[_user][_credentialId];
require(c.issuedAt > 0, "Credential not found");
return (
c.credentialHash,
c.issuer,
c.valid
);
}
}