(BlockChain) ERC721Enumerable 구현
              
          2023. 3. 12. 13:32ㆍBlockChain
반응형
    
    
    
  https://developerjjh.tistory.com/173
(BlockChain) ERC721 구현
https://developerjjh.tistory.com/171 (BlockChain) IERC721Metadata 구현 interface IERC721Metadata.sol 전체 코드 // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IERC721Metadata { function name() external view returns (string memory);
developerjjh.tistory.com
ERC721Enumerable 구현 코드
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./ERC721.sol";
contract ERC721Enumerable is ERC721 {
  uint[] private _allTokens;
  mapping(address => mapping(uint => uint)) private _ownedTokens;
  mapping(uint => uint) private _ownedTokensIndex;
  constructor(
    string memory _name,
    string memory _symbol
  ) ERC721(_name, _symbol) {}
  function mint(address _to) public {
    _mint(_to, _allTokens.length);
  }
  function _beforeTokenTransfer(
    address _from,
    address _to,
    uint _tokenId
  ) internal override {
    if (_from == address(0)) _allTokens.push(_allTokens.length);
    else {
      uint latestTokenIndex = ERC721.balanceOf(_from) - 1;
      uint tokenIndex = _ownedTokensIndex[_tokenId];
      if (tokenIndex != latestTokenIndex) {
        uint latestTokenId = _ownedTokens[_from][latestTokenIndex];
        _ownedTokens[_from][tokenIndex] = latestTokenId;
        _ownedTokensIndex[latestTokenId] = tokenIndex;
      }
      delete _ownedTokens[_from][latestTokenIndex];
      delete _ownedTokensIndex[_tokenId];
    }
    uint length = ERC721.balanceOf(_to);
    _ownedTokens[_to][length] = _tokenId;
    _ownedTokensIndex[_tokenId] = length;
  }
  function totalSupply() public view returns (uint) {
    return _allTokens.length;
  }
  function tokenByIndex(uint _index) public view returns (uint) {
    require(_index < _allTokens.length);
    return _allTokens[_index];
  }
  function tokenOfOwnerByIndex(
    address _owner,
    uint _index
  ) public view returns (uint) {
    require(_index < balanceOf(_owner));
    return _ownedTokens[_owner][_index];
  }
}- uint[] private _allTokens : minting(생성)된 모든 토큰의 tokenId 배열
- mapping (address => mapping (uint => uint )) private _ownedTokens : 소유자의 토큰의 Index를 통해 tokenId를 접근
- address => ( index => tokenId )
 
- mapping ( uint => uint ) private _ownedTokenIndex : token의 Id에 대한 index
- tokenId = > index
 
- function mint (address _to) : token의 Id는 자동 생성되니 mint 해서 넣을 _to의 주소값만 매개변수로 받는다
- function _beforeTokenTranfer(address _from, address _to, uint _tokenId) : mint, transferFrom 메서드에서 호출
- _mint() 함수에서 호출 되어서 실행됐을 때 ( _from == address(0) )
- 새로운 토큰 발행 시 모든 토큰 배열(allTokens)에 추가 (push 메서드)
 
- transferFrom() 함수에서 호출되어서 실행됐을 때 ( _from != address(0) )
- uint latestTokenIndex = ERC721.balanceOf(_from) -1 : 소유자의 토큰의 마지막 index 저장
- uint tokenIndex = _ownedTokensIndex[_tokenId] : _tokenId에 대한 소유자의 기준 index를 저장
- if (tokenIndex != latestTokenIndex) : 보내려는 토큰이 마지막 토큰이 아니라면
- uint latestTokenId = _ownedTokens[_from][latestTokenIndex] : 소유자의 마지막 토큰의 Id를 저장
- _ownedTokens[_from][tokenIndex] = latestTokenId : 보낸 계정의 토큰들 중 tokenIndex에 해당하는 값을 위에서 저장한 값으로 정의
- 보내려는 토큰이 마지막 토큰인지 비교하는 조건문이 끝나고
- delete _ownedTokens[_from][latestTokenIndex]
 delete _ownedTokensIndex[_tokenId] : 소유자 기준의 토큰 삭제 (보내는 토큰)
- 이후 받는 계정 쪽에 보낼 토큰에 정보를 추가
- uint length = ERC721.balanceOf(_to)
 _ownedTokens[_to][length] = _tokenId
 _ownedTokensIndex[_tokenId] = length
 
- uint latestTokenIndex = ERC721.balanceOf(_from) -1 : 소유자의 토큰의 마지막 index 저장
 
- _mint() 함수에서 호출 되어서 실행됐을 때 ( _from == address(0) )
- function totalSupply() : 모든 토큰 개수, 길이를 반환한다
- function tokenByIndex(uint _index) : _index를 기준으로 전체 토큰 목록 중 해당하는 token을 반환
- function tokenOfOwnerByIndex (address _owner, uint _index) : 소유자(_owner)와 소유자가 가진 토큰의 _index로 token의 Id를 찾아 반환해 준다
'BlockChain' 카테고리의 다른 글
| (BlockChain) Remix 활용 (0) | 2023.03.13 | 
|---|---|
| (BlockChain) Token Swap (0) | 2023.03.13 | 
| (BlockChain) ERC721 구현 (0) | 2023.03.12 | 
| (BlockChain) IERC721 구현 (0) | 2023.03.11 | 
| (BlockChain) IERC721Metadata 구현 (0) | 2023.03.10 |