DCIPs/assets/eip-5496/contracts/extensions/ERC5496Cloneable.sol

58 lines
2.3 KiB
Solidity

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../ERC5496.sol";
import "./IERC5496Cloneable.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC5496Cloneable is ERC5496, IERC5496Cloneable {
struct CloneableRecord {
// account => shared
mapping(address => bool) shared;
// account => refer
mapping(address => address) referrer;
}
// privId => isCloneable
mapping(uint => bool) public cloneable;
// tokenId => privId => CloneableRecord
mapping(uint => mapping(uint => CloneableRecord)) cloneableSetting;
function supportsInterface(bytes4 interfaceId) public override virtual view returns (bool) {
return interfaceId == type(IERC5496Cloneable).interfaceId || super.supportsInterface(interfaceId);
}
function hasPrivilege(
uint256 tokenId,
uint256 privId,
address user
) public override virtual view returns(bool) {
if ( privilegeBook[tokenId].privilegeEntry[privId].expiresAt >= block.timestamp ){
return cloneableSetting[tokenId][privId].shared[user] || super.hasPrivilege(tokenId, privId, user);
}
return ownerOf(tokenId) == user;
}
function clonePrivilege(uint tokenId, uint privId, address referrer) external returns (bool) {
require(cloneable[privId], "privilege not cloneable");
return _clonePrivilege(tokenId, privId, referrer);
}
function _clonePrivilege(uint tokenId, uint privId, address referrer) internal returns (bool) {
require(privilegeBook[tokenId].privilegeEntry[privId].user == referrer || cloneableSetting[tokenId][privId].shared[referrer], "referrer not exists");
if (cloneableSetting[tokenId][privId].referrer[msg.sender] == address(0)) {
cloneableSetting[tokenId][privId].shared[msg.sender] = true;
cloneableSetting[tokenId][privId].referrer[msg.sender] = referrer;
emit PrivilegeCloned(tokenId, privId, referrer, msg.sender);
return true;
}
return false;
}
}