refactor: FleekERC721

This commit is contained in:
Felipe Mendes 2022-11-28 15:36:26 -03:00
parent 2c4c5ed59f
commit e07d6852ab
2 changed files with 124 additions and 71 deletions

View File

@ -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));
}
}

View File

@ -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];
}
}
}