跳转到内容

NFT(非同质化代币)介绍

NFT(非同质化代币)介绍

NFT(Non-Fungible Token,非同质化代币)是一种特殊的区块链代币,每一个都是独一无二的,不可互换。

什么是 NFT

同质化 vs 非同质化

同质化代币(Fungible Token)

  • 每个代币完全相同,可以互换
  • 例如:1 ETH = 1 ETH,1 USDC = 1 USDC
  • 就像纸币,一张 100 元和另一张 100 元没有区别

非同质化代币(Non-Fungible Token)

  • 每个代币都是独一无二的
  • 不可互换,不能等量替换
  • 就像画作,蒙娜丽莎和向日葵各有其独特价值

NFT 的核心特性

  1. 唯一性:每个 NFT 有唯一的 tokenId
  2. 所有权可验证:区块链上公开记录所有权
  3. 不可伪造:加密技术保证真实性
  4. 可编程:支持版税、解锁内容等复杂逻辑

ERC721 标准

ERC721 是以太坊 NFT 的核心标准,定义了所有 NFT 合约必须实现的接口:

interface IERC721 {
// 查询某地址持有的 NFT 数量
function balanceOf(address owner) external view returns (uint256);
// 查询某个 tokenId 的所有者
function ownerOf(uint256 tokenId) external view returns (address);
// 将 NFT 从 from 转移到 to
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
// 授权某地址操作特定 NFT
function approve(address to, uint256 tokenId) external;
// 授权某地址操作所有 NFT
function setApprovalForAll(address operator, bool approved) external;
// 查询某 tokenId 的授权地址
function getApproved(uint256 tokenId) external view returns (address);
// 查询是否授权给某操作者
function isApprovedForAll(address owner, address operator) external view returns (bool);
// 关键事件
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
}

ERC721Metadata 扩展

interface IERC721Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
// 返回 NFT 的元数据链接(通常是 IPFS 链接)
function tokenURI(uint256 tokenId) external view returns (string memory);
}

ERC1155(多代币标准)

ERC1155 是改进版本,支持在同一合约中同时管理同质化和非同质化代币,更适合游戏场景:

// 一次批量转移多种代币
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids, // 代币 ID 列表
uint256[] calldata amounts, // 对应数量列表
bytes calldata data
) external;

NFT 元数据

NFT 的元数据通常按 OpenSea 标准格式存储在 IPFS 上:

{
"name": "Cool Ape #1234",
"description": "一只独特的猿猴,来自 Cool Apes 系列",
"image": "ipfs://QmXxx.../1234.png",
"external_url": "https://coolapes.io/1234",
"attributes": [
{
"trait_type": "背景",
"value": "蓝色"
},
{
"trait_type": "眼睛",
"value": "激光眼"
},
{
"trait_type": "帽子",
"value": "派对帽",
"rarity": "1%"
},
{
"display_type": "number",
"trait_type": "战斗力",
"value": 9527
}
]
}

上传到 IPFS

const { NFTStorage, File } = require('nft.storage');
const fs = require('fs');
const client = new NFTStorage({ token: process.env.NFT_STORAGE_KEY });
async function uploadNFT(imagePath, metadata) {
const imageData = fs.readFileSync(imagePath);
const nft = await client.store({
name: metadata.name,
description: metadata.description,
image: new File([imageData], 'image.png', { type: 'image/png' }),
attributes: metadata.attributes
});
console.log('IPFS CID:', nft.ipnft);
console.log('元数据链接:', nft.url);
return nft.url;
}

创建 NFT 合约

基础 NFT 合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MyNFT is ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 public constant MAX_SUPPLY = 10000;
uint256 public constant MINT_PRICE = 0.05 ether;
string public baseTokenURI;
bool public saleActive = false;
event NFTMinted(address indexed to, uint256 indexed tokenId);
constructor(string memory _baseURI, address initialOwner)
ERC721("My NFT Collection", "MNFT")
Ownable(initialOwner)
{
baseTokenURI = _baseURI;
}
// 开关公售
function toggleSale() external onlyOwner {
saleActive = !saleActive;
}
// 公开铸造
function mint(uint256 quantity) external payable {
require(saleActive, "公售未开启");
require(quantity > 0 && quantity <= 10, "每次最多铸造10个");
require(_tokenIds.current() + quantity <= MAX_SUPPLY, "超过最大供应量");
require(msg.value >= MINT_PRICE * quantity, "ETH不足");
for (uint256 i = 0; i < quantity; i++) {
_tokenIds.increment();
uint256 newId = _tokenIds.current();
_safeMint(msg.sender, newId);
emit NFTMinted(msg.sender, newId);
}
}
// Owner 免费铸造(赠品/团队保留)
function ownerMint(address to, uint256 quantity) external onlyOwner {
require(_tokenIds.current() + quantity <= MAX_SUPPLY, "超过最大供应量");
for (uint256 i = 0; i < quantity; i++) {
_tokenIds.increment();
_safeMint(to, _tokenIds.current());
}
}
// 返回 tokenURI(元数据链接)
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "Token不存在");
return string(abi.encodePacked(baseTokenURI, Strings.toString(tokenId), ".json"));
}
function totalSupply() public view returns (uint256) {
return _tokenIds.current();
}
// 提款
function withdraw() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
}

带白名单的 NFT

import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
contract WhitelistNFT is ERC721URIStorage, Ownable {
bytes32 public merkleRoot; // Merkle 树根,用于验证白名单
mapping(address => bool) public whitelistClaimed;
// 设置白名单 Merkle Root
function setMerkleRoot(bytes32 _root) external onlyOwner {
merkleRoot = _root;
}
// 白名单铸造
function whitelistMint(bytes32[] calldata proof) external {
require(!whitelistClaimed[msg.sender], "已经铸造过");
// 验证 Merkle 证明
bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
require(MerkleProof.verify(proof, merkleRoot, leaf), "无效的白名单证明");
whitelistClaimed[msg.sender] = true;
// 铸造逻辑...
}
}

带版税的 NFT(ERC2981)

import "@openzeppelin/contracts/token/common/ERC2981.sol";
contract RoyaltyNFT is ERC721URIStorage, ERC2981, Ownable {
constructor(address initialOwner) ERC721("Royalty NFT", "RNFT") Ownable(initialOwner) {
// 设置 5% 版税,给 owner
_setDefaultRoyalty(initialOwner, 500); // 500 = 5%
}
// ERC2981 版税查询(市场调用此接口支付版税)
function royaltyInfo(uint256 tokenId, uint256 salePrice)
public view override
returns (address receiver, uint256 royaltyAmount)
{
// 每次二次销售,creator 获得 salePrice 的 5%
return super.royaltyInfo(tokenId, salePrice);
}
}

NFT 市场生态

主流 NFT 市场

市场特点费用
OpenSea最大 NFT 市场,支持多链2.5%
Blur专为交易者设计,聚合器0.5%
Magic Eden多链市场,Solana 起家2%
Foundation艺术家友好,策展质量高5%
LooksRare代币激励交易2%

使用 OpenSea API

const { OpenSeaSDK, Chain } = require('opensea-js');
const { ethers } = require('ethers');
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const sdk = new OpenSeaSDK(wallet, {
chain: Chain.Mainnet,
apiKey: process.env.OPENSEA_API_KEY,
});
// 查询 NFT 信息
const asset = await sdk.api.getNFT(
'0xContractAddress',
'1234' // tokenId
);
// 创建购买挂单
const offer = await sdk.createBuyOrder({
asset: {
tokenId: '1234',
tokenAddress: '0xContractAddress',
},
accountAddress: wallet.address,
startAmount: 0.1, // 0.1 ETH
});

与 NFT 交互的前端代码

// React + wagmi 示例
import { useReadContract, useWriteContract } from 'wagmi';
import { erc721Abi } from 'viem';
const NFT_ADDRESS = '0xYourNFTAddress';
function NFTViewer({ tokenId }: { tokenId: bigint }) {
const { data: owner } = useReadContract({
address: NFT_ADDRESS,
abi: erc721Abi,
functionName: 'ownerOf',
args: [tokenId],
});
const { data: tokenURI } = useReadContract({
address: NFT_ADDRESS,
abi: erc721Abi,
functionName: 'tokenURI',
args: [tokenId],
});
return (
<div>
<p>Token #{tokenId.toString()}</p>
<p>所有者: {owner}</p>
<p>元数据: {tokenURI}</p>
</div>
);
}
function MintButton() {
const { writeContract, isPending } = useWriteContract();
return (
<button
onClick={() => writeContract({
address: NFT_ADDRESS,
abi: [...], // 你的 NFT ABI
functionName: 'mint',
args: [1n], // 铸造 1 个
value: BigInt(0.05e18), // 0.05 ETH
})}
disabled={isPending}
>
{isPending ? '铸造中...' : '铸造 NFT'}
</button>
);
}

NFT 应用场景

数字艺术

艺术家可以直接向全球买家销售数字作品,并通过版税机制从二次销售中持续获益。

游戏道具

游戏内物品作为 NFT,玩家真正拥有并可自由交易:

// 游戏道具 NFT
contract GameItem is ERC1155 {
uint256 public constant SWORD = 1;
uint256 public constant SHIELD = 2;
uint256 public constant POTION = 3;
// 批量铸造装备
function craftItems(address player, uint256[] memory ids, uint256[] memory amounts) external {
_mintBatch(player, ids, amounts, "");
}
}

音乐版权

音乐 NFT 允许粉丝购买版权份额,自动分配流媒体收益。

会员 & 访问权

NFT 作为会员证明,持有者享有特殊权益:

contract MembershipNFT is ERC721 {
mapping(uint256 => MembershipTier) public tierOf;
enum MembershipTier { Bronze, Silver, Gold }
modifier onlyMember() {
require(balanceOf(msg.sender) > 0, "必须持有会员NFT");
_;
}
function accessPremiumContent() external onlyMember view returns (string memory) {
return "这是独家内容...";
}
}

现实资产代币化(RWA)

房产、艺术品、股权等现实资产的链上表示。

NFT 市场趋势

  • 数字艺术:Beeple 以 6900 万美元出售 NFT 画作
  • PFP(头像)项目:CryptoPunks、BAYC 等蓝筹 NFT
  • 链游(GameFi):Axie Infinity、Gods Unchained
  • 音乐 NFT:Royal.io 等平台
  • SBT(灵魂绑定代币):不可转让的身份/成就证明

总结

NFT 已经成为 Web3 生态的重要组成部分:

  1. 技术基础:ERC721/ERC1155 标准,存储在区块链上的所有权记录
  2. 元数据:通常存储在 IPFS,遵循 OpenSea 元数据标准
  3. 应用场景:数字艺术、游戏、音乐、会员、RWA 等
  4. 市场生态:OpenSea、Blur 等交易市场

进一步学习: