솔리디티를 이용하여 NFT Marketplace 만들어보기 1 (컨트랙트)
솔리디티를 이용하여 NFT 마켓 개발 실습
아래의 강의보고 실습 진행
개발 완료 화면
제작할 웹사이트 내용 확인
1. IPFS 파일 업로드 페이지
- form에서 데이터를 받아와 블록체인의 데이터를 읽는 기능 구현
2. MyNFT
- 자신이 민팅한 NFT 리스트 볼 수 있음
- 상세내용을 확인 할 수있는 페이지 제공
- NFT 삭제 기능 구현
- 등록한 NFT 판매 등록 (판매 페이지에 등록되는 기능 구현)
3. NFT 구매 기능 구현
개발환경
- remix
- vscode
* IPFS (InterPlanetary File System)
- 분산형 파일 시스템에 데이터를 저장하고 인터넷으로 공유하기 위한 프로토콜
- 데이터의 내용을 변환한 해시값을 이용해 전세계의 컴퓨터에 분산 저장되어 있는 콘텐츠를 찾아 보여줌
정리
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MintNftToken is ERC721Enumerable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
...
}
ERC721 (참고)
- 대체 불가능한 토큰의 소유권을 나타내는 표준 (각 토큰은 unique 함)
Openzeppelin의 Counters 라이브러리
- 토큰의 아이디 값으로 순차적으로 증가하는 번호를 많이 사용한다고 함
* 보통은 기존 토큰 발행 수에 +1을 한다고 함
- 이 프로젝트에서는 Openzeppelin의 Counters를 이용하여 토큰 아이디 줌
using Counters for Counters.Counter;
using A for B → A라이브러리에서 B 유형까지 모든 기능 첨부한다는 의미
Counters 라이브러리 안에 있는 모든 functions를 할당
컨트랙트가 배포될때 토큰의 이름과 심볼 지정
constructor(string _name, string memory _symbol) ERC721(_name, _symbol) {}
// 아래와 같이 픽스해서 사용해도 됨
constructor() ERC721("iki", "jquery_symbol"){}
ERC721에 있는 rokenURI function을 override해서 작성
- 특정 자산에 대한 고유한 URI (Uniform Resource Identifier)
- URI는 ERC721을 준수하는 JSON 파일을 가리킬 수 있음
mapping(uint =>string) public tokenURIs ;
function tokenURI(uint _tokenId) override public view returns (string memory) {
return tokenURIs[_tokenId] ;
}
민팅
function mintNFT( string memory _tokenURI) public returns (uint256)
IPFS에서 전달 받은 메타 JSON을 파라미터로 넘김
function mintNFT( string memory _tokenURI) public returns (uint256) {}
토큰 아이디 값을 증가 시켜 전달 받은 메타 JSON 정보 저장
_tokenIds.increment();
uint256 tokenId = _tokenIds.current();
tokenURIs[tokenId] = _tokenURI;
NFT 발행 함수
_mint(msg.sender, tokenId);
발행한 토큰 리스트 확인
function getNftTokens(address _nftTokenOwner) view public returns (NftTokenData[] memory)
balanceOf()를 이용해 오너가 몇개의 토큰을 가지고 있는지 알아냄
알아낸 수 만큼 for문을 돌려 토큰 리스트를 얻을 수 있음
판매 등록
function setSaleNftToken(uint256 _tokenId, uint256 _price) public
isApprovedForAll(nftTokenOwner, address(this) (ERC721 관련 처리)
- 인자값으로 전달받은 owner가 소유하고 있는 모든 nft에 대한 대리인이 두번째 파라미터로 전달 받은 사람이 맞는지 확인, true/false 반환
- false 값이 반환되면 판매를 하지 못하기 때문에 true 바꿔주는 과정 필요
require(isApprovedForAll(nftTokenOwner, address(this)), "nft token owner did not approve token.");
판매 리스트 확인
function getSaleNftTokens() public view returns (NftTokenData[] memory)
구매 함수
function buyNftToken(uint256 _tokenId) public payable
IERC721(address(this)).safeTransferFrom(nftTokenOwner, msg.sender, _tokenId);
- address(this) : 컨트랙트의 address 의미
//판매 리스트에서 삭제
removeToken(_tokenId);
판매 리스트에서 삭제
function removeToken(uint256 _tokenId) private
삭제할 요소의 구매 가격을 0으로 바꾸고 전체 루프를 돌려 0인 값을 찾음
nftTokenPrices[_tokenId] = 0;
for(uint256 i = 0; i<onSaleNftTokenArray.length; i ++){
if(nftTokenPrices[onSaleNftTokenArray[i]] ==0){
...
}
}
0인 값을 배열의 마지막으로 보내고 값을 삭제
onSaleNftTokenArray[i] = onSaleNftTokenArray[onSaleNftTokenArray.length -1] ;
onSaleNftTokenArray.pop();
토큰 삭제
function burn( uint256 _tokenId) public
토큰 삭제
_burn(_tokenId);
리스트 에서 삭제
removeToken(_tokenId);
전체 코드는 깃허브에 있음
lotteryDapp : https://github.com/dlwltn98/jqueryNfpMarketplace
출처, 참고 :
https://docs.openzeppelin.com/contracts/4.x/erc721