BlockChain
(BlockChain) ERC721Enumerable 구현
JJeongHyun
2023. 3. 12. 13:32
반응형
https://developerjjh.tistory.com/173
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를 찾아 반환해 준다