// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; abstract contract BEBase is AccessControl, ERC721Enumerable, Ownable { mapping(uint256 => bool) public lockedTokens; string private _baseTokenURI = "https://market.cebg.games/api/nft/info/"; bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE"); bytes32 public constant LOCK_ROLE = keccak256("LOCK_ROLE"); event Lock(uint256 indexed tokenId); event UnLock(uint256 indexed tokenId); function _baseURI() internal view virtual override returns (string memory) { return _baseTokenURI; } /** * @dev Creates a new token for `to`. Its token ID will be automatically * assigned (and available on the emitted {IERC721-Transfer} event), and the token * URI autogenerated based on the base URI passed at construction. * * See {ERC721-_mint}. * * Requirements: * * - the caller must have the `MINTER_ROLE`. */ function mint( address to, uint256 tokenId ) external virtual onlyRole(MINTER_ROLE) { require(!_exists(tokenId), "Must have unique tokenId"); _mint(to, tokenId); } /** * @dev Add factory to mint item */ function setMintFactory(address factory) external onlyOwner { _grantRole(MINTER_ROLE, factory); } /** * @dev Remove factory */ function removeMintFactory(address factory) external onlyOwner { _revokeRole(MINTER_ROLE, factory); } /** * @dev Add factory to burn item */ function grantBurnRole(address proxy) external onlyOwner { _grantRole(BURN_ROLE, proxy); } /** * @dev Remove proxy */ function revokeBurnProxy(address proxy) external onlyOwner { _revokeRole(BURN_ROLE, proxy); } /** * @dev Add address to lock item */ function grantLockRole(address account) external onlyOwner { _grantRole(LOCK_ROLE, account); } /** * @dev Remove address for lock item */ function revokeLockRole(address account) external onlyOwner { _revokeRole(LOCK_ROLE, account); } /** * @dev Lock token to use in game or for rental */ function lock(uint256 tokenId) external onlyRole(LOCK_ROLE) { require(_exists(tokenId), "Must be valid tokenId"); require(!lockedTokens[tokenId], "Token has already locked"); lockedTokens[tokenId] = true; emit Lock(tokenId); } /** * @dev Unlock token to use blockchain or sale on marketplace */ function unlock(uint256 tokenId) external onlyRole(LOCK_ROLE) { require(_exists(tokenId), "Must be valid tokenId"); require(lockedTokens[tokenId], "Token has already unlocked"); lockedTokens[tokenId] = false; emit UnLock(tokenId); } /** * @dev Get lock status */ function isLocked(uint256 tokenId) external view returns (bool) { return lockedTokens[tokenId]; } /** * @dev Set token URI */ function updateBaseURI(string calldata baseTokenURI) external onlyOwner { _baseTokenURI = baseTokenURI; } /** * @dev See {IERC165-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface( bytes4 interfaceId ) public view virtual override(AccessControl, ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } /** * @dev Burns `tokenId`. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn( address owner, uint256 tokenId ) external virtual onlyRole(BURN_ROLE) { require(_exists(tokenId), "TokenId not exists"); require(!lockedTokens[tokenId], "Can not burn locked token"); require( ownerOf(tokenId) == owner, "current address is not owner of this item now" ); _burn(tokenId); } }