@@ -33,7 +33,7 @@ from vyper.interfaces import ERC721
33
33
implements: ERC721
34
34
```
35
35
36
- ERC-721 接口内置在 Vyper 语言中。 [ 您可以点击此处查看代码定义 。] ( https://github.com/vyperlang/vyper/blob/master/vyper/builtin_interfaces/ERC721.py ) 接口定义是用 Python 而不是 Vyper 编写的,因为接口不仅在区块链内使用, 而且在外部客户端向区块链发送交易时也使用,而客户端可能 是用 Python 编写的。
36
+ ERC-721 接口内置在 Vyper 语言中。 [ 你可以点击此处查看代码定义 。] ( https://github.com/vyperlang/vyper/blob/master/vyper/builtin_interfaces/ERC721.py ) 接口定义是用 Python 而不是 Vyper 编写的,因为接口不仅在区块链内使用, 而且在外部客户端向区块链发送交易时也使用,而客户端可能 是用 Python 编写的。
37
37
38
38
第一行导入接口,第二行指定我们在这里执行它。
39
39
@@ -47,7 +47,7 @@ interface ERC721Receiver:
47
47
48
48
ERC-721 支持两类转账:
49
49
50
- - `transferFrom`,让发送者指定任何目的地地址并让发送者 承担转账责任。 这意味着您可以转账到一个无效的地址 ,在这种情况下,NFT 将永远丢失。
50
+ - `transferFrom`,让发送者指定任何目的地地址并让发送者 承担转账责任。 这意味着你可以转账到一个无效的地址 ,在这种情况下,NFT 将永远丢失。
51
51
- `safeTransferFrom`,检查目的地址是否是合约。 如果是,ERC-721 合约 将会询问接收合约是否要接收这笔 NFT 转账。
52
52
53
53
接收合约必须执行 `ERC721Receiver` 才能回应 `safeTransferFrom` 请求。
@@ -112,7 +112,7 @@ event Approval:
112
112
tokenId: indexed(uint256)
113
113
```
114
114
115
- ERC-721 批准与 ERC-20 限额类似。 特定地址只允许转移特定 代币。 这就形成了一种合约在接受代币时作出回应的机制。 合约不能侦听 事件,所以如果您只是把代币转移给合约 ,它们不会“知道”这笔转账。 因此,代币所有者 首先提交批准,然后向合约发送请求:“我批准你转移 代币 X,请执行......”。
115
+ ERC-721 批准与 ERC-20 限额类似。 特定地址只允许转移特定 代币。 这就形成了一种合约在接受代币时作出回应的机制。 合约不能侦听 事件,所以如果你只是把代币转移给合约 ,它们不会“知道”这笔转账。 因此,代币所有者 首先提交批准,然后向合约发送请求:“我批准你转移 代币 X,请执行......”。
116
116
117
117
这是一种设计选择,使 ERC-721 标准与 ERC-20 标准类似。 由于 ERC-721 代币 为非同质化代币,合约还可以通过查看代币的所有权来确定 它得到了一个特定代币。
118
118
@@ -129,7 +129,7 @@ event ApprovalForAll:
129
129
approved: bool
130
130
```
131
131
132
- 有时候,拥有一个能够管理某个帐户所有特定类型代币(由一个特定合约 管理的所有代币)的 * 运营者 * 是很有用的 ,这类似于委托书。 例如,我可能想把这样一种权力赋予一个合约,即 检查我是否已经 6 个月没有联系它了,如果属实,就会把我的资产分配给我的继承者(如果他们中一人要求这样做,合约在没有 被交易调用时什么都做不了)。 在 ERC-20 中,我们只需给继承合约提供一个高限额即可。 但这对 ERC-721 不起作用,因为代币是非同质化的。 这是对应的。
132
+ 有时候,拥有一个能够管理某个帐户所有特定类型代币(由一个特定合约 管理的所有代币)的_运营者_是很有用的 ,这类似于委托书。 例如,我可能想把这样一种权力赋予一个合约,即 检查我是否已经 6 个月没有联系它了,如果属实,就会把我的资产分配给我的继承者(如果他们中一人要求这样做,合约在没有 被交易调用时什么都做不了)。 在 ERC-20 中,我们只需给继承合约提供一个高限额即可。 但这对 ERC-721 不起作用,因为代币是非同质化的。 这是对应的。
133
133
134
134
` approved ` 值表示事件是等待批准,还是等待撤回批准。
135
135
@@ -161,7 +161,7 @@ ownerToNFTokenCount: HashMap[address, uint256]
161
161
ownerToOperators: HashMap[address, HashMap[address, bool ]]
162
162
```
163
163
164
- 一个帐户可能有多个运营者。 仅有 ` HashMap ` 不足以跟踪它们,因为每个键都会生成单一值。 然而,可以将 ` HashMap[address, bool] ` 作为值。 默认情况下,每个地址的都值是 ` False ` ,这意味着它 不是运营者。 您可以根据需要将值设置为 ` True ` 。
164
+ 一个帐户可能有多个运营者。 仅有 ` HashMap ` 不足以跟踪它们,因为每个键都会生成单一值。 然而,可以将 ` HashMap[address, bool] ` 作为值。 默认情况下,每个地址的都值是 ` False ` ,这意味着它 不是运营者。 你可以根据需要将值设置为 ` True ` 。
165
165
166
166
``` python
167
167
# @dev Address of minter, who can mint a token
@@ -202,7 +202,7 @@ def __init__():
202
202
"""
203
203
```
204
204
205
- 在 Python 和 Vyper 中,通过指定多行字符串(以 ` """ ` 起始和结束),您还可以创建注释 ,但不能以任何方式使用它。 这些注释也可以包括 [ NatSpec] ( https://vyper.readthedocs.io/en/latest/natspec.html ) 注释。
205
+ 在 Python 和 Vyper 中,通过指定多行字符串(以 ` """ ` 起始和结束),你还可以创建注释 ,但不能以任何方式使用它。 这些注释也可以包括 [ NatSpec] ( https://vyper.readthedocs.io/en/latest/natspec.html ) 注释。
206
206
207
207
``` python
208
208
self .supportedInterfaces[ERC165_INTERFACE_ID ] = True
@@ -221,7 +221,7 @@ def __init__():
221
221
@external
222
222
```
223
223
224
- 函数定义前面以 (` @ ` ) 开头的这些关键词称为 * 修饰符 * 。 它们 规定能够调用函数的环境。
224
+ 函数定义前面以 (` @ ` ) 开头的这些关键词称为_修改器 _ 。 它们 规定能够调用函数的环境。
225
225
226
226
- ` @view ` 指定此函数为 view 函数。
227
227
- ` @external ` 指定该特定函数可以由交易及其它合约调用。
@@ -295,7 +295,7 @@ def getApproved(_tokenId: uint256) -> address:
295
295
return self .idToApprovals[_tokenId]
296
296
```
297
297
298
- 注意,` getApproved ` * 可以 * 返回零 。 如果代币有效,则返回 ` self.idToApprovals[_tokenId] ` 。 如果没有批准者,该值为 0。
298
+ 注意,` getApproved ` _ 可以_返回零 。 如果代币有效,则返回 ` self.idToApprovals[_tokenId] ` 。 如果没有批准者,该值为 0。
299
299
300
300
``` python
301
301
@view
@@ -323,7 +323,7 @@ def isApprovedForAll(_owner: address, _operator: address) -> bool:
323
323
@internal
324
324
```
325
325
326
- 修饰符 ` @internal ` 表示该函数只能由 同一合约内的其他函数访问。 按照惯例,这些函数名称也以下划线 (` _ ` ) 开头。
326
+ 修改器 ` @internal ` 表示该函数只能由 同一合约内的其他函数访问。 按照惯例,这些函数名称也以下划线 (` _ ` ) 开头。
327
327
328
328
``` python
329
329
def _isApprovedOrOwner (_spender : address, _tokenId : uint256) -> bool :
@@ -347,7 +347,7 @@ def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool:
347
347
2 . 该地址经批准可以使用该代币
348
348
3 . 该地址是代表代币所有者的运营者
349
349
350
- 上面的函数可以是一个视图函数,因为它并不改变状态。 为了降低运营成本,任何 * 可以 * 成为视图函数的函数都 * 应该 * 成为视图函数 。
350
+ 上面的函数可以是一个视图函数,因为它并不改变状态。 为了降低运营成本,任何_可以 _ 成为视图函数的函数都_应该_成为视图函数 。
351
351
352
352
``` python
353
353
@internal
@@ -451,7 +451,7 @@ def transferFrom(_from: address, _to: address, _tokenId: uint256):
451
451
self ._transferFrom(_from, _to, _tokenId, msg.sender)
452
452
```
453
453
454
- 此函数允许您向任意地址转账 。 除非该地址是用户或是知道如何转移代币的 合约,否则您转移的任何代币都将卡在该地址中变得毫无用处 。
454
+ 此函数允许你向任意地址转账 。 除非该地址是用户或是知道如何转移代币的 合约,否则你转移的任何代币都将卡在该地址中变得毫无用处 。
455
455
456
456
``` python
457
457
@external
@@ -485,7 +485,7 @@ def safeTransferFrom(
485
485
if _to.is_contract: # check if `_to` is a contract address
486
486
```
487
487
488
- 首先检查地址是否为合约(如果有代码)。 如果不是,假定它是一个用户 地址,并且该用户能够使用或转移代币。 但不要让该地址 给您一种虚假的安全感。 如果您将代币转移到一个没有人知道私钥的地址 ,即使使用了 ` safeTransferFrom ` ,也可能损失代币。
488
+ 首先检查地址是否为合约(如果有代码)。 如果不是,假定它是一个用户 地址,并且该用户能够使用或转移代币。 但不要让该地址 给你一种虚假的安全感。 如果你将代币转移到一个没有人知道私钥的地址 ,即使使用了 ` safeTransferFrom ` ,也可能损失代币。
489
489
490
490
``` python
491
491
returnValue: bytes32 = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data)
@@ -518,7 +518,7 @@ def approve(_approved: address, _tokenId: uint256):
518
518
assert _approved != owner
519
519
```
520
520
521
- 根据惯例,如果您不想要批准者,可以指定零地址而不是您自己 。
521
+ 根据惯例,如果你不想要批准者,可以指定零地址而不是你自己 。
522
522
523
523
``` python
524
524
# Check requirements
@@ -527,7 +527,7 @@ def approve(_approved: address, _tokenId: uint256):
527
527
assert (senderIsOwner or senderIsApprovedForAll)
528
528
```
529
529
530
- 要设置批准,您可以是所有者 ,也可以是所有者授权的运营者。
530
+ 要设置批准,你可以是所有者 ,也可以是所有者授权的运营者。
531
531
532
532
``` python
533
533
# Set the approval
@@ -578,7 +578,7 @@ def mint(_to: address, _tokenId: uint256) -> bool:
578
578
assert msg.sender == self .minter
579
579
```
580
580
581
- 只有铸币者(创建 ERC-721 合约的帐户)可以铸造新代币。 如果我们将来想改变铸币者的 身份,这可能会成为一个问题。 在生产合约 中,您可能需要一个函数 ,允许 铸币者将铸币者特权转让给其他人。
581
+ 只有铸币者(创建 ERC-721 合约的帐户)可以铸造新代币。 如果我们将来想改变铸币者的 身份,这可能会成为一个问题。 在生产合约 中,你可能需要一个函数 ,允许 铸币者将铸币者特权转让给其他人。
582
582
583
583
``` python
584
584
# Throws if `_to` is zero address
@@ -616,17 +616,17 @@ def burn(_tokenId: uint256):
616
616
617
617
# 使用此合约 {#using-contract}
618
618
619
- 与 Solidity 相比,Vyper 中没有继承。 这种有意而为之的设计选择,是为了使代码 更清晰,从而更容易受保护。 因此,要创建您自己的 Vyper ERC-721 合约,您可以 利用[ 此合约] ( https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy ) ,并修改 它以实现想要的业务逻辑。
619
+ 与 Solidity 相比,Vyper 中没有继承。 这种有意而为之的设计选择,是为了使代码 更清晰,从而更容易受保护。 因此,要创建你自己的 Vyper ERC-721 合约,你可以 利用[ 此合约] ( https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy ) ,并修改 它以实现想要的业务逻辑。
620
620
621
621
# 总结 {#conclusion}
622
622
623
623
回顾一下,下面是此合约中最重要的几点:
624
624
625
625
- 要通过安全转账方式接收 ERC-721 代币,合约必须实现 ` ERC721Receiver ` 接口。
626
- - 即使使用了安全转账方式,如果您将代币发送到私钥未知 的地址,代币仍然会被卡住。
626
+ - 即使使用了安全转账方式,如果你将代币发送到私钥未知 的地址,代币仍然会被卡住。
627
627
- 当操作出现问题时,最好 ` revert ` 该调用,而不是只返回 失败值。
628
628
- 有了所有者,ERC-721 代币才存在。
629
- - 有三种经过授权的 NFT 转账方式。 您可以是所有者 ,可以针对特定代币获得批准, 或者可以是所有者全部代币的运营者。
629
+ - 有三种经过授权的 NFT 转账方式。 你可以是所有者 ,可以针对特定代币获得批准, 或者可以是所有者全部代币的运营者。
630
630
- 过去的事件只在区块链之外可见。 区块链中运行的代码无法看到它们。
631
631
632
632
现在去实现安全的 Vyper 合约吧。
0 commit comments