Skip to content

Instantly share code, notes, and snippets.

@batyanko
Created October 27, 2021 11:27
Show Gist options
  • Save batyanko/cd65d3ea3d3036d2019b2a05a259a032 to your computer and use it in GitHub Desktop.
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=
// 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