Building a Decentralized Intellectual Property Management System with Advanced Smart Contracts On Celo

Building a Decentralized Intellectual Property Management System with Advanced Smart Contracts On Celo https://celo.academy/uploads/default/optimized/2X/f/f3ab4ca99a58cfd908a8c8b1e6f052fed7290a15_2_1024x576.png
none 0.0 0

Introduction

Welcome to this tutorial. In this tutorial, we’re going to dive into a fascinating topic - the management of intellectual property (IP) using blockchain technology. The Celo network provides a rich infrastructure for creating and managing unique, non-fungible tokens (NFTs) that can represent a wide variety of real-world assets. One innovative application of this technology is in the world of IP rights, where each unique token can represent a unique piece of intellectual property. This tutorial will guide you through the inner workings of such a smart contract, explaining each function in detail.

You can find the repository for this tutorial Here

Prerequisites

To follow this tutorial, you will need the following:

  • Basic understanding of Solidity and smart contracts.
  • A Development Environment Like Remix.
  • The Celo Extension Wallet.

Contract Developement

The complete code contract look like this

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

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract IPManagement is ERC721URIStorage, Ownable {

    uint private counter;

    enum Category { Patent, Copyright, Trademark }

    struct IP {
        string ipDescription;
        uint256 price;
        Category category;
        address payable owner;
        bool purchased;
    }

    mapping (uint => IP) public ips;

    event IPRegistered (
        uint tokenId,
        string ipDescription,
        uint256 price,
        address payable owner,
        Category category
    );

    event IPPurchased (
        uint tokenId,
        string ipDescription,
        uint256 price,
        address payable owner,
        Category category
    );

    constructor() ERC721("IPManagement", "IPM") {}

    function registerIP(string memory _description, uint256 _price, Category _category, string memory tokenURI) public onlyOwner {
        counter++;
        uint tokenId = counter;

        _mint(msg.sender, tokenId);
        _setTokenURI(tokenId, tokenURI);

        ips[tokenId] = IP(_description, _price, _category, payable(msg.sender), false);
        emit IPRegistered(tokenId, _description, _price, payable(msg.sender), _category);
    }
    
    function purchaseIP(uint tokenId) public payable {
        IP memory _ip = ips[tokenId];
        require(!_ip.purchased, "IP already purchased");
        require(msg.value == _ip.price, "Incorrect value sent");

        _ip.owner.transfer(msg.value);
        _ip.purchased = true;
        ips[tokenId] = _ip;

        _transfer(_ip.owner, msg.sender, tokenId);

        emit IPPurchased(tokenId, _ip.ipDescription, msg.value, _ip.owner, _ip.category);
    }

    function updateIP(uint tokenId, string memory _description, uint256 _price, Category _category) public {
        IP memory _ip = ips[tokenId];
        require(_ip.owner == msg.sender, "Only owner can update the IP");
        _ip.ipDescription = _description;
        _ip.price = _price;
        _ip.category = _category;
        ips[tokenId] = _ip;
    }

    function deleteIP(uint tokenId) public {
        IP memory _ip = ips[tokenId];
        require(_ip.owner == msg.sender, "Only owner can delete the IP");
        delete ips[tokenId];
        _burn(tokenId);
    }
}

Code Breakdown

Let’s break it down piece by piece:

Imports and Inheritance

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract IPManagement is ERC721URIStorage, Ownable {

This contract imports two contracts from OpenZeppelin: ERC721URIStorage and Ownable.

  • ERC721URIStorage is an extension of the ERC721 standard, which provides basic functionality to create unique, non-fungible tokens. It also includes a URI for metadata that might be used to identify the token externally.
  • Ownable provides basic authorization control functions, simplifying the implementation of user permissions. It sets the original owner of the contract to the sender(account deploying the contract) and restricts certain functions to be accessible only by the owner.

Contract Variables and Types

uint private counter;

enum Category { Patent, Copyright, Trademark }

struct IP {
    string ipDescription;
    uint256 price;
    Category category;
    address payable owner;
    bool purchased;
}

mapping (uint => IP) public ips;

counter is a private variable that keeps track of the number of registered IPs.

Category is an enumerated type (enum) that specifies three types of intellectual property: Patent, Copyright, and Trademark.

IP is a struct, a custom defined type that groups together related data of varying types. This struct represents an intellectual property (IP), and includes a description, a price, a category (from the Category enum), an owner’s address, and a flag indicating whether the IP has been purchased.

ips is a public mapping that associates each tokenId (an unsigned integer) with an IP struct.

Events

event IPRegistered (
    uint tokenId,
    string ipDescription,
    uint256 price,
    address payable owner,
    Category category
);

event IPPurchased (
    uint tokenId,
    string ipDescription,
    uint256 price,
    address payable owner,
    Category category
);

Events are a way for smart contracts to emit information that external consumers (like web3 applications) can listen for and react to.

  • IPRegistered event is emitted when a new IP is registered.
  • IPPurchased event is emitted when an IP is purchased.

Constructor

constructor() ERC721("IPManagement", "IPM") {}

The constructor handles the name and symbol of our IP Management ERC721 token.

RegisterIP Function

 function registerIP(string memory _description, uint256 _price, Category _category, string memory tokenURI) public onlyOwner {
        counter++;
        uint tokenId = counter;

        _mint(msg.sender, tokenId);
        _setTokenURI(tokenId, tokenURI);

        ips[tokenId] = IP(_description, _price, _category, payable(msg.sender), false);
        emit IPRegistered(tokenId, _description, _price, payable(msg.sender), _category);
    }

The registerIP() function allows the contract owner to register a new IP. It increments the counter , mints a new ERC721 token, and sets the token’s URI. It also creates a new IP struct and stores it in the ips mapping, then emits an IPRegistered event.

PurchaseIP Function

 function purchaseIP(uint tokenId) public payable {
        IP memory _ip = ips[tokenId];
        require(!_ip.purchased, "IP already purchased");
        require(msg.value == _ip.price, "Incorrect value sent");

        _ip.owner.transfer(msg.value);
        _ip.purchased = true;
        ips[tokenId] = _ip;

        _transfer(_ip.owner, msg.sender, tokenId);

        emit IPPurchased(tokenId, _ip.ipDescription, msg.value, _ip.owner, _ip.category);
    }

The purchaseIP() function allows a user to purchase an IP, provided it hasn’t been purchased already and the correct amount of Celo is sent. The purchase amount is transferred to the previous owner, and ownership of the token (and thus, the IP) is transferred to the buyer. Then it updates the purchased flag in the ips mapping and emits an IPPurchased event.

Update IP Function

 function updateIP(uint tokenId, string memory _description, uint256 _price, Category _category) public {
        IP memory _ip = ips[tokenId];
        require(_ip.owner == msg.sender, "Only owner can update the IP");
        _ip.ipDescription = _description;
        _ip.price = _price;
        _ip.category = _category;
        ips[tokenId] = _ip;
    }

The updateIP() function allows the owner of an IP to update its details, such as the description, price, and category. Before making these changes, it checks that the sender is the current owner of the IP.

Delete IP Function

  function deleteIP(uint tokenId) public {
        IP memory _ip = ips[tokenId];
        require(_ip.owner == msg.sender, "Only owner can delete the IP");
        delete ips[tokenId];
        _burn(tokenId);
    }

The deleteIP() function allows the owner of an IP to delete it. Before deletion, it checks that the sender is the current owner of the IP. Then, it removes the IP struct from the ips mapping and burns the associated token, effectively removing it from circulation.

Deployment

To deploy our smart contract successfully, we need the celo extention wallet which can be downloaded from here

Next, we need to fund our newly created wallet which can done using the celo alfojares faucet Here

Now, click on the plugin logo at the bottom left corner and search for celo plugin.

Install the plugin and click on the celo logo which will show in the side tab after the plugin is installed.

Next connect your Celo wallet, select the contract you want to deploy and finally click on deploy to deploy your contract.

Conclusion

Congratulations! You’ve reached the end of this tutorial. I hope this detailed walkthrough of the IPManagement smart contract gave you a clear understanding of how blockchain technology can be used to manage intellectual property rights. By now, you should have a solid grasp on how the contract functions, how ERC721 tokens are used to represent unique intellectual properties, and how ownership and transfers of these tokens map to the ownership and sales of IPs.

Next Steps

I hope you learned a lot from this tutorial. Here are some relevant links that would aid your learning further.

About the author

I’m Jonathan Iheme, A full stack block-chain Developer from Nigeria.

linkedIn
Twitter

9 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:

4 Likes

I will be reviewing this

1 Like

@ishan.pathak2711 still waiting

@ishan.pathak2711 it’s over 2days now

1 Like

I was busy with final term exams but fortunately it ended today ,sorry for being late

1 Like

Alright…wish u success

1 Like

This is a good one @4undRaiser

1 Like

Great tutorial! I found the step-by-step breakdown of the IPManagement smart contract very helpful. The code is clear and well-explained, making it easy to follow along. I appreciate the use of OpenZeppelin contracts for ERC721 functionality and ownership control. One suggestion I have is to include more details about the deployment process, such as how to set up the development environment and interact with the contract using Remix. Overall, excellent work, and I look forward to more tutorials from the Celo Academy!

2 Likes

Your tutorial not only equips developers with the necessary tools but also highlights the potential of decentralized solutions in transforming the current landscape of IP management. Well done on providing a clear and concise guide that opens up exciting possibilities for innovation and protection of creative works on the Celo blockchain. Great job!