EIP-721(Ethereum Improvement Proposals), 이더리움 개선 제안 토론이 721번째라는 의미이다. 해당 토론에서 제안된 것으로 EIP-20 토론에서 제안되었던 Fungibal Token과는 성격이다른 Non_Fungible 토큰이 제안되었다.
EIP-20: Token Standard
EIP-721: Non-Fungible Token Standard
Node.js, Ganache-cli 설치되어 있는 상태
npm install @openzeppelin/contracts
npm install -g truffle
mkdir NFT
cd NFT
truffle init // truffle 초기화
npm init // npm 초기화
compilers: {
solc: {
version: '0.8.7',
settings: {
evmVersion: 'london',
},
},
},
1-2 네트워크 설정 networks: {
ganache: {
host: '127.0.0.1',
port: 8545,
network_id: '*',
},
},
NFT/contracts/NFT.sol 작성
해당 코드에 대한 설명은 Ethereum NFT Tutorials에 있습니다.
//Contract based on [https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyNFTs is ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() public ERC721("MyNFTs", "MNFT") {}
function mintNFT(string memory tokenURI)
public onlyOwner
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
NFT/migrations/1_initial_migration.js 파일 수정
const Migrations = artifacts.require('Migrations');
const MyNFTs = artifacts.require('MyNFTs.sol'); // MyNFTs.sol 파일 추가
module.exports = function (deployer) {
deployer.deploy(Migrations);
deployer.deploy(MyNFTs); // MyNFTs를 배포에 추가
};
가나슈(Ganache)란 테스트 목적으로 PC에 설치해서 사용할 수 있는 일종의 간이 블록체인이다. 간이 블록체인이기 때문에 네트워크와 연결할 필요없이 로컬에서 작동시킬 수 있어, 계약을 손쉽게 배포 및 테스트해볼 수 있다.
트러플(Truffle)은 이더리움 기반 디앱을 쉽게 개발할 수 있도록 도와주는 블록체인 프레임워크이다. 스마트 컨트랙트(smart contract) 컴파일, 배포, 관리, 테스트까지 빠르고 쉽게 할 수 있다.
npm install -g ganache-cli
설치가 되지 않을 경우 sudo npm install -g ganache-cli
관리자 권한을 얻은 후 진행해주세요
> anache-cli
Ganache CLI v6.12.2 (ganache-core: 2.13.2)
Available Accounts
==================
(0) 0x81B8f47D611825af4B06F52eeE18D22023856dB0 (100 ETH)
(1) 0x5F898fcaDc9F3055a86822d6c90cec238E31674F (100 ETH)
(2) 0x8cab73C3BE667B3b5951E26B1d368d13C99596e3 (100 ETH)
(3) 0x3f031b5E30d20a7cCf3CCa2683a5c1F2553E4Ce6 (100 ETH)
(4) 0x5c8cC1dd06B8087d2Af6A67566475fbF0d439275 (100 ETH)
(5) 0x567eEB38f06D467e302A82dB6fEE67f976Fb81F7 (100 ETH)
(6) 0xe6bf46a2f1Df3DF184dBF06992dfC8C76989350a (100 ETH)
(7) 0x88F0D240feBc05f6260cF8b222784b5C6a72E932 (100 ETH)
(8) 0xc2CED7c7364C3891B82f964Fe09B992CFB0Ce751 (100 ETH)
(9) 0xFe2ccb8a343Da28f14B1299a46C583C220ADbf13 (100 ETH)
Private Keys
==================
(0) 0x57f53902481dcc3876f39a5640678a6f7e3aa4e7bd08ec48c652846bf9eb2ce5
(1) 0xe18f6c8bd79d6ac0fce1401a90b2037dcbf520c9873567b6100004c514ca1035
(2) 0xe3f8b14f8f314c607a2d1240aedc9782d78d26ceb364309bcb621365d4f91989
(3) 0x5a6626241f62413e07ed7617bf24bba5ae2add590992726c7ac73405cdc4ff8b
(4) 0xcd3d7d29a08cf7cd819f2498dd51d5bdc688ca3f06eccc1ce8a609b57b4a3f95
(5) 0xa1736b191c87885dfee16d5a8c3d58514e8f9e4f5d9d898ed42fb933b2e8216b
(6) 0x3fe897dc89c871826e77fc259c5999a0201cc05c8ccf7fc0ba03320771a9085e
(7) 0x2271e3ae4261d48c392e8c1ab8ba620b366836f10c1093388970c1a4cd89cdf0
(8) 0x71e01977327c39233c63d735ae7ff9422d4e51d990e6be1b773a82c4ec7db33a
(9) 0xff6c18f6d003332184566d3bf8dd606158a4ad5202e01410df8f909c4f9a3ea6
HD Wallet
==================
Mnemonic: seat draft clean light balcony general trim uphold have dinner cargo burst
Base HD Path: m/44'/60'/0'/0/{account_index}
Gas Price
==================
20000000000
Gas Limit
==================
6721975
Call Gas Limit
==================
9007199254740991
Listening on 127.0.0.1:8545
10개의 지갑이 생성된 것을 확인할 수 있습니다.
truffle-config.js 파일과 동일한 경로에서 명령 실행
truffle migrate --compile-all --network ganache
// network 뒤에 나오는 ganache는 앞서 작성한 truffle-config.js의 network에 설정한 부분입니다.
배포를 하기위한 컨트랙트의 Instance를 활용해 컨트랙트 확인
1-1 컨트랙트를 조작하기 위해 truffle 콘솔로 진입합니다.
truffle console --network ganache
1-2 배포하려는 NFT의 이름과 심볼 확인
truffle(ganache)> instance = await MyNFTs.deployed()
undefined
truffle(ganache)> instance.name()
'MyNFTs'
truffle(ganache)> instance.symbol()
'MNFT'
1-3 NFT.sol에서 작성한 mintNFT()를 이용한 컨트랙트 배포
mintNFT의 첫번째 인자값으로 tokenURI를 작성해 넣어줍니다.
두번째 인자값으로는 발행할 계정의 주소를 입력해줍니다. 여기서 accounts[0]은 가나슈로 생성한 10개의 주소 중 첫번째 주소를 의미합니다.
tokenURI는
NFT.STORAGE 해당 주소를 이용해 만들 수 있습니다.
instance.mintNFT("사용자의 TokenURI", { from: accounts[0] })
# Tx Information
NFT.STORAGE에서 회원가입한 후 이미지를 올리게되면
이러한 화면을 만나볼 수 있습니다.
NFT.STORAGE
View URL을 통해 올리고자 한 사진이 올라갔는지 확인 후 메타데이터로 변경해줘야합니다.
새로운 경로에서 작업해주세요
새로운 경로 metadata/
npm init
npm install nft.storage
API Key는 NFT이미지를 업로드한 NFT.Storage에서 받을 수 있습니다.
Name, description, 업로드한 이미지가 있는 파일의 경로 등을 입력해주세요
import { NFTStorage, File } from 'nft.storage';
import fs from 'fs';
const NFT_STORAGE_TOKEN ='API Key'; //API 키입력
const client = new NFTStorage({ token: NFT_STORAGE_TOKEN });
const metadata = await client.store({
name: "FdongFdong NFT",
description: "FdongFdong",
image: new File([fs.readFileSync('./temp.PNG')], 'temp.PNG', {
type: 'image/PNG',
}),
attributes: [
{
trait_type: 'Rarity',
value: 'LEGENDARY',
},
],
});
console.log(metadata.url);
터미널창에서 해당 Js 파일을 실행하여 json형식의 메타데이터를 발급받아주세요
> node nft.js
(node:18503) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
ipfs://.../metadata.json
출력 받은 값을 검색창에 입력해보세요
https://ipfs.io/ipfs/{발급 받은 메타데이터.json}
단순이 이미지 파일만 올린다고 쉽게 만들어지는 것이 아니란 것을 알게되었다.
블록체인은 새로운 것을 학습할 때 마다 다른 정보에 비해 검색되는 내용들이 작다는것을 알게되었다.
심지어 영어다. 블록체인 관련 공부와 함께 영어공부도 꾸준히 해야할 것 같다.
해당 블로깅을 진행하며 이미지, 동영상등 NFT화 하기 위해 블록체인에 바로 올리는 것이 아니라는 것을 알게되었으며 여러 NFT 홈페이지에서는 메타데이터로 올리는 것을 선호하고 있다고 한다.. 그 이유로는 첨부되는 데이터의 양만큼의 가스비가 들기 때문이다.
직접 만들며 스탭 바이 스탭으로 진행해보니 세세한 부분까지 공부하게 되어 발전하는 모습이 체감으로 와닿는것 같다.