Truffle을 이용한 ERC-721개발

ERC-721을 NFT라 부르는 이유

EIP-721, 이더리움 개선 제안의 721번째 토론에서 ERC-20으로 생성한 Fungible Token이 아닌
단 하나의 토큰으로써 식별, 추적이 가능한 Non-Fungible Token이다.

ERC-721개발

개발은 udemy 강의(https://www.udemy.com/course/the-complete-nft-web-developer-course-zero-to-professional/)를 참고하였습니다.

개발 개요

  1. Open Zeppelin ERC-721코드 리팩토링
  2. NFT전송 및 Truffle 콘솔 테스트(Ganache Network 사용)
  3. NFT 마켓플레이스에서 NFT 호스팅(Ganache Network 사용)

1. Open Zeppelin ERC-721코드 리팩토링

1. import 구현

import './ERC165.sol';
import './interfaces/IERC721.sol';
import './libraries/Counters.sol';

'ERC165.sol'에서는 인터페이스 ID를 가져와서 사용가능한 인터페이스인지 확인했다.
'IERC721.sol'은 ERC721과 인터페이스 역할을 하며 IERC721의 함수를 ERC721에서 상속하여 사용했다.
'Counters.sol'에서는 underflow, overflow를 방지하는 Safemath내용이 담겨져있다.

2. mapping, constructor 구현

    mapping(uint256 => address) private _tokenOwner;
    mapping(address => Counters.Counter) private _OwnedTokensCount;
    mapping(uint256 => address) private _tokenApprovals;

    constructor() {
        _registerInterface(bytes4(keccak256('balanceOf(bytes4)')^
        keccak256('ownerOf(bytes4)')^keccak256('transferFrom(bytes4)')));
    }

매핑을 통해 토큰소유자, 토큰개수 등을 만들어 함수 구현에 사용하였고, 생성자에서 'ERC165.sol'에서 상속받은 _registerInterface함수를 호출했다.

3. ERC-721 함수 구현

    function balanceOf(address _owner) public view override returns(uint256) {
        require(_owner != address(0), 'owner query for non-existent token');
        return _OwnedTokensCount[_owner].current();
    }

    function ownerOf(uint256 _tokenId) public view override returns(address) {
        address owner = _tokenOwner[_tokenId];
        require(owner != address(0), 'owner query for non-existent token');
        return owner;
    }

    function _exists(uint256 tokenId) internal view returns(bool){
        address owner = _tokenOwner[tokenId];
        return owner != address(0);
    }

balanceOf 함수는 'owner' 계정이 존재한다면 'owner' 계정의 NFT 개수를 반환한다.
ownerOf 함수는 'tokenId'에 명시된 NFT의 owner 계정을 반환한다.
_exists 함수는 지정한 토큰이 존재하는지 여부를 반환한다.

    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), 'ERC721: minting to the zero address');
        require(!_exists(tokenId), 'ERC721: token already minted');
        _tokenOwner[tokenId] = to;
        _OwnedTokensCount[to].increment();

        emit Transfer(address(0), to, tokenId);
    }

_mint 함수는 새 토큰을 발행하기 위한 내부 함수이다. 'tokenId'가 존재하면 되돌린다.


    function _transferFrom(address _from, address _to, uint256 _tokenId) 
        require(_to != address(0), 'Error - ERC721 Transfer to the zreo address');
        require(ownerOf(_tokenId) == _from, 'Trying to transfer a token the address does not own!');

        _OwnedTokensCount[_from].decrement();
        _OwnedTokensCount[_to].increment();

        _tokenOwner[_tokenId] = _to;

        emit Transfer(_from, _to, _tokenId);
    }

    function transferFrom(address _from, address _to, uint256 _tokenId) override public {
        require(isApprovedOrOwner(msg.sender, _tokenId));
        _transferFrom(_from, _to, _tokenId);
    }

_transferFrom함수는 '_tokenID'의 소유권을 다른 주소로 전송하기 위한 내부 함수이다.
토큰을 전송하면 '_from'의 토큰 개수를 감소시키고 '_to'의 토큰 개수를 증가시킨다.

    function approve(address _to, uint256 tokenId) public {
        address owner = ownerOf(tokenId);
        require(_to != owner, 'Error - approval to current owner');
        require(msg.sender == owner, 'Current caller is not the owner of the token');
        _tokenApprovals[tokenId] = _to;
        emit Approval(owner, _to, tokenId);
    }

    function isApprovedOrOwner(address spender, uint256 tokenId) internal view returns(bool) {
        require(_exists(tokenId), 'token does not exist');
        address owner = ownerOf(tokenId);
        return(spender == owner );
    }

isApprovedOrOwner함수는 지정된 납부자가 주어진 토큰 ID를 전송할 수 있는지 여부를 반환한다.


2. NFT전송 및 Truffle 콘솔 테스트(Ganache Network 사용)

1. truffle-config.js의 port를 Ganache port와 일치하게 수정

2. truffle을 이용해 컴파일, 배포

Ganache 네트워크에 연결해 배포하였고, 1번 계정의 Address 잔액이 줄어들은 것을 확인할 수 있다.

Ganache 네트워크에 쌓인 블록도 확인할 수 있다.

3. Mint 함수를 이용해 nft 민팅

민팅한 주소로 'balanceOf'함수를 이용해 확인한 결과 토큰이 1개 담긴것을 확인할 수 있다.

4. trasferFrom 함수를 이용해 nft 전송 및 확인

Ganache 네트워크의 1번 주소에서 2번 주소로 전송하였고, balanceOf함수를 통해
잘 전송된 것을 확인할 수 있다.

3. NFT 마켓플레이스에서 NFT 호스팅(Ganache Network 사용)

1. https://imgbb.com/을 이용하여 jpg파일을 html 형식으로 변환한다.

2. UPLOAD를 하면 HTML 형식으로 변환된 것을 확인할 수 있다.

3. 변환된 HTML 형식으로 React로 개발한 NFT Marketplace에 NFT를 생성할 수 있다.

개발 회고

개발 회고 방법론은 KPT(KEEP, PROBLEM, TRY)를 따른다.

Keep

NFT에 많은 관심이 있었고, 어떤 식으로 구현하는지 알아보고 싶어 Udemy 강의를 찾아 듣게 되었다.
코드만 봐서는 이해되지 않았던 부분들이 직접 가상의 NFT Marketplace를 만들어 Ganache Network
에 배포해서 NFT가 블록체인 상에 어떻게 저장되는지 확인할 수 있어서 좋았다.

Problem

강의를 보면서 따라한 Code들을 직접 처음부터 구현하라고 하면 하지 못할것이다.
직접 구현하는 경험을 많이 쌓아야겠다.

Try

모바일 DApp Marketplace를 만들어서 klip과 연동시켜보았으면 좋겠다.

깃허브 주소

https://github.com/djshinnn/ERC721-NFT

좋은 웹페이지 즐겨찾기