Release NFT v1

/// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract ReleaseNFT is ERC721URIStorage, IERC2981, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;

    // Struct to hold the release type and metadata
    struct ReleaseMetadata {
        string title;
        string genre;
        string subgenre;
        string primaryArtist;
        string[] featuredArtists;
        // Add other metadata fields as necessary

    // Mapping from tokenId to ReleaseMetadata
    mapping(uint256 => ReleaseMetadata) private _releaseMetadata;

    // Mapping from tokenId to royalty info
    mapping(uint256 => RoyaltyInfo) private _royalties;

    struct RoyaltyInfo {
        address recipient;
        uint256 amount;

    constructor() ERC721("ReleaseNFT", "RLS") {}

    // Function to mint a new Release NFT
    function mintRelease(
        address recipient,
        string memory tokenURI,
        ReleaseMetadata memory metadata,
        RoyaltyInfo memory royaltyInfo
    ) public onlyOwner {
        uint256 newItemId = _tokenIdCounter.current();

        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);
        _releaseMetadata[newItemId] = metadata;
        _setRoyaltyInfo(newItemId, royaltyInfo.recipient, royaltyInfo.amount);

    // Override for IERC2981 - Royalty info for exchanges that support it
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        returns (address receiver, uint256 royaltyAmount)
        RoyaltyInfo memory royalties = _royalties[tokenId];
        return (royalties.recipient, (salePrice * royalties.amount) / 10000);

    // Set royalty information for a token
    function _setRoyaltyInfo(uint256 tokenId, address recipient, uint256 amount) internal {
        require(amount <= 10000, "Royalty too high");
        _royalties[tokenId] = RoyaltyInfo(recipient, amount);

    // Get release metadata for a token
    function getReleaseMetadata(uint256 tokenId) public view returns (ReleaseMetadata memory) {
        require(_exists(tokenId), "ERC721Metadata: Query for nonexistent token");
        return _releaseMetadata[tokenId];

    // Override required by Solidity
    function _burn(uint256 tokenId) internal override(ERC721URIStorage) {
        delete _releaseMetadata[tokenId];
        delete _royalties[tokenId];

    // Override required by Solidity for ERC721 and ERC721URIStorage
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721) {
        super._beforeTokenTransfer(from, to, tokenId);

    function supportsInterface(bytes4 interfaceId) public view override(ERC721, IERC165) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);

Last updated