번개멍
ERC20 토큰 발행 및 ERC721 NFT 발행 본문
openzeppelin을 이용하여 ERC20 기반의 토큰을 Sepolia 테스트넷에 발행 및 ERC721 기반의 NFT 발행하는 작업을 진행해보겠다.
yarn add @openzeppelin/contracts
openzeppelin 을 설치하고 싶었지만.... node의 버전 문제가 생겼고 다운그레이드를 진행하였다.
내 node --version 은 19.0.1 이고 hardhat이 지원하는 18.0.0.으로 변경하고자 node 버전 관리 모듈인 n을 이용하려고 한다.
npm install n
sudo n 18.0.0
n 설치후 노드 버전을 변경하고 싶었으나
installed된 노드 위치와 active된 노드의 위치가 달라서 노드 버전을 계속 새로 설치하고 버전을 변경해도 active된 노드 버전이 변경되지 않는다고 한다...
드럽게 안된다...
실패...
node, nvm, npm 다 지우고 다시 한다...
ERC721 NFT를 발행해보자...
ERC721 용 폴더를 생성합니다.
npx hardhat
npx 를 이용해서 hardhat 을 설치합니다.
hardhat을 설치하게 되면 위에 사진처럼 샘플 프로젝트가 생성됩니다.
NFT를 생성하기 위해 openzeppelin을 설치 합니다.
npm install @openzeppelin/contracts
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Artwork is ERC721 {
uint256 public tokenCounter;
mapping (uint256 => string) private _tokenURIs;
constructor(
string memory name,
string memory symbol
) ERC721(name, symbol) {
tokenCounter = 0; //초기 민트하는 nft의 횟수를 0으로 지정합니다.
}
function mint(string memory _tokenURI) public {
_safeMint(msg.sender, tokenCounter);
_setTokenURI(tokenCounter, _tokenURI);
tokenCounter++;
}
function _setTokenURI(uint256 _tokenId, string memory _tokenURI) internal virtual{
require(
_exists(_tokenId),
"ERC721Metadata : URI set of nonexistent token"
);
_tokenURIs[_tokenId] = _tokenURI;
}
function tokenURI(uint256 _tokenId) public view virtual override returns(string memory){
require(
_exists(_tokenId),
"ERC721Metadata: URI set of nonexistent token"
);
return _tokenURIs[_tokenId];
}
}
//코드 설명
npx hardhat compile
npm install --sava-dev chai
스마트컨트랙트의 경우 자바와 다르게 한번 배포하면 수정은 불가하기에 테스트 코드가 굉장히 중요하다.
/test 디렉토리 안에 테스트 파일을 작성합니다.
const { expect } = require('chai');
const { ethers } = require("hardhat")
describe("Artwork Smart Contract Tests", function() {
this.beforeEach(async function() {
// This is executed before each test
const Artwork = await ethers.getContractFactory("Artwork");
artwork = await Artwork.deploy("Artwork Con", "ART");
})
it("NFT is minted successfully", async function() {
[account1] = await ethers.getSigners();
expect(await artwork.balanceOf(account1.address)).to.equal(0);
const tokenURI = "https://opensea-creatures-api.herokuapp.com/api/creature/1"
const tx = await artwork.connect(account1).mint(tokenURI);
expect(await artwork.balanceOf(account1.address)).to.equal(1);
})
it("tokenURI is set sucessfully", async function() {
[account1, account2] = await ethers.getSigners();
const tokenURI_1 = "https://opensea-creatures-api.herokuapp.com/api/creature/1"
const tokenURI_2 = "https://opensea-creatures-api.herokuapp.com/api/creature/2"
const tx1 = await artwork.connect(account1).mint(tokenURI_1);
const tx2 = await artwork.connect(account2).mint(tokenURI_2);
expect(await artwork.tokenURI(0)).to.equal(tokenURI_1);
expect(await artwork.tokenURI(1)).to.equal(tokenURI_2);
})
})
npx hardhat test
.env 파일을 이용해서 환경변수 방식을 사용하기 위해 dotenv를 설치합니다.
npm install dotenv
npm install @nomiclabs/hardhat-etherscan
hardhat.config.js 파일을 수정합니다.
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-etherscan")
require("dotenv").config();
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
task("deploy", "Deploy the smart contracts", async(taskArgs, hre) => {
const Artwork = await hre.ethers.getContractFactory("Artwork");
const artwork = await Artwork.deploy("Artwork Contract", "ART");
await artwork.deployed();
await hre.run("verify:verify", {
address: artwork.address,
constructorArguments: [
"Artwork Contract",
"ART"
]
})
})
module.exports = {
solidity: "0.8.4",
networks: {
mumbai: {
url: "https://matic-testnet-archive-rpc.bwarelabs.com",
accounts: [
process.env.PRIVATE_KEY,
]
}
},
etherscan: {
apiKey: process.env.POLYGONSCAN_KEY,
}
};
npx hardhat deploy --network mumbai
deploy를 진행하는데 오류가 나네요... hardhat-waffle 모듈을 찾을수 없는 문제입니다.
npm install @nomiclabs/hardhat-waffle
실패....
Reason: The Etherscan API responded that the address 0x43aAB3Bf55ee50dCE2b3894393C3948394A47cba does not have bytecode.
이런 오류가 발생하면서 작동하지 않는다... 온갖 방법을 다 써도 안된다...
임시해결
위에 오류가 난 이유로는 etherscan api 자체의 오류로 다들 비슷한 오류를 겪고 있다. 하지만 나는 해당오류랑 또다른 오류에 봉착한 상태이다….
이를 임시로 컨트랙트의 주소를 로그로 찍은뒤 검증하는 부분에 로그로 찍은 주소를 입력했다.
생성한 컨트랙트의 주소를 확인할수 있고 TestNet Scan에서 확인할 수 있다.
https://mumbai.polygonscan.com/
ipfs metadata 값을 이용해야합니다.
저는 pinta라는 ipfs지원 하는 친구를 사용하였습니다.
https://app.pinata.cloud/pinmanager
metamask 연결한 뒤 mint 영역 URI 부분에 ipfs 형태의 이미지 주소를 입력후 Write 를 누르게 되면 아래 사진과 같이 발행이 가능합니다.
'코딩이야기 > blockchain' 카테고리의 다른 글
Web3j (0) | 2023.10.24 |
---|---|
_mint vs _safeMint 차이점 (0) | 2022.12.23 |
SmartContract 프레임워크 선택 (0) | 2022.12.13 |