로컬 환경에서 NFT 발행하기
NFT를 민팅해서 OpenSea 플랫폼에서 판매도 가능하지만 테스트 목적으로 NFT를 발행하는 경우 Local 환경에서도 가능합니다. 로컬 환경에서 컨트랙트를 블록체인에 배포하고, NFT를 발행하기 위해서는 Ganache와 Truffle를 사용합니다.
우선 Truffle 환경을 준비합니다.
$ truffle init
Starting init...
================
> Copying project files to /home/ys/project/BEB_05/22_ERC721/02_ERC721_truffle
Init successful, sweet!
Try our scaffold commands to get started:
$ truffle create contract YourContractName # scaffold a contract
$ truffle create test YourTestName # scaffold a test
http://trufflesuite.com/docs
package.json을 초기화 합니다.
$ npm init
이제 폴더 구조는 다음과 같습니다.
.
├── contracts
│ └── Migrations.sol
├── migrations
│ └── 1_initial_migration.js
├── package.json
├── test
└── truffle-config.js
3 directories, 4 files
Truffle 네트워크 환경 설정
truffle-config.js 에서 solc 를 설정합니다. Compiler 버전은 각각 다르겠지만 이번 경우에는 0.8.7 버전을 사용합니다.
네트워크는 ganache를 사용할 예정이므로 networks에 ganache를 추가합니다.
컨트랙트 파일 작성
네트워크 환경설정이 마치면 contracts/TestNFTs.sol 파일을 생성하고 아래 코드를 복사합니다. ERC-721 Openzeppelin 라이브러리르 참조하므로 따로 설치를 진행합니다.
//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 TestNFTs is ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() public ERC721("TestNFT", "NFT"){}
function mintNFT(string memory tokenURI) public onlyOwner returns(uint256){
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
openzeppelin 라이브러리 설치
$ npm install @openzeppelin/contracts
Migration 파일 수정
솔리디티 코드를 정상적으로 배포하기 위해 migration/1_Initial_migrations.js 파일에 TestNFT.sol 파일을 추가해줍니다.
const Migrations = artifacts.require("Migrations");
const TestNFTs = artifacts.require('TestNFTs');
module.exports = function (deployer) {
deployer.deploy(Migrations);
deployer.deploy(TestNFTs);
};
Ganache-cli 실행
이제 로컬환경에서 Ganache 환경을 실행합니다. 터미널에서 ganache-cli를 실행합니다.
$ ganache-cli
10개의 테스트 계정이 생성되고 localhost:8545 포트에서 실행됩니다.
Ganache CLI v6.12.2 (ganache-core: 2.13.2)
Available Accounts
==================
(0) 0x7eD125634CB17101EAf8654553A21170D8d5AFB4 (100 ETH)
(1) 0x034fC277e13e51eA5aE3Ff281EB962442A65D57A (100 ETH)
(2) 0xfCf555BAA3A7A04aC5B3033624AD2295Ecd92cF3 (100 ETH)
(3) 0x9506C5531f90329980bA1D13F125F715d69Ec706 (100 ETH)
(4) 0xB9156830900a7dD12aAd0B53df686124ebcCEcFE (100 ETH)
(5) 0x3d18F99097C000Ef86DAde1E7D520CbEd00a08E5 (100 ETH)
(6) 0xa495a2cD06888990620ec0DBED0Ad3F95A7a8fCf (100 ETH)
(7) 0x178ec2F6254327190f288a409679667B1EF20885 (100 ETH)
(8) 0xd931F38F99a539967bf1D18eEeB1fb757e55C0be (100 ETH)
(9) 0xa12B8a1638b132Db3E5A754e90852Cacddb2EDEb (100 ETH)
Private Keys
==================
(0) 0xcc8c8e53ff5182c3c365362b0dc02ec7a786b37af07d57ce272b80eaebcf432b
(1) 0x77a7a2e4886082431537d75e5f90d3f6d50f0795bf55e801585b416dc6bf8087
(2) 0x4fe215e8e2a96e422f381b5133905a14fa8ae9e85bb570f8a28d5dd57e058b22
(3) 0x9ada2e3de50348aa38dcc2e4b880a8e6e7bb928d4b7a6be60616409dfae61467
(4) 0xa724120c34cc643e1765f2fa188c0874cfbf3f794e6df273c6d17ac02c5e7806
(5) 0xff226aa0b8b92f392ebced647b691604356365dc4701ee33328dfc9887b7aa2f
(6) 0x8eb29723718a681b57f13f8f2015e33d3131d331ef41ff53d81dd45a2285fc15
(7) 0x3d3eb94b2e5920e1074d71907cee45678a071e22e970233662eb960c9678cb6a
(8) 0x863c6071f3245bbb85cccf54ad64aba44a7dceb0c986f1574a4015ff96b6f96f
(9) 0xfb02075bf320477a83fd34e11463ba6179e9e437057284e4335d6505f5570c3a
HD Wallet
==================
Mnemonic: profit energy top glass swarm federal range spatial unaware subway share merge
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
실행 중인 ganache 네트워크에 truffle로 작성한 solidity 파일을 배포합니다. truffle-config.js 에서 ganache 네트워크 설정이 일치해야 합니다.
$ truffle migrate --compile-all --network ganache
정상적으로 배포가 완료되었습니다. 배포 트랜잭션/블록의 정보가 기록되고, 총 가스비가 출력됩니다.
Starting migrations...
======================
> Network name: 'ganache'
> Network id: 1658383486730
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0xabf4e0afe90e41eb47b6ba85d804c78be74f59985e0b2a83d6118e3daf16e9bd
> Blocks: 0 Seconds: 0
> contract address: 0xc5447254031E8aEf3718C76e601f8f57b76cA3AD
> block number: 1
> block timestamp: 1658383918
> account: 0x7eD125634CB17101EAf8654553A21170D8d5AFB4
> balance: 99.99502292
> gas used: 248854 (0x3cc16)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00497708 ETH
Deploying 'TestNFTs'
--------------------
> transaction hash: 0xb345600f002426b99785db6a147ff634b4118cb92200156a671b2b2382dbd176
> Blocks: 0 Seconds: 0
> contract address: 0xAc2823Ceaf239E8aA86290C492f724b50177166D
> block number: 2
> block timestamp: 1658383919
> account: 0x7eD125634CB17101EAf8654553A21170D8d5AFB4
> balance: 99.94401744
> gas used: 2550274 (0x26ea02)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.05100548 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.05598256 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.05598256 ET
Truffle => Ganache 네트워크 접근
배포가 정상적으로 완료되면 Ganache에 배포된 컨트랙트를 조작할 수 있습니다.
$ truffle console --network ganache
truffle(ganache)>
우선 배포한 컨트랙트의 Instance를 받아옵니다.
truffle(ganache)> instance = await TestNFTs.deployed()
undefined
Instance로 컨트랙트의 함수에 접근이 가능합니다.
truffle(ganache)> instance.name()
'TestNFT'
truffle(ganache)> instance.symbol()
'NFT'
Instance를 통해 mintNFT() 함수를 실행합니다. tokenURI는 임의의 문자열을 삽입합니다.
$ truffle(ganache)> instance.mintNFT("https://about-tech.tistory.com/")
ganache 네트워크에 트랜잭션이 올라가고 블록이 생성됩니다.
{
tx: '0x0b55d4af14a7c4fe903d71ac3f47a01451071c29c718335cb4cfb3151938b685',
receipt: {
transactionHash: '0x0b55d4af14a7c4fe903d71ac3f47a01451071c29c718335cb4cfb3151938b685',
transactionIndex: 0,
blockHash: '0x3d725e18b57213ef083b3ff90c667bffb5524a3b76da051dcfecc5542ab65cdf',
blockNumber: 4,
from: '0x7ed125634cb17101eaf8654553a21170d8d5afb4',
to: '0xac2823ceaf239e8aa86290c492f724b50177166d',
gasUsed: 113246,
cumulativeGasUsed: 113246,
contractAddress: null,
logs: [ [Object] ],
status: true,
logsBloom: '0x00200100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000008000000000000000000042000000000000000008000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000',
rawLogs: [ [Object] ]
},
logs: [
{
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x0b55d4af14a7c4fe903d71ac3f47a01451071c29c718335cb4cfb3151938b685',
blockHash: '0x3d725e18b57213ef083b3ff90c667bffb5524a3b76da051dcfecc5542ab65cdf',
blockNumber: 4,
address: '0xAc2823Ceaf239E8aA86290C492f724b50177166D',
type: 'mined',
removed: false,
id: 'log_6a747750',
event: 'Transfer',
args: [Result]
}
]
}
Ganache 터미널 창에는 새로 생성된 블록과 트랜잭션 정보가 기록됩니다. 트랜잭션 해시값이 위와 동일합니다.
발행한 NFT의 tokenURI를 출력합니다.
$ truffle(ganache)> instance.tokenURI(1)
'https://about-tech.tistory.com/'
메인넷에 배포하는 경우
truffle에서 솔리디티로 작성한 컨트랙트를 메인넷에 배포하는 경우 truffle-config.js의 networks 부분을 메인넷으로 수정해주고, truffle 실행시 --network 옵션을 사용해 특정 network를 명시합니다.
Reference
'Blockchain' 카테고리의 다른 글
[Blockchain] 블록체인 샤딩(sharding) 이란? (0) | 2022.07.22 |
---|---|
[Blockchain] 이중 지불 문제란? (0) | 2022.07.22 |
[Blockchain] OpenSea NFT 민팅 하는 방법 (0) | 2022.07.21 |
[Blockchain] NFT 만드는 법 (ERC-721 표준 사용) (0) | 2022.07.20 |
[Blockchain] ERC-721 구조? (1) | 2022.07.20 |
댓글