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 version0.8.17
.contract Library {
: This declares a new Solidity contract calledLibrary
.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 calledBook
as a struct.// this struct will store the details of the book
: This is a comment that describes the purpose of theBook
struct.uint256 id;
: This declares an unsigned integer variable calledid
to store the book ID.string name;
: This declares a string variable calledname
to store the book title.string author;
: This declares a string variable calledauthor
to store the name of the book author.uint256 year;
: This declares an unsigned integer variable calledyear
to store the publication year of the book.bool isFinished;
: This declares a boolean variable calledisFinished
to store whether the book has been finished or not.}
: This closes theBook
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 ofBook
structs calledbooks
. This array will store all the books added to the library.mapping(uint256 =>address) public bookToOwner;
: This declares a public mapping calledbookToOwner
that maps a book ID (represented as auint256
) 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 thebookToOwner
mapping.event AddBook( address, uint);
: This declares a new event calledAddBook
that takes in two arguments: an address (representing the person who added the book) and auint
(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 calledaddBook
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), andfinished
(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 theaddBook
function.books.push(Book(books.length, _name, _author, _year,finished));
: This line creates a newBook
struct with the given parameters and adds it to the end of thebooks
array. Thebooks.length
parameter represents the ID of the book (since IDs start at 0 and are assigned sequentially as books are added to the library), andfinished
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 thebookToOwner
mapping for the new book to the address of the person who added the book (which is stored inmsg.sender
).emit AddBook(msg.sender, books.length-1);
: This line emits anAddBook
event with two arguments:msg.sender
(representing the address of the person who added the book) andbooks.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 namedresult
with a length equal to the length of thebooks
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 (themsg.sender
).If the book satisfies the above conditions, it is added to the
result
array at the index specified by thecounter
variable and thecounter
is incremented.After the loop ends, a new dynamic array of
Book
structures namedresult2
is created with a length equal tocounter
.Another loop is started that iterates through the first
counter
elements of theresult
array and copies them into theresult2
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 parameterfalse
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 argumenttrue
._getBooks
is a helper function that returns an array ofBook
structs which are either finished or unfinished based on the value of thefinished
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 theisFinished
status of a book identified bybookId
tofinished
.The function takes two parameters:
bookId
of typeuint
andfinished
of typebool
.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 thebooks
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 specifiedbookId
is set to the value offinished
.
Github Code
Click here to access the smart contracts repo, I will be adding more contracts frequently