본문 바로가기
Blockchain

[Blockchain] Local 환경에서 NFT 민팅하는 방법

by 개발자 염상진 2022. 7. 21.

 

 로컬 환경에서 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] OpenSea NFT 민팅 하는 방법

OpenSea는 NFT를 거래하는 대표적인 플랫폼입니다. OpenSea에서 지원하는 블록체인은 이더리움, 폴리곤, 솔라나, 클레이튼이 있습니다. 테스트넷으로는 이더리움 Rinkeby와 클레이튼의 Baobab을 지원하

about-tech.tistory.com

 

[Blockchain] NFT 만드는 법 (ERC-721 표준 사용)

ERC-721 컨트랙트 컴파일 ⓐ Remix IDE를 실행합니다. ⓑ 새로운 프로젝트를 실행하고 contracts 폴더에 testNFT.sol 파일을 생성합니다. ⓒ openzeppelin에서 제공하는 라이브러리를 사용해 ERC-721 컨트랙트 코

about-tech.tistory.com

 

 

[Blockchain] ERC-721 구조?

ERC-721 표준은 NFT(대체 불가능한 토큰, Non-fungible Token)을 발행하는 스마트 컨트랙트를 정의하고 있습니다. ERC-20을 기본으로 해서 제작되어 유사한 함수를 가지고 있지만, 특정 자산에 대해 대체

about-tech.tistory.com

 

댓글