跳转到内容

链上存储

链上存储

本页内容正在整理中,欢迎贡献

概述

以太坊链上存储(EVM Storage)成本极高,不适合存储大量数据。实际开发中,NFT 图片、元数据、用户文件等大型数据通常存储在去中心化存储网络(IPFS、Arweave、Filecoin)上,链上只存储对应的哈希或 CID。

主要内容

存储方案对比

方案类型持久性成本适合场景
EVM Storage链上永久极高(约 $20K/MB)关键状态数据
Calldata链上永久(区块)小型不变数据
Blob(EIP-4844)链上临时~18 天Rollup 数据
IPFS去中心化依赖固定服务NFT 元数据、图片
Arweave去中心化永久(一次付费)永久存档
Filecoin去中心化合约期内大文件长期存储

EVM 链上存储成本

// 存储成本估算
// SSTORE(写入新槽):20,000 gas
// 假设 Gas Price = 20 Gwei,ETH = $3,000
// 每个 32 字节槽 ≈ 20,000 × 20 Gwei × $3,000 = $1.2
// 1 MB 数据 ≈ 32,768 个槽 ≈ $39,000(!)
// 结论:链上不适合存储大文件

链上存储最佳实践:

// ✅ 好的做法:只存储必要的状态
mapping(address => uint256) public balances;
mapping(uint256 => address) public tokenOwner;
// ❌ 坏的做法:在链上存储大型文件
string public fullDocument; // 不要这样做!
// ✅ 正确做法:链上存哈希,文件放链下
string public documentIPFSHash; // "ipfs://QmXxx..."

IPFS(InterPlanetary File System)

特点:

  • 内容寻址(CID = 内容的哈希),内容不可篡改
  • 去中心化 P2P 网络
  • 默认不持久化——需要”固定(Pin)“才能保证可访问

使用 NFT.Storage(免费,针对 NFT):

import { NFTStorage, File } from "nft.storage";
const client = new NFTStorage({ token: process.env.NFT_STORAGE_TOKEN! });
// 上传 NFT 元数据
const metadata = await client.store({
name: "My NFT #1",
description: "这是第一个 NFT",
image: new File([imageBuffer], "image.png", { type: "image/png" }),
attributes: [
{ trait_type: "Background", value: "Blue" },
{ trait_type: "Eyes", value: "Golden" },
],
});
console.log("IPFS URL:", metadata.url);
// ipfs://bafy.../metadata.json

固定服务(Pinning Services):

服务免费额度说明
Pinata1 GB最流行,适合 NFT
NFT.Storage免费专为 NFT 设计
Web3.Storage5 GBFilecoin 支持
Infura IPFS5 GB付费

Arweave(永久存储)

特点:

  • 一次付费,永久存储
  • 基于”捐赠”模型(利息支付未来存储成本)
  • 适合需要永久不可更改的数据(NFT、文件存档)
import Arweave from "arweave";
const arweave = Arweave.init({
host: "arweave.net",
port: 443,
protocol: "https",
});
// 使用 Bundlr/Turbo 更方便(支持以太坊钱包付费)
import { NodeBundlr } from "@bundlr-network/client";
const bundlr = new NodeBundlr(
"https://node2.bundlr.network",
"ethereum",
process.env.PRIVATE_KEY!
);
const tags = [{ name: "Content-Type", value: "image/png" }];
const receipt = await bundlr.uploadFile("./image.png", { tags });
console.log("Arweave ID:", receipt.id);
console.log("URL:", `https://arweave.net/${receipt.id}`);

NFT 元数据标准

ERC-721 和 ERC-1155 的 tokenURI 通常返回如下 JSON:

{
"name": "My NFT #1",
"description": "这是一个示例 NFT",
"image": "ipfs://QmXxxx.../image.png",
"external_url": "https://myproject.io/nft/1",
"attributes": [
{ "trait_type": "Background", "value": "Ocean" },
{ "trait_type": "Rarity", "value": "Rare", "display_type": "string" },
{ "trait_type": "Level", "value": 5, "display_type": "number" }
]
}

IPFS URL 的注意事项

// IPFS CID 有两种格式,确保使用网关可访问的格式
const ipfsUrl = "ipfs://QmXxxx.../metadata.json";
// 转换为 HTTP 网关 URL(供前端访问)
function ipfsToHttp(url: string, gateway = "https://ipfs.io"): string {
if (url.startsWith("ipfs://")) {
return url.replace("ipfs://", `${gateway}/ipfs/`);
}
return url;
}
// 推荐的公共网关
const GATEWAYS = [
"https://ipfs.io",
"https://cloudflare-ipfs.com",
"https://gateway.pinata.cloud",
];

深入阅读