123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- pragma solidity ^0.6.0;
- import "../../GSN/Context.sol";
- import "./ERC721.sol";
- import "./IERC721Metadata.sol";
- import "../../introspection/ERC165.sol";
- contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
- // Token name
- string private _name;
- // Token symbol
- string private _symbol;
- // Optional mapping for token URIs
- mapping(uint256 => string) private _tokenURIs;
- // Base URI
- string private _baseURI;
- /*
- * bytes4(keccak256('name()')) == 0x06fdde03
- * bytes4(keccak256('symbol()')) == 0x95d89b41
- * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
- *
- * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
- */
- bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
- /**
- * @dev Constructor function
- */
- constructor (string memory name, string memory symbol) public {
- _name = name;
- _symbol = symbol;
- // register the supported interfaces to conform to ERC721 via ERC165
- _registerInterface(_INTERFACE_ID_ERC721_METADATA);
- }
- /**
- * @dev Gets the token name.
- * @return string representing the token name
- */
- function name() external view override returns (string memory) {
- return _name;
- }
- /**
- * @dev Gets the token symbol.
- * @return string representing the token symbol
- */
- function symbol() external view override returns (string memory) {
- return _symbol;
- }
- /**
- * @dev Returns the URI for a given token ID. May return an empty string.
- *
- * If the token's URI is non-empty and a base URI was set (via
- * {_setBaseURI}), it will be added to the token ID's URI as a prefix.
- *
- * Reverts if the token ID does not exist.
- */
- function tokenURI(uint256 tokenId) external view override returns (string memory) {
- require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
- string memory _tokenURI = _tokenURIs[tokenId];
- // Even if there is a base URI, it is only appended to non-empty token-specific URIs
- if (bytes(_tokenURI).length == 0) {
- return "";
- } else {
- // abi.encodePacked is being used to concatenate strings
- return string(abi.encodePacked(_baseURI, _tokenURI));
- }
- }
- /**
- * @dev Internal function to set the token URI for a given token.
- *
- * Reverts if the token ID does not exist.
- *
- * TIP: if all token IDs share a prefix (e.g. if your URIs look like
- * `http://api.myproject.com/token/<id>`), use {_setBaseURI} to store
- * it and save gas.
- */
- function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
- require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
- _tokenURIs[tokenId] = _tokenURI;
- }
- /**
- * @dev Internal function to set the base URI for all token IDs. It is
- * automatically added as a prefix to the value returned in {tokenURI}.
- */
- function _setBaseURI(string memory baseURI) internal virtual {
- _baseURI = baseURI;
- }
- /**
- * @dev Returns the base URI set via {_setBaseURI}. This will be
- * automatically added as a preffix in {tokenURI} to each token's URI, when
- * they are non-empty.
- */
- function baseURI() external view returns (string memory) {
- return _baseURI;
- }
- function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
- super._beforeTokenTransfer(from, to, tokenId);
- if (to == address(0)) { // When burning tokens
- // Clear metadata (if any)
- if (bytes(_tokenURIs[tokenId]).length != 0) {
- delete _tokenURIs[tokenId];
- }
- }
- }
- }
|