Domain expertise for writing smart contracts in the healthcare industry. Use this skill whenever a developer is writing, reviewing, or designing Solidity contracts that touch healthcare data, insurance claims, patient records, billing, access control, or drug supply chains. Trigger even when the user only mentions healthcare + blockchain tangentially — e.g., "I'm building a patient portal on-chain", "how do I handle insurance claims in a contract", "HIPAA and smart contracts", "EHR on Ethereum". Always combine this skill with Solidity best practices. Never let a developer ship healthcare contracts without applying this skill.
You are helping developers write smart contracts for the healthcare industry. This domain has unique legal, privacy, and data architecture constraints that must shape every design decision. Your job is to enforce those constraints proactively — not wait to be asked.
This is the most important rule in healthcare contracts.
Healthcare data (PII, PHI) must NEVER be stored on a public blockchain. This violates HIPAA, GDPR, and most regional equivalents. The blockchain stores only:
Sensitive data lives off-chain in encrypted, access-controlled storage (IPFS+encryption, AWS HealthLake, Azure Health Data Services, or self-hosted FHIR servers). The contract holds a content-addressed pointer (hash) to that storage.
Pattern to always suggest:
// WRONG — never do this
struct Patient {
string name;
string diagnosis;
uint256 dateOfBirth;
}
// CORRECT
struct PatientRecord {
bytes32 dataHash; // keccak256 of off-chain FHIR bundle
string offChainURI; // encrypted IPFS CID or FHIR server ref
address dataController; // GDPR data controller
uint256 lastUpdated;
bool isActive;
}
Problem: Patient controls who can read their health records. Pattern: Token-gated access with revocation.
contract PatientAccessControl {
// patient => provider => expiry timestamp
mapping(address => mapping(address => uint256)) public accessGrants;
event AccessGranted(address indexed patient, address indexed provider, uint256 expiry);
event AccessRevoked(address indexed patient, address indexed provider);
function grantAccess(address provider, uint256 durationSeconds) external {
accessGrants[msg.sender][provider] = block.timestamp + durationSeconds;
emit AccessGranted(msg.sender, provider, block.timestamp + durationSeconds);
}
function revokeAccess(address provider) external {
delete accessGrants[msg.sender][provider];
emit AccessRevoked(msg.sender, provider);
}
function hasAccess(address patient, address provider) public view returns (bool) {
return accessGrants[patient][provider] > block.timestamp;
}
}
Key points: access is time-bounded, revocable, and patient-controlled. The audit trail is in the events — never store PHI in event data either.
Problem: Automate claims from submission → adjudication → payment. Stages: Submitted → UnderReview → Approved/Denied → Paid/Appealed
enum ClaimStatus { Submitted, UnderReview, Approved, Denied, Paid, Appealed }
struct Claim {
bytes32 claimDataHash; // hash of off-chain FHIR Claim resource
address patient;
address provider;
address insurer;
uint256 amountRequested; // in smallest currency unit (e.g., cents)
uint256 amountApproved;
ClaimStatus status;
uint256 submittedAt;
uint256 resolvedAt;
}
Key design decisions to always raise:
Problem: Provider requests insurer approval before a procedure. Pattern: Multi-party sign-off with deadline enforcement.
struct PriorAuth {
bytes32 requestHash; // hash of procedure + diagnosis codes (ICD-10/CPT)
address provider;
address insurer;
address patient;
uint256 requestedAt;
uint256 deadline; // insurer must respond by this timestamp
bool approved;
bool resolved;
}
Always enforce the deadline: if insurer doesn't respond by deadline, auto-approve or
escalate — mirror real-world regulations (most US states mandate 72h turnaround).
Problem: Track a drug batch from manufacturer to patient to prevent counterfeits. Pattern: NFT-style token per batch with custody transfers.
struct DrugBatch {
bytes32 batchHash; // hash of: NDC code + lot number + expiry + manufacturer
address currentCustodian;
uint256 manufacturedAt;
uint256 expiresAt;
bool recalled;
address[] custodyChain; // full chain: manufacturer → distributor → pharmacy
}
Key: recalled flag must be settable by manufacturer and regulators (FDA/EMA).
Always emit events on custody transfer for off-chain indexing.
Problem: Record patient consent for data use (research, sharing, treatment). Pattern: Granular, timestamped, revocable consent registry.
struct Consent {
address patient;
bytes32 purposeHash; // hash of the consent purpose (e.g., "clinical_trial_X")
uint256 grantedAt;
uint256 expiresAt; // 0 = indefinite
bool active;
}
Consent must be: specific (not blanket), time-bounded, and revocable at any time.
| Anti-Pattern | Why It's Wrong | Fix |
|---|---|---|
| Storing patient name/DOB on-chain | HIPAA violation | Store keccak256 hash only |
Using string for medical codes | Gas-inefficient, inconsistent | Use bytes32 for ICD-10/CPT/NDC |
| Centralized oracle for claim data | Single point of failure + manipulation | Use Chainlink or multi-oracle |
| No access expiry on data grants | Violates minimum necessary rule | Always add expiresAt |
| Float arithmetic for billing amounts | Precision errors in financial settlement | Use integer cents |
| Storing IP addresses in events | HIPAA identifier | Never log any of the 18 identifiers |
| Upgradeable proxy without timelock | Admin can change rules mid-claim | Add governance timelock |
| No emergency pause | Can't respond to breaches | Implement Pausable pattern |
Every healthcare contract should define these roles explicitly (use OpenZeppelin AccessControl):
bytes32 public constant PATIENT_ROLE = keccak256("PATIENT");
bytes32 public constant PROVIDER_ROLE = keccak256("PROVIDER"); // doctor/hospital
bytes32 public constant INSURER_ROLE = keccak256("INSURER");
bytes32 public constant REGULATOR_ROLE = keccak256("REGULATOR"); // FDA, CMS, state
bytes32 public constant AUDITOR_ROLE = keccak256("AUDITOR"); // read-only audit
Patient always has sovereign control over their own data. Regulator can pause contracts and flag recalls. Auditor has read-only access — never write permissions.
bytes32 for all codes (ICD-10, CPT, NDC, NPI) — never stringFor deeper detail, read these when needed:
references/regulatory-detail.md — Full HIPAA/GDPR rule breakdown with contract implicationsreferences/fhir-data-models.md — FHIR R4 resource structures mapped to Solidity structsreferences/claims-lifecycle.md — Full claims state machine with all edge cases