Update ERC721 to latest 1.11.0 from OpenZeppelin-solidity (#11)
* Update ERC721 to latest 1.11.0 from OpenZeppelin-solidity * Hardcode supported interfaces instead of using lookup table. This avoids shifting storage when extending supports interface. * Update build artifacts * Fix linter errors
This commit is contained in:
committed by
GitHub
parent
8f4610e007
commit
c46f0353d1
20
contracts/introspection/ERC165.sol
Normal file
20
contracts/introspection/ERC165.sol
Normal file
@ -0,0 +1,20 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC165
|
||||
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||
*/
|
||||
interface ERC165 {
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface
|
||||
* @param _interfaceId The interface identifier, as specified in ERC-165
|
||||
* @dev Interface identification is specified in ERC-165. This function
|
||||
* uses less than 30,000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
}
|
||||
32
contracts/introspection/ERC165Support.sol
Normal file
32
contracts/introspection/ERC165Support.sol
Normal file
@ -0,0 +1,32 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./ERC165.sol";
|
||||
|
||||
/**
|
||||
* @title ERC165Support
|
||||
* @dev Implements ERC165 returning true for ERC165 interface identifier
|
||||
*/
|
||||
contract ERC165Support is ERC165 {
|
||||
|
||||
bytes4 internal constant InterfaceId_ERC165 = 0x01ffc9a7;
|
||||
/**
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _supportsInterface(_interfaceId);
|
||||
}
|
||||
|
||||
function _supportsInterface(bytes4 _interfaceId)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _interfaceId == InterfaceId_ERC165;
|
||||
}
|
||||
}
|
||||
@ -7,15 +7,22 @@ contract ERC721ReceiverMock is ERC721Receiver {
|
||||
bytes4 retval;
|
||||
bool reverts;
|
||||
|
||||
event Received(address _address, uint256 _tokenId, bytes _data, uint256 _gas);
|
||||
event Received(
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data,
|
||||
uint256 _gas
|
||||
);
|
||||
|
||||
function ERC721ReceiverMock(bytes4 _retval, bool _reverts) public {
|
||||
constructor(bytes4 _retval, bool _reverts) public {
|
||||
retval = _retval;
|
||||
reverts = _reverts;
|
||||
}
|
||||
|
||||
function onERC721Received(
|
||||
address _address,
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data
|
||||
)
|
||||
@ -24,7 +31,8 @@ contract ERC721ReceiverMock is ERC721Receiver {
|
||||
{
|
||||
require(!reverts);
|
||||
emit Received(
|
||||
_address,
|
||||
_operator,
|
||||
_from,
|
||||
_tokenId,
|
||||
_data,
|
||||
gasleft() // msg.gas was deprecated in solidityv0.4.21
|
||||
|
||||
@ -9,7 +9,7 @@ import "../token/ERC721/ERC721Token.sol";
|
||||
* and a public setter for metadata URI
|
||||
*/
|
||||
contract ERC721TokenMock is ERC721Token {
|
||||
function ERC721TokenMock(string name, string symbol) public {
|
||||
constructor(string name, string symbol) public {
|
||||
ERC721Token.initialize(name, symbol);
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,14 @@ 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 tokenOfOwnerByIndex(
|
||||
address _owner,
|
||||
uint256 _index
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (uint256 _tokenId);
|
||||
|
||||
function tokenByIndex(uint256 _index) public view returns (uint256);
|
||||
}
|
||||
|
||||
@ -19,8 +26,8 @@ contract ERC721Enumerable is ERC721Basic {
|
||||
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
*/
|
||||
contract ERC721Metadata is ERC721Basic {
|
||||
function name() public view returns (string _name);
|
||||
function symbol() public view returns (string _symbol);
|
||||
function name() external view returns (string _name);
|
||||
function symbol() external view returns (string _symbol);
|
||||
function tokenURI(uint256 _tokenId) public view returns (string);
|
||||
}
|
||||
|
||||
|
||||
@ -1,27 +1,45 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../../introspection/ERC165.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721 Non-Fungible Token Standard basic interface
|
||||
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
*/
|
||||
contract ERC721Basic {
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
|
||||
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
|
||||
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
|
||||
contract ERC721Basic is ERC165 {
|
||||
event Transfer(
|
||||
address indexed _from,
|
||||
address indexed _to,
|
||||
uint256 indexed _tokenId
|
||||
);
|
||||
event Approval(
|
||||
address indexed _owner,
|
||||
address indexed _approved,
|
||||
uint256 indexed _tokenId
|
||||
);
|
||||
event ApprovalForAll(
|
||||
address indexed _owner,
|
||||
address indexed _operator,
|
||||
bool _approved
|
||||
);
|
||||
|
||||
function balanceOf(address _owner) public view returns (uint256 _balance);
|
||||
function ownerOf(uint256 _tokenId) public view returns (address _owner);
|
||||
function exists(uint256 _tokenId) public view returns (bool _exists);
|
||||
|
||||
function approve(address _to, uint256 _tokenId) public;
|
||||
function getApproved(uint256 _tokenId) public view returns (address _operator);
|
||||
function getApproved(uint256 _tokenId)
|
||||
public view returns (address _operator);
|
||||
|
||||
function setApprovalForAll(address _operator, bool _approved) public;
|
||||
function isApprovedForAll(address _owner, address _operator) public view returns (bool);
|
||||
function isApprovedForAll(address _owner, address _operator)
|
||||
public view returns (bool);
|
||||
|
||||
function transferFrom(address _from, address _to, uint256 _tokenId) public;
|
||||
function safeTransferFrom(address _from, address _to, uint256 _tokenId) public;
|
||||
function safeTransferFrom(address _from, address _to, uint256 _tokenId)
|
||||
public;
|
||||
|
||||
function safeTransferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
|
||||
@ -4,19 +4,41 @@ import "./ERC721Basic.sol";
|
||||
import "./ERC721Receiver.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../AddressUtils.sol";
|
||||
import "../../introspection/ERC165Support.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721 Non-Fungible Token Standard basic implementation
|
||||
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
*/
|
||||
contract ERC721BasicToken is ERC721Basic {
|
||||
contract ERC721BasicToken is ERC165Support, ERC721Basic {
|
||||
|
||||
bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;
|
||||
/*
|
||||
* 0x80ac58cd ===
|
||||
* bytes4(keccak256('balanceOf(address)')) ^
|
||||
* bytes4(keccak256('ownerOf(uint256)')) ^
|
||||
* bytes4(keccak256('approve(address,uint256)')) ^
|
||||
* bytes4(keccak256('getApproved(uint256)')) ^
|
||||
* bytes4(keccak256('setApprovalForAll(address,bool)')) ^
|
||||
* bytes4(keccak256('isApprovedForAll(address,address)')) ^
|
||||
* bytes4(keccak256('transferFrom(address,address,uint256)')) ^
|
||||
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
|
||||
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
|
||||
*/
|
||||
|
||||
bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;
|
||||
/*
|
||||
* 0x4f558e79 ===
|
||||
* bytes4(keccak256('exists(uint256)'))
|
||||
*/
|
||||
|
||||
using SafeMath for uint256;
|
||||
using AddressUtils for address;
|
||||
|
||||
// Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
|
||||
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
|
||||
// which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
|
||||
bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
|
||||
bytes4 private constant ERC721_RECEIVED = 0x150b7a02;
|
||||
|
||||
// Mapping from token ID to owner
|
||||
mapping (uint256 => address) internal tokenOwner;
|
||||
@ -48,6 +70,15 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
_;
|
||||
}
|
||||
|
||||
function _supportsInterface(bytes4 _interfaceId)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return super._supportsInterface(_interfaceId) ||
|
||||
_interfaceId == InterfaceId_ERC721 || _interfaceId == InterfaceId_ERC721Exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the balance of the specified address
|
||||
* @param _owner address to query the balance of
|
||||
@ -71,7 +102,7 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Returns whether the specified token exists
|
||||
* @param _tokenId uint256 ID of the token to query the existance of
|
||||
* @param _tokenId uint256 ID of the token to query the existence of
|
||||
* @return whether the token exists
|
||||
*/
|
||||
function exists(uint256 _tokenId) public view returns (bool) {
|
||||
@ -81,9 +112,9 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Approves another address to transfer the given token ID
|
||||
* @dev The zero address indicates there is no approved address.
|
||||
* @dev There can only be one approved address per token at a given time.
|
||||
* @dev Can only be called by the token owner or an approved operator.
|
||||
* The zero address indicates there is no approved address.
|
||||
* There can only be one approved address per token at a given time.
|
||||
* Can only be called by the token owner or an approved operator.
|
||||
* @param _to address to be approved for the given token ID
|
||||
* @param _tokenId uint256 ID of the token to be approved
|
||||
*/
|
||||
@ -92,16 +123,14 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
require(_to != owner);
|
||||
require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
|
||||
|
||||
if (getApproved(_tokenId) != address(0) || _to != address(0)) {
|
||||
tokenApprovals[_tokenId] = _to;
|
||||
emit Approval(owner, _to, _tokenId);
|
||||
}
|
||||
tokenApprovals[_tokenId] = _to;
|
||||
emit Approval(owner, _to, _tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the approved address for a token ID, or zero if no address set
|
||||
* @param _tokenId uint256 ID of the token to query the approval of
|
||||
* @return address currently approved for a the given token ID
|
||||
* @return address currently approved for the given token ID
|
||||
*/
|
||||
function getApproved(uint256 _tokenId) public view returns (address) {
|
||||
return tokenApprovals[_tokenId];
|
||||
@ -109,7 +138,7 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Sets or unsets the approval of a given operator
|
||||
* @dev An operator is allowed to transfer all tokens of the sender on their behalf
|
||||
* An operator is allowed to transfer all tokens of the sender on their behalf
|
||||
* @param _to operator address to set the approval
|
||||
* @param _approved representing the status of the approval to be set
|
||||
*/
|
||||
@ -125,19 +154,33 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
* @param _operator operator address which you want to query the approval of
|
||||
* @return bool whether the given operator is approved by the given owner
|
||||
*/
|
||||
function isApprovedForAll(address _owner, address _operator) public view returns (bool) {
|
||||
function isApprovedForAll(
|
||||
address _owner,
|
||||
address _operator
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return operatorApprovals[_owner][_operator];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers the ownership of a given token ID to another address
|
||||
* @dev Usage of this method is discouraged, use `safeTransferFrom` whenever possible
|
||||
* @dev Requires the msg sender to be the owner, approved, or operator
|
||||
* Usage of this method is discouraged, use `safeTransferFrom` whenever possible
|
||||
* Requires the msg sender to be the owner, approved, or operator
|
||||
* @param _from current owner of the token
|
||||
* @param _to address to receive the ownership of the given token ID
|
||||
* @param _tokenId uint256 ID of the token to be transferred
|
||||
*/
|
||||
function transferFrom(address _from, address _to, uint256 _tokenId) public canTransfer(_tokenId) {
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _tokenId
|
||||
)
|
||||
public
|
||||
canTransfer(_tokenId)
|
||||
{
|
||||
require(_from != address(0));
|
||||
require(_to != address(0));
|
||||
|
||||
@ -150,11 +193,12 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Safely transfers the ownership of a given token ID to another address
|
||||
* @dev If the target address is a contract, it must implement `onERC721Received`,
|
||||
* which is called upon a safe transfer, and return the magic value
|
||||
* `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
|
||||
* the transfer is reverted.
|
||||
* @dev Requires the msg sender to be the owner, approved, or operator
|
||||
* If the target address is a contract, it must implement `onERC721Received`,
|
||||
* which is called upon a safe transfer, and return the magic value
|
||||
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
|
||||
* the transfer is reverted.
|
||||
*
|
||||
* Requires the msg sender to be the owner, approved, or operator
|
||||
* @param _from current owner of the token
|
||||
* @param _to address to receive the ownership of the given token ID
|
||||
* @param _tokenId uint256 ID of the token to be transferred
|
||||
@ -173,11 +217,11 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Safely transfers the ownership of a given token ID to another address
|
||||
* @dev If the target address is a contract, it must implement `onERC721Received`,
|
||||
* which is called upon a safe transfer, and return the magic value
|
||||
* `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
|
||||
* the transfer is reverted.
|
||||
* @dev Requires the msg sender to be the owner, approved, or operator
|
||||
* If the target address is a contract, it must implement `onERC721Received`,
|
||||
* which is called upon a safe transfer, and return the magic value
|
||||
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
|
||||
* the transfer is reverted.
|
||||
* Requires the msg sender to be the owner, approved, or operator
|
||||
* @param _from current owner of the token
|
||||
* @param _to address to receive the ownership of the given token ID
|
||||
* @param _tokenId uint256 ID of the token to be transferred
|
||||
@ -204,14 +248,28 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
* @return bool whether the msg.sender is approved for the given token ID,
|
||||
* is an operator of the owner, or is the owner of the token
|
||||
*/
|
||||
function isApprovedOrOwner(address _spender, uint256 _tokenId) internal view returns (bool) {
|
||||
function isApprovedOrOwner(
|
||||
address _spender,
|
||||
uint256 _tokenId
|
||||
)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
address owner = ownerOf(_tokenId);
|
||||
return _spender == owner || getApproved(_tokenId) == _spender || isApprovedForAll(owner, _spender);
|
||||
// Disable solium check because of
|
||||
// https://github.com/duaraghav8/Solium/issues/175
|
||||
// solium-disable-next-line operator-whitespace
|
||||
return (
|
||||
_spender == owner ||
|
||||
getApproved(_tokenId) == _spender ||
|
||||
isApprovedForAll(owner, _spender)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal function to mint a new token
|
||||
* @dev Reverts if the given token ID already exists
|
||||
* Reverts if the given token ID already exists
|
||||
* @param _to The address that will own the minted token
|
||||
* @param _tokenId uint256 ID of the token to be minted by the msg.sender
|
||||
*/
|
||||
@ -223,7 +281,7 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Internal function to burn a specific token
|
||||
* @dev Reverts if the token does not exist
|
||||
* Reverts if the token does not exist
|
||||
* @param _tokenId uint256 ID of the token being burned by the msg.sender
|
||||
*/
|
||||
function _burn(address _owner, uint256 _tokenId) internal {
|
||||
@ -234,7 +292,7 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Internal function to clear current approval of a given token ID
|
||||
* @dev Reverts if the given address is not indeed the owner of the token
|
||||
* Reverts if the given address is not indeed the owner of the token
|
||||
* @param _owner owner of the token
|
||||
* @param _tokenId uint256 ID of the token to be transferred
|
||||
*/
|
||||
@ -242,7 +300,6 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
require(ownerOf(_tokenId) == _owner);
|
||||
if (tokenApprovals[_tokenId] != address(0)) {
|
||||
tokenApprovals[_tokenId] = address(0);
|
||||
emit Approval(_owner, address(0), _tokenId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +327,7 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
|
||||
/**
|
||||
* @dev Internal function to invoke `onERC721Received` on a target address
|
||||
* @dev The call is not executed if the target address is not a contract
|
||||
* The call is not executed if the target address is not a contract
|
||||
* @param _from address representing the previous owner of the given token ID
|
||||
* @param _to target address that will receive the tokens
|
||||
* @param _tokenId uint256 ID of the token to be transferred
|
||||
@ -289,7 +346,8 @@ contract ERC721BasicToken is ERC721Basic {
|
||||
if (!_to.isContract()) {
|
||||
return true;
|
||||
}
|
||||
bytes4 retval = ERC721Receiver(_to).onERC721Received(_from, _tokenId, _data);
|
||||
bytes4 retval = ERC721Receiver(_to).onERC721Received(
|
||||
msg.sender, _from, _tokenId, _data);
|
||||
return (retval == ERC721_RECEIVED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import "./ERC721Receiver.sol";
|
||||
|
||||
|
||||
contract ERC721Holder is ERC721Receiver {
|
||||
function onERC721Received(address, uint256, bytes) public returns(bytes4) {
|
||||
function onERC721Received(address, address, uint256, bytes) public returns(bytes4) {
|
||||
return ERC721_RECEIVED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,27 +4,35 @@ pragma solidity ^0.4.21;
|
||||
/**
|
||||
* @title ERC721 token receiver interface
|
||||
* @dev Interface for any contract that wants to support safeTransfers
|
||||
* from ERC721 asset contracts.
|
||||
* from ERC721 asset contracts.
|
||||
*/
|
||||
contract ERC721Receiver {
|
||||
/**
|
||||
* @dev Magic value to be returned upon successful reception of an NFT
|
||||
* Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`,
|
||||
* Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`,
|
||||
* which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
|
||||
*/
|
||||
bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
|
||||
bytes4 internal constant ERC721_RECEIVED = 0x150b7a02;
|
||||
|
||||
/**
|
||||
* @notice Handle the receipt of an NFT
|
||||
* @dev The ERC721 smart contract calls this function on the recipient
|
||||
* after a `safetransfer`. This function MAY throw to revert and reject the
|
||||
* transfer. This function MUST use 50,000 gas or less. Return of other
|
||||
* than the magic value MUST result in the transaction being reverted.
|
||||
* Note: the contract address is always the message sender.
|
||||
* @param _from The sending address
|
||||
* after a `safetransfer`. This function MAY throw to revert and reject the
|
||||
* transfer. Return of other than the magic value MUST result in the
|
||||
* transaction being reverted.
|
||||
* Note: the contract address is always the message sender.
|
||||
* @param _operator The address which called `safeTransferFrom` function
|
||||
* @param _from The address which previously owned the token
|
||||
* @param _tokenId The NFT identifier which is being transfered
|
||||
* @param _data Additional data with no specified format
|
||||
* @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
|
||||
* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
|
||||
*/
|
||||
function onERC721Received(address _from, uint256 _tokenId, bytes _data) public returns(bytes4);
|
||||
function onERC721Received(
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data
|
||||
)
|
||||
public
|
||||
returns(bytes4);
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ pragma solidity ^0.4.21;
|
||||
|
||||
import "./ERC721.sol";
|
||||
import "./ERC721BasicToken.sol";
|
||||
import "../../introspection/ERC165.sol";
|
||||
import "zos-lib/contracts/migrations/Migratable.sol";
|
||||
|
||||
|
||||
@ -11,7 +12,24 @@ import "zos-lib/contracts/migrations/Migratable.sol";
|
||||
* Moreover, it includes approve all functionality using operator terminology
|
||||
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
*/
|
||||
contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
contract ERC721Token is Migratable, ERC165Support, ERC721BasicToken, ERC721 {
|
||||
|
||||
bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
|
||||
/**
|
||||
* 0x780e9d63 ===
|
||||
* bytes4(keccak256('totalSupply()')) ^
|
||||
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^
|
||||
* bytes4(keccak256('tokenByIndex(uint256)'))
|
||||
*/
|
||||
|
||||
bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
|
||||
/**
|
||||
* 0x5b5e139f ===
|
||||
* bytes4(keccak256('name()')) ^
|
||||
* bytes4(keccak256('symbol()')) ^
|
||||
* bytes4(keccak256('tokenURI(uint256)'))
|
||||
*/
|
||||
|
||||
// Token name
|
||||
string internal name_;
|
||||
|
||||
@ -19,7 +37,7 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
string internal symbol_;
|
||||
|
||||
// Mapping from owner to list of owned token IDs
|
||||
mapping (address => uint256[]) internal ownedTokens;
|
||||
mapping(address => uint256[]) internal ownedTokens;
|
||||
|
||||
// Mapping from token ID to index of the owner tokens list
|
||||
mapping(uint256 => uint256) internal ownedTokensIndex;
|
||||
@ -41,11 +59,20 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
symbol_ = _symbol;
|
||||
}
|
||||
|
||||
function _supportsInterface(bytes4 _interfaceId)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return super._supportsInterface(_interfaceId) ||
|
||||
_interfaceId == InterfaceId_ERC721Enumerable || _interfaceId == InterfaceId_ERC721Metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the token name
|
||||
* @return string representing the token name
|
||||
*/
|
||||
function name() public view returns (string) {
|
||||
function name() external view returns (string) {
|
||||
return name_;
|
||||
}
|
||||
|
||||
@ -53,13 +80,13 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
* @dev Gets the token symbol
|
||||
* @return string representing the token symbol
|
||||
*/
|
||||
function symbol() public view returns (string) {
|
||||
function symbol() external view returns (string) {
|
||||
return symbol_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns an URI for a given token ID
|
||||
* @dev Throws if the token ID does not exist. May return an empty string.
|
||||
* Throws if the token ID does not exist. May return an empty string.
|
||||
* @param _tokenId uint256 ID of the token to query
|
||||
*/
|
||||
function tokenURI(uint256 _tokenId) public view returns (string) {
|
||||
@ -73,7 +100,14 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
* @param _index uint256 representing the index to be accessed of the requested tokens list
|
||||
* @return uint256 token ID at the given index of the tokens list owned by the requested address
|
||||
*/
|
||||
function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256) {
|
||||
function tokenOfOwnerByIndex(
|
||||
address _owner,
|
||||
uint256 _index
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
require(_index < balanceOf(_owner));
|
||||
return ownedTokens[_owner][_index];
|
||||
}
|
||||
@ -88,7 +122,7 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
|
||||
/**
|
||||
* @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
|
||||
* 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
|
||||
*/
|
||||
@ -99,7 +133,7 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
|
||||
/**
|
||||
* @dev Internal function to set the token URI for a given token
|
||||
* @dev Reverts if the token ID does not exist
|
||||
* Reverts if the token ID does not exist
|
||||
* @param _tokenId uint256 ID of the token to set its URI
|
||||
* @param _uri string URI to assign
|
||||
*/
|
||||
@ -145,7 +179,7 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
|
||||
/**
|
||||
* @dev Internal function to mint a new token
|
||||
* @dev Reverts if the given token ID already exists
|
||||
* 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
|
||||
*/
|
||||
@ -158,7 +192,7 @@ contract ERC721Token is Migratable, ERC721, ERC721BasicToken {
|
||||
|
||||
/**
|
||||
* @dev Internal function to burn a specific token
|
||||
* @dev Reverts if the token does not exist
|
||||
* 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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user