ERC721の図書館システム

# 全体コード
```solidity:ERC721LibrarySystem.sol
pragma solidity ^0.4.25;

import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol";

contract Sample721 is ERC721Full, ERC721Mintable {
  using SafeMath for uint256;
 
  uint256 totalNumberOfBooks;
  uint256 totalNumberOfBorrowers;
  uint256 currentNumberOfBorrowers;

  struct bookDetails {  
    uint256 id;
    string titleOfBook;
    bool isBorrowed;
  } mapping (uint256 => bookDetails) books;
  
  constructor() ERC721Full("Binsu", "BS2") public {
    totalNumberOfBooks = 0;
    totalNumberOfBorrowers = 0;
    currentNumberOfBorrowers = 0;
  }
  
  function addBooks(string title) public {
    totalNumberOfBooks+=1;
    books[totalNumberOfBooks] = bookDetails(totalNumberOfBooks, title, false);
  }
  
  function borrowBook(uint256 bookID) public {
    require(books[bookID].isBorrowed == false);
    require(currentNumberOfBorrowers < totalNumberOfBooks);
    
    totalNumberOfBorrowers+=1;
    currentNumberOfBorrowers+=1;
    
    mint(msg.sender, bookID);
    books[bookID].isBorrowed = true;
  }
  
  function returnBook(uint256 bookID) public {
    require(books[bookID].isBorrowed == true);
    require(getTheCurrentBorrower(bookID) == msg.sender);
    _removeTokenFrom(msg.sender, bookID);
    currentNumberOfBorrowers-=1;
    books[bookID].isBorrowed = false;
  }
  
  function getTotalNumberOfBooks() public constant returns (uint256) {
    return totalNumberOfBooks;
  }

  function getCurrentNumberOfBorrowers() public constant returns (uint256) {
    return currentNumberOfBorrowers;
  }
  
  function getTheCurrentBorrower(uint256 bookID) public constant returns (address) {
    return ownerOf(bookID);
  }
  
  function checkNumberOfBooksBorrowedByBorrower() public constant returns (uint256) {
    return balanceOf(msg.sender);
  }
}
```
このコードは、ERC721テンプレートを使用してライブラリシステムを作成した方法を示しています。 ERC721Mintable.solとSafeMath.solとERC721Full.solをGithubからインポートする必要があります。また、ERC721Mintable.solとSafeMath.solをContractで拡張する必要があります。

## 変数を初期化します
```
  uint256 totalNumberOfBooks;
  uint256 totalNumberOfBorrowers;
  uint256 currentNumberOfBorrowers;

  struct bookDetails {  
    uint256 id;
    string titleOfBook;
    bool isBorrowed;
  } mapping (uint256 => bookDetails) books;
  
  constructor() ERC721Full("Binsu", "BS2") public {
    totalNumberOfBooks = 0;
    totalNumberOfBorrowers = 0;
    currentNumberOfBorrowers = 0;
  }
```
この例では、totalNumberOfBooksとtotalNumberOfBorrowersとcurrentNumberOfBorrowersを知る必要があります。これはロジスティクスのためのものです。次は、本のデータ構造を作ることです。IDとtitleとbooleanを含んでいます。次に、本のためのマップストレージを作成します。最後にコンストラクタ内の変数を初期化することです。
## アクション関数
```
  function addBooks(string title) public {
    totalNumberOfBooks+=1;
    books[totalNumberOfBooks] = bookDetails(totalNumberOfBooks, title, false);
  }
  
  function borrowBook(uint256 bookID) public {
    require(books[bookID].isBorrowed == false);
    require(currentNumberOfBorrowers < totalNumberOfBooks);
    
    totalNumberOfBorrowers+=1;
    currentNumberOfBorrowers+=1;
    
    mint(msg.sender, bookID);
    books[bookID].isBorrowed = true;
  }
  
  function returnBook(uint256 bookID) public {
    require(books[bookID].isBorrowed == true);
    require(getTheCurrentBorrower(bookID) == msg.sender);
    _removeTokenFrom(msg.sender, bookID);
    currentNumberOfBorrowers-=1;
    books[bookID].isBorrowed = false;
  }
  
  function getTotalNumberOfBooks() public constant returns (uint256) {
    return totalNumberOfBooks;
  }

  function getCurrentNumberOfBorrowers() public constant returns (uint256) {
    return currentNumberOfBorrowers;
  }
  
  function getTheCurrentBorrower(uint256 bookID) public constant returns (address) {
    return ownerOf(bookID);
  }
  
  function checkNumberOfBooksBorrowedByBorrower() public constant returns (uint256) {
    return balanceOf(msg.sender);
  }
```
最後の部分はアクション関数です。 私たちはこの機能を使って本を作りと本を借りて本を返しと何本の本が作られたかを見てと何人が本を借りているのかを見てと誰が特定の本を借りているのかを見ます。

ソース:
https://github.com/OpenZeppelin/openzeppelin-solidity
https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Full.sol
https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Mintable.sol