ERC721Metadata.sol 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. pragma solidity ^0.6.0;
  2. import "../../GSN/Context.sol";
  3. import "./ERC721.sol";
  4. import "./IERC721Metadata.sol";
  5. import "../../introspection/ERC165.sol";
  6. contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
  7. // Token name
  8. string private _name;
  9. // Token symbol
  10. string private _symbol;
  11. // Optional mapping for token URIs
  12. mapping(uint256 => string) private _tokenURIs;
  13. // Base URI
  14. string private _baseURI;
  15. /*
  16. * bytes4(keccak256('name()')) == 0x06fdde03
  17. * bytes4(keccak256('symbol()')) == 0x95d89b41
  18. * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
  19. *
  20. * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
  21. */
  22. bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
  23. /**
  24. * @dev Constructor function
  25. */
  26. constructor (string memory name, string memory symbol) public {
  27. _name = name;
  28. _symbol = symbol;
  29. // register the supported interfaces to conform to ERC721 via ERC165
  30. _registerInterface(_INTERFACE_ID_ERC721_METADATA);
  31. }
  32. /**
  33. * @dev Gets the token name.
  34. * @return string representing the token name
  35. */
  36. function name() external view override returns (string memory) {
  37. return _name;
  38. }
  39. /**
  40. * @dev Gets the token symbol.
  41. * @return string representing the token symbol
  42. */
  43. function symbol() external view override returns (string memory) {
  44. return _symbol;
  45. }
  46. /**
  47. * @dev Returns the URI for a given token ID. May return an empty string.
  48. *
  49. * If the token's URI is non-empty and a base URI was set (via
  50. * {_setBaseURI}), it will be added to the token ID's URI as a prefix.
  51. *
  52. * Reverts if the token ID does not exist.
  53. */
  54. function tokenURI(uint256 tokenId) external view override returns (string memory) {
  55. require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
  56. string memory _tokenURI = _tokenURIs[tokenId];
  57. // Even if there is a base URI, it is only appended to non-empty token-specific URIs
  58. if (bytes(_tokenURI).length == 0) {
  59. return "";
  60. } else {
  61. // abi.encodePacked is being used to concatenate strings
  62. return string(abi.encodePacked(_baseURI, _tokenURI));
  63. }
  64. }
  65. /**
  66. * @dev Internal function to set the token URI for a given token.
  67. *
  68. * Reverts if the token ID does not exist.
  69. *
  70. * TIP: if all token IDs share a prefix (e.g. if your URIs look like
  71. * `http://api.myproject.com/token/<id>`), use {_setBaseURI} to store
  72. * it and save gas.
  73. */
  74. function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
  75. require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
  76. _tokenURIs[tokenId] = _tokenURI;
  77. }
  78. /**
  79. * @dev Internal function to set the base URI for all token IDs. It is
  80. * automatically added as a prefix to the value returned in {tokenURI}.
  81. */
  82. function _setBaseURI(string memory baseURI) internal virtual {
  83. _baseURI = baseURI;
  84. }
  85. /**
  86. * @dev Returns the base URI set via {_setBaseURI}. This will be
  87. * automatically added as a preffix in {tokenURI} to each token's URI, when
  88. * they are non-empty.
  89. */
  90. function baseURI() external view returns (string memory) {
  91. return _baseURI;
  92. }
  93. function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
  94. super._beforeTokenTransfer(from, to, tokenId);
  95. if (to == address(0)) { // When burning tokens
  96. // Clear metadata (if any)
  97. if (bytes(_tokenURIs[tokenId]).length != 0) {
  98. delete _tokenURIs[tokenId];
  99. }
  100. }
  101. }
  102. }