ユーザ用ツール

サイト用ツール


blockchain:トレーサビリティを提供するdapps開発

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

次のリビジョン
前のリビジョン
blockchain:トレーサビリティを提供するdapps開発 [2022/05/18 08:51] – 作成 dotblockchain:トレーサビリティを提供するdapps開発 [2022/05/31 04:49] (現在) dot
行 1: 行 1:
 +
 +====== トレーサビリティを提供する DApps ======
 +
 +
 {{:blockchain:traceabilitynft.drawio.png?600|}} {{:blockchain:traceabilitynft.drawio.png?600|}}
 +
 +  * create はERC721.sol の _mint(to), _safeMint(to, tokenId) で実現できる
 +    * _safeMint は誤って NFT の所有者がコントラクトアドレスになることを防ぐ
 +  * deliver は ERC721.sol の transferFrom(from, to, tokenId), safeTransferFrom(from, to, tokenId) で実現できる
 +  * burn は ERC721.sol の burn(tokenId) で実現できる
 +
 +===== 課題 =====
 +
 +
 +  - トレースはどう実現すべきか?
 +    * ブロックチェーンのトランザクションログからトレース?
 +      * 追加で履歴を書き込まないためガス代が安く済むと思われる
 +    * スマートコントラクトに transferFrom の履歴を保持する?
 +      * 追加で履歴を表すデータを書き込むためガス代がかかる
 +  - あるアカウントが所有している NFT を全件取得するには?
 +    * balanceOf(address) で所有する NFT の総数は分かる
 +    * ItemNFT に所有する NFT を全件返すメソッドを実装すれば実現することはできる
 +    * 他に良い方法がないのか?  
 +
 +===== コード =====
 +
 +実装中のコード。
 +
 +ItemNFT.sol
 +
 +<code JavaScript>
 +// SPDX-License-Identifier: MIT
 +pragma solidity >=0.4.22 <0.9.0;
 +
 +import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
 +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
 +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
 +import "@openzeppelin/contracts/access/AccessControl.sol";
 +import "@openzeppelin/contracts/utils/Counters.sol";
 +
 +contract ItemNFT is ERC721, ERC721Enumerable, ERC721Burnable, AccessControl {
 +    using Counters for Counters.Counter;
 +
 +    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
 +    Counters.Counter private _tokenIdCounter;
 +
 +    constructor() ERC721("Item NFT", "INFT") {
 +        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
 +        _grantRole(MINTER_ROLE, msg.sender);
 +    }
 +
 +    function _baseURI() internal pure override returns (string memory) {
 +        return "https://dummy.com/api/v1/tokens/";
 +    }
 +
 +    function safeMint(address to) public onlyRole(MINTER_ROLE) {
 +        uint256 tokenId = _tokenIdCounter.current();
 +        _tokenIdCounter.increment();
 +        _safeMint(to, tokenId);
 +    }
 +
 +    // The following functions are overrides required by Solidity.
 +
 +    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
 +        internal
 +        override(ERC721, ERC721Enumerable)
 +    {
 +        super._beforeTokenTransfer(from, to, tokenId);
 +    }
 +
 +    function supportsInterface(bytes4 interfaceId)
 +        public
 +        view
 +        override(ERC721, ERC721Enumerable, AccessControl)
 +        returns (bool)
 +    {
 +        return super.supportsInterface(interfaceId);
 +    }
 +}
 +</code>
 +
 +ItemNFT.tsx
 +
 +<code JavaScript>
 +import React, { useContext, useState } from "react";
 +import { ItemNFTContext } from "./../hardhat/SymfoniContext";
 +import { SignerContext } from "./../hardhat/SymfoniContext";
 +import { BigNumber } from "ethers";
 +
 +interface Props {}
 +
 +export const ItemNFT: React.FC<Props> = () => {
 +  const ItemNFT = useContext(ItemNFTContext);
 +  const Signer = useContext(SignerContext);
 +  const [address, setAddress] = useState<string>("");
 +  Signer[0]?.getAddress().then((address) => {
 +    setAddress(address);
 +  });
 +  const [tokenId, setTokenId] = useState<BigNumber>();
 +  const [tokenURI, setTokenURI] = useState<string>("");
 +
 +  const handleGetAccounts = async (
 +    e: React.MouseEvent<HTMLButtonElement, MouseEvent>
 +  ) => {
 +    e.preventDefault();
 +    console.log(Signer);
 +  };
 +
 +  const handleSafeMint = async (
 +    e: React.MouseEvent<HTMLButtonElement, MouseEvent>
 +  ) => {
 +    e.preventDefault();
 +    if (!ItemNFT.instance) throw Error("ItemNFT instance not ready");
 +    if (ItemNFT.instance) {
 +      const tx = await ItemNFT.instance.safeMint(address);
 +      const waitLog = await tx.wait();
 +      const event = waitLog.events ? waitLog.events[0] : undefined;
 +      if(event !== undefined){
 +        const _tokenId = event.args ? event.args.tokenId : undefined;
 +        setTokenId(_tokenId);
 +      }
 +    }
 +  };
 +
 +  const handleTokenURI = async (
 +    e: React.MouseEvent<HTMLButtonElement, MouseEvent>
 +  ) => {
 +    e.preventDefault();
 +    if (!ItemNFT.instance) throw Error("ItemNFT instance not ready");
 +    if (ItemNFT.instance) {
 +      if (tokenId !== undefined && tokenId.toNumber() >= 0){
 +        const tokenURI = await ItemNFT.instance.tokenURI(tokenId);
 +        setTokenURI(tokenURI);
 +      }
 +    }
 +  };
 +
 +  return (
 +    <div>
 +      <button onClick={(e) => handleGetAccounts(e)}>GetAccounts</button>
 +      <p>Signer: { address }</p>
 +      <button onClick={(e) => handleSafeMint(e)}>mint</button>
 +      <p>tokenId: { tokenId?.toNumber() }</p>
 +      <button onClick={(e) => handleTokenURI(e)}>get tokenURI</button>
 +      <p>tokenURI: { tokenURI }</p>
 +    </div>
 +  );
 +};
 +</code>
 +
blockchain/トレーサビリティを提供するdapps開発.1652863918.txt.gz · 最終更新: 2022/05/18 08:51 by dot