Health Data Privacy Vault

What it does:
Stores patient health data in an encrypted, privacy-preserving vault on-chain while allowing selective access to authorized parties.

Why it matters:
Protects sensitive medical information, ensures compliance with privacy regulations, and gives patients full control over who can view or use their data.

How it works:

  • Patients encrypt their health data off-chain (IPFS or similar)

  • Encrypted data hash is stored on-chain in the vault

  • Patients grant access to hospitals, researchers, or insurers via smart permissions

  • Access rights can be updated, revoked, or time-limited

  • All access requests and grants are logged immutably

  • Third parties can verify data integrity without seeing raw data

  • Patients maintain full auditability of all interactions

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title HealthDataPrivacyVault
 * @author Nam
 * @notice Secure, patient-controlled storage for encrypted health data
 */
contract HealthDataPrivacyVault {

    // -------------------- STRUCTS --------------------

    struct DataRecord {
        string dataHash; // IPFS / encrypted data hash
        uint256 timestamp;
    }

    struct AccessGrant {
        bool allowed;
        uint256 expiresAt; // 0 = no expiry
    }

    // -------------------- STORAGE --------------------

    mapping(address => DataRecord[]) private patientData;
    mapping(address => mapping(address => AccessGrant)) private accessControl;

    // -------------------- EVENTS --------------------

    event DataStored(address indexed patient, string dataHash);
    event AccessGranted(address indexed patient, address indexed grantee, uint256 expiresAt);
    event AccessRevoked(address indexed patient, address indexed grantee);

    // -------------------- DATA MANAGEMENT --------------------

    /**
     * @notice Store encrypted health data
     */
    function storeData(string calldata _dataHash) external {
        patientData[msg.sender].push(DataRecord({
            dataHash: _dataHash,
            timestamp: block.timestamp
        }));

        emit DataStored(msg.sender, _dataHash);
    }

    /**
     * @notice Grant access to a third party
     */
    function grantAccess(address _grantee, uint256 _expiresAt) external {
        require(_grantee != address(0), "Invalid grantee");

        accessControl[msg.sender][_grantee] = AccessGrant({
            allowed: true,
            expiresAt: _expiresAt
        });

        emit AccessGranted(msg.sender, _grantee, _expiresAt);
    }

    /**
     * @notice Revoke access
     */
    function revokeAccess(address _grantee) external {
        accessControl[msg.sender][_grantee] = AccessGrant({
            allowed: false,
            expiresAt: 0
        });

        emit AccessRevoked(msg.sender, _grantee);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    /**
     * @notice Check if a grantee has access
     */
    function hasAccess(address _patient, address _grantee) public view returns (bool) {
        AccessGrant memory grant = accessControl[_patient][_grantee];
        if (!grant.allowed) return false;
        if (grant.expiresAt > 0 && block.timestamp > grant.expiresAt) return false;
        return true;
    }

    /**
     * @notice Retrieve patient's data (only for authorized parties)
     */
    function getData(address _patient) external view returns (DataRecord[] memory) {
        require(hasAccess(_patient, msg.sender) || msg.sender == _patient, "Access denied");
        return patientData[_patient];
    }
}