Advertisement
Infinity99HD

Untitled

Aug 14th, 2022
1,239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity >=0.8.15;
  3.  
  4. import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; //ERC-1155 STD
  5. import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; //reentrancy guard
  6. import "@openzeppelin/contracts/access/Ownable.sol"; //onlyOwner modifier
  7. import "@openzeppelin/contracts/utils/Counters.sol"; //implements Counter object
  8. import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol"; //ERC-1155 STD
  9. import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; //implements RBAC for its current token
  10. import "./Utilities.sol";
  11.  
  12. contract Platform_ERC1155 is ERC1155,ReentrancyGuard,Ownable,AccessControlEnumerable
  13. {
  14.    
  15.     mapping (uint256 => string) private _tokenURIs; //keep track of token URIs
  16.     mapping (uint256 => bool) public isNFT; //keep track of which tokens are ERC20-like and which others are ERC721-like
  17.     mapping (uint256 => bool) private tokenMinted; //keep track of already minted tokenIds
  18.     mapping (uint256 => bool) private isBurnable; //keep track of burnable tokens
  19.  
  20.     address[] public childNFT_address; //keep track of minted ERC20 objects in the blockchain. NOT YET IMPLEMENTED
  21.  
  22.     string internal _contractURI; //opensea contract-level metadata : https://docs.opensea.io/docs/contract-level-metadata
  23.  
  24.     //Access Control Roles declaration
  25.     bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); //has minting permissions (can create CustomNFT istances)
  26.     bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); //has burn permissions (can burn custom NFTs)
  27.     bytes32 public constant READER_ROLE = keccak256("READER_ROLE"); //has read permission about roles and CustomNFT objects
  28.     bytes32 public constant LIMITED_ROLE = keccak256("LIMITED_ROLE"); //allows childNFTs to read Platform status such as permissions
  29.  
  30.     constructor(string memory contract_uri) ERC1155("")
  31.     {
  32.         _contractURI = contract_uri;
  33.         _grantRole(DEFAULT_ADMIN_ROLE,msg.sender);
  34.     }
  35.  
  36.  
  37.     /**
  38.      * @dev return custom contract URI (collection metadata) as described by OpenSea: https://docs.opensea.io/docs/contract-level-metadata
  39.      *
  40.      */
  41.     function contractURI() public view returns (string memory) { return _contractURI; }
  42.  
  43.     /**
  44.      * @dev custom Mint implementation. Allows to check for contract_uri, burnable and NFT validation.
  45.      *
  46.      * @param to: address, the target of our mint
  47.      * @param tokenId: uint, token id we want to mint (can be both existent or not)
  48.      * @param amount: uint, amount of tokenId we want to mint
  49.      * @param contract_uri: string, URI we want to assign to tokenID, is set only if it's the first time minting the specific tokenId
  50.      * @param burnable: bool, allows the user to burn token with burnToken() function.
  51.      * @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)
  52.      *
  53.      */
  54.     function mint(address to, uint256 tokenId, uint256 amount, string memory contract_uri, bool burnable, bool _isNFT) public nonReentrant onlyRole(MINTER_ROLE)
  55.     {
  56.         require(!Utilities.compareStrings(contract_uri,""),"Token URI cannot be empty!");
  57.  
  58.         if(_exists(tokenId)) { _mint(to,tokenId,amount,""); } //if it exist already, just mint the NFT
  59.         else
  60.         {
  61.             _mint(to,tokenId,amount,"");
  62.             tokenMinted[tokenId] = true;
  63.  
  64.             //allows users to block current token burn. this is permanent.
  65.             if(burnable) { isBurnable[tokenId] = true; }
  66.             else { isBurnable[tokenId] = false; }
  67.  
  68.             if(_isNFT) //check if the token wants to be an ERC20 or ERC721 standard
  69.             {
  70.                 _setTokenUri(tokenId,contract_uri);
  71.                 isNFT[tokenId] = true;
  72.             }
  73.             else
  74.             {
  75.                 // SAMPLE CODE, TO BE DONE YET
  76.  
  77.                 // CustomNFT newContract = new CustomNFT(name,symbol,NFT_Platform(address(this)));
  78.                 // childNFT_address.push(address(newContract));
  79.                 // childNFT[name] = newContract;
  80.                 // _grantRole(LIMITED_ROLE, address(newContract)); //allows contracts to call hasPermission, see LIMITED_ROLE comment
  81.             }
  82.         }
  83.     }
  84.  
  85.     function mint2(address to, uint256 tokenId, uint256 amount, string memory contract_uri, bool burnable, bool _isNFT) public nonReentrant //only for test purposes
  86.     {
  87.         require(!Utilities.compareStrings(contract_uri,""),"Token URI cannot be empty!");
  88.  
  89.         if(_exists(tokenId)) { _mint(to,tokenId,amount,""); } //if it exist already, just mint the NFT
  90.         else
  91.         {
  92.             _mint(to,tokenId,amount,"");
  93.             tokenMinted[tokenId] = true;
  94.  
  95.             //allows users to block current token burn. this is permanent.
  96.             if(burnable) { isBurnable[tokenId] = true; }
  97.             else { isBurnable[tokenId] = false; }
  98.  
  99.             if(_isNFT) //check if the token wants to be an ERC20 or ERC721 standard
  100.             {
  101.                 _setTokenUri(tokenId,contract_uri);
  102.                 isNFT[tokenId] = true;
  103.             }
  104.             else
  105.             {
  106.                 // SAMPLE CODE, TO BE DONE YET
  107.  
  108.                 // CustomNFT newContract = new CustomNFT(name,symbol,NFT_Platform(address(this)));
  109.                 // childNFT_address.push(address(newContract));
  110.                 // childNFT[name] = newContract;
  111.                 // _grantRole(LIMITED_ROLE, address(newContract)); //allows contracts to call hasPermission, see LIMITED_ROLE comment
  112.             }
  113.         }
  114.     }
  115.  
  116.     /**
  117.      * @dev token burn custom implementation. Allows to control which tokenId is burnable (by the mint function) and to effectively burn it
  118.      * from the blockchain.
  119.      *
  120.      * @param contract_address: address, of tokenId owner
  121.      * @param tokenId: uint, token id we want to burn
  122.      * @param amount: uint, amount of tokenId we want to burn
  123.      *
  124.      */
  125.     function burnToken(address contract_address, uint256 tokenId, uint256 amount) public nonReentrant onlyRole(BURNER_ROLE) //definitely destroys a token
  126.     {
  127.         require(_exists(tokenId),"Token not existent!");    
  128.         require(isBurnable[tokenId], "Token is not burnable!");
  129.        
  130.         _burn(contract_address,tokenId,amount);
  131.         _tokenURIs[tokenId] = ""; //restore mapping to default value
  132.         tokenMinted[tokenId] = false;
  133.  
  134.         //no need to emit event, ERC721 takes care of this with a Transfer to the 0 address by default
  135.     }
  136.  
  137.     function burnToken2(address contract_address, uint256 tokenId, uint256 amount) public nonReentrant //only for test purposes
  138.     {
  139.         require(_exists(tokenId),"Token not existent!");    
  140.         require(isBurnable[tokenId], "Token is not burnable!");
  141.        
  142.         _burn(contract_address,tokenId,amount);
  143.         _tokenURIs[tokenId] = ""; //restore mapping to default value
  144.         tokenMinted[tokenId] = false;
  145.  
  146.         //no need to emit event, ERC721 takes care of this with a Transfer event to the 0 address by default
  147.     }
  148.  
  149.     /**
  150.      * @dev _exists custom ERC1155 implementation. Allow to check if a specific tokenId exist.
  151.      *
  152.      * @param tokenId: uint, token id of which we want to check the existence
  153.      */
  154.     function _exists(uint256 tokenId) internal view virtual returns (bool) { return tokenMinted[tokenId]; }
  155.  
  156.     /**
  157.      * @dev uri function override, allows to assign a custom URI for each token ID
  158.      *
  159.      * @param tokenId: uint, token id of which we want to get the URI set by _SetTokenURI
  160.      */
  161.     function uri(uint256 tokenId) override public view returns (string memory)
  162.     {
  163.         require(_exists(tokenId),"ERC1155: query for non-existent object");
  164.         return(_tokenURIs[tokenId]);
  165.     }
  166.  
  167.     /**
  168.      * @dev Custom _SetTokenURI ERC721 implementation. Allows URIs to be different for each tokenId
  169.      *
  170.      * @param tokenId: integer, the ID of which we want to change URI
  171.      * @param tokenURI: string, valid internet URI reachable by the blockchain on which there's a JSON Stored following
  172.      * OpenSeas's metadata standards: https://docs.opensea.io/docs/metadata-standards  
  173.      *
  174.      */
  175.     function _setTokenUri(uint256 tokenId, string memory tokenURI) private
  176.     {
  177.          _tokenURIs[tokenId] = tokenURI;
  178.          emit URI(uri(tokenId), tokenId);
  179.     }
  180.  
  181.     /**
  182.      * @dev This function returns an array of addresses associated with custom "role" account
  183.      *
  184.      * Requirements: AccessControlEnumerable imported in custom contract
  185.      *
  186.      * @param role: string, role that will be converted in bytes of which we want to enumerate addresses
  187.      */
  188.     function getPrivilegedAccounts(string memory role) public view onlyRole(READER_ROLE) returns(address[] memory)
  189.     {
  190.         bytes32 role_bytes = keccak256(abi.encodePacked(role));
  191.  
  192.         address[] memory members = new address[](getRoleMemberCount(role_bytes));
  193.         for(uint i=0; i < getRoleMemberCount(role_bytes); i ++) { members[i] = getRoleMember(role_bytes,i); }
  194.  
  195.         return members;
  196.     }
  197.  
  198.     function getPrivilegedAccounts2(string memory role) public view returns(address[] memory) //only for test purposes
  199.     {
  200.         bytes32 role_bytes = keccak256(abi.encodePacked(role));
  201.  
  202.         address[] memory members = new address[](getRoleMemberCount(role_bytes));
  203.         for(uint i=0; i < getRoleMemberCount(role_bytes); i ++) { members[i] = getRoleMember(role_bytes,i); }
  204.  
  205.         return members;
  206.     }
  207.  
  208.     function supportsInterface(bytes4 interfaceId) public view override(ERC1155, AccessControlEnumerable) returns (bool) { return super.supportsInterface(interfaceId); }
  209.  
  210. }
  211.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement