例如,一家当地的披萨店提供 30% 的折扣券,并且该店的老板鼓励他们的消费者与朋友分享该优惠券,然后朋友就可以获得该优惠券。假设 Tom 从商店获得了 30% 的折扣券,并且他与 Alice 分享了该优惠券。Alice 也获得了该优惠券,并且 Alice 的推荐人是 Tom。在某些特定情况下,Tom 可能会从商店获得更多奖励。这将有助于商家在消费者中传播促销活动。
functionunwrap(uint256tokenId,addressto)external{require(getBlockTimestamp()>=privilegeBook[tokenId].lastExpiresAt,"privilege not yet expired");require(ownerOf(tokenId)==msg.sender,"not owner");_burn(tokenId);IERC721(nft).transferFrom(address(this),to,tokenId);emitUnwrap(nft,tokenId,msg.sender,to);}
// SPDX-License-Identifier: CC0-1.0
pragmasolidity^0.8.0;import"@openzeppelin/contracts/token/ERC721/ERC721.sol";import"@openzeppelin/contracts/utils/introspection/IERC165.sol";import"./IERC5496.sol";contractERC5496isERC721,IERC5496{structPrivilegeRecord{addressuser;uint256expiresAt;}structPrivilegeStorage{uintlastExpiresAt;// privId => PrivilegeRecord
mapping(uint=>PrivilegeRecord)privilegeEntry;}uintpublicprivilegeTotal;// tokenId => PrivilegeStorage
mapping(uint=>PrivilegeStorage)publicprivilegeBook;mapping(address=>mapping(address=>bool))privateprivilegeDelegator;constructor(stringmemoryname_,stringmemorysymbol_)ERC721(name_,symbol_){}functionsetPrivilege(uinttokenId,uintprivId,addressuser,uint64expires)externalvirtual{require((hasPrivilege(tokenId,privId,ownerOf(tokenId))&&_isApprovedOrOwner(msg.sender,tokenId))||_isDelegatorOrHolder(msg.sender,tokenId,privId),"ERC721: transfer caller is not owner nor approved");require(expires<block.timestamp+30days,"expire time invalid");require(privId<privilegeTotal,"invalid privilege id");privilegeBook[tokenId].privilegeEntry[privId].user=user;if(_isApprovedOrOwner(msg.sender,tokenId)){privilegeBook[tokenId].privilegeEntry[privId].expiresAt=expires;if(privilegeBook[tokenId].lastExpiresAt<expires){privilegeBook[tokenId].lastExpiresAt=expires;}}emitPrivilegeAssigned(tokenId,privId,user,uint64(privilegeBook[tokenId].privilegeEntry[privId].expiresAt));}functionhasPrivilege(uint256tokenId,uint256privId,addressuser)publicvirtualviewreturns(bool){if(privilegeBook[tokenId].privilegeEntry[privId].expiresAt>=block.timestamp){returnprivilegeBook[tokenId].privilegeEntry[privId].user==user;}returnownerOf(tokenId)==user;}functionprivilegeExpires(uint256tokenId,uint256privId)publicvirtualviewreturns(uint256){returnprivilegeBook[tokenId].privilegeEntry[privId].expiresAt;}function_setPrivilegeTotal(uinttotal)internal{emitPrivilegeTotalChanged(total,privilegeTotal);privilegeTotal=total;}functiongetPrivilegeInfo(uinttokenId,uintprivId)externalviewreturns(addressuser,uint256expiresAt){return(privilegeBook[tokenId].privilegeEntry[privId].user,privilegeBook[tokenId].privilegeEntry[privId].expiresAt);}functionsetDelegator(addressdelegator,boolenabled)external{privilegeDelegator[msg.sender][delegator]=enabled;}function_isDelegatorOrHolder(addressdelegator,uint256tokenId,uintprivId)internalvirtualviewreturns(bool){addressholder=privilegeBook[tokenId].privilegeEntry[privId].user;return(delegator==holder||isApprovedForAll(holder,delegator)||privilegeDelegator[holder][delegator]);}functionsupportsInterface(bytes4interfaceId)publicoverridevirtualviewreturns(bool){returninterfaceId==type(IERC5496).interfaceId||super.supportsInterface(interfaceId);}}