跳转至主要内容
Change page

ERC-721 非同质化代币标准

页面最后更新: 2025年9月17日

简介

什么是非同质化代币?

非同质化代币(NFT)用于以唯一的方式标识某人或者某物。 此类型的代币可以被完美地用于出售下列物品的平台:收藏品、密钥、彩票、音乐会座位编号、体育比赛等。 这种类型的代币有着惊人的潜力,因此它需要一个适当的标准。ERC-721 就是为解决这个问题而来!

ERC-721 是什么?

ERC-721 为 NFT 引入了一个标准,换言之,这种类型的代币是独一无二的,并且可能与来自同一智能合约的另一代币有不同的价值,也许是因为它的年份、稀有性、甚至是它的观感。 稍等,看起来怎么样呢?

可以! 所有 NFT 都有一个名为 tokenIduint256 变量,因此对于任何 ERC-721 合约,该配对 contract address, uint256 tokenId 必须是全局唯一的。 也就是说,一个去中心化应用程序可以有一个“转换器”,它 使用 tokenId 作为输入并输出一些很酷的东西的图像,比如僵尸、武器、技能或超棒的猫咪!

前提条件

正文

ERC-721(Ethereum Request for Comments 721),由 William Entriken、Dieter Shirley、Jacob Evans、Nastassia Sachs 在 2018 年 1 月提出,是一个在智能合约中实现代币 API 的非同质化代币标准。

它提供了一些功能,例如将代币从一个帐户转移到另一个帐户,获取帐户的当前代币余额,获取代币的所有者,以及整个网络的可用代币总供应量。 除此之外,它还具有其他功能,例如批准帐户中一定数量的代币可以被第三方帐户转移。

如果一个智能合约实现了下列方法和事件,它就可以被称为 ERC-721 非同质化代币合约。 一旦被部署,它将负责跟踪在以太坊上创建的代币。

来自 EIP-721opens in a new tab

方法

1 function balanceOf(address _owner) external view returns (uint256);
2 function ownerOf(uint256 _tokenId) external view returns (address);
3 function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
4 function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
5 function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
6 function approve(address _approved, uint256 _tokenId) external payable;
7 function setApprovalForAll(address _operator, bool _approved) external;
8 function getApproved(uint256 _tokenId) external view returns (address);
9 function isApprovedForAll(address _owner, address _operator) external view returns (bool);
显示全部

事件

1 event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
2 event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
3 event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

示例

让我们看看一个标准是多么重要,它使我们能够简单地在以太坊上检查任何 ERC-721 代币合约。 我们只需要合约的应用程序二进制接口(ABI)就可以创造任何 ERC-721 代币的接口。 下面我们将使用一个简化的应用程序二进制接口,让例子变得更为简单。

Web3.py 示例

首先,请确保您已安装 Web3.pyopens in a new tab Python 程序库:

1pip install web3
1from web3 import Web3
2from web3._utils.events import get_event_data
3
4
5w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))
6
7ck_token_addr = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d" # CryptoKitties 合约
8
9acc_address = "0xb1690C08E213a35Ed9bAb7B318DE14420FB57d8C" # CryptoKitties 销售拍卖
10
11# 这是一个 ERC-721 NFT 合约的简化版合约应用程序二进制接口 (ABI)。
12# 它只会公开以下方法:balanceOf(address)、name()、ownerOf(tokenId)、symbol()、totalSupply()
13simplified_abi = [
14 {
15 'inputs': [{'internalType': 'address', 'name': 'owner', 'type': 'address'}],
16 'name': 'balanceOf',
17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],
18 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True
19 },
20 {
21 'inputs': [],
22 'name': 'name',
23 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],
24 'stateMutability': 'view', 'type': 'function', 'constant': True
25 },
26 {
27 'inputs': [{'internalType': 'uint256', 'name': 'tokenId', 'type': 'uint256'}],
28 'name': 'ownerOf',
29 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}],
30 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True
31 },
32 {
33 'inputs': [],
34 'name': 'symbol',
35 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],
36 'stateMutability': 'view', 'type': 'function', 'constant': True
37 },
38 {
39 'inputs': [],
40 'name': 'totalSupply',
41 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],
42 'stateMutability': 'view', 'type': 'function', 'constant': True
43 },
44]
45
46ck_extra_abi = [
47 {
48 'inputs': [],
49 'name': 'pregnantKitties',
50 'outputs': [{'name': '', 'type': 'uint256'}],
51 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True
52 },
53 {
54 'inputs': [{'name': '_kittyId', 'type': 'uint256'}],
55 'name': 'isPregnant',
56 'outputs': [{'name': '', 'type': 'bool'}],
57 'payable': False, 'stateMutability': 'view', 'type': 'function', 'constant': True
58 }
59]
60
61ck_contract = w3.eth.contract(address=w3.to_checksum_address(ck_token_addr), abi=simplified_abi+ck_extra_abi)
62name = ck_contract.functions.name().call()
63symbol = ck_contract.functions.symbol().call()
64kitties_auctions = ck_contract.functions.balanceOf(acc_address).call()
65print(f"{name} [{symbol}] 在拍卖中的 NFT:{kitties_auctions}")
66
67pregnant_kitties = ck_contract.functions.pregnantKitties().call()
68print(f"{name} [{symbol}] 怀孕的 NFT:{pregnant_kitties}")
69
70# 使用 Transfer 事件 ABI 获取已转移的 Kitties 的信息。
71tx_event_abi = {
72 'anonymous': False,
73 'inputs': [
74 {'indexed': False, 'name': 'from', 'type': 'address'},
75 {'indexed': False, 'name': 'to', 'type': 'address'},
76 {'indexed': False, 'name': 'tokenId', 'type': 'uint256'}],
77 'name': 'Transfer',
78 'type': 'event'
79}
80
81# 我们需要事件签名来筛选日志
82event_signature = w3.keccak(text="Transfer(address,address,uint256)").hex()
83
84logs = w3.eth.get_logs({
85 "fromBlock": w3.eth.block_number - 120,
86 "address": w3.to_checksum_address(ck_token_addr),
87 "topics": [event_signature]
88})
89
90# 注意:
91# - 如果没有返回 Transfer 事件,请将区块数从 120 调高。
92# - 如果没有找到任何 Transfer 事件,你也可以尝试在此处获取一个 tokenId:
93# https://etherscan.io/address/0x06012c8cf97BEaD5deAe237070F9587f8E7A266d#events
94# 点击展开事件日志并复制其 "tokenId" 参数
95recent_tx = [get_event_data(w3.codec, tx_event_abi, log)["args"] for log in logs]
96
97if recent_tx:
98 kitty_id = recent_tx[0]['tokenId'] # 从上面的链接在此处粘贴 "tokenId"
99 is_pregnant = ck_contract.functions.isPregnant(kitty_id).call()
100 print(f"{name} [{symbol}] NFT {kitty_id} 是否怀孕:{is_pregnant}")
显示全部

除了标准事件之外,CryptoKitties 合约还有其它一些有趣的事件。

我们来看看其中的两个:PregnantBirth

1# 使用 Pregnant 和 Birth 事件 ABI 获取关于新 Kitties 的信息。
2ck_extra_events_abi = [
3 {
4 'anonymous': False,
5 'inputs': [
6 {'indexed': False, 'name': 'owner', 'type': 'address'},
7 {'indexed': False, 'name': 'matronId', 'type': 'uint256'},
8 {'indexed': False, 'name': 'sireId', 'type': 'uint256'},
9 {'indexed': False, 'name': 'cooldownEndBlock', 'type': 'uint256'}],
10 'name': 'Pregnant',
11 'type': 'event'
12 },
13 {
14 'anonymous': False,
15 'inputs': [
16 {'indexed': False, 'name': 'owner', 'type': 'address'},
17 {'indexed': False, 'name': 'kittyId', 'type': 'uint256'},
18 {'indexed': False, 'name': 'matronId', 'type': 'uint256'},
19 {'indexed': False, 'name': 'sireId', 'type': 'uint256'},
20 {'indexed': False, 'name': 'genes', 'type': 'uint256'}],
21 'name': 'Birth',
22 'type': 'event'
23 }]
24
25# 我们需要事件签名来筛选日志
26ck_event_signatures = [
27 w3.keccak(text="Pregnant(address,uint256,uint256,uint256)").hex(),
28 w3.keccak(text="Birth(address,uint256,uint256,uint256,uint256)").hex(),
29]
30
31# 这是一个 Pregnant 事件:
32# - https://etherscan.io/tx/0xc97eb514a41004acc447ac9d0d6a27ea6da305ac8b877dff37e49db42e1f8cef#eventlog
33pregnant_logs = w3.eth.get_logs({
34 "fromBlock": w3.eth.block_number - 120,
35 "address": w3.to_checksum_address(ck_token_addr),
36 "topics": [ck_event_signatures[0]]
37})
38
39recent_pregnants = [get_event_data(w3.codec, ck_extra_events_abi[0], log)["args"] for log in pregnant_logs]
40
41# 这是一个 Birth 事件:
42# - https://etherscan.io/tx/0x3978028e08a25bb4c44f7877eb3573b9644309c044bf087e335397f16356340a
43birth_logs = w3.eth.get_logs({
44 "fromBlock": w3.eth.block_number - 120,
45 "address": w3.to_checksum_address(ck_token_addr),
46 "topics": [ck_event_signatures[1]]
47})
48
49recent_births = [get_event_data(w3.codec, ck_extra_events_abi[1], log)["args"] for log in birth_logs]
显示全部
  • Etherscan NFT Trackeropens in a new tab 按转账量列出了以太坊上的顶尖 NFT。
  • CryptoKittiesopens in a new tab 是一款游戏,围绕着我们称之为“加密猫”的、可繁殖、可收藏且非常可爱的 生物。
  • Sorareopens in a new tab 是一款全球性的梦幻足球游戏,你可以在其中收集限量版收藏品、 管理你的球队并参加比赛以赢取奖品。
  • 以太坊域名服务 (ENS)opens in a new tab 提供了一种安全和去中心化的方式,可以使用简单的、人类可读的名称来定位 链上和链下的资源。
  • POAPopens in a new tab 向参加活动或完成特定操作的人免费发放 NFT。 POAP 的创建和分发是免费的。
  • Unstoppable Domainsopens in a new tab 是一家总部位于旧金山的公司,在 区块链上构建域名。 区块链域名将加密货币地址替换为人类可读的名称,并可用于启用 抗审查网站。
  • Gods Unchained Cardsopens in a new tab 是以太坊区块链上的一款集换式卡牌游戏 (TCG),它使用 NFT 为 游戏内资产带来真正的所有权。
  • Bored Ape Yacht Clubopens in a new tab 是一个由 10,000 个独特 NFT 组成的收藏系列。它既是可证明其稀有性的艺术品,也充当俱乐部的会员代币,可为成员提供多种特权和福利,而且在社区的努力下,这些特权和福利还会随着时间的推移不断增加。

扩展阅读{#further-reading}

本文对你有帮助吗?