// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "./IERC5334.sol"; contract ERC5334 is ERC721, IERC5334 { struct UserInfo { address user; // address of user role uint64 expires; // unix timestamp, user expires uint8 level; // user level } mapping (uint256 => UserInfo) internal _users; constructor(string memory name_, string memory symbol_) ERC721(name_,symbol_) { } /// @notice set the user and expires and level of a NFT /// @dev The zero address indicates there is no user /// Throws if `tokenId` is not valid NFT /// @param user The new user of the NFT /// @param expires UNIX timestamp, The new user could use the NFT before expires /// @param level user level function setUser(uint256 tokenId, address user, uint64 expires, uint8 level) public virtual{ require(_isApprovedOrOwner(msg.sender, tokenId),"ERC721: transfer caller is not owner nor approved"); UserInfo storage info = _users[tokenId]; info.user = user; info.expires = expires; info.level = level emit UpdateUser(tokenId,user,expires,level); } /// @notice Get the user address of an NFT /// @dev The zero address indicates that there is no user or the user is expired /// @param tokenId The NFT to get the user address for /// @return The user address for this NFT function userOf(uint256 tokenId)public view virtual returns(address){ if( uint256(_users[tokenId].expires) >= block.timestamp){ return _users[tokenId].user; } else{ return address(0); } } /// @notice Get the user expires of an NFT /// @dev The zero value indicates that there is no user /// @param tokenId The NFT to get the user expires for /// @return The user expires for this NFT function userExpires(uint256 tokenId) public view virtual returns(uint256){ return _users[tokenId].expires; } /// @notice Get the user level of an NFT /// @dev The zero value indicates that there is no user /// @param tokenId The NFT to get the user level for /// @return The user level for this NFT function userLevel(uint256 tokenId) public view virtual returns(uint256){ return _users[tokenId].level; } /// @dev See {IERC165-supportsInterface}. function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC5334).interfaceId || super.supportsInterface(interfaceId); } function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override{ super._beforeTokenTransfer(from, to, tokenId); if (from != to && _users[tokenId].user != address(0)) { delete _users[tokenId]; emit UpdateUser(tokenId, address(0), 0, 0); } } }