What data does an NFT typically store?

I’m working on an NFT marketplace using Solidity. I’ve built a custom smart contract that extends OpenZeppelin’s ERC-721. My NFTs have 5 attributes: id, image (IPFS hash), description, collection, and creator address.

I’m unsure where to store these attributes. Right now, I have an Image struct with these fields in an array. When minting, I use the Image object’s id and creator’s address. This means I’m keeping the data separate from the ERC-721 contract.

I’m confused about what an NFT actually contains. Are the attributes part of the NFT, or is the NFT just a reference in my struct?

Is my approach correct? Does the ERC-721 standard only provide basic NFT functions, or am I storing data in the wrong place?

Here’s a simplified version of my contract:

contract NFTMarket is ERC721Full {
  struct TokenData {
    uint256 id;
    string ipfsHash;
    string details;
    string group;
    address payable creator;
  }

  TokenData[] public tokens;
  mapping(uint256 => bool) public tokenExists;

  function createToken(string memory hash, string memory details, string memory group) public {
    require(bytes(hash).length > 0 && bytes(details).length > 0 && bytes(group).length > 0);
    require(msg.sender != address(0));

    uint256 newId = tokens.length + 1;
    tokens.push(TokenData(newId, hash, details, group, msg.sender));
    _mint(msg.sender, newId);
    tokenExists[newId] = true;
  }
}

Any advice on improving this code would be great. I’m new to Ethereum development, so I hope this isn’t a silly question. Thanks!

yo, i’ve worked on nft projects before. ur approach is solid, but consider tokenURI for metadata storage. it’s more flexible. also, storing ipfs hash on-chain might be costly. maybe use off-chain storage?

ur struct idea is cool, but ERC721 already handles most of that. focus on unique attributes. and yeah, ERC721 is just a base - u build on top of it. keep experimenting!

Your approach is on the right track, but there are some optimizations to consider. The ERC-721 standard provides a foundation, and you’re extending it correctly. However, storing all that data on-chain can be expensive. Consider using the tokenURI function to point to off-chain metadata stored on IPFS. This way, you only need to store the token ID and URI on-chain.

For your struct, focus on essential on-chain data like the creator’s address and any attributes that affect token behavior. Move descriptive elements off-chain. This reduces gas costs and allows for easier updates to non-critical information.

Regarding your code, the tokenExists mapping is redundant since ERC721 already tracks token existence. You could simplify by removing it and using _exists(tokenId) from OpenZeppelin’s implementation.

Lastly, consider implementing a metadata update function if you foresee needing to modify token information in the future. This adds flexibility to your contract design.

hey there, fellow nft enthusiast! :wave:

i’ve been tinkering with nfts for a while now, and your question got me thinking. it’s actually pretty cool how you’re approaching this!

so, about what an nft actually stores - it’s kinda like a digital fingerprint, you know? the erc-721 standard is basically just giving you the skeleton, and you get to flesh it out however you want.

your approach of using a separate struct for the token data is interesting! it makes me wonder tho - have you considered using the tokenURI function that comes with erc721? it could potentially simplify things a bit.

also, i’m curious about your decision to store the ipfs hash directly in the contract. have you thought about any potential drawbacks to this? like, what if you wanted to update the metadata later?

oh, and one more thing - i noticed you’re using ERC721Full. any particular reason for that choice? i’ve been playing around with the newer ERC721URIStorage lately and it’s pretty nifty.

anyway, keep up the awesome work! it’s always exciting to see new ideas in the nft space. what other cool features are you planning to add to your marketplace? :rocket: