Created
October 27, 2021 11:27
-
-
Save batyanko/cd65d3ea3d3036d2019b2a05a259a032 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.7+commit.e28d00a7.js&optimize=false&runs=200&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.0; | |
import "./Ownable.sol"; | |
contract Library is Ownable { | |
uint8 private constant NEVER_BORROWED = 0; // Default value. | |
uint8 private constant BORROWED_NOW = 1; | |
uint8 private constant BORROWED_BEFORE = 2; | |
mapping(uint => mapping(address => uint)) private isbnUserStatus; | |
mapping(uint => address[]) private allTimeBorrowers; | |
mapping(uint => uint) private bookAvailability; | |
mapping(uint => bool) private booksExisting; // Keep this mapping to avoid looping below list; | |
uint[] private books = [0]; // Reserve placeholder for book '0'; | |
function addBook(uint isbn13, uint count) public onlyOwner { | |
// TODO Verify validity of ISBN-13. | |
// Register existence if book is new. | |
if (!booksExisting[isbn13]) { | |
books.push(isbn13); | |
booksExisting[isbn13] = true; | |
} | |
bookAvailability[isbn13] += count; | |
} | |
function alreadyBorrowed(uint isbn13) private view returns(bool) { | |
return isbnUserStatus[isbn13][msg.sender] == BORROWED_NOW; | |
} | |
function copiesAvailable(uint isbn13) private view returns(bool) { | |
return bookAvailability[isbn13] > 0; | |
} | |
modifier canBorrow(uint isbn13) { | |
require(!alreadyBorrowed(isbn13), "Book already borrowed by user"); | |
require(copiesAvailable(isbn13), "Book is not available"); | |
_; | |
} | |
// TODO count cost of returning storage. | |
// Excluding unborrowable books by current user. | |
function viewBooks() public view returns(uint[] memory) { | |
uint[] memory result = new uint[](books.length); | |
uint count; | |
for (uint i = 1; i < books.length; i++) { | |
if (!alreadyBorrowed(books[i]) && copiesAvailable(books[i])) { | |
result[count] = books[i]; | |
count++; | |
} | |
} | |
// TODO Look for cheaper way than looping twice. | |
uint[] memory finalResult = new uint[](count); | |
for (uint i = 0; i < count; i++) { | |
finalResult[i] = result[i]; | |
} | |
return finalResult; | |
} | |
function borrowBook(uint isbn13) public canBorrow(isbn13) { | |
if (isbnUserStatus[isbn13][msg.sender] == NEVER_BORROWED) { | |
allTimeBorrowers[isbn13].push(msg.sender); | |
} | |
isbnUserStatus[isbn13][msg.sender] = BORROWED_NOW; | |
bookAvailability[isbn13]--; | |
} | |
function returnBook(uint isbn13) public { | |
require(isbnUserStatus[isbn13][msg.sender] == BORROWED_NOW, "Nothing to return"); | |
isbnUserStatus[isbn13][msg.sender] = BORROWED_BEFORE; | |
bookAvailability[isbn13]++; | |
} | |
function borrowHistory(uint isbn13) public view returns(address[] memory) { | |
return allTimeBorrowers[isbn13]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment