文書の過去の版を表示しています。
目次
OpenZeppelin で ERC721(NFT) トークンの作成
ほぼ OpenZeppelin オフィシャルのドキュメント通りに NFT スマートコントラクトを実装します。
今回作成する GameItem NFT は NFT の所有者とtokenURIを保持するように実装されています。
tokenURI は NFT を生成する際に指定されます。その指定された URI の所有者を NFT で記録しているということになります。 URI はブロックチェーンの外にありますので、所有者が所有する物はブロックチェーンの外にあることになります。このようなデータを「オフチェーン」と呼びます。逆に、所有する物もブロックチェーン上に記録することを「オンチェーン」と呼びます。
前提
Truffle と npm をインストールしておいてください。
プロジェクト作成
> mkdir nft_project > cd nft_project nft_project> truffle init
Truffleを使ったスマートコントラクト開発 を参考に truffle-config.js の設定をしてください。(どの ethereum ブロックチェーンに接続するか設定する必要があります。)
OpenZeppelin のインストール
npm を使用して OpenZeppelin をインストールします。
nft_project> npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help init` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (nft_project) version: (1.0.0) description: entry point: (truffle-config.js) test command: git repository: keywords: author: license: (ISC) About to write to C:\Users\miyazato\work\ethereum\nft_project\package.json: { "name": "nft_project", "version": "1.0.0", "description": "", "main": "truffle-config.js", "directories": { "test": "test" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } Is this OK? (yes) nft_project> npm install --save-dev @openzeppelin/contracts
NFTの実装
nft_project> truffle create contract GameItem nft_project> code contracts/GameItem.sol
// contracts/GameItem.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "../node_modules/@openzeppelin/contracts/utils/Counters.sol"; contract GameItem is ERC721URIStorage { using Counters for Counters.Counter; Counters.Counter private _tokenIds; constructor() ERC722("GameItem", "ITM") {} function awardItem(address player, string memory tokenURI) public returns (uint256) { uint256 newItemId = _tokenIds.current(); _mint(player, newItemId); _setTokenURI(newItemId, tokenURI); _tokenIds.increment(); return newItemId; } }
マイグレーション
nft_project> truffle create migration GameItem nft_project> code .\migrations\1651959757_game_item.js
const GameItem = artifacts.require("GameItem"); module.exports = function(_deployer) { // Use deployer to state migration tasks. _deployer.deploy(GameItem) };
デプロイ
nft_project> truffle migrate
実行(Mint)
今回作成したスマートコントラクトの awardItem を実行すると、新しい NFT が生成されます。 新たな NFT を生成することを Mint と言います。実際 awardItem のソースコードでは「_mint(player, newItemId);」と _mint メソッドを呼び出しています。 Mint は英語の「Minting 鋳造(ちゅうぞう)」から来ています。(例: minting authority 造幣局)
nft_project> truffle console truffle(development)> let gameItem = await GameItem.deployed(); truffle(development)> let address = await web3.eth.getAccounts(); truffle(development)> let playerAddress = address[0]; truffle(development)> gameItem.awardItem(playerAddress, "https://game.example/item-id-8u5h2m.json"); { tx: '0xf32a1d6dd67167b16537ddc0308cdd5918773aca77f91438be056adf38a212bf', receipt: { transactionHash: '0xf32a1d6dd67167b16537ddc0308cdd5918773aca77f91438be056adf38a212bf', transactionIndex: 0, blockHash: '0x3c932e396c46e28469fa2db720481e5d1814a624061429bd5eab1a135c0382ff', blockNumber: 5, from: '0x9384fc1b3f3cc59e6e30a0ba0267451570bb7aa6', to: '0x36c73d181564e2bc7ef390f7067ffabf4c23d535', gasUsed: 153238, cumulativeGasUsed: 153238, contractAddress: null, logs: [ [Object] ], status: true, logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000008000000000000000000000000000000000020000000000002000000000000000000000000000000000000000000000000040020000000100000000000000000000000000000000000000000000000000000000000', rawLogs: [ [Object] ] }, logs: [ { logIndex: 0, transactionIndex: 0, transactionHash: '0xf32a1d6dd67167b16537ddc0308cdd5918773aca77f91438be056adf38a212bf', blockHash: '0x3c932e396c46e28469fa2db720481e5d1814a624061429bd5eab1a135c0382ff', blockNumber: 5, address: '0x36c73D181564e2BC7Ef390F7067FfABf4C23d535', type: 'mined', id: 'log_ca6a0b3b', event: 'Transfer', args: [Result] } ] }
Mint した1つめの NFT (TOKENID が 0)の所有者と NFT に保存されている tokenURI を確認します。
truffle(development)> gameItem.ownerOf(0) '0x9384FC1B3F3CC59e6e30a0BA0267451570bb7AA6' truffle(development)> gameItem.tokenURI(0) 'https://game.example/item-id-8u5h2m.json'