Help us understand the problem. What is going on with this article?

ERC-721で簡単な図書館システムを作っていること

More than 1 year has passed since last update.

今日、ERC-721で簡単な図書館システムを作りました。Ropstenのテストネット上でこのスマートコントラクトを作りました。

ERC-20 vs. ERC-721トークン基準

ERC-20トークン基準は暗号柄を作るに使っているだけ。ERC-20トークン基準とは異なり、ERC-721トークン基準は様々資産を管理できます。例えば、CryptoKittiesはERC-721トークン基準で資産を管理しています。

コード

libraryContractNFT.sol
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; 
    }
}

このコードは単純な図書館システム。本を付け加えれて借りれて返​せ​るにできます。

スタート

libraryContractNFT.sol
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関数

libraryContractNFT.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;
    }
    ...
}

このスマートコントラクトはOpenZeppelinのERC-720 Token Implementationに相続しています。

Constructor関数に様々な価値を定義しています。例えば、トークンの名前や記号です。I am also set as the contractCreator, where all books will be stored if not borrowed by anyone.

基本的な関数

libraryContractNFT.sol
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.

補足

libraryContractNFT.sol
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)にこのスマートコントラクトを見れます。

もっと読む:

sbenemerito
日本語を勉強中の留学生。自らの技術力の向上に関心を持つ、ウェブ開発とシステムの自動化、変化を恐れないエンジニア。主に Python、Javascript 使い。
bit-okutama
外国人ITエンジニア育成を目的とした日本語学校です
http://bit-okutama.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away