今日、ERC-721で簡単な図書館システムを作りました。Ropstenのテストネット上でこのスマートコントラクトを作りました。
ERC-20 vs. ERC-721トークン基準
ERC-20トークン基準は暗号柄を作るに使っているだけ。ERC-20トークン基準とは異なり、ERC-721トークン基準は様々資産を管理できます。例えば、CryptoKittiesはERC-721トークン基準で資産を管理しています。
コード
pragma solidity ^0.4.25;
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/access/roles/MinterRole.sol";
contract LibraryNFT is ERC721Full, MinterRole {
    struct Book {
        uint256 id;
        string title;
        string author;
    }
    Book[] private bookCollection;
    address private _contractCreator;
    mapping(address => uint8) private _borrowedCount;
    constructor() ERC721Full("LibraryNFT", "LIB") public {
        _contractCreator = msg.sender;
    }
    function moveBook(address _from, address _to, uint256 _tokenId) private {
        require(_to != address(0));
        super._clearApproval(_from, _tokenId);
        super._removeTokenFrom(_from, _tokenId);
        super._addTokenTo(_to, _tokenId);
        emit Transfer(_from, _to, _tokenId);
    }
    function addBook(string _title, string _author) public onlyMinter returns (bool) {
        super._mint(_contractCreator, bookCollection.length+1);
        bookCollection.push(Book(bookCollection.length+1, _title, _author));
        return true;
    }
    function borrowBook(uint256 _bookId) public {
        require(_borrowedCount[msg.sender] < 5);
        require(super.ownerOf(_bookId) == _contractCreator);
        moveBook(super.ownerOf(_bookId), msg.sender, _bookId);
        _borrowedCount[msg.sender]++;
    }
    function returnBook(uint256 _bookId) public {
        moveBook(msg.sender, _contractCreator, _bookId);
        _borrowedCount[msg.sender]--;
    }
    
    function getBookTitle(uint256 _bookId) public view returns (string) {
        return bookCollection[_bookId-1].title; 
    }
    
    function getBookAuthor(uint256 _bookId) public view returns (string) {
        return bookCollection[_bookId-1].author; 
    }
}
このコードは単純な図書館システム。本を付け加えれて借りれて返せるにできます。
スタート
pragma solidity ^0.4.25;
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/access/roles/MinterRole.sol";
最初の行にSolidityのバージョンを入れます。次、we import OpenZeppelin's ERC-721 Token implementation, and MinterRole to determine who is able to mint new tokens. In this case, this is equivalent to adding new books.
Constructor関数
contract LibraryNFT is ERC721Full, MinterRole {
    struct Book {
        uint256 id;
        string title;
        string author;
    }
    Book[] private bookCollection;
    address private _contractCreator;
    mapping(address => uint8) private _borrowedCount;
    constructor() ERC721Full("LibraryNFT", "LIB") public {
        _contractCreator = msg.sender;
    }
    ...
}
このスマートコントラクトはOpenZeppelinのERC-720 Token Implementationに相続しています。
Constructor関数に様々な価値を定義しています。例えば、トークンの名前や記号です。I am also set as the contractCreator, where all books will be stored if not borrowed by anyone.
基本的な関数
pragma solidity ^0.4.25;
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/access/roles/MinterRole.sol";
contract LibraryNFT is ERC721Full, MinterRole {
    ...
    function moveBook(address _from, address _to, uint256 _tokenId) private {
        require(_to != address(0));
        super._clearApproval(_from, _tokenId);
        super._removeTokenFrom(_from, _tokenId);
        super._addTokenTo(_to, _tokenId);
        emit Transfer(_from, _to, _tokenId);
    }
    function addBook(string _title, string _author) public onlyMinter returns (bool) {
        super._mint(_contractCreator, bookCollection.length+1);
        bookCollection.push(Book(bookCollection.length+1, _title, _author));
        return true;
    }
    function borrowBook(uint256 _bookId) public {
        require(_borrowedCount[msg.sender] < 5);
        require(super.ownerOf(_bookId) == _contractCreator);
        moveBook(super.ownerOf(_bookId), msg.sender, _bookId);
        _borrowedCount[msg.sender]++;
    }
    function returnBook(uint256 _bookId) public {
        moveBook(msg.sender, _contractCreator, _bookId);
        _borrowedCount[msg.sender]--;
    }
}
Here are the required functions for the 図書館システム. First, I made my own implementation of transferTo, because I had to disregard the owner of the book. Then, we have functions to enable the adding, borrowing, and returning of books. A user is limited to borrowing only up to 5 books.
補足
contract LibraryNFT is ERC721Full, MinterRole {
    ...
    function getBookTitle(uint256 _bookId) public view returns (string) {
        return bookCollection[_bookId-1].title; 
    }
    
    function getBookAuthor(uint256 _bookId) public view returns (string) {
        return bookCollection[_bookId-1].author; 
    }
}
この補足の関数は「本の作家はだれですか?」と「本のタイトルは何ですか?」という質問に答えるものです。
Contract Address (0x21d069a5c270fa892897a2b9ad4be6d24f989ebe)にこのスマートコントラクトを見れます。
もっと読む: