|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/extensions/ERC721URIStorage.sol)
|
|
|
|
|
|
|
|
pragma solidity ^0.8.20;
|
|
|
|
|
|
|
|
import {ERC721} from "../ERC721.sol";
|
|
|
|
import {Strings} from "../../../utils/Strings.sol";
|
|
|
|
import {IERC4906} from "../../../interfaces/IERC4906.sol";
|
|
|
|
import {IERC165} from "../../../interfaces/IERC165.sol";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev ERC721 token with storage based token URI management.
|
|
|
|
*/
|
|
|
|
abstract contract ERC721URIStorage is IERC4906, ERC721 {
|
|
|
|
using Strings for uint256;
|
|
|
|
|
|
|
|
// Optional mapping for token URIs
|
|
|
|
mapping(uint256 tokenId => string) private _tokenURIs;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev See {IERC165-supportsInterface}
|
|
|
|
*/
|
|
|
|
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
|
|
|
|
return interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev See {IERC721Metadata-tokenURI}.
|
|
|
|
*/
|
|
|
|
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
|
|
|
|
_requireMinted(tokenId);
|
|
|
|
|
|
|
|
string memory _tokenURI = _tokenURIs[tokenId];
|
|
|
|
string memory base = _baseURI();
|
|
|
|
|
|
|
|
// If there is no base URI, return the token URI.
|
|
|
|
if (bytes(base).length == 0) {
|
|
|
|
return _tokenURI;
|
|
|
|
}
|
|
|
|
// If both are set, concatenate the baseURI and tokenURI (via string.concat).
|
|
|
|
if (bytes(_tokenURI).length > 0) {
|
|
|
|
return string.concat(base, _tokenURI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.tokenURI(tokenId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
|
|
|
|
*
|
|
|
|
* Emits {MetadataUpdate}.
|
|
|
|
*/
|
|
|
|
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
|
|
|
|
_tokenURIs[tokenId] = _tokenURI;
|
|
|
|
emit MetadataUpdate(tokenId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev See {ERC721-_update}. When burning, this override will additionally check if a
|
|
|
|
* token-specific URI was set for the token, and if so, it deletes the token URI from
|
|
|
|
* the storage mapping.
|
|
|
|
*/
|
|
|
|
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
|
|
|
|
address previousOwner = super._update(to, tokenId, auth);
|
|
|
|
|
|
|
|
if (to == address(0) && bytes(_tokenURIs[tokenId]).length != 0) {
|
|
|
|
delete _tokenURIs[tokenId];
|
|
|
|
}
|
|
|
|
|
|
|
|
return previousOwner;
|
|
|
|
}
|
|
|
|
}
|