无题
ERC721
ERC-721 提供了代表单一资产的唯一标示符到地址的映射,由 Dapper labs Dieter Shirley 创造出来并由 CryptoKitties 带向市场。
ERC721合约的主要构成
- 3个库合约:
Address.sol
,Context.sol
和Strings.sol
- 3个接口合约:
IERC721.sol
,IERC721Receiver.sol
,IERC721Metadata.sol
- 1个
EIP165
合约:ERC165.sol
本文内容参照了A大关于Solidity的学习笔记文章,教程内容由社区成员创作完善而成,每个知识点后面都结合具体的例子,Github1.9K⭐︎。目前还在不断完善中,欢迎大家一起完善。文章仓库链接:
https://github.com/AmazingAng/WTF-Solidity
同时也参照了@崔棉大师关于Solidity的教学资源,B站链接:
ERC-721的依赖项
合约名字 | 合约类型 | 链接 | 描述 |
Address.sol | 标准库 | https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol | 与地址类型相关的函数集合,提供地址信息的确认与权限判断功能。 |
Context.sol | 标准库 | https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Context.sol | 提供有关当前执行上下文的信息,包括事务的发送方及其数据。而这些通常可以通过味精获得。发送者和味精。数据,它们不应该以这样一种直接的方式被访问,因为在处理元事务时,发送和支付执行的帐户可能不是实际的发送者(就应用程序而言)。 |
Strings.sol | 标准库 | https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol | 提供基础的字符串操作。 |
IERC721.sol | 接口定义 | https://eips.ethereum.org/EIPS/eip-721 | 主合约 |
IERC721Receiver.sol | 接口 | https://www.notion.so/ERC-721-4562e8d3cd3447fcbbb136f8ea4ff81b#a44b8a6172be44108c50c4304d11bd0f | 接收NFT的目标合约必须实现这个接口 |
IERC721Metadata.sol | 接口 | https://www.notion.so/ERC-721-4562e8d3cd3447fcbbb136f8ea4ff81b#9558ccc545754ad5a7412c3d8138e5ad | 关于NFT源数据的说明,tokenURI就是在这里定义的 |
EIP165 | 接口 | https://eips.ethereum.org/EIPS/eip-165 | 创建一个标准方法来发布和检测智能合约实现的接口。 |
合约构成图
知识补充:关于Doxygen Tags 的介绍:
Doxygen能将程序中的特定批注转换成为说明文件。它可以依据程序本身的结构,将程序中按规范注释的批注经过处理生成一个纯粹的参考手册,通过提取代码结构或借助自动生成的包含依赖图(include dependency graphs)、继承图(inheritance diagram)以及协作图(collaboration diagram)来可视化文档之间的关系, Doxygen生成的帮助文档的格式可以是CHM、RTF、PostScript、PDF、HTML等。
详细介绍:Doxygen快速入门 - 知乎 (zhihu.com)
Solidity语法习惯中的Doxygen Tags
Tag | 描述 | 使用Tag时候的上下文 |
---|---|---|
@title | 合约的标题 | 合约、接口 |
@author | 作者姓名 | 合约、接口、函数 |
@notice | 功能性介绍 | 合约、接口、函数 |
@dev | 一些额外的细节 | 合约、接口、函数 |
@param | 参数列表 | 函数 |
@return | 函数返回值 | 函数 |
ERC721标准库合约
1 | pragma solidity ^0.8.10; |
个人心得:
需求是最高级别的抽象:在开发项目之前一定要弄清楚需求分析。
接口是第二高级别的抽象:学习智能合约要从接口出发,吃透了弄明白了,就可以拿着对接口的理解去批判对接口的实现。对一开始不太理解的接口最好不要从实现去反推合约的功能,那样就会陷入接口开发人员自己的理解中跳不出来,那时的自己已经缴械了。
接口的定义之上,是需求的第一性原理:比如在我理解来,721合约正式解决了 归属权流转的问题,利用这个原则,将来就可以不断改进721合约的方向。现实中围绕着归属权展开的一些列问题,都可以用以改进721合约。 买卖,借贷,赎回,抵押,被盗,销毁,拍卖,众筹,以物易物,分红,批量的mint,批量的transform……这一切的现实应用,都是将来改进合约的方向,所以要紧扣“第一性原理”
ERC165
1 | interface ERC165 { |
ERC721TokenReceiver
1 | // 钱包/经纪/拍卖申请如果要接受安全转移,则必须实现这个接口 |
ERC721Metadata
1 | /// 元数据扩展是可选的ERC-721智能合约(见下面的说明)。这允许询问你的智能合约的名称和你的NFTs所代表的资产的细节。 |
以#1623号雷达猫的Metadata文件举例说明:
1 | { |
Address.sol(暂时只看isContract()
方法就行了)
先导知识
外部账户(EOA
):由掌握私钥的人控制的账户;合约账户(CA
):账户由智能合约组成,没有私钥。
只有合约账户才有代码,其中存储的是 codeHash,合约的方法**isContract()**利用这个属性来判断目标地址是不是合约地址。
1 | // SPDX-License-Identifier: MIT |
Context.sol
1 | /** |
String.sol
1 | // SPDX-License-Identifier: MIT |