contract SM_ART_NFT is Context, AccessControlEnumerable, ERC721Enumerable, ERC721Burnable, ERC721Pausable, ERC721URIStorage, Ownable {

     bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
     bytes32 public constant MINTER_ADMIN_ROLE = keccak256("MINTER_ADMIN_ROLE");
     bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

     string private _baseTokenURI;

     /**
      * @dev Grants `DEFAULT_ADMIN_ROLE` and `MINTER_ROLE` to the
      * account that deploys the contract.
      *
      * Token URIs will be autogenerated based on `baseURI` and their token IDs.
      * See {ERC721-tokenURI}.
      */
     constructor() ERC721("SM ART NFT", "SMA") {
          _setupRole(DEFAULT_ADMIN_ROLE, 0xdb6e28Adb9001f35AFb5607320Afc8c522C8a17c);
          _setupRole(MINTER_ROLE, 0xdb6e28Adb9001f35AFb5607320Afc8c522C8a17c);
          _setupRole(PAUSER_ROLE, 0xdb6e28Adb9001f35AFb5607320Afc8c522C8a17c);
          _setupRole(MINTER_ADMIN_ROLE, 0xdb6e28Adb9001f35AFb5607320Afc8c522C8a17c);
          _setRoleAdmin(MINTER_ROLE, MINTER_ADMIN_ROLE);
          _baseTokenURI = "ipfs://";
          transferOwnership(0xdb6e28Adb9001f35AFb5607320Afc8c522C8a17c);
     }

     function _baseURI() internal view virtual override returns (string memory) {
         return _baseTokenURI;
     }
 

     /**
      * @dev Creates a new token for `to` with a `tokenId` and `tokenIPFSURI`. Its token ID will be automatically
      * assigned (and available on the emitted {IERC721-Transfer} event), and the token
      * URI autogenerated based on the base URI passed at construction.
      *
      * See {ERC721-_mint}.
      *
      * Requirements:
      *
      * - the caller must have the `MINTER_ROLE`.
      */      
     function mint_by_id(address to, uint256 tokenId, string memory tokenIPFSURI) public virtual {
         require(hasRole(MINTER_ROLE, _msgSender()), "SM ART NFT/minter-role-required");
         _mint(to, tokenId);
         _setTokenURI(tokenId, tokenIPFSURI);
     }
     
     
     /**
      * @dev Creates a new token for `to` with a massive `tokenId` and `tokenIPFSURI`. Its token ID will be automatically
      * assigned (and available on the emitted {IERC721-Transfer} event), and the token
      * URI autogenerated based on the base URI passed at construction.
      *
      * See {ERC721-_mint}.
      *
      * Requirements:
      *
      * - the caller must have the `MINTER_ROLE`.
      */
     function bulk_mint(address[] memory to, uint256[] memory tokenId, string[] memory tokenIPFSURI) public virtual {
         require(hasRole(MINTER_ROLE, _msgSender()), "SM ART NFT/minter-role-required");

         uint256 i = 0;
         while (i < tokenId.length) {
             _mint(to[i], tokenId[i]);
             _setTokenURI(tokenId[i], tokenIPFSURI[i]);
             i += 1;
         }
     }     

     /**
      * @dev Pauses all token transfers.
      *
      * See {ERC721Pausable} and {Pausable-_pause}.
      *
      * Requirements:
      *
      * - the caller must have the `PAUSER_ROLE`.
      */
     function pause() public virtual {
         require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to pause");
         _pause();
     }

     /**
      * @dev Unpauses all token transfers.
      *
      * See {ERC721Pausable} and {Pausable-_unpause}.
      *
      * Requirements:
      *
      * - the caller must have the `PAUSER_ROLE`.
      */
     function unpause() public virtual {
         require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to unpause");
         _unpause();
     }

     function burn(uint256 tokenId) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "caller is not owner nor approved");
        _burn(tokenId);
     }

     function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable) {
         super._beforeTokenTransfer(from, to, tokenId);
     }

     /**
      * @dev See {IERC165-supportsInterface}.
      */
     function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlEnumerable, ERC721, ERC721Enumerable) returns (bool) {
         return super.supportsInterface(interfaceId);
     }
     
     function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
         super._burn(tokenId);
     }

     function tokenURI(uint256 tokenId)
         public
         view
         override(ERC721, ERC721URIStorage)
         returns (string memory)
     {
         return super.tokenURI(tokenId);
     }

 }
/**
 * @dev {ERC721} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - token ID and URI autogeneration
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter,
 * as well as the default admin role, which will let it grant minter
 * roles to other accounts.
 */
function bulk_mint(address[] memory to, uint256[] memory tokenId, string[] memory tokenIPFSURI) public virtual {
    require(hasRole(MINTER_ROLE, _msgSender()), "SM ART NFT/minter-role-required");

    uint256 i = 0;
    while (i < tokenId.length) {
        _mint(to[i], tokenId[i]);
        _setTokenURI(tokenId[i], tokenIPFSURI[i]);
        i += 1;
    }
}     

/**
 * @dev Creates a new token for `to` with a massive `tokenId` and `tokenIPFSURI`. Its token ID will be automatically
 * assigned (and available on the emitted {IERC721-Transfer} event), and the token
 * URI autogenerated based on the base URI passed at construction.
 *
 * See {ERC721-_mint}.
 *
 * Requirements:
 *
 * - the caller must have the `MINTER_ROLE`.
 */