782 lines
22 KiB
Solidity
782 lines
22 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
|
|
pragma solidity ^0.8.7;
|
|
|
|
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
|
|
import "@openzeppelin/contracts/utils/Base64.sol";
|
|
import "@openzeppelin/contracts/utils/Strings.sol";
|
|
import "./FleekAccessControl.sol";
|
|
import "./FleekBilling.sol";
|
|
import "./FleekPausable.sol";
|
|
import "./FleekAccessPoints.sol";
|
|
import "./util/FleekENS.sol";
|
|
import "./util/FleekStrings.sol";
|
|
import "./IERCX.sol";
|
|
|
|
error MustBeTokenOwner(uint256 tokenId);
|
|
error MustBeTokenVerifier(uint256 tokenId);
|
|
error ThereIsNoTokenMinted();
|
|
|
|
contract FleekERC721 is
|
|
IERCX,
|
|
Initializable,
|
|
ERC721Upgradeable,
|
|
FleekAccessControl,
|
|
FleekPausable,
|
|
FleekBilling,
|
|
FleekAccessPoints
|
|
{
|
|
using Strings for uint256;
|
|
using FleekStrings for FleekERC721.Token;
|
|
using FleekStrings for string;
|
|
using FleekStrings for uint24;
|
|
|
|
event NewMint(
|
|
uint256 indexed tokenId,
|
|
string name,
|
|
string description,
|
|
string externalURL,
|
|
string ENS,
|
|
string commitHash,
|
|
string gitRepository,
|
|
string logo,
|
|
uint24 color,
|
|
bool accessPointAutoApproval,
|
|
address indexed minter,
|
|
address indexed owner,
|
|
address verifier
|
|
);
|
|
|
|
event MetadataUpdate(uint256 indexed _tokenId, string key, address value, address indexed triggeredBy);
|
|
|
|
uint256 private _appIds;
|
|
mapping(uint256 => Token) private _apps;
|
|
mapping(uint256 => address) private _tokenVerifier;
|
|
mapping(uint256 => bool) private _tokenVerified;
|
|
|
|
/**
|
|
* @dev This constructor sets the state of implementation contract to paused
|
|
* and disable initializers, not allowing interactions with the implementation
|
|
* contracts.
|
|
*/
|
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
constructor() {
|
|
_setPausable(true);
|
|
_pause();
|
|
_disableInitializers();
|
|
}
|
|
|
|
/**
|
|
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
|
|
*/
|
|
function initialize(
|
|
string memory _name,
|
|
string memory _symbol,
|
|
uint256[] memory initialBillings
|
|
) public initializer {
|
|
__ERC721_init(_name, _symbol);
|
|
__FleekAccessControl_init();
|
|
__FleekBilling_init(initialBillings);
|
|
__FleekPausable_init();
|
|
}
|
|
|
|
/**
|
|
* @dev Checks if caller is the verifier of the token.
|
|
*/
|
|
modifier requireTokenVerifier(uint256 tokenId) {
|
|
if (_tokenVerifier[tokenId] != msg.sender) revert MustBeTokenVerifier(tokenId);
|
|
_;
|
|
}
|
|
|
|
/**
|
|
* @dev Mints a token and returns a tokenId.
|
|
*
|
|
* If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the caller must have ``collectionOwner``'s admin role.
|
|
* - billing for the minting may be applied.
|
|
* - the contract must be not paused.
|
|
*
|
|
*/
|
|
function mint(
|
|
address to,
|
|
string memory name,
|
|
string memory description,
|
|
string memory externalURL,
|
|
string calldata ens,
|
|
string memory commitHash,
|
|
string memory gitRepository,
|
|
string memory logo,
|
|
uint24 color,
|
|
bool accessPointAutoApproval,
|
|
address verifier
|
|
) public payable requirePayment(Billing.Mint) returns (uint256) {
|
|
FleekENS.requireENSOwner(ens);
|
|
uint256 tokenId = _appIds;
|
|
_mint(to, tokenId);
|
|
|
|
_appIds += 1;
|
|
|
|
Token storage app = _apps[tokenId];
|
|
app.name = name;
|
|
app.description = description;
|
|
app.externalURL = externalURL;
|
|
app.ENS = ens;
|
|
app.logo = logo;
|
|
app.color = color;
|
|
|
|
// The mint interaction is considered to be the first build of the site. Updates from now on all increment the currentBuild by one and update the mapping.
|
|
app.currentBuild = 0;
|
|
app.builds[0] = Build(commitHash, gitRepository);
|
|
|
|
emit NewMint(
|
|
tokenId,
|
|
name,
|
|
description,
|
|
externalURL,
|
|
ens,
|
|
commitHash,
|
|
gitRepository,
|
|
logo,
|
|
color,
|
|
accessPointAutoApproval,
|
|
msg.sender,
|
|
to,
|
|
verifier
|
|
);
|
|
|
|
_tokenVerifier[tokenId] = verifier;
|
|
_tokenVerified[tokenId] = false;
|
|
_setAccessPointAutoApproval(tokenId, accessPointAutoApproval);
|
|
|
|
return tokenId;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the token metadata associated with the `tokenId`.
|
|
*
|
|
* Returns a based64 encoded string value of the URI.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
*
|
|
*/
|
|
function tokenURI(uint256 tokenId) public view virtual override(ERC721Upgradeable, IERCX) returns (string memory) {
|
|
_requireMinted(tokenId);
|
|
address owner = ownerOf(tokenId);
|
|
bool accessPointAutoApproval = _getAccessPointAutoApproval(tokenId);
|
|
bool verified = _tokenVerified[tokenId];
|
|
Token storage app = _apps[tokenId];
|
|
|
|
return string(abi.encodePacked(_baseURI(), app.toString(owner, accessPointAutoApproval, verified).toBase64()));
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the token metadata associated with the `tokenId`.
|
|
*
|
|
* Returns multiple string and uint values in relation to metadata fields of the App struct.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
*
|
|
*/
|
|
function getToken(
|
|
uint256 tokenId
|
|
)
|
|
public
|
|
view
|
|
virtual
|
|
returns (string memory, string memory, string memory, string memory, uint256, string memory, uint24)
|
|
{
|
|
_requireMinted(tokenId);
|
|
Token storage app = _apps[tokenId];
|
|
return (app.name, app.description, app.externalURL, app.ENS, app.currentBuild, app.logo, app.color);
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the last minted tokenId.
|
|
*/
|
|
function getLastTokenId() public view virtual returns (uint256) {
|
|
uint256 current = _appIds;
|
|
if (current == 0) revert ThereIsNoTokenMinted();
|
|
return current - 1;
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC165-supportsInterface}.
|
|
*/
|
|
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Upgradeable) returns (bool) {
|
|
return super.supportsInterface(interfaceId);
|
|
}
|
|
|
|
/**
|
|
* @dev Override of _beforeTokenTransfer of ERC721.
|
|
* Here it needs to update the token controller roles for mint, burn and transfer.
|
|
*/
|
|
function _beforeTokenTransfer(
|
|
address from,
|
|
address to,
|
|
uint256 tokenId,
|
|
uint256 batchSize
|
|
) internal virtual override whenNotPaused {
|
|
if (from != address(0) && to != address(0)) {
|
|
// Transfer
|
|
_clearTokenRoles(tokenId);
|
|
} else if (from == address(0)) {
|
|
// Mint
|
|
// TODO: set contract owner as controller
|
|
} else if (to == address(0)) {
|
|
// Burn
|
|
_clearTokenRoles(tokenId);
|
|
}
|
|
super._beforeTokenTransfer(from, to, tokenId, batchSize);
|
|
}
|
|
|
|
/**
|
|
* @dev A baseURI internal function implementation to be called in the `tokenURI` function.
|
|
*/
|
|
function _baseURI() internal view virtual override returns (string memory) {
|
|
return "data:application/json;base64,";
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `externalURL` metadata field of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenExternalURL} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenExternalURL(
|
|
uint256 tokenId,
|
|
string memory _tokenExternalURL
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].externalURL = _tokenExternalURL;
|
|
emit MetadataUpdate(tokenId, "externalURL", _tokenExternalURL, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `ENS` metadata field of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenENS} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenENS(
|
|
uint256 tokenId,
|
|
string calldata _tokenENS
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
FleekENS.requireENSOwner(_tokenENS);
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].ENS = _tokenENS;
|
|
emit MetadataUpdate(tokenId, "ENS", _tokenENS, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `name` metadata field of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenName} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenName(
|
|
uint256 tokenId,
|
|
string memory _tokenName
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].name = _tokenName;
|
|
emit MetadataUpdate(tokenId, "name", _tokenName, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `description` metadata field of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenDescription} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenDescription(
|
|
uint256 tokenId,
|
|
string memory _tokenDescription
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].description = _tokenDescription;
|
|
emit MetadataUpdate(tokenId, "description", _tokenDescription, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `logo` metadata field of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenLogo} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenLogo(
|
|
uint256 tokenId,
|
|
string memory _tokenLogo
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].logo = _tokenLogo;
|
|
emit MetadataUpdate(tokenId, "logo", _tokenLogo, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `color` metadata field of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenColor} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenColor(
|
|
uint256 tokenId,
|
|
uint24 _tokenColor
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].color = _tokenColor;
|
|
emit MetadataUpdate(tokenId, "color", _tokenColor, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `logo` and `color` metadata fields of a minted `tokenId`.
|
|
*
|
|
* May emit a {NewTokenLogo} and a {NewTokenColor} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenLogoAndColor(uint256 tokenId, string memory _tokenLogo, uint24 _tokenColor) public virtual {
|
|
setTokenLogo(tokenId, _tokenLogo);
|
|
setTokenColor(tokenId, _tokenColor);
|
|
}
|
|
|
|
/**
|
|
* @dev Adds a new build to a minted `tokenId`'s builds mapping.
|
|
*
|
|
* May emit a {NewBuild} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setTokenBuild(
|
|
uint256 tokenId,
|
|
string memory _commitHash,
|
|
string memory _gitRepository
|
|
) public virtual requireTokenRole(tokenId, TokenRoles.Controller) {
|
|
_requireMinted(tokenId);
|
|
_apps[tokenId].builds[++_apps[tokenId].currentBuild] = Build(_commitHash, _gitRepository);
|
|
emit MetadataUpdate(tokenId, "build", [_commitHash, _gitRepository], msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Burns a previously minted `tokenId`.
|
|
*
|
|
* May emit a {Transfer} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must be the owner of the token.
|
|
* - the contract must be not paused.
|
|
*
|
|
*/
|
|
function burn(uint256 tokenId) public virtual requireTokenOwner(tokenId) {
|
|
super._burn(tokenId);
|
|
|
|
if (bytes(_apps[tokenId].externalURL).length != 0) {
|
|
delete _apps[tokenId];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @dev Sets an address as verifier of a token.
|
|
* The verifier must have `CollectionRoles.Verifier` role.
|
|
*
|
|
* May emit a {MetadataUpdate} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must be the owner of the token.
|
|
* - the verifier must have `CollectionRoles.Verifier` role.
|
|
*
|
|
*/
|
|
function setTokenVerifier(uint256 tokenId, address verifier) public requireTokenOwner(tokenId) {
|
|
if (!hasCollectionRole(CollectionRoles.Verifier, verifier))
|
|
revert MustHaveCollectionRole(uint8(CollectionRoles.Verifier));
|
|
_requireMinted(tokenId);
|
|
_tokenVerifier[tokenId] = verifier;
|
|
emit MetadataUpdate(tokenId, "verifier", verifier, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the verifier of a token.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
*
|
|
*/
|
|
function getTokenVerifier(uint256 tokenId) public view returns (address) {
|
|
_requireMinted(tokenId);
|
|
return _tokenVerifier[tokenId];
|
|
}
|
|
|
|
/**
|
|
* @dev Sets the verification status of a token.
|
|
*
|
|
* May emit a {MetadataUpdate} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must be the token verifier.
|
|
* - the sender must have `CollectionRoles.Verifier` role.
|
|
*
|
|
*/
|
|
function setTokenVerified(
|
|
uint256 tokenId,
|
|
bool verified
|
|
) public requireCollectionRole(CollectionRoles.Verifier) requireTokenVerifier(tokenId) {
|
|
_requireMinted(tokenId);
|
|
_tokenVerified[tokenId] = verified;
|
|
emit MetadataUpdate(tokenId, "verified", verified, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the verification status of a token.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
*
|
|
*/
|
|
function isTokenVerified(uint256 tokenId) public view returns (bool) {
|
|
_requireMinted(tokenId);
|
|
return _tokenVerified[tokenId];
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////
|
|
ACCESS POINTS
|
|
//////////////////////////////////////////////////////////////*/
|
|
|
|
/**
|
|
* @dev Add a new AccessPoint register for an app token.
|
|
* The AP name should be a DNS or ENS url and it should be unique.
|
|
* Anyone can add an AP but it should requires a payment.
|
|
*
|
|
* May emit a {NewAccessPoint} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - billing for add acess point may be applied.
|
|
* - the contract must be not paused.
|
|
*
|
|
*/
|
|
function addAccessPoint(
|
|
uint256 tokenId,
|
|
string memory apName
|
|
) public payable whenNotPaused requirePayment(Billing.AddAccessPoint) {
|
|
_requireMinted(tokenId);
|
|
_addAccessPoint(tokenId, apName);
|
|
}
|
|
|
|
/**
|
|
* @dev Remove an AccessPoint registry for an app token.
|
|
* It will also remove the AP from the app token APs list.
|
|
*
|
|
* May emit a {RemoveAccessPoint} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the AP must exist.
|
|
* - must be called by the AP owner.
|
|
* - the contract must be not paused.
|
|
*
|
|
*/
|
|
function removeAccessPoint(string memory apName) public whenNotPaused {
|
|
_removeAccessPoint(apName);
|
|
}
|
|
|
|
/**
|
|
* @dev Updates the `accessPointAutoApproval` settings on minted `tokenId`.
|
|
*
|
|
* May emit a {MetadataUpdate} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must be minted and valid.
|
|
* - the sender must have the `tokenController` role.
|
|
*
|
|
*/
|
|
function setAccessPointAutoApproval(uint256 tokenId, bool _apAutoApproval) public requireTokenOwner(tokenId) {
|
|
_requireMinted(tokenId);
|
|
_setAccessPointAutoApproval(tokenId, _apAutoApproval);
|
|
emit MetadataUpdate(tokenId, "accessPointAutoApproval", _apAutoApproval, msg.sender);
|
|
}
|
|
|
|
/**
|
|
* @dev Set approval settings for an access point.
|
|
* It will add the access point to the token's AP list, if `approved` is true.
|
|
*
|
|
* May emit a {ChangeAccessPointApprovalStatus} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the tokenId must exist and be the same as the tokenId that is set for the AP.
|
|
* - the AP must exist.
|
|
* - must be called by a token controller.
|
|
*/
|
|
function setApprovalForAccessPoint(
|
|
uint256 tokenId,
|
|
string memory apName,
|
|
bool approved
|
|
) public requireTokenOwner(tokenId) {
|
|
_setApprovalForAccessPoint(tokenId, apName, approved);
|
|
}
|
|
|
|
/**
|
|
* @dev Set the content verification of a AccessPoint registry.
|
|
*
|
|
* May emit a {ChangeAccessPointContentVerify} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the AP must exist.
|
|
* - the sender must have the token controller role.
|
|
*
|
|
*/
|
|
function setAccessPointContentVerify(
|
|
string memory apName,
|
|
bool verified
|
|
) public requireCollectionRole(CollectionRoles.Verifier) requireTokenVerifier(_getAccessPointTokenId(apName)) {
|
|
_setAccessPointContentVerify(apName, verified);
|
|
}
|
|
|
|
/**
|
|
* @dev Set the name verification of a AccessPoint registry.
|
|
*
|
|
* May emit a {ChangeAccessPointNameVerify} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the AP must exist.
|
|
* - the sender must have the token controller role.
|
|
*
|
|
*/
|
|
function setAccessPointNameVerify(
|
|
string memory apName,
|
|
bool verified
|
|
) public requireCollectionRole(CollectionRoles.Verifier) requireTokenVerifier(_getAccessPointTokenId(apName)) {
|
|
_setAccessPointNameVerify(apName, verified);
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////
|
|
ACCESS CONTROL
|
|
//////////////////////////////////////////////////////////////*/
|
|
|
|
/**
|
|
* @dev Requires caller to have a selected collection role.
|
|
*/
|
|
modifier requireCollectionRole(CollectionRoles role) {
|
|
_requireCollectionRole(role);
|
|
_;
|
|
}
|
|
|
|
/**
|
|
* @dev Requires caller to have a selected token role.
|
|
*/
|
|
modifier requireTokenRole(uint256 tokenId, TokenRoles role) {
|
|
if (ownerOf(tokenId) != msg.sender) _requireTokenRole(tokenId, role);
|
|
_;
|
|
}
|
|
|
|
/**
|
|
* @dev Requires caller to be selected token owner.
|
|
*/
|
|
modifier requireTokenOwner(uint256 tokenId) {
|
|
if (ownerOf(tokenId) != msg.sender) revert MustBeTokenOwner(tokenId);
|
|
_;
|
|
}
|
|
|
|
/**
|
|
* @dev Grants the collection role to an address.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the caller should have the collection role.
|
|
*
|
|
*/
|
|
function grantCollectionRole(
|
|
CollectionRoles role,
|
|
address account
|
|
) public whenNotPaused requireCollectionRole(CollectionRoles.Owner) {
|
|
_grantCollectionRole(role, account);
|
|
}
|
|
|
|
/**
|
|
* @dev Grants the token role to an address.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the caller should have the token role.
|
|
*
|
|
*/
|
|
function grantTokenRole(
|
|
uint256 tokenId,
|
|
TokenRoles role,
|
|
address account
|
|
) public whenNotPaused requireTokenOwner(tokenId) {
|
|
_grantTokenRole(tokenId, role, account);
|
|
}
|
|
|
|
/**
|
|
* @dev Revokes the collection role of an address.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the caller should have the collection role.
|
|
*
|
|
*/
|
|
function revokeCollectionRole(
|
|
CollectionRoles role,
|
|
address account
|
|
) public whenNotPaused requireCollectionRole(CollectionRoles.Owner) {
|
|
_revokeCollectionRole(role, account);
|
|
}
|
|
|
|
/**
|
|
* @dev Revokes the token role of an address.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the caller should have the token role.
|
|
*
|
|
*/
|
|
function revokeTokenRole(
|
|
uint256 tokenId,
|
|
TokenRoles role,
|
|
address account
|
|
) public whenNotPaused requireTokenOwner(tokenId) {
|
|
_revokeTokenRole(tokenId, role, account);
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////
|
|
PAUSABLE
|
|
//////////////////////////////////////////////////////////////*/
|
|
|
|
/**
|
|
* @dev Sets the contract to paused state.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the sender must have the `controller` role.
|
|
* - the contract must be pausable.
|
|
* - the contract must be not paused.
|
|
*
|
|
*/
|
|
function pause() public requireCollectionRole(CollectionRoles.Owner) {
|
|
_pause();
|
|
}
|
|
|
|
/**
|
|
* @dev Sets the contract to unpaused state.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the sender must have the `controller` role.
|
|
* - the contract must be paused.
|
|
*
|
|
*/
|
|
function unpause() public requireCollectionRole(CollectionRoles.Owner) {
|
|
_unpause();
|
|
}
|
|
|
|
/**
|
|
* @dev Sets the contract to pausable state.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the sender must have the `owner` role.
|
|
* - the contract must be in the oposite pausable state.
|
|
*
|
|
*/
|
|
function setPausable(bool pausable) public requireCollectionRole(CollectionRoles.Owner) {
|
|
_setPausable(pausable);
|
|
}
|
|
|
|
/*//////////////////////////////////////////////////////////////
|
|
BILLING
|
|
//////////////////////////////////////////////////////////////*/
|
|
|
|
/**
|
|
* @dev Modifier to require billing with a given key.
|
|
*/
|
|
modifier requirePayment(Billing key) {
|
|
_requirePayment(key);
|
|
_;
|
|
}
|
|
|
|
/**
|
|
* @dev Sets the billing value for a given key.
|
|
*
|
|
* May emit a {BillingChanged} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the sender must have the `collectionOwner` role.
|
|
*
|
|
*/
|
|
function setBilling(Billing key, uint256 value) public requireCollectionRole(CollectionRoles.Owner) {
|
|
_setBilling(key, value);
|
|
}
|
|
|
|
/**
|
|
* @dev Withdraws all the funds from contract.
|
|
*
|
|
* May emmit a {Withdrawn} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - the sender must have the `collectionOwner` role.
|
|
*
|
|
*/
|
|
function withdraw() public requireCollectionRole(CollectionRoles.Owner) {
|
|
_withdraw();
|
|
}
|
|
}
|