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"; import "@openzeppelin/contracts/access/AccessControl.sol";
abstract contract FleekAccessControl is AccessControl { abstract contract FleekAccessControl is AccessControl {
bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); bytes32 public constant COLLECTION_OWNER_ROLE =
bytes32 public constant CONTROLLER_ROLE = keccak256("CONTROLLER_ROLE"); keccak256("COLLECTION_OWNER_ROLE");
bytes32 public constant COLLECTION_CONTROLLER_ROLE =
keccak256("COLLECTION_CONTROLLER_ROLE");
constructor() { constructor() {
_setRoleAdmin(OWNER_ROLE, DEFAULT_ADMIN_ROLE); _setRoleAdmin(COLLECTION_OWNER_ROLE, DEFAULT_ADMIN_ROLE);
_grantRole(OWNER_ROLE, msg.sender); _grantRole(COLLECTION_OWNER_ROLE, msg.sender);
} }
modifier requireOwner() { modifier requireCollectionOwner() {
require( require(
hasRole(OWNER_ROLE, msg.sender), hasRole(COLLECTION_OWNER_ROLE, msg.sender),
"FleekAccessControl: must have owner role" "FleekAccessControl: must have collection owner role"
); );
_; _;
} }
modifier requireController() { modifier requireCollectionController() {
bool hasPermission = hasRole(CONTROLLER_ROLE, msg.sender) ||
hasRole(DEFAULT_ADMIN_ROLE, msg.sender);
require( require(
hasPermission, hasRole(COOLECTION_OWNER_ROLE, msg.sender) ||
"FleekAccessControl: caller is not a controller" 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; 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 "@openzeppelin/contracts/utils/Counters.sol";
import "./FleekAccessControl.sol"; import "./FleekAccessControl.sol";
import "../interfaces/IFleekERC721.sol"; import "../interfaces/IFleekERC721.sol";
import "./FleekSite.sol"; import "./FleekSite.sol";
contract FleekERC721 is IFleekERC721, ERC721URIStorage, FleekAccessControl { contract FleekERC721 is ERC721, FleekAccessControl {
using Strings for uint256;
using Counters for Counters.Counter; using Counters for Counters.Counter;
Counters.Counter private _tokenIds; struct Build {
mapping(uint256 => address) private _contracts; string _commit;
string _repository;
}
constructor( struct Site {
string memory name, string URI; //ipfs hash example
string memory symbol string ENS;
) ERC721(name, symbol) {} 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( function mint(
uint8 fleekContract, address to,
string memory base64EncodedMetadata, string memory URI,
address account string memory ENS,
) public override requireController returns (uint256) { string memory commit,
uint256 newItemId = _tokenIds.current(); string memory repository
_safeMint(account, newItemId); ) public payable requireCollectionOwner returns (uint256) {
_setTokenURI(newItemId, base64EncodedMetadata); uint256 tokenId = _tokenIds.current();
_grantRole(_tokenRole(tokenId), to);
// it should be something like a switch _mint(to, tokenId);
if (fleekContract == FleekContract.Site) {
_mintSite(newItemId, account);
}
_tokenIds.increment(); _tokenIds.increment();
return newItemId; _sites[tokenId] = Site(URI, ENS, 0, [Build(commit, repository)]);
return tokenId;
} }
function updateTokenURI( function upgradeTokenBuild(
address tokenHolderAddress,
uint256 tokenId, uint256 tokenId,
string memory base64EncodedMetadata string memory commit,
) public override requireController { string memory repository
address tokenOwner = ownerOf(tokenId); ) public payable require requireMinted(tokenId) requireTokenOwner(tokenId) {
require( _setTokenBuild(commit, repository);
tokenOwner == tokenHolderAddress,
"Address does not own provided tokenId"
);
_setTokenURI(tokenId, base64EncodedMetadata);
} }
function getCurrentTokenId() public view override returns (uint256) { function tokenURI(
return _tokenIds.current(); uint256 tokenId
}
function supportsInterface(
bytes4 interfaceId
) )
public public
view view
virtual virtual
override(IERC165, ERC721, AccessControl) override
returns (bool) requireMinted(tokenId)
returns (string memory)
{ {
return super.supportsInterface(interfaceId); address memory owner = ownerOf(tokenId);
} Site memory site = _sites[tokenId];
function tokenContract( // prettier-ignore
uint256 tokenId bytes memory dataURI = abi.encodePacked(
) public view override returns (address) { '{',
return _contracts[tokenId]; '"owner":"', owner, '",',
} '"ENS":"', site.ENS, '",',
'"URI":"', site.URI, '",',
function _mintSite( '"build:{',
uint256 _newTokenId, '"id":"', site.currentBuild, '",',
address account '"commit":"', site.builds[site.currentBuild]._commit, '",',
) internal returns (address) { '"repository":"', site.builds[site.currentBuild]._repository, '"'
// it should receive the parameters from user request '}',
_contracts[_newTokenId] = FleekSite( '}'
"name",
"description",
"thumbnail",
"external_url"
); );
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];
}
} }
} }