Implement tokensByIndex extension

- Remove restrictions from mock mint and burn calls
This commit is contained in:
Santiago Palladino
2018-03-09 12:58:16 -03:00
parent d726c79e5f
commit 54a1d2eacc
8 changed files with 184 additions and 60 deletions

View File

@ -7,7 +7,7 @@ import "./ERC721Basic.sol";
contract ERC721Enumerable is ERC721Basic {
function totalSupply() public view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256 _tokenId);
// function tokenByIndex(uint256 _index) public view returns (uint256);
function tokenByIndex(uint256 _index) public view returns (uint256);
}
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension

View File

@ -19,9 +19,6 @@ contract ERC721BasicToken is ERC721Basic {
// Equals to bytes4(keccak256("onERC721Received(address,uint256,bytes)"))
bytes4 ERC721_RECEIVED = 0xf0b9e5ba;
// Total amount of tokens
uint256 internal totalTokens;
// Mapping from token ID to owner
mapping (uint256 => address) internal tokenOwner;
@ -194,7 +191,6 @@ contract ERC721BasicToken is ERC721Basic {
function doMint(address _to, uint256 _tokenId) internal {
require(_to != address(0));
addToken(_to, _tokenId);
totalTokens = totalTokens.add(1);
Transfer(0x0, _to, _tokenId);
}
@ -203,11 +199,10 @@ contract ERC721BasicToken is ERC721Basic {
* @dev Reverts if the token does not exist
* @param _tokenId uint256 ID of the token being burned by the msg.sender
*/
function doBurn(uint256 _tokenId) onlyOwnerOf(_tokenId) internal {
clearApproval(msg.sender, _tokenId);
removeToken(msg.sender, _tokenId);
totalTokens = totalTokens.sub(1);
Transfer(msg.sender, 0x0, _tokenId);
function doBurn(address _owner, uint256 _tokenId) internal {
clearApproval(_owner, _tokenId);
removeToken(_owner, _tokenId);
Transfer(_owner, 0x0, _tokenId);
}
/**

View File

@ -24,6 +24,12 @@ contract ERC721Token is ERC721, ERC721BasicToken {
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) internal ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] internal allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) internal allTokensIndex;
/**
* @dev Constructor function
*/
@ -73,7 +79,18 @@ contract ERC721Token is ERC721, ERC721BasicToken {
* @return uint256 representing the total amount of tokens
*/
function totalSupply() public view returns (uint256) {
return totalTokens;
return allTokens.length;
}
/**
* @dev Gets the token ID at a given index of all the tokens in this contract
* @dev Reverts if the index is greater or equal to the total number of tokens
* @param _index uint256 representing the index to be accessed of the tokens list
* @return uint256 token ID at the given index of the tokens list
*/
function tokenByIndex(uint256 _index) public view returns (uint256) {
require(_index < totalSupply());
return allTokens[_index];
}
/**
@ -113,4 +130,38 @@ contract ERC721Token is ERC721, ERC721BasicToken {
ownedTokensIndex[lastToken] = tokenIndex;
}
/**
* @dev Internal function to mint a new token
* @dev Reverts if the given token ID already exists
* @param _to address the beneficiary that will own the minted token
* @param _tokenId uint256 ID of the token to be minted by the msg.sender
*/
function doMint(address _to, uint256 _tokenId) internal {
super.doMint(_to, _tokenId);
allTokensIndex[_tokenId] = allTokens.length;
allTokens.push(_tokenId);
}
/**
* @dev Internal function to burn a specific token
* @dev Reverts if the token does not exist
* @param _owner owner of the token to burn
* @param _tokenId uint256 ID of the token being burned by the msg.sender
*/
function doBurn(address _owner, uint256 _tokenId) internal {
super.doBurn(_owner, _tokenId);
uint256 tokenIndex = allTokensIndex[_tokenId];
uint256 lastTokenIndex = allTokens.length.sub(1);
uint256 lastToken = allTokens[lastTokenIndex];
allTokens[tokenIndex] = lastToken;
allTokens[lastTokenIndex] = 0;
allTokens.length--;
allTokensIndex[_tokenId] = 0;
allTokensIndex[lastToken] = tokenIndex;
}
}