강의수강 정리/코드스테이츠

Unit4 : Truffle을 이용한 ERC-721 개발

Koartifact 2021. 12. 13. 18:48

로컬 환경에서 ERC-721을 개발하고, Truffle을 이용한 배포를 실습합니다.

로컬에서 NFT를 개발하기 위해, Truffle과 Ganache를 사용합니다.

 

 

 

1) 폴더를 하나 생성하고 환경세팅

 

Truffle

truffle 프레임워크는 스마트 컨트랙트(solidity) 개발시 개발, 배포 및 테스트 환경을 제공 합니다. 이 프레임워크는 node.js에서 동작을 하며 npm 으로 설치를 할수 있습니다.

 

https://github.com/trufflesuite/truffle

 

GitHub - trufflesuite/truffle: A tool for developing smart contracts. Crafted with the finest cacaos.

A tool for developing smart contracts. Crafted with the finest cacaos. - GitHub - trufflesuite/truffle: A tool for developing smart contracts. Crafted with the finest cacaos.

github.com

설치 후 ' truffle version '  버전확인

 

# 폴더 생성
mkdir truffle721
# 폴더 진입
cd truffle721
# truffle 초기화
truffle init
# npm 초기화
npm init

개발 환경 준비를 마쳤다면, VScode를 실행합니다.

콘솔에 'code .' 입력

VScode에 나타나는 폴더와 파일의 구조는 다음과 같습니다.

먼저 몇 가지 세팅을 하고, 코드를 가져오겠습니다.

truffle-config.js 를 열고, solc를 설정합니다. solc 는 Solidity, Compiler의 버전 등을 설정합니다.
이 예시에서 사용하는 Solidity의 버전은 "0.8.7"이고, Compiler의 버전은 "london"입니다.
주석을 제거하고, 다음과 같이 설정을 수정합니다.

다음은 네트워크 설정을 편집합니다. Ganache를 이용해 로컬 환경에서 테스트할 예정이므로, 먼저 Ganache를 등록합니다.
다음과 같이 주석을 제거하고, developement를 구분하기 좋게 ganache 로 변경합니다.

이제 로컬 환경에서 Truffle과 Ganache를 이용해 개발하는 환경을 구축했습니다. Ganache를 이용한 배포는 다른 콘텐츠에서 다룹니다.

이전 콘텐츠에서 작성한 코드를 가져오겠습니다. 몇 가지 방법이 있지만, 간단한 코드이므로 복사 & 붙여넣기로 콘텐츠를 진행합니다.

 

 

//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;
    }
}

 

함수 mintNFT 에서 변경된 부분은 다음과 같습니다.

  • 파라미터 address recipient 삭제
  • 파라미터 address recipient 를 사용하는 _mint 함수 실행부에서, recipient 를 msg.sender 로 대체

이렇게 변경하면, 오너의 지갑 주소에서만 함수 mintNFT 를 실행할 수 있고, 새로운 NFT는 항상 오너의 지갑 주소로 발행됩니다.

mint 함수는 사용하려는 형태에 따라 편집해서 사용합니다. 정해진 수량의 NFT만 제공하는 경우, NFT를 미리 발행해둔 채 tokenUri 만 업데이트하는 형태로 사용하기도 합니다. 개인 작가처럼 꾸준히 새로운 작품을 NFT로 발행하려면, mint 함수를 생성해두는 편이 좋습니다. 상황에 따라 알맞는 형태로 함수를 구현하세요.

편집한 코드를 복사하세요. VScode로 넘어가서 계속 진행합니다.

contract/ 폴더 아래에 MyNFTs.sol 파일을 생성합니다. 이 파일에 아까 복사해 둔 코드를 붙여넣습니다.

[주의] 이때 Remix에서 복사해오지 않은 경우(ex. 메모장에 코드를 붙여넣고 다시 복사한 경우 등), 코드의 컨벤션이 깨질 수 있습니다. 코드 편집기에서 복사하여, 코드 편집기로 붙여넣는 편이 가장 안전합니다.

이 파일에서는 OpenZeppelin의 파일을 참조하고 있습니다. 따라서, npm 을 통해 openzeppelin 을 설치해야 합니다.

이 경로의 터미널에서 다음의 명령어를 통해 openzeppelin 을 설치하세요.

npm install @openzeppelin/contracts

붙여넣은 코드가 정상적으로 배포되기 위해서는, migration 파일을 설정해야 합니다.
migration/ 폴더로 이동하여 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를 배포에 추가
};

이걸로 ERC721을 이용한 개발을 마쳤습니다. 배포 콘텐츠를 통해, 작성한 컨트랙트를 로컬에서 Truffle과 Ganache로 배포합니다.

 

2. Truffle로 ERC-721 배포하기

로컬 환경에서 Ganache를 이용해 컨트랙트를 배포합니다.
먼저, 새로운 터미널을 열고 ganache-cli 를 실행합니다.

# 새로운 터미널에서 ganache-cli 실행
ganache-cli

기존의 터미널에서 Truffle로 배포합니다. 이때, truffle-config.js 파일의 network 에 설정한 ganache 로 실행해야 합니다.

[주의] 실행하는 터미널의 현 위치가 package.json, truffle-config.js 의 위치와 동일한지 확인하세요. 맨 처음 truffle init 을 실행한 위치와 동일합니다.

truffle migrate --compile-all --network ganache

위 명령어에서 --network 에 이어 나오는 ganache 는 truffle-config.js 에서 설정한 network 의 키입니다.
위 명령어를 통해 로컬의 ganache-cli 와 연결하고, 컨트랙트를 배포합니다.

컨트랙트의 배포가 잘 이루어졌다면, Truffle console을 이용해 컨트랙트를 조작할 수 있습니다. 다음의 명령어를 터미널 프롬프트에 입력하고, Truffle console에 진입합니다.

truffle console --network ganache

Truffle console에서, 배포한 컨트랙트의 인스턴스를 받아옵니다. 그리고 배포한 컨트랙트가, 작성한 코드와 일치하는지 확인합니다.

instance = await MyNFTs.deployed()
instance.name()
# 'MyNFTs'
instance.symbol()
# 'MNFT'

배포된 컨트랙트에 대한 확인을 마쳤으면, 작성한 함수가 잘 동작하는지 확인합니다. 이때 함수의 마지막 파라미터로 실행할 지갑 주소를 함께 전달해야 합니다. 이 지갑의 주소는 ganache-cli 의 첫번째 지갑(0번째 인덱스 지갑) 주소입니다. Ganache를 이용해 컨트랙트를 배포할 때에는, default로 첫번째 지갑(0번째 인덱스 지갑)의 주소에서 컨트랙트를 배포합니다.

instance.mintNFT("https://urclass-images.s3.ap-northeast-2.amazonaws.com/beb/section4/unit4/test.json", { from: accounts[0] })
# Tx Information

그 다음 발행된 NFT로부터 tokenURI 를 확인합니다.

instance.tokenURI(1)
# "https://urclass-images.s3.ap-northeast-2.amazonaws.com/beb/section4/unit4/test.json"

앞으로 다른 네트워크(ex. 메인넷)에 배포할 때에는 truffle-config.js 에 네트워크 정보를 추가하고, Truffle 명령어 중 옵션 --network 와 함께 네트워크의 정보를 담고있는 키를 입력하면 됩니다.

 

- 회고

Keep

기존 학습 내용을 블로깅하면서 정리할 수 있는 시간이 된 것 같다.

 

Problem

막상 기록하면서 다시 해보려니 잘 안되서 급하게 했다.

 

Try

다른 유닛들도 해보고 익숙해지도록 해야겠다