Create Library Management Smart Contract

Create Library Management Smart Contract

Learn how to create library management smart contract step by step

Library Management Smart contract

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
contract Library {
    constructor() {

    }
    struct Book {
        // this struct will store the details of the book
        uint256 id;
        string name;
        string author;
        uint256 year;
        bool isFinished;
    }

    Book[] private books;

    mapping(uint256 =>address) public bookToOwner; 
// this mapping will map the book id to the owner address


    event AddBook( address, uint);


    function addBook(string memory _name, string memory _author, uint256 _year,bool finished) external {
        //  this function will add a book to the library
        books.push(Book(books.length, _name, _author, _year,finished));
        bookToOwner[books.length-1] = msg.sender;
        emit AddBook(msg.sender, books.length-1);
    }

    function _getBooks(bool finished) private view returns(Book[] memory) {
        //  this function will return all the books in the library
        Book[] memory result = new Book[](books.length);
        uint256 counter = 0;
        for(uint256 i = 0; i < books.length; i++) {
            if(books[i].isFinished == finished && bookToOwner[i] == msg.sender) {
                result[counter] = books[i];
                counter++;
            }
        }
        Book[] memory result2 = new Book[](counter);
        for(uint256 i = 0; i < counter; i++) {
            result2[i] = result[i];
        }
        return result2;
    }

    function getUnfinishedBooks() external view returns(Book[] memory) {
        //  this function will return all the books in the library which are not finished   
        return _getBooks(false);
    }

    function getFinishedBooks() external view returns(Book[] memory) {
        // this function will return all the books in the library which are finished
        return _getBooks(true);
    }


    function setFinished( uint bookId, bool finished ) external {
        // this function will set the finished status of a book
        require(bookId < books.length, "Book does not exist");
        require(bookToOwner[bookId] == msg.sender, "You are not the owner of this book");
        books[bookId].isFinished = finished;
    }

}

Smart Contract Explanation and Breakdown

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
contract Library {
    constructor() {

    }
  • // SPDX-License-Identifier: UNLICENSED: This is a comment in the Solidity code that specifies the license under which the code is released.

  • pragma solidity 0.8.17;: This statement specifies the version of the Solidity compiler to use when compiling the contract. In this case, it specifies the version 0.8.17.

  • contract Library {: This declares a new Solidity contract called Library.

  • constructor() {: This is the constructor function of the contract. Since it's empty, it doesn't do anything when the contract is deployed.

  • }: This closes the constructor function.

  • }: This closes the contract.

 struct Book {
        // this struct will store the details of the book
        uint256 id;
        string name;
        string author;
        uint256 year;
        bool isFinished;
    }
  • struct Book {: This declares a new custom data type called Book as a struct.

  • // this struct will store the details of the book: This is a comment that describes the purpose of the Book struct.

  • uint256 id;: This declares an unsigned integer variable called id to store the book ID.

  • string name;: This declares a string variable called name to store the book title.

  • string author;: This declares a string variable called author to store the name of the book author.

  • uint256 year;: This declares an unsigned integer variable called year to store the publication year of the book.

  • bool isFinished;: This declares a boolean variable called isFinished to store whether the book has been finished or not.

  • }: This closes the Book struct definition.

    Book[] private books;

    mapping(uint256 =>address) public bookToOwner; 
// this mapping will map the book id to the owner address


    event AddBook( address, uint);
  • Book[] private books;: This declares a private dynamic array of Book structs called books. This array will store all the books added to the library.

  • mapping(uint256 =>address) public bookToOwner;: This declares a public mapping called bookToOwner that maps a book ID (represented as a uint256) to the address of the person who added the book to the library. This is used to keep track of who owns which book.

  • // this mapping will map the book id to the owner address: This is a comment that describes the purpose of the bookToOwner mapping.

  • event AddBook( address, uint);: This declares a new event called AddBook that takes in two arguments: an address (representing the person who added the book) and a uint (representing the book ID). This event will be emitted every time a new book is added to the library, and can be used by external contracts to monitor changes to the library.

    function addBook(string memory _name, string memory _author, uint256 _year,bool finished) external {
        //  this function will add a book to the library
        books.push(Book(books.length, _name, _author, _year,finished));
        bookToOwner[books.length-1] = msg.sender;
        emit AddBook(msg.sender, books.length-1);
    }
  • function addBook(string memory _name, string memory _author, uint256 _year,bool finished) external {: This declares a function called addBook that takes in four arguments: _name (a string representing the name of the book), _author (a string representing the name of the book's author), _year (an unsigned integer representing the year the book was published), and finished (a boolean value representing whether or not the book has been finished).

  • // this function will add a book to the library: This is a comment that describes the purpose of the addBook function.

  • books.push(Book(books.length, _name, _author, _year,finished));: This line creates a new Book struct with the given parameters and adds it to the end of the books array. The books.length parameter represents the ID of the book (since IDs start at 0 and are assigned sequentially as books are added to the library), and finished represents whether or not the book has been finished. The other parameters represent the name of the book, the author of the book, and the year the book was published.

  • bookToOwner[books.length-1] = msg.sender;: This line sets the value of the bookToOwner mapping for the new book to the address of the person who added the book (which is stored in msg.sender).

  • emit AddBook(msg.sender, books.length-1);: This line emits an AddBook event with two arguments: msg.sender (representing the address of the person who added the book) and books.length-1 (representing the ID of the new book). This allows external contracts to monitor changes to the library.

 function _getBooks(bool finished) private view returns(Book[] memory) {
        //  this function will return all the books in the library
        Book[] memory result = new Book[](books.length);
        uint256 counter = 0;
        for(uint256 i = 0; i < books.length; i++) {
            if(books[i].isFinished == finished && bookToOwner[i] == msg.sender) {
                result[counter] = books[i];
                counter++;
            }
        }
        Book[] memory result2 = new Book[](counter);
        for(uint256 i = 0; i < counter; i++) {
            result2[i] = result[i];
        }
        return result2;
    }
  • _getBooks is a private function, meaning that it can only be called within the contract and not from outside.

  • The function takes a boolean parameter named finished, which indicates whether to return the books that are finished or unfinished.

  • The function creates a new dynamic array of Book structures named result with a length equal to the length of the books array.

  • A counter variable named counter is initialized to 0.

  • A loop is started that iterates through all the books in the books array and checks if the book is finished and is owned by the caller (the msg.sender).

  • If the book satisfies the above conditions, it is added to the result array at the index specified by the counter variable and the counter is incremented.

  • After the loop ends, a new dynamic array of Book structures named result2 is created with a length equal to counter.

  • Another loop is started that iterates through the first counter elements of the result array and copies them into the result2 array.

  • Finally, the function returns the result2 array that contains only the books that satisfy the specified conditions.

   function getUnfinishedBooks() external view returns(Book[] memory) {
        //  this function will return all the books in the library which are not finished   
        return _getBooks(false);
    }

This part of the code defines a function named getUnfinishedBooks that:

  • Is publicly accessible (with external modifier).

  • Returns an array of Book structs wrapped in a dynamic memory array.

  • Calls the _getBooks function with the parameter false which retrieves books that are not finished.

  • Returns the array of books retrieved from _getBooks.

  • Does not modify any state variables.

Therefore, this function allows anyone to view the books in the library that are not finished, without modifying the state of the contract.

    function getFinishedBooks() external view returns(Book[] memory) {
        // this function will return all the books in the library which are finished
        return _getBooks(true);
    }

This code defines a function called getFinishedBooks which has the following properties:

  • It is a public function that can be called from outside the contract.

  • It takes no arguments.

  • It returns an array of Book structs.

  • It uses the view modifier, which indicates that the function will not modify the state of the contract.

  • The function calls the private _getBooks function with the argument true.

  • _getBooks is a helper function that returns an array of Book structs which are either finished or unfinished based on the value of the finished parameter.

  • The true argument passed to _getBooks indicates that only books which are marked as finished will be returned.

  • The function returns an array of Book structs containing all books in the library that are marked as finished.

    function setFinished( uint bookId, bool finished ) external {
        // this function will set the finished status of a book
        require(bookId < books.length, "Book does not exist");
        require(bookToOwner[bookId] == msg.sender, "You are not the owner of this book");
        books[bookId].isFinished = finished;
    }

}
  • The setFinished function sets the isFinished status of a book identified by bookId to finished.

  • The function takes two parameters: bookId of type uint and finished of type bool.

  • The function is defined as external, which means that it can be called from outside the contract by other contracts or user wallets.

  • The require statements enforce two conditions that must be met before the function can execute successfully. If either of these conditions is false, the function will revert and any changes made will be reverted as well:

    • bookId < books.length ensures that the book exists in the books array.

    • bookToOwner[bookId] == msg.sender ensures that the caller of the function is the owner of the book.

  • If the conditions are met, the isFinished property of the book at the specified bookId is set to the value of finished.

Github Code

Click here to access the smart contracts repo, I will be adding more contracts frequently