Hello! Welcome back to your course on Ethereum development.
In our previous lessons, we built both ERC-721 and ERC-1155 contracts. In both cases, we saw a tokenURI or uri function that points to a JSON file containing the NFT's metadata—its name, description, and image. So far, we've used placeholder URLs like https://my-api.com/items/{id}.json.
This raises a critical question: what happens if my-api.com goes offline? The smart contract and the token ownership would still exist on-chain, but the associated art and metadata would be lost, rendering the NFT incomplete. This is a significant vulnerability for digital assets meant to be permanent.
This lesson tackles that problem head-on by introducing decentralized storage.
Learning Outcome: By the end of this lesson, you will be able to integrate decentralized storage (e.g., IPFS) for NFT metadata, managing on-chain URIs and off-chain asset retrieval.
We will cover the entire workflow: from preparing your assets and uploading them to the InterPlanetary File System (IPFS), to structuring the metadata, and finally, linking it all from your smart contract in a secure and permanent way.
1. Why Decentralized Storage? The IPFS Paradigm
The fundamental issue with using a standard HTTPS URL for NFT metadata is that it's location-addressed. It points to a specific file on a specific server. If the server moves, goes down, or the file is deleted, the link breaks.
IPFS solves this with content addressing. Instead of asking "where is the file?", you ask "what is the file?". Every piece of content on IPFS is identified by a unique cryptographic hash of its contents, called a Content Identifier (CID).
Key characteristics of this approach:
- Immutability: If you change even one pixel in an image, its CID will change completely. This guarantees that the content linked from your NFT can never be altered without it being obvious.
- Decentralization: Content is retrieved from any node on the network that has it, not just a single server. This makes it highly resilient to censorship or single points of failure.
- Persistence: As long as at least one node on the IPFS network chooses to "pin" (store) the content, it will remain available.
For a deeper dive into these concepts and best practices, the official IPFS documentation is the best source.
Best Practices for Storing NFT Data using IPFS
This guide from the IPFS documentation explains the best practices for using IPFS with NFTs. It covers linking, metadata structure, and the crucial concept of data persistence.
Please read the sections 'Persistence and availability' and 'Summary'. Focus on understanding what 'pinning' is and why it's essential for ensuring your NFT data remains online. The summary provides a great recap of the core principles.
2. The End-to-End Workflow: From Image to On-Chain URI
Now, let's walk through the practical steps of preparing and uploading your NFT assets and metadata. The process involves two main uploads: first the images, then the metadata that points to those images.
We will use a pinning service called Pinata, which makes it easy to upload content to IPFS and ensures it remains pinned and available. The following video provides a clear, step-by-step demonstration of this entire workflow.
NFT Image & Metadata Storage Using IPFS
This video from Bit-Rush Crypto provides a complete, practical walkthrough of uploading NFT assets and metadata to IPFS using Pinata and then updating a smart contract.
Watch the video from 00:49 to 11:51. This covers the entire process: Setting up Pinata (a pinning service). Uploading the image folder to get an image CID. Updating the metadata JSON files to point to the images using the new CID. Uploading the metadata folder to get the final metadata CID. Updating the smart contract's base URI with the metadata CID. This visual guide will make the abstract steps very concrete.
To summarize the workflow shown in the video:
- Upload Assets: Place all your images (e.g.,
1.png,2.png) in a folder and upload the entire folder to Pinata. This gives you a single CID for the image directory. - Update Metadata: Your metadata files (e.g.,
1.json,2.json) should contain animagefield. You'll update this field to point to the correct image within the IPFS directory you just uploaded. The format isipfs://<IMAGE_FOLDER_CID>/1.png. - Upload Metadata: Place all your updated JSON files in a new folder and upload it to Pinata. This gives you a second CID, this time for the metadata directory.
- Set Contract URI: This final metadata CID is what you'll use to set the
baseURIin your NFT smart contract.
3. On-Chain URIs and Off-Chain Retrieval
Now that you have your metadata on IPFS, how do wallets and marketplaces like OpenSea actually display your NFT? They follow a specific retrieval process that bridges the on-chain and off-chain worlds.
Let's break down the different types of links involved.
Best Practices for Storing NFT Data using IPFS
Let's return to the IPFS documentation to understand the specific formats for linking to IPFS content and structuring your metadata.
Read the sections 'Types of IPFS links and when to use them' and 'Metadata'. Pay close attention to: The distinction between a raw CID, an ipfs:// URI, and an HTTP Gateway URL. The recommendation to use the ipfs:// scheme as the canonical link in your smart contract and within your metadata files.
Here is the retrieval flow, which leverages your front-end development experience:
- On-Chain Call: A front-end application calls the
tokenURI(1)function on your smart contract. - Return IPFS URI: The contract returns the canonical IPFS URI, for example:
ipfs://bafybeibnsoufr2renqzsh347nrx54wcubt5lgkeivez63xvivplfwhtpym/1. - Gateway Resolution: The application can't resolve
ipfs://natively. It converts this URI into an HTTP Gateway URL, likehttps://ipfs.io/ipfs/bafybeibnsoufr2renqzsh347nrx54wcubt5lgkeivez63xvivplfwhtpym/1. - Fetch Metadata: The application makes an HTTP GET request to the gateway URL and receives the JSON metadata for token 1.
- Parse and Fetch Image: The app parses the JSON, finds the
imagefield (e.g.,ipfs://bafybeict2.../1.png), converts that to another gateway URL, and fetches the image to display to the user.
4. Smart Contract Implementation Strategies
How you manage the tokenURI on-chain depends on your collection's needs. There are two primary patterns, both supported by OpenZeppelin.
Method 1: Base URI + Token ID Concatenation (Most Common)
This is the method used in the video and is ideal for collections where metadata is named sequentially (e.g., 1.json, 2.json, ...).
- You store a single
_baseTokenURIin the contract, which is your IPFS metadata folder's URI:ipfs://<METADATA_FOLDER_CID>/. - The
tokenURIfunction automatically appends thetokenIdto this base URI. - Pros: Extremely gas-efficient, as you only store one string for the entire collection.
- Cons: Inflexible. All metadata must follow a predictable naming scheme.
The LearnWeb3 tutorial provides a complete contract example using this approach.
Build your own NFT collection with metadata stored on IPFS
This tutorial from LearnWeb3 provides a full example of an NFT contract designed to work with IPFS metadata.
Read the 'Contract' section. You don't need to set up the project, just focus on the LW3Punks.sol code. Notice how the constructor accepts a baseURI and how the tokenURI function concatenates it with the tokenId and a .json suffix. Also, note how the IPFS CID is passed during deployment.
Method 2: Individual Token URIs (ERC721URIStorage)
What if your metadata isn't sequential? Or what if you want to reveal NFTs one by one? For this, you can use OpenZeppelin's ERC721URIStorage extension.
- This extension provides an internal
_setTokenURI(tokenId, uri)function and a mapping to store a unique URI for each token ID. - Pros: Maximum flexibility. Each token can have a completely different and unrelated URI.
- Cons: Much higher gas cost, as you are writing a full string to storage for every token minted.
The following video explains the difference between these two approaches by looking directly at the OpenZeppelin contract code.
ERC 721 URI Storage: OpenZeppelin Solidity implementation
This video by BlockchainBob clearly contrasts the default ERC-721 token URI generation with the ERC721URIStorage extension.
Please watch these two segments: Default ERC-721 Token URI Generation (00:57 - 03:11): This explains the standard base URI + token ID concatenation method. ERC-721 URI Storage Implementation (04:03 - 05:17): This shows how the extension overrides the default behavior to use a mapping for individual URIs. This will solidify your understanding of the on-chain implementation choices.
Conclusion
You have now learned how to break free from centralized servers and give your NFTs true digital permanence. By leveraging IPFS, you ensure that your token's metadata and assets are as resilient and decentralized as the blockchain itself.
Key Takeaways:
- Content Addressing: IPFS uses Content Identifiers (CIDs) to create immutable, verifiable links to data.
- Pinning is Crucial: For data to persist on IPFS, it must be "pinned" by at least one node. Pinning services like Pinata handle this for you.
- Two-Step Upload: The standard workflow is to first upload images to get a CID, update metadata to reference that CID, and then upload the metadata.
ipfs://is the Standard: Use theipfs://URI scheme in your smart contracts and metadata. Client applications use HTTP gateways to resolve these links for users.- On-Chain Strategies: You can use a gas-efficient
baseURIfor sequential collections or the more flexibleERC721URIStoragefor individual URIs.
Next Steps:
Now that your NFTs have permanent, decentralized metadata, the next step in many projects is to control who can mint them. In our next lesson, we will implement an NFT mint with an allowlist using Merkle proofs, a powerful cryptographic technique for managing pre-sale access efficiently and securely.
Can't find a good explanation? Sign up and we'll make it for you
Sign up