NFT,全称为非同质化代币(Non-Fungible Token),是一种基于区块链技术的数字资产。与比特币等传统加密货币不同,NFT是唯一的、不可替代的,每一个NFT都有其独特的标识信息。
// 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);
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。