[Truffle] ropsten testnet에 ERC-721 배포
🖼 Purpose
solidity를 사용해 간단한 NFT 발행을 위한 개발을 진행하고자 한다.
- 컨트랙트는 truffle을 이용해 infura-ropsten 네트워크에 배포된다.
- NFT 수령인의 주소와 NFT의 정보를 담고 있는 엔드포인트 URL을 입력하면 NFT가 민팅되는 함수를 구현할 것이다.
⌨️ 진행 과정
-
github repository 링크
https://github.com/beigeyoon/ha4-truffle-erc721
-
ropsten 네트워크에 배포된 컨트랙트 주소
0xC57f2e576f78f3C6C325867314c78b3bb453416d
-
컨트랙트 etherscan 링크
https://ropsten.etherscan.io/address/0xC57f2e576f78f3C6C325867314c78b3bb453416d
github repository 링크
https://github.com/beigeyoon/ha4-truffle-erc721
ropsten 네트워크에 배포된 컨트랙트 주소
0xC57f2e576f78f3C6C325867314c78b3bb453416d
컨트랙트 etherscan 링크
https://ropsten.etherscan.io/address/0xC57f2e576f78f3C6C325867314c78b3bb453416d
대략적인 개발 흐름은 다음과 같다.
- truffle 개발 환경 설정 (ropsten network)
- 코드 작성
- truffle을 통해 네트워크에 배포
- NFT 민팅 실행
(1) truffle 개발 환경 설정
프로젝트 루트 디렉토리에서 터미널을 열고 truffle 개발 환경을 셋팅해준다.
truffle init
npm init
npm install -D truffle-plugin-verify
❗️
truffle-plugin-verify
etherscan에서 컨트랙트 코드를 자동으로 검증할 수 있게 하는 플러그인이다. 이 플러그인이 없으면 컨트랙트를 배포하고 etherscan에서 코드를 Verify & Publish 하려고 할 때 아래와 같은 에러 메시지가 뜰 것이다. 에러 메시지가 말해주는 대로 Remix를 사용한다면 에러가 발생하지 않겠지만truffle-plugin-verify
플러그인을 사용하여 truffle로 진행해보려고 한다.
truffle-config.js 설정
truffle-config.js 파일에서 네트워크 관련 설정을 해줘야 한다. 파일의 주석처리 된 내용 중 다음과 같이 Infura를 통해 배포하고자 할 때 추가되어야 할 코드들이 담겨 있다. 이 내용에 따르면 배포에 이용하고자 하는 계정(나는 메타마스크 이용 예정)의 니모닉 코드와 Infura API key가 필요하다.
Infura를 사용하기 위해 @truffle/hdwallet-provider
를 설치해준다.
npm install @truffle/hdwallet-provider
❗️ [중요] 메타마스크에서 니모닉 코드를 가져온 뒤 프로젝트 폴더 내에 .secret
파일을 생성하여 그 안에 니모닉을 담는다. 이 파일은 절대 유출되면 안되므로 .gitignore
파일에 추가해야 한다.
주석 처리되어있던 아래의 코드들을 활성화 해주고, YOUR-PROJECT-ID
에 Infura API KEY를 복사해서 붙여 넣어준다.
const HDWalletProvider = require('@truffle/hdwallet-provider');
const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim();
module.exports = {
networks: {
ropsten: {
provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
network_id: 3, // Ropsten's id
gas: 5500000, // Ropsten has a lower block limit than mainnet
confirmations: 2, // # of confs to wait between deployments. (default: 0)
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
},
},
// plugins와 api_keys는 truffle-plugin-verify 사용을 위해 추가한 것이다.
plugins: [
'truffle-plugin-verify'
],
api_keys: {
etherscan: 'VDPIVK42DMZVGX9F5XK4T2JA2DZQWPZCF9'
}
}
(2) contract 코드 작성
truffle 및 ropsten network에 대한 세팅이 완료되었으므로 배포할 컨트랙트 코드를 작성한다. OpenZeppelin의 erc721 라이브러리를 활용하기 위해 OpenZeppenlin을 프로젝트에 설치해준다.
npm install @openzeppelin/contracts
프로젝트의 contracts 폴더 내에 sol 파일을 생성하고 컨트랙트 코드를 작성한다. ERC721 표준 코드에는 NFT 민팅 함수가 구현되어 있지 않다. 따라서 OpenZeppelin의 ERC721 코드를 상속 받았어도 민팅을 위한 함수는 스스로 작성해주어야 한다. 민팅의 방식은 개발자와 제공 서비스에 따라서 로직이 크게 달라질 수 있기 때문에 표준에는 민팅 함수가 구현되어 있지 않은 듯 하다.
아래의 코드는 NFT 정보가 담긴 NFT를 tokenURI로 입력하면 NFT가 민팅되도록 하고 있다. 오직 컨트랙트 생성자(owner)만이 민팅을 실행할 수 있으며, 민팅된 NFT는 owner에게 발급된다.
//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 yooniNFT is ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
// "MyNFTs"와 "MNFT"는 NFT 컨트랙트의 이름과 심볼이 될 것이다.
constructor() public ERC721("yooniNFT", "YN") {}
function mintNFT(string memory tokenURI)
public onlyOwner
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
(3) migration 코드 작성
migrations 폴더 내의 1_initial_migration.js 코드를 아래와 같이 수정하여 작성한 yooniNFT.sol 코드도 배포될 수 있도록 한다.
const Migrations = artifacts.require('Migrations');
const yooniNFT = artifacts.require('yooniNFT.sol'); // yooniNFT.sol 파일 추가
module.exports = function (deployer) {
deployer.deploy(Migrations);
deployer.deploy(yooniNFT); // yooniNFT를 배포에 추가
};
(4) truffle로 ropsten에 배포하기
프로젝트 루트 디렉토리에서 터미널을 열고 truffle을 통해 배포를 진행한다. ropsten 네트워크와 상호작용해야 하기 때문에 시간이 걸릴 수 있다.
truffle migrate --compile-all --network ropsten
성공적으로 배포되었다면 터미널에 아래와 같이 뜰 것이다.
etherscan에서의 컨트랙트 코드 검증을 위해 truffle-plugin-verify
를 실행한다. 플러그인을 제대로 실행하면 etherscan에서 컨트랙트 코드를 verify & publish 하지 않아도 코드가 자동적으로 검증되어 올라가 있다.
truffle run verify yooniNFTs --network ropsten
컨트랙트가 잘 배포되었는지 확인하기 위해 truffle-console
에 진입해 배포된 컨트랙트의 인스턴스를 얻어 name과 symbol을 확인한다.
truffle console --network ropsten
name과 symbol을 잘 받아오고 있음을 확인할 수 있다. 배포가 잘 되었다는 뜻이다! 🥳
🖥 동작 확인
(1) truffle에서 NFT 발행
컨트랙트가 잘 배포되었으니, 이제 직접 NFT를 발행해 보려고 한다. 민팅 함수를 실행하기 위해서는 tokenURI
가 필요하며 미리 NFT storage에서 tokenURI
를 생성해두었다.
✨ 실습에 활용할 나의 NFT 이미지
truffle console
에서 민팅 함수를 실행한다. 시간이 꽤 걸린다.
instance.mintNFT("ipfs://bafkreigvfb6bxdp6qon2gpps2qsaeplsgizomaken4ig76awufzf2zahc4")
민팅이 성공적으로 되면, 아래와 같이 트랜잭션 정보가 터미널에 뜨게 된다.
(2) etherscan에서 NFT 발행
새로운 tokenURI
를 생성하고, etherscan에서 두 번째 NFT를 발행해 보았다.
NFT가 성공적으로 발행되어 tokenId
를 통해 생성된 NFT의 tokenURI
를 확인할 수 있다.
✏️ 개발 회고
ERC-721 표준 코드가 이미 OpenZeppelin 라이브러리에 있으므로 그대로 끌어와 배포하면 되지 않을까 간단하게 생각했었지만, 의외로 신경써주어야 할 부분들이 꽤 있었고 그런 부분들을 해결하면서 많이 배운 것 같다.
우선, 기존에 truffle로는 ganache 환경으로 실습을 진행했던 것과 달리 ropsten 테스트넷을 활용했다. ropsten 네트워크로 환경을 맞춰주기 위해서는 @truffle/hdwallet-provider
라이브러리, Infura API KEY, 메타마스크 계정 니모닉 코드를 사용해야 했다.
그리고 truffle에서 ropsten network로 컨트랙트를 배포할 때, OpenZeppelin과 같은 라이브러리를 상속받은 경우 etherscan에 코드 검증(verify & publish)에서 에러가 뜬다. 구글링 결과 라이브러리까지 포함된 단일 병합 코드를 업로드해야 한다고 하는데 사실 무슨 말인지 이해가 잘 가지 않았고(🥲) 다행히 이런 상황에서 자동으로 코드를 verify & publish 해주는 truffle-plugin-verify
라이브러리를 알게 되어 etherscan에 코드를 잘 올릴 수 있었다. (truffle이 아닌 remix에서 배포를 진행했다면 라이브러리를 사용한 컨트랙트여도 에러 없이 코드가 잘 올라간다.)
또한 NFT 엔드포인트 URI를 생성하기 위해 NFT stroage라는 서비스를 이용했는데, 간단한 제작을 위해 단순히 이미지만 업로드하여 URI를 받아와서 사용했다. 하지만 실제 tokenURI는 NFT의 메타데이터 정보가 체계적인 방식으로 저장되어 있기 때문에, 메타데이터를 포함시키기 위한 추가적인 학습이 필요할 듯 하다.
Author And Source
이 문제에 관하여([Truffle] ropsten testnet에 ERC-721 배포), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yooni/Truffle-truffle을-통한-ERC-721-배포저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)