Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // SPDX-License-Identifier: GPL-3.0
- pragma solidity >=0.8.15;
- import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; //ERC-1155 STD
- import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; //reentrancy guard
- import "@openzeppelin/contracts/access/Ownable.sol"; //onlyOwner modifier
- import "@openzeppelin/contracts/utils/Counters.sol"; //implements Counter object
- import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol"; //ERC-1155 STD
- import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; //implements RBAC for its current token
- import "./Utilities.sol";
- contract Platform_ERC1155 is ERC1155,ReentrancyGuard,Ownable,AccessControlEnumerable
- {
- mapping (uint256 => string) private _tokenURIs; //keep track of token URIs
- mapping (uint256 => bool) public isNFT; //keep track of which tokens are ERC20-like and which others are ERC721-like
- mapping (uint256 => bool) private tokenMinted; //keep track of already minted tokenIds
- mapping (uint256 => bool) private isBurnable; //keep track of burnable tokens
- address[] public childNFT_address; //keep track of minted ERC20 objects in the blockchain. NOT YET IMPLEMENTED
- string internal _contractURI; //opensea contract-level metadata : https://docs.opensea.io/docs/contract-level-metadata
- //Access Control Roles declaration
- bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); //has minting permissions (can create CustomNFT istances)
- bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); //has burn permissions (can burn custom NFTs)
- bytes32 public constant READER_ROLE = keccak256("READER_ROLE"); //has read permission about roles and CustomNFT objects
- bytes32 public constant LIMITED_ROLE = keccak256("LIMITED_ROLE"); //allows childNFTs to read Platform status such as permissions
- constructor(string memory contract_uri) ERC1155("")
- {
- _contractURI = contract_uri;
- _grantRole(DEFAULT_ADMIN_ROLE,msg.sender);
- }
- /**
- * @dev return custom contract URI (collection metadata) as described by OpenSea: https://docs.opensea.io/docs/contract-level-metadata
- *
- */
- function contractURI() public view returns (string memory) { return _contractURI; }
- /**
- * @dev custom Mint implementation. Allows to check for contract_uri, burnable and NFT validation.
- *
- * @param to: address, the target of our mint
- * @param tokenId: uint, token id we want to mint (can be both existent or not)
- * @param amount: uint, amount of tokenId we want to mint
- * @param contract_uri: string, URI we want to assign to tokenID, is set only if it's the first time minting the specific tokenId
- * @param burnable: bool, allows the user to burn token with burnToken() function.
- * @param _isNFT: bool, allows the user to know if token minted is ERC20 or ERC721-like (for erc20 tokens, a separated contract is deployed on the blockchain)
- *
- */
- function mint(address to, uint256 tokenId, uint256 amount, string memory contract_uri, bool burnable, bool _isNFT) public nonReentrant onlyRole(MINTER_ROLE)
- {
- require(!Utilities.compareStrings(contract_uri,""),"Token URI cannot be empty!");
- if(_exists(tokenId)) { _mint(to,tokenId,amount,""); } //if it exist already, just mint the NFT
- else
- {
- _mint(to,tokenId,amount,"");
- tokenMinted[tokenId] = true;
- //allows users to block current token burn. this is permanent.
- if(burnable) { isBurnable[tokenId] = true; }
- else { isBurnable[tokenId] = false; }
- if(_isNFT) //check if the token wants to be an ERC20 or ERC721 standard
- {
- _setTokenUri(tokenId,contract_uri);
- isNFT[tokenId] = true;
- }
- else
- {
- // SAMPLE CODE, TO BE DONE YET
- // CustomNFT newContract = new CustomNFT(name,symbol,NFT_Platform(address(this)));
- // childNFT_address.push(address(newContract));
- // childNFT[name] = newContract;
- // _grantRole(LIMITED_ROLE, address(newContract)); //allows contracts to call hasPermission, see LIMITED_ROLE comment
- }
- }
- }
- function mint2(address to, uint256 tokenId, uint256 amount, string memory contract_uri, bool burnable, bool _isNFT) public nonReentrant //only for test purposes
- {
- require(!Utilities.compareStrings(contract_uri,""),"Token URI cannot be empty!");
- if(_exists(tokenId)) { _mint(to,tokenId,amount,""); } //if it exist already, just mint the NFT
- else
- {
- _mint(to,tokenId,amount,"");
- tokenMinted[tokenId] = true;
- //allows users to block current token burn. this is permanent.
- if(burnable) { isBurnable[tokenId] = true; }
- else { isBurnable[tokenId] = false; }
- if(_isNFT) //check if the token wants to be an ERC20 or ERC721 standard
- {
- _setTokenUri(tokenId,contract_uri);
- isNFT[tokenId] = true;
- }
- else
- {
- // SAMPLE CODE, TO BE DONE YET
- // CustomNFT newContract = new CustomNFT(name,symbol,NFT_Platform(address(this)));
- // childNFT_address.push(address(newContract));
- // childNFT[name] = newContract;
- // _grantRole(LIMITED_ROLE, address(newContract)); //allows contracts to call hasPermission, see LIMITED_ROLE comment
- }
- }
- }
- /**
- * @dev token burn custom implementation. Allows to control which tokenId is burnable (by the mint function) and to effectively burn it
- * from the blockchain.
- *
- * @param contract_address: address, of tokenId owner
- * @param tokenId: uint, token id we want to burn
- * @param amount: uint, amount of tokenId we want to burn
- *
- */
- function burnToken(address contract_address, uint256 tokenId, uint256 amount) public nonReentrant onlyRole(BURNER_ROLE) //definitely destroys a token
- {
- require(_exists(tokenId),"Token not existent!");
- require(isBurnable[tokenId], "Token is not burnable!");
- _burn(contract_address,tokenId,amount);
- _tokenURIs[tokenId] = ""; //restore mapping to default value
- tokenMinted[tokenId] = false;
- //no need to emit event, ERC721 takes care of this with a Transfer to the 0 address by default
- }
- function burnToken2(address contract_address, uint256 tokenId, uint256 amount) public nonReentrant //only for test purposes
- {
- require(_exists(tokenId),"Token not existent!");
- require(isBurnable[tokenId], "Token is not burnable!");
- _burn(contract_address,tokenId,amount);
- _tokenURIs[tokenId] = ""; //restore mapping to default value
- tokenMinted[tokenId] = false;
- //no need to emit event, ERC721 takes care of this with a Transfer event to the 0 address by default
- }
- /**
- * @dev _exists custom ERC1155 implementation. Allow to check if a specific tokenId exist.
- *
- * @param tokenId: uint, token id of which we want to check the existence
- */
- function _exists(uint256 tokenId) internal view virtual returns (bool) { return tokenMinted[tokenId]; }
- /**
- * @dev uri function override, allows to assign a custom URI for each token ID
- *
- * @param tokenId: uint, token id of which we want to get the URI set by _SetTokenURI
- */
- function uri(uint256 tokenId) override public view returns (string memory)
- {
- require(_exists(tokenId),"ERC1155: query for non-existent object");
- return(_tokenURIs[tokenId]);
- }
- /**
- * @dev Custom _SetTokenURI ERC721 implementation. Allows URIs to be different for each tokenId
- *
- * @param tokenId: integer, the ID of which we want to change URI
- * @param tokenURI: string, valid internet URI reachable by the blockchain on which there's a JSON Stored following
- * OpenSeas's metadata standards: https://docs.opensea.io/docs/metadata-standards
- *
- */
- function _setTokenUri(uint256 tokenId, string memory tokenURI) private
- {
- _tokenURIs[tokenId] = tokenURI;
- emit URI(uri(tokenId), tokenId);
- }
- /**
- * @dev This function returns an array of addresses associated with custom "role" account
- *
- * Requirements: AccessControlEnumerable imported in custom contract
- *
- * @param role: string, role that will be converted in bytes of which we want to enumerate addresses
- */
- function getPrivilegedAccounts(string memory role) public view onlyRole(READER_ROLE) returns(address[] memory)
- {
- bytes32 role_bytes = keccak256(abi.encodePacked(role));
- address[] memory members = new address[](getRoleMemberCount(role_bytes));
- for(uint i=0; i < getRoleMemberCount(role_bytes); i ++) { members[i] = getRoleMember(role_bytes,i); }
- return members;
- }
- function getPrivilegedAccounts2(string memory role) public view returns(address[] memory) //only for test purposes
- {
- bytes32 role_bytes = keccak256(abi.encodePacked(role));
- address[] memory members = new address[](getRoleMemberCount(role_bytes));
- for(uint i=0; i < getRoleMemberCount(role_bytes); i ++) { members[i] = getRoleMember(role_bytes,i); }
- return members;
- }
- function supportsInterface(bytes4 interfaceId) public view override(ERC1155, AccessControlEnumerable) returns (bool) { return super.supportsInterface(interfaceId); }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement