Skip to content

Develop Smart Contract for Patient Data Sharing #23

@sbhavani

Description

@sbhavani

Description

Develop the core AccessControl smart contract for managing patient data access permissions on the Ethereum blockchain.

Requirements

  1. Create a Solidity smart contract (AccessControl.sol) that implements:

    • Access granting functionality
    • Access verification with optional password protection
    • Time-based expiry for shared data
    • Ownership and permission controls
  2. Key Contract Features:

    • Store references to IPFS content identifiers (CIDs) with associated metadata
    • Support time-limited access through expiry timestamps
    • Include optional password protection via hashed passwords
    • Emit events for tracking access creation and verification
    • Allow access verification without modifying blockchain state
  3. Project Setup:

    • Set up Hardhat or Truffle development environment
    • Configure for local development and testnet deployment
    • Create proper testing framework

Implementation Details

The contract should be implemented as specified in the PRD:

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

contract AccessControl {
    struct AccessGrant {
        address owner;
        string ipfsCid; // CID of the encrypted data on IPFS
        uint256 expiryTime; // Unix timestamp
        bytes32 passwordHash; // Optional password hash (keccak256)
        bool exists;
    }

    mapping(bytes32 => AccessGrant) public accessGrants; // accessId => AccessGrant

    event AccessCreated(bytes32 indexed accessId, address indexed owner, string ipfsCid, uint256 expiryTime);
    event AccessVerified(bytes32 indexed accessId, address indexed viewer);
    event AccessDenied(bytes32 indexed accessId, address indexed viewer, string reason);

    modifier onlyValidGrant(bytes32 accessId) {
        require(accessGrants[accessId].exists, "Access grant does not exist");
        require(block.timestamp < accessGrants[accessId].expiryTime, "Access grant has expired");
        _;
    }

    function createAccess(
        string memory _ipfsCid,
        uint256 _durationSeconds,
        bytes32 _passwordHash // Use bytes32(0) if no password
    ) external returns (bytes32 accessId) {
        require(_durationSeconds > 0, "Duration must be positive");

        accessId = keccak256(abi.encodePacked(msg.sender, _ipfsCid, block.timestamp, _durationSeconds));
        uint256 expiry = block.timestamp + _durationSeconds;

        accessGrants[accessId] = AccessGrant({
            owner: msg.sender,
            ipfsCid: _ipfsCid,
            expiryTime: expiry,
            passwordHash: _passwordHash,
            exists: true
        });

        emit AccessCreated(accessId, msg.sender, _ipfsCid, expiry);
        return accessId;
    }

    function verifyAccess(
        bytes32 _accessId,
        string memory _passwordInput // Empty string if no password attempt
    ) external view onlyValidGrant(_accessId) returns (string memory ipfsCid) {
        AccessGrant storage grantToVerify = accessGrants[_accessId];

        if (grantToVerify.passwordHash != bytes32(0)) { // Password is set
            if (keccak256(abi.encodePacked(_passwordInput)) != grantToVerify.passwordHash) {
                revert("Invalid password");
            }
        }
        
        return grantToVerify.ipfsCid;
    }

    function getAccessGrantDetails(bytes32 _accessId) 
        external view 
        returns (address owner, string memory ipfsCid, uint256 expiryTime, bool hasPassword) 
    {
        AccessGrant storage grantDetails = accessGrants[_accessId];
        require(grantDetails.exists, "Grant does not exist");
        return (grantDetails.owner, grantDetails.ipfsCid, grantDetails.expiryTime, grantDetails.passwordHash != bytes32(0));
    }
}
  1. Development Steps:

    • Set up the Hardhat/Truffle project structure
    • Implement the AccessControl.sol contract according to the provided code
    • Write comprehensive tests for all contract functions
    • Deploy to a test network
    • Document the deployed contract address and ABI
  2. Additional Features to Consider:

    • Gas optimization
    • Enhanced error messages
    • Contract upgradeability pattern
    • Function to allow owners to revoke access before expiry

Testing Requirements

  1. Unit tests for all contract functions:

    • Creating access grants
    • Verifying access with and without passwords
    • Checking expired grants
    • Handling invalid passwords
    • Retrieving grant details
  2. Gas usage optimization tests

  3. Integration tests with frontend components

Acceptance Criteria

  • Smart contract successfully deployed to a test network
  • All functions work as described in the requirements
  • Events are emitted correctly
  • Password protection works securely
  • Time-based expiration functions as intended
  • Contract address and ABI are documented and available for frontend integration
  • All tests pass successfully
  • Gas optimization has been considered

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions