Building a Smart Contract for Managing Medical Records on Celo

Building a Smart Contract for Managing Medical Records on Celo https://celo.academy/uploads/default/optimized/2X/e/e8c248bc6d9e44d3bddc5fea192c2e18400b9adb_2_1024x576.jpeg
none 0.0 0

Introduction

Hey there! we will explore the technical aspects of creating a smart contract on Celo, which aims to effectively handle medical records. The primary objective is to establish a secure and efficient system for storing and managing data, focusing on preserving privacy and security. Additionally, the contract incorporates access controls to ensure that only authorized individuals have the ability to view and interact with the medical records.

Moreover, this tutorial will offer insights into the use of Celo composer when building a project. It aims to provide a comprehensive overview of the step-to-step development process.

Let’s get started!

Prerequisite

Before we dive into this tutorial, you should have:

  • Understanding on how to use a terminal
  • Basic knowledge of blockchain concepts
  • Familiarity with the Solidity
  • Basic understanding of Celo Composer

Requirements

  • Node js
  • A code editor
  • Celo Extension Wallet or Metamask

Setting up the Project

Celo Composer is a powerful tool that enables you to create and launch decentralized applications on the Celo blockchain with ease. Whether you’re an experienced developer or just getting started with blockchain technology, Celo Composer simplifies the process of building, deploying, and updating dApps on Celo.

With Celo Composer, You have access to a variety of ready-to-use frameworks and examples, which can help you get started on your project right away.

So to begin, let’s set up our project by running the following command on our terminal

npx @Celo_Academy/celo-composer create

The terminal would display prompts so you can choose your framework.
For this tutorial, we would be using react-celo and hardhat and then add the preferred name you chose for the project.

Now open your terminal and install the dependencies using the following command

Yarn  

Still on your terminal, open your project on a code editor by running the command

 code .

Note

Write the smart contract

In this step, we will be creating the smart contract for the medical records but before we begin, let’s navigate to the contracts folder through the hardhat directory and create a new file

MedicalRecord.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract MedicalRecord {

    address private owner;

    mapping(bytes32 => Record) private records;
    mapping(address => bool) private authorizedUsers;
    mapping(bytes32 => Restrictions) private accessRestrictions;

// SPDX-License-Identifier: MIT specifies the license under which the code is released.

The pragma solidity ^0.8.0; statement specifies the version of the Solidity compiler to be used which in our case would be 0.8.0 and above.

contract MedicalRecord declares the name of the smart contract as MedicalRecord

address private owner; declares a private variable owner of type address. It is used to store the address of the owner of the medical record contract.

The mapping(bytes32 => Record) private records; line declares a private mapping named records that maps a bytes32 key to a struct Record.

The mapping(address => bool) private authorizedUsers; line declares a private mapping named authorizedUsers that maps an address key to a bool value. It is used to keep track of authorized users who have access to the medical records.

mapping(bytes32 => Restrictions) private accessRestrictions;is a private mapping namedaccessRestrictionsthat maps a bytes32 key to a struct that will be calledRestrictions`.

   struct Record {
        bytes data;
        uint256 timestamp;
    }


    struct Restrictions {
        mapping(address => bool) authorizedUsers;
        uint8 minRole;
        uint256 expirationDate;
    }

The Record struct is used to store its properties. bytes data which stores the actual data of the medical record and uint256 timestamp which stores the time when the medical record was created.

The Restrictions struct is used to manage access control and define additional constraints such as authorizedUsers, minRole, and expirationDate for accessing the medical record

    enum Roles {
        Patient,
        Doctor,
        Administrator
    }


    mapping(address => Roles) private userRoles;


    constructor() {
        owner = msg.sender;
    }

The Roles enum provides a way to define the Patient,Doctor and Administrator roles that can be assigned to users in the contract.

The userRoles mapping is used to store the assigned roles for each user. It associates an address with a Roles enum value

The constructor sets the owner variable to the deploying address, which implies that the deployer of the contract is considered the initial owner

    function authorizeUser(address user) public onlyOwner {
        authorizedUsers[user] = true;
    }


    function removeAuthorization(address user) public onlyOwner {
        authorizedUsers[user] = false;
    }


    function setUserRole(address user, Roles role) public onlyOwner {
        userRoles[user] = role;
    }

The authorizeUser function allows the contract owner to authorize a user by setting their authorization status to true.

The removeAuthorization function allows the contract owner to remove the authorization of a user by setting their authorization status to false.

The setUserRole function allows the contract owner to set the role of a user by assigning a value from the Roles enum to the specified user.

    function getRecord(bytes32 key) public view onlyAuthorized returns (bytes memory) {
        Record storage record = records[key];
        Restrictions storage restrictions = accessRestrictions[key];
        require(block.timestamp < restrictions.expirationDate, "This record has expired.");
        require(uint8(userRoles[msg.sender]) >= restrictions.minRole, "Your role is not high enough to access this record.");
        require(restrictions.authorizedUsers[msg.sender], "You are not authorized to access this record.");
        return record.data;
    }

The getRecord function allows authorized users to retrieve specific medical records based on a given key. It verifies the expiration date, role requirements, and authorization status before returning the record data.

    function setRecord(bytes32 key, bytes memory data, uint256 expirationDate, uint8 minRole, address[] memory _authorizedUsers) public onlyOwner {
        Record storage record = records[key];
        record.data = data;
        record.timestamp = block.timestamp;
        Restrictions storage restrictions = accessRestrictions[key];
        restrictions.expirationDate = expirationDate;
        restrictions.minRole = minRole;
        for (uint i = 0; i < _authorizedUsers.length; i++) {
            restrictions.authorizedUsers[_authorizedUsers[i]] = true;
        }
    }

The setRecord function allows the contract owner to set or update a medical record by providing the key, data, expiration date, minimum role, and a list of authorized users. It updates the record’s data and timestamp, as well as the access restrictions associated with the record, including the expiration date, minimum role, and authorized users.

    function deleteRecord(bytes32 key) public onlyOwner {
        delete records[key];
        delete accessRestrictions[key];
    }


    function getOwner() public view returns (address) {
        return owner;
    }


    modifier onlyOwner {
        require(msg.sender == owner, "Only the owner can perform this action.");
        _;
    }

    
    modifier onlyAuthorized {
        require(authorizedUsers[msg.sender], "You are not authorized to perform this action.");
        _;
    }
}

The deleteRecord function allows the contract owner to delete a medical record and its associated access restrictions.This function allows the contract owner to delete a medical record identified by the given key.

The getOwner function provides the address of the contract owner.

The onlyOwner modifier ensures that only the contract owner can execute specific functions by restricting access to functions that can only be executed by the contract owner.

The onlyAuthorized modifier ensures that only authorized users can execute specific functions. It restricts access to functions that can only be executed by authorized users.

Now your final code should be looking like this

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract MedicalRecord {

    address private owner;

    mapping(bytes32 => Record) private records;
    mapping(address => bool) private authorizedUsers;
    mapping(bytes32 => Restrictions) private accessRestrictions;


    struct Record {
        bytes data;
        uint256 timestamp;
    }


    struct Restrictions {
        mapping(address => bool) authorizedUsers;
        uint8 minRole;
        uint256 expirationDate;
    }


    enum Roles {
        Patient,
        Doctor,
        Administrator
    }


    mapping(address => Roles) private userRoles;


    constructor() {
        owner = msg.sender;
    }


    function authorizeUser(address user) public onlyOwner {
        authorizedUsers[user] = true;
    }


    function removeAuthorization(address user) public onlyOwner {
        authorizedUsers[user] = false;
    }


    function setUserRole(address user, Roles role) public onlyOwner {
        userRoles[user] = role;
    }


    function getRecord(bytes32 key) public view onlyAuthorized returns (bytes memory) {
        Record storage record = records[key];
        Restrictions storage restrictions = accessRestrictions[key];
        require(block.timestamp < restrictions.expirationDate, "This record has expired.");
        require(uint8(userRoles[msg.sender]) >= restrictions.minRole, "Your role is not high enough to access this record.");
        require(restrictions.authorizedUsers[msg.sender], "You are not authorized to access this record.");
        return record.data;
    }


    function setRecord(bytes32 key, bytes memory data, uint256 expirationDate, uint8 minRole, address[] memory _authorizedUsers) public onlyOwner {
        Record storage record = records[key];
        record.data = data;
        record.timestamp = block.timestamp;
        Restrictions storage restrictions = accessRestrictions[key];
        restrictions.expirationDate = expirationDate;
        restrictions.minRole = minRole;
        for (uint i = 0; i < _authorizedUsers.length; i++) {
            restrictions.authorizedUsers[_authorizedUsers[i]] = true;
        }
    }


    function deleteRecord(bytes32 key) public onlyOwner {
        delete records[key];
        delete accessRestrictions[key];
    }


    function getOwner() public view returns (address) {
        return owner;
    }


    modifier onlyOwner {
        require(msg.sender == owner, "Only the owner can perform this action.");
        _;
    }

    
    modifier onlyAuthorized {
        require(authorizedUsers[msg.sender], "You are not authorized to perform this action.");
        _;
    }
}

Connect your wallet

Under the hardhat folder, create a .env file and add the following command to it

MNEMONIC=""
PRIVATE_KEY=""
CELOSCAN_API_KEY=""

Add your private key of your celo testnet account on the metamask wallet. Please ensure you are using a test account. If you do not have one, you can download a metamask wallet, add celo network and then fund your wallet by requesting tokens on celo alfajores faucet.

Learn more:

Deploy the contract

Navigate to the deploy.js file in the deploy folder and paste the following

module.exports = async ({ getNamedAccounts, deployments }) => {
  const { deploy } = deployments;
  const { deployer } = await getNamedAccounts();

  await deploy("MedicalRecord", {
    from: deployer,
    //args: ["hello world"],
    log: true,
  });

module.exports.tags = ["MedicalRecord"];

Deploy your smart contracts by running this command on your terminal

yarn deploy 

If successful, you should be able to see it on the terminal as it first of all, compiles the smart contract and then deploys the contract to an address.

You can verify your contract was deployed by searching for the address on Alfajores.

Conclusion

In this tutorial, you have learnt how to set up your environment, write the smart contract, connect our wallet and effectively deployed our smart contract for managing Medical Records on Celo with Solidity using Celo Composer.

Reference

5 Likes

A nice concept. I await the outcome

3 Likes

Congratulations on being among the highest voted proposals for this week! I’m moving this to todo so that you can get started on this project. :mortar_board: :seedling:

3 Likes

I’ll be reviewing this @Kyrian

3 Likes

Hi, please your repository link isn’t functional. Kindly correct this as I have to check the code

3 Likes

Also, please kindly add screenshots of the code when it’s compiled and deployed. Thanks

3 Likes

Hi, Kindly check that again.

2 Likes

Oh, that’s great. Kindly share screenshot of the tutorial being compiled and deployed to the blockchain to help our readers.

1 Like

Hello, any update on this?

1 Like

I didn’t take one. If I attempt to deploy again, it would result in a “nothing to compile” message.
Did you face any challenges during your attempt? @Jorshimayor

2 Likes

I’d advise using hardhat or truffle to compile and deploy your contract.

Alternatively you could check it on the Celo block explorer since it has been deployed before

Check out this documentation on how to build on Celo

Let me know if you have further issues

3 Likes

3 Likes

@Jorshimayor you might find this article resourceful in learning more about celo composer.

3 Likes

Hi Kyrian, that’s great, but you can just screenshot the terminal and show the readers the expected results.

2 Likes

Thanks, just checked it out. You could add the pictures just like Joe did as this is a great project and the readers will need a lot of pictures of the results to help their projects.

Good work Kyrian

3 Likes

Sure! Had to drop it here for your perusal because I wasn’t able to edit my post.
Would make the changes soon as i can.

2 Likes

Glad I could help!

3 Likes

Wow, you can’t edit your post till now? You’ll probably have to tag Joe either here or on discord

2 Likes

How could you now post your articles if you couldn’t edit your post

2 Likes

Hello, any update

2 Likes