NFTを発行する独自コントラクトをInfuraのテストネット(Ropsten)にデプロイする
割と日本語のブロックチェーン関連の記事がないので、書いてみました。
この記事では、solidityで独自コントラクトを作成し、テストネットにデプロイまでを行います。
NFTとは
代替不可能なトークンのことです。
ERC721という規格で定められたinterfaceが実装されている=NFTと考えてもらって大丈夫です。
ちなみに代替可能トークンはFTって呼ばれます。
具体的には、以下のinterfaceで定義されているfunctionが実装されていればNFTです。
interface ERC721{
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
これ全部実装するのはキツいので、今回はopenzeppelin
というツールを使って実装をしていきます。
必要なもの
- Node
- Infuraのアカウント
- dappsの情報処理をイーサリアムブロックチェーン上で可能にするホスティングサービス。
-
https://infura.io/
- 無料で使えます!
参考になるリンク
出来上がり
以下リポジトリにデプロイまで行ったコードを入れてあります。
https://github.com/tkyatg/hardhat-nft-example
プロジェクト作成
hardhat
という、スマートコントラクを作るツールを使います。
有名なものだとtruffle
などがありますが
新しいバージョンのtruffle
は不具合があったり、使いにくいなどが理由で
hardhat
が流行っている印象があります。
以下コマンドを実行して空のプロジェクトを作成します。
npm init --yes
npm install --save-dev hardhat
npm install @openzeppelin/contracts web3
npx hardhat
hardhatのプロジェクト作成時、質問は基本yesで、プロジェクトタイプはCreate a basic sample project
を選びました。
スマートコントラクト実装
次にNFTを作成するスマコン実装をします。
contracts/Greeter.sol
を削除して、contracts/Nft.sol
を作成して、以下の内容を書きます。
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract Nft is ERC721, ERC721URIStorage, ERC721Enumerable, ReentrancyGuard {
uint256 private latestTokenId = 1;
constructor(string memory name, string memory symbol)
ERC721(name, symbol)
{}
function mint(string memory _tokenURI) public {
uint256 tokenId = latestTokenId;
_mint(msg.sender, tokenId);
_setTokenURI(tokenId, _tokenURI);
latestTokenId++;
}
function _burn(uint256 tokenId)
internal
override(ERC721, ERC721URIStorage)
{
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
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)
returns (bool)
{
return super.supportsInterface(_interfaceId);
}
}
openzeppelin
のERC721
を継承することで、既にNFTと言っても過言ではないです。
(openzeppelinがNFTに必要なメソッドの実装までしてくれているためです。)
さらに便利なスマコンにするためにERC721URIStorage
とERC721Enumerable
, ReentrancyGuard
も継承します。
継承したERC721の内部実装が気になる方はGit
で確認を。
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol
今回はNFTを作成するファンクションmint
を実装しています。
mint以外のfunctionは継承元を呼んでいるだけです。
本来であれば単体テストを書くべきですが、めんどくさいので今回はスキップ。
デプロイ用スクリプトを修正
scripts/sample-script.js
を削除して、scripts/deploy.js
を作成し、以下のように編集します。
const { ethers } = require("hardhat");
async function main() {
const Nft = await ethers.getContractFactory("Nft");
const nft = await Nft.deploy("name", "symbol");
await nft.deployed();
console.log("Nft deployed to:", nft.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
デプロイ用の環境作成
infura
アカウントを作成し、プロジェクト作成してください。
ethereumのテストネットであれば、上限はありますが無料で使えます。
https://infura.io/dashboard
プロジェクト作成すると、以下のような画面が出てきます。
ENDPOINT
をROPSTEN
に変えて、https://ropsten.infura.io/v3/...
のリンクをコピーしておいてください。後で使います。
hardhat.config.jsの修正をして、デプロイ先をinfuraに向ける
metamask
のprivate key
を取得して、hardhat.config.js
を以下のように書き換えます。
import { HardhatUserConfig } from "hardhat/config";
const config: HardhatUserConfig = {
solidity: "0.8.4",
networks: {
ropsten: {
url: "{先ほどinfuraで取得したURL}",
accounts: ["{metamaskのプライベートキー}"],
},
},
};
export default config;
ちなみにmatamaskのプライベートキーは流失したら終わりです。
絶対にgitにはpushしないこと。
あと、infuraのurlはropstenに切り替えてから取得すること。
メインネットにするとメチェクチャ高くつきます。
テストネットにデプロイ
以下コマンドを実行するだけです。
$ npx hardhat run --network ropsten scripts/deploy.js
Nft deployed to: {デプロイ先のコントラクトアドレス}
少し地味ですが、infuraのコンソールのアクセスボリュームが増えます。
下のようになっていたらデプロイできている(多分)
最後に
次回はデプロイしたコントラクトにフロントアプリから接続してみたいと思います。
twitterのフォローお願いします!
https://twitter.com/takuya_develop
あと定期的に渋谷でブロックチェーンもくもく会やるので、ぜひ参加してください〜。
ブロックチェーンについて語り合いましょう!
https://block-chain.connpass.com/event/236396/
Discussion