// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.18; import "./SmartAssetBase.sol"; import "../Interfaces/ISmartAssetUpdatable.sol"; /** * @title SmartAssetUpdatable. * @author Arianee - Dynamic NFTs for real-world use cases and consumer engagement (www.arianee.org). */ abstract contract SmartAssetUpdatable is SmartAssetBase, ISmartAssetUpdatable { /** * @notice Mapping from token id to its last update. */ mapping(uint256 => TokenUpdate) internal idToLastUpdate; /** * @notice This emits when a token is updated. */ event TokenUpdated(uint256 indexed tokenId, bytes32 indexed imprint); /** * Update a token imprint. * @param tokenId The token ID. * @param newImprint The new token imprint. */ function updateToken(uint256 tokenId, bytes32 newImprint) external isIssuer(tokenId) { _requireMinted(tokenId); idToLastUpdate[tokenId] = TokenUpdate({imprint: newImprint, updateTimestamp: block.timestamp}); emit TokenUpdated(tokenId, newImprint); } /** * @notice Try to retrieve the last update of a given token. * @dev Throws if the token is not minted. * @param tokenId The token ID. * @return The last update of the token if any. */ function getLastUpdateOf(uint256 tokenId) public view returns (TokenUpdate memory) { _requireMinted(tokenId); return idToLastUpdate[tokenId]; } /** * @notice Try to retrieve the last imprint of a given token. * @dev If the token has never been updated, the original imprint is returned. * @param tokenId The token ID. * @return The last imprint of the token. */ function getLastImprintOf(uint256 tokenId) public view returns (bytes32) { TokenUpdate memory lastUpdate = getLastUpdateOf(tokenId); if (lastUpdate.updateTimestamp == 0) { return super.imprintOf(tokenId); } else { return lastUpdate.imprint; } } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(ISmartAssetUpdatable).interfaceId || super.supportsInterface(interfaceId); } }