By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
Study Guide – Decentralized Storage (IPFS, Filecoin, Arweave)
Decentralized storage moves data off a single server and spreads it across a peer‑to‑peer network. Instead of a cloud provider owning the files, anyone running a node can serve (or “pin”) them, and the content is addressed by a cryptographic hash. This makes NFTs, DAO proposals, or DeFi front‑ends tamper‑proof because the metadata lives on an immutable, censorship‑resistant layer. Real‑world example: an NFT minting dApp stores the artwork on IPFS, pins the hash on Filecoin for long‑term guarantees, and the token’s tokenURI points to that hash—so the image can never be taken down by a centralized host.
tokenURI
CID
Qm...
solidity function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_exists(tokenId), "ERC721: nonexistent token"); return string(abi.encodePacked("ipfs://", _tokenURIs[tokenId])); }
ipfs-http-client
```js const { create } = require('ipfs-http-client'); const ipfs = create({ url: 'https://ipfs.infura.io:5001/api/v0' });
async function uploadJSON(obj) { const { cid } = await ipfs.add(JSON.stringify(obj)); return cid.toString(); // → CID } ```
```js const { Web3Storage, File } = require('web3.storage'); const client = new Web3Storage({ token: process.env.W3S_TOKEN });
async function storeOnFilecoin(data) { const file = new File([JSON.stringify(data)], 'metadata.json'); const cid = await client.put([file]); // pins to IPFS + backs with Filecoin return cid; } ```
```js const Arweave = require('arweave'); const arweave = Arweave.init({ host: 'arweave.net', port: 443, protocol: 'https' });
async function writeArweave(data) { const wallet = await arweave.wallets.generate(); // or load existing keyfile const tx = await arweave.createTransaction({ data: JSON.stringify(data) }, wallet); tx.addTag('Content-Type', 'application/json'); await arweave.transactions.sign(tx, wallet); const response = await arweave.transactions.post(tx); return tx.id; // transaction ID = permanent address } ```
IPFSResolver
solidity library IPFSResolver { function toBase58(bytes memory data) internal pure returns (string memory) { // minimal implementation omitted for brevity } }
gateway
ipfs://
https://ipfs.io/ipfs/<cid>
client.put()
lotus
setTokenURI(tokenId, cid)
ipfs://<cid>
writeArweave()
ar://<txId>
Mistake: Storing the full IPFS URL (https://ipfs.io/ipfs/...) in tokenURI. Correction: Store only the CID (or ipfs:// URI). This lets you switch gateways later without redeploying the contract.
https://ipfs.io/ipfs/...
Mistake: Assuming a CID is immutable forever. Correction: A CID points to a hash of the data; if the underlying data changes, the CID changes. Pin the CID and optionally back it with Filecoin to avoid accidental GC.
Mistake: Forgetting to set the correct MIME type when uploading to Arweave. Correction: Always add a Content-Type tag; otherwise browsers may render the data as plain text, breaking UI expectations.
Content-Type
Mistake: Using a low‑gas bytes32 field to store a CID (which is ~46‑bytes). Correction: Store the CID off‑chain (in a mapping) or keep it as a string/bytes variable; otherwise you’ll truncate the hash.
bytes32
string
bytes
Mistake: Relying on a single public IPFS gateway for production. Correction: Deploy a fallback strategy (multiple gateways or a local node) to avoid downtime and censorship.
Scenario: Your NFT contract stores tokenURI = "https://ipfs.io/ipfs/QmX...". The gateway goes down. What happens? Answer: The UI can’t fetch the metadata, breaking the NFT display. Why: The contract hard‑coded an HTTP gateway; swapping to another gateway requires a contract upgrade.
tokenURI = "https://ipfs.io/ipfs/QmX..."
Scenario: A developer uploads a 5 MB image to IPFS, then immediately deletes the local node. Will the image stay accessible? Answer: Not necessarily; unless another node pins it or a Filecoin deal is made, the content may be garbage‑collected.
Scenario: You see a contract that stores a CID in a bytes32 variable. Is this safe? Answer: No – a CID is ~46 bytes; truncating it loses data and makes the hash invalid.
price_per_byte * file_size
web3.storage
https://<gateway>/ipfs/<cid>
You now have a ready‑to‑code, interview‑proof cheat sheet for decentralized storage. Happy building!
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.