NFT,全称为非同质化代币(Non-Fungible Token),是一种基于区块链技术的数字资产。与比特币等传统加密货币不同,NFT是唯一的、不可替代的,每一个NFT都有其独特的标识信息。
1. 基本概念
- 非同质化:传统的加密货币如比特币是同质化的,即每一个比特币都是相同且可以互换的。而NFT是独一无二的,每个NFT都有独特的属性和价值,无法与其他NFT互换。
- 区块链技术:NFT通常建立在以太坊(Ethereum)等支持智能合约的区块链平台上。区块链确保了NFT的透明性、不可篡改性和安全性。
2. 特点
- 独特性:每个NFT都有独特的标识符,能够在区块链上唯一标识。
- 不可分割性:大多数NFT是不可分割的,即不能像比特币一样分割成更小的单位。
- 所有权:NFT的所有权记录在区块链上,可以被验证和追踪。
- 稀缺性:创作者可以通过限制发行量来确保NFT的稀缺性,从而增加其价值。
3. 应用领域
- 艺术品:数字艺术品是NFT最早也是最广泛的应用之一。艺术家可以通过发行NFT来销售他们的数字作品,保证作品的独特性和所有权。
- 收藏品:NFT也被广泛应用于数字收藏品,如虚拟卡牌、游戏道具等。这些数字收藏品通过NFT的形式确保其唯一性和可验证性。
- 虚拟房地产:在虚拟世界(如Decentraland和Cryptovoxels)中,用户可以购买、出售和交易虚拟土地,这些土地通常以NFT的形式存在。
- 音乐和视频:音乐家和视频创作者也开始通过NFT销售他们的作品,确保版权和收益分配的透明性。
- 门票和证书:NFT可以用来发行独特的数字门票或证书,确保其真实性和不可篡改性。
4. 优势
- 防伪:NFT可以验证数字资产的真实性和所有权,防止伪造和欺诈。
- 透明性:所有交易和所有权变更都记录在区块链上,任何人都可以查看和验证。
- 去中心化:无需第三方中介,交易可以直接在区块链上进行。
5. 实现示例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
// 定义 IERC165 接口,用于接口检测
interface IERC165 {
function supportsInterface(bytes4 interfaceID) external pure returns (bool);
}
// 定义 ERC721 标准接口,继承自 IERC165 接口
interface IERC721 is IERC165 {
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId)
external
view
returns (address operator);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator)
external
view
returns (bool);
}
// 实现 ERC721 合约,继承自 IERC721 接口
contract ERC721 is IERC721 {
// 定义事件,用于跟踪代币转移和授权操作
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
// map from token id to owner
mapping(uint256 => address) _ownerOf;
// map owner address to token count
mapping(address => uint256) _balanceOf;
// map token id to approved address
mapping(uint256 => address) _approvals;
// map from owner to operator approvals
mapping(address => mapping(address => bool)) public isApprovedForAll;
// 检查合约是否实现了某个接口
function supportsInterface(bytes4 interfaceID)
external
pure
returns (bool)
{
return
interfaceID == type(IERC721).interfaceId ||
interfaceID == type(IERC165).interfaceId;
}
// 查询 token ID 的所有者
function ownerOf(uint256 tokenId) external view returns (address owner) {
owner = _ownerOf[tokenId];
require(owner != address(0), "token id doesn`t exist");
}
// 查询某个地址的持有 token 数量
function balanceOf(address owner) external view returns (uint256) {
require(owner != address(0), "owner address == address(0)");
return _balanceOf[owner];
}
// 设置或取消对某个操作员的全权操作授权
function setApprovalForAll(address operator, bool approved) external {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
// 批准某个地址可以转移指定的 token
function approve(address spender, uint256 id) external {
address owner = _ownerOf[id];
require(
msg.sender == owner || isApprovedForAll[owner][msg.sender],
"not authorized"
);
_approvals[id] = spender;
emit Approval(owner, spender, id);
}
// 查询某个 token 被批准的地址
function getApproved(uint256 id) external view returns (address) {
require(_ownerOf[id] != address(0), "token doesn't exist");
return _approvals[id];
}
// 内部函数,验证地址是否被批准或为所有者
function _isApprovedOrOwner(
address owner,
address spender,
uint256 id
) internal view returns (bool) {
return (spender == owner ||
isApprovedForAll[owner][spender] ||
spender == _approvals[id]);
}
// 转移 token,从一个地址到另一个地址
function transferFrom(
address from,
address to,
uint256 id
) public {
require(from == _ownerOf[id], "from != owner");
require(to != address(0), "transfer to zero address");
require(_isApprovedOrOwner(from, msg.sender, id), "not authorized");
_balanceOf[from]--;
_balanceOf[to]++;
_ownerOf[id] = to;
delete _approvals[id];
emit Transfer(from, to, id);
}
// 安全转移 token,从一个地址到另一个地址
function safeTransferFrom(
address from,
address to,
uint256 id
) external {
transferFrom(from, to, id);
}
// 内部函数,用于铸造新的 token
function _mint(address to, uint256 id) internal {
require(to != address(0), "mint to zero address");
require(_ownerOf[id] == address(0), "already minted");
_balanceOf[to]++;
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
// 内部函数,用于销毁已存在的 token
function _burn(uint256 id) internal {
address owner = _ownerOf[id];
require(owner != address(0), "not minted");
_balanceOf[owner] -= 1;
delete _ownerOf[id];
delete _approvals[id];
emit Transfer(owner, address(0), id);
}
}
// 示例合约,继承自 ERC721
contract ERC721Example is ERC721 {
// 铸造新的 token
function mint(uint256 id) external {
_mint(msg.sender, id);
}
// 销毁指定 token
function burn(uint256 id) external {
_burn(id);
}
}
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
腾讯云开发者社区:孟斯特