refactor: FleekERC721
This commit is contained in:
parent
2c4c5ed59f
commit
e07d6852ab
|
|
@ -6,29 +6,45 @@ import "../interfaces/IFleekSite.sol";
|
|||
import "@openzeppelin/contracts/access/AccessControl.sol";
|
||||
|
||||
abstract contract FleekAccessControl is AccessControl {
|
||||
bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE");
|
||||
bytes32 public constant CONTROLLER_ROLE = keccak256("CONTROLLER_ROLE");
|
||||
bytes32 public constant COLLECTION_OWNER_ROLE =
|
||||
keccak256("COLLECTION_OWNER_ROLE");
|
||||
bytes32 public constant COLLECTION_CONTROLLER_ROLE =
|
||||
keccak256("COLLECTION_CONTROLLER_ROLE");
|
||||
|
||||
constructor() {
|
||||
_setRoleAdmin(OWNER_ROLE, DEFAULT_ADMIN_ROLE);
|
||||
_grantRole(OWNER_ROLE, msg.sender);
|
||||
_setRoleAdmin(COLLECTION_OWNER_ROLE, DEFAULT_ADMIN_ROLE);
|
||||
_grantRole(COLLECTION_OWNER_ROLE, msg.sender);
|
||||
}
|
||||
|
||||
modifier requireOwner() {
|
||||
modifier requireCollectionOwner() {
|
||||
require(
|
||||
hasRole(OWNER_ROLE, msg.sender),
|
||||
"FleekAccessControl: must have owner role"
|
||||
hasRole(COLLECTION_OWNER_ROLE, msg.sender),
|
||||
"FleekAccessControl: must have collection owner role"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier requireController() {
|
||||
bool hasPermission = hasRole(CONTROLLER_ROLE, msg.sender) ||
|
||||
hasRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
||||
modifier requireCollectionController() {
|
||||
require(
|
||||
hasPermission,
|
||||
"FleekAccessControl: caller is not a controller"
|
||||
hasRole(COOLECTION_OWNER_ROLE, msg.sender) ||
|
||||
hasRole(COLLECTION_CONTROLLER_ROLE, msg.sender),
|
||||
"FleekAccessControl: must have collection controller role"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier requireTokenController(uint256 tokenId) {
|
||||
require(
|
||||
hasRole(_tokenRole(tokenId, "CONTROLLER"), msg.sender),
|
||||
"FleekAccessControl: must have token role"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
function _tokenRole(
|
||||
uint256 tokenId,
|
||||
string role
|
||||
) internal pure returns (bytes32) {
|
||||
return keccak256(abi.encodePacked("TOKEN_", role, tokenId));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,87 +2,124 @@
|
|||
|
||||
pragma solidity ^0.8.7;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
|
||||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
||||
import "@openzeppelin/contracts/utils/Counters.sol";
|
||||
import "./FleekAccessControl.sol";
|
||||
import "../interfaces/IFleekERC721.sol";
|
||||
import "./FleekSite.sol";
|
||||
|
||||
contract FleekERC721 is IFleekERC721, ERC721URIStorage, FleekAccessControl {
|
||||
contract FleekERC721 is ERC721, FleekAccessControl {
|
||||
using Strings for uint256;
|
||||
using Counters for Counters.Counter;
|
||||
|
||||
Counters.Counter private _tokenIds;
|
||||
mapping(uint256 => address) private _contracts;
|
||||
struct Build {
|
||||
string _commit;
|
||||
string _repository;
|
||||
}
|
||||
|
||||
constructor(
|
||||
string memory name,
|
||||
string memory symbol
|
||||
) ERC721(name, symbol) {}
|
||||
struct Site {
|
||||
string URI; //ipfs hash example
|
||||
string ENS;
|
||||
uint256 currentBuild;
|
||||
Build[] builds;
|
||||
}
|
||||
|
||||
Counters.Counter private _tokenIds;
|
||||
mapping(uint256 => Site) private _sites;
|
||||
|
||||
modifier requireMinted(uint256 tokenId) {
|
||||
require(_requireMinted(tokenId), "FleekERC721: token not minted");
|
||||
}
|
||||
|
||||
function mint(
|
||||
uint8 fleekContract,
|
||||
string memory base64EncodedMetadata,
|
||||
address account
|
||||
) public override requireController returns (uint256) {
|
||||
uint256 newItemId = _tokenIds.current();
|
||||
_safeMint(account, newItemId);
|
||||
_setTokenURI(newItemId, base64EncodedMetadata);
|
||||
|
||||
// it should be something like a switch
|
||||
if (fleekContract == FleekContract.Site) {
|
||||
_mintSite(newItemId, account);
|
||||
}
|
||||
|
||||
address to,
|
||||
string memory URI,
|
||||
string memory ENS,
|
||||
string memory commit,
|
||||
string memory repository
|
||||
) public payable requireCollectionOwner returns (uint256) {
|
||||
uint256 tokenId = _tokenIds.current();
|
||||
_grantRole(_tokenRole(tokenId), to);
|
||||
_mint(to, tokenId);
|
||||
_tokenIds.increment();
|
||||
return newItemId;
|
||||
_sites[tokenId] = Site(URI, ENS, 0, [Build(commit, repository)]);
|
||||
return tokenId;
|
||||
}
|
||||
|
||||
function updateTokenURI(
|
||||
address tokenHolderAddress,
|
||||
function upgradeTokenBuild(
|
||||
uint256 tokenId,
|
||||
string memory base64EncodedMetadata
|
||||
) public override requireController {
|
||||
address tokenOwner = ownerOf(tokenId);
|
||||
require(
|
||||
tokenOwner == tokenHolderAddress,
|
||||
"Address does not own provided tokenId"
|
||||
);
|
||||
_setTokenURI(tokenId, base64EncodedMetadata);
|
||||
string memory commit,
|
||||
string memory repository
|
||||
) public payable require requireMinted(tokenId) requireTokenOwner(tokenId) {
|
||||
_setTokenBuild(commit, repository);
|
||||
}
|
||||
|
||||
function getCurrentTokenId() public view override returns (uint256) {
|
||||
return _tokenIds.current();
|
||||
}
|
||||
|
||||
function supportsInterface(
|
||||
bytes4 interfaceId
|
||||
function tokenURI(
|
||||
uint256 tokenId
|
||||
)
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override(IERC165, ERC721, AccessControl)
|
||||
returns (bool)
|
||||
override
|
||||
requireMinted(tokenId)
|
||||
returns (string memory)
|
||||
{
|
||||
return super.supportsInterface(interfaceId);
|
||||
}
|
||||
address memory owner = ownerOf(tokenId);
|
||||
Site memory site = _sites[tokenId];
|
||||
|
||||
function tokenContract(
|
||||
uint256 tokenId
|
||||
) public view override returns (address) {
|
||||
return _contracts[tokenId];
|
||||
}
|
||||
|
||||
function _mintSite(
|
||||
uint256 _newTokenId,
|
||||
address account
|
||||
) internal returns (address) {
|
||||
// it should receive the parameters from user request
|
||||
_contracts[_newTokenId] = FleekSite(
|
||||
"name",
|
||||
"description",
|
||||
"thumbnail",
|
||||
"external_url"
|
||||
// prettier-ignore
|
||||
bytes memory dataURI = abi.encodePacked(
|
||||
'{',
|
||||
'"owner":"', owner, '",',
|
||||
'"ENS":"', site.ENS, '",',
|
||||
'"URI":"', site.URI, '",',
|
||||
'"build:{',
|
||||
'"id":"', site.currentBuild, '",',
|
||||
'"commit":"', site.builds[site.currentBuild]._commit, '",',
|
||||
'"repository":"', site.builds[site.currentBuild]._repository, '"'
|
||||
'}',
|
||||
'}'
|
||||
);
|
||||
return _contracts[_newTokenId];
|
||||
|
||||
return string(abi.encodePacked(_baseURI(), dataURI));
|
||||
}
|
||||
|
||||
function _baseURI() internal view virtual override returns (string memory) {
|
||||
return "data:application/json;base64,";
|
||||
}
|
||||
|
||||
function _setTokenURI(
|
||||
uint256 tokenId,
|
||||
string memory _tokenURI
|
||||
) internal virtual requireMinted(tokenId) requireTokenController(tokenId) {
|
||||
_sites[tokenId].URI = _tokenURI;
|
||||
}
|
||||
|
||||
function _setTokenENS(
|
||||
uint256 tokenId,
|
||||
string memory _tokenENS
|
||||
) internal virtual requireMinted(tokenId) requireTokenController(tokenId) {
|
||||
_sites[tokenId].ENS = _tokenENS;
|
||||
}
|
||||
|
||||
function _setTokenBuild(
|
||||
uint256 tokenId,
|
||||
string memory _commit,
|
||||
string memory _repository
|
||||
) internal virtual requireMinted(tokenId) requireTokenController(tokenId) {
|
||||
_sites[tokenId].builds.push(Build(_commit, _repository));
|
||||
_sites[tokenId].currentBuild = _sites[tokenId].builds.length - 1;
|
||||
}
|
||||
|
||||
function _burn(uint256 tokenId) internal virtual override {
|
||||
require(
|
||||
ownerOf(tokenId) == msg.sender,
|
||||
"FleekERC721: must be token owner"
|
||||
);
|
||||
super._burn(tokenId);
|
||||
|
||||
if (bytes(_sites[tokenId]).length != 0) {
|
||||
delete _sites[tokenId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue