文章共2000字,预计阅读时间10分钟。 Web3是个令人眼花缭乱的地方,里面充斥着新颖的词汇:币、代币、NFT、跨链桥、Defi、Cefi,这些都让入门者感到非常困惑。 新手可能花好几天时间,看了好几个项目的白皮书,最终都不明白什么是代币,什么是NFT。有人好不容易清楚了代币的含义,依然会疑惑,以太坊不是已经有了主币ETH,为什么还有个代币wETH? 本文试图从代码角度帮助弄清以太坊上的各种代币,他们有什么功能,以及通常是如何实现这些功能的,欢迎交流。TL;DR ERC全称EthereumRequestforComment,中文名为以太坊意见征求稿,目前经常使用的有ERC20和ERC721两个标准,前者用于发行同质化代币,后者用于发行非同质化代币(即NFT,nonfungibletoken)。 满足标准的合约所记录的数据就被称为代币,代币只是被记录在合约中的数据,铸造、转账、销毁操作也只是在合约中修改记录的数值。 ERC标准规定了合约的接口,其他应用(例如OpenSea)可以通过合约的接口来操作代币。 容易误解的是,ERC标准仅仅规定了合约的接口格式,至于合约具体怎样实现这些接口,ERC标准是不做规定的,所以能有各式各样的NFT。ERC20 ERC20标准规定了以下6个函数和2个事件interfaceIERC20{functiontotalSupply()externalviewreturns(uint256);functionbalanceOf(addressaccount)externalviewreturns(uint256);functiontransfer(addressto,uint256amount)externalreturns(bool);functionallowance(addressowner,addressspender)externalviewreturns(uint256);functionapprove(addressspender,uint256amount)externalreturns(bool);functiontransferFrom(addressfrom,addressto,uint256amount)externalreturns(bool);eventTransfer(addressindexedfrom,addressindexedto,uint256value);eventApproval(addressindexedowner,addressindexedspender,uint256value);} 6个函数的含义分别是totalSupply():获取代币的总发行量balanceOf(addressaccount):获取account地址代币的余额transfer(addressto,uint256amount):函数的调用者直接向to地址发送amount数量代币allowance(addressowner,addressspender):获取owner向spender地址批准了多少消费额度approve(addressspender,uint256amount):函数的调用者向spender地址批准amount数量消费额度transferFrom(addressfrom,addressto,uint256amount):函数的调用者使用from地址给的消费额度向to地址发送amount数量代币 2个事件的含义分别是Transfer:转账时发出,记录from地址向to地址发送了amount数量代币Approval:批准消费额度时发出,记录owner地址向spender地址批准了value消费额度 其中approve、transferFrom和allowance可能比较难理解,一个简单的例子就是父母给零花钱,花钱的虽然是子女,但钱是从父母钱包里面扣除的。 如果合约实现了以上6个函数和2个事件,我们就可以说满足ERC20标准。通常项目方还会在合约中添加mint函数和burn函数,用来增发代币和销毁代币,这里是ERC20合约的一种实现方式。 满足ERC20标准的合约所铸造出来的代币,就可以上线uniswap等去中心化交易所,用来交换别的虚拟货币了。因为去中心化交易所需要调用transferFrom方法,而以太坊的主币ETH并没有这个接口,所以查看ETH在uniswap中具体的交易情况,能发现ETH总是先被存入wETH合约转换成同等数量的wETH代币,之后uniswap再调用transferFrom进行各种代币间的交换。ERC721 ERC721标准规定了以下10个函数和3个事件interfaceIERC165{functionsupportsInterface(bytes4interfaceID)externalviewreturns(bool);}interfaceIERC721isIERC165{eventTransfer(addressindexedfrom,addressindexedto,uint256indexedtokenId);eventApproval(addressindexedowner,addressindexedapproved,uint256indexedtokenId);eventApprovalForAll(addressindexedowner,addressindexedoperator,boolapproved);functionbalanceOf(addressowner)externalviewreturns(uint256balance);functionownerOf(uint256tokenId)externalviewreturns(addressowner);functionsafeTransferFrom(addressfrom,addressto,uint256tokenId)external;functionsafeTransferFrom(addressfrom,addressto,uint256tokenId,bytescalldatadata)external;functiontransferFrom(addressfrom,addressto,uint256tokenId)external;functionapprove(addressto,uint256tokenId)external;functiongetApproved(uint256tokenId)externalviewreturns(addressoperator);functionsetApprovalForAll(addressoperator,boolapproved)external;functionisApprovedForAll(addressowner,addressoperator)externalviewreturns(bool);} ERC721标准是继承了ERC165标准的,其中ERC165标准规定了函数supportsInterface(bytes4interfaceID)用于发布并检测合约实现了什么接口。 ERC165标准使得外部可以查询合约是否支持接口,如果支持,查询接口的版本,以便用户可以调整与合约交互的方式。 剩下9个函数的含义分别是balanceOf(addressowner):获取owner地址代币的余额ownerOf(uint256tokenId):获取tokenId号代币的owner地址safeTransferFrom(addressfrom,addressto,uint256tokenId,bytescalldatadata):安全地将tokenId号代币从from地址发送到to地址并附加data信息(data信息在token发送到合约账户时会用到,可以用data来操作接收的合约,安全发送指的是合约会检查to地址是不是合法的token接收者)safeTransferFrom(addressfrom,addressto,uint256tokenId):同上,data信息为空transferFrom(addressfrom,addressto,uint256tokenId):将tokenId号代币从from地址发送到to地址,一般用于发送给他人账户,如果to地址是合约账户则可能出错approve(addressto,uint256tokenId):函数调用者将tokenId号代币批准给to地址getApproved(uint256tokenId):获取tokenId号代币被批准给了哪个地址setApprovalForAll(addressoperator,boolapproved):函数调用者管理第三方operator地址的权限,approved表示是否给第三方批准isApprovedForAll(addressowner,addressoperator):获取owner地址是否批准第三方operator地址操作自己所有的代币 3个事件的含义分别是Transfer:转账时发出,记录from地址向to地址发送了tokenId号代币Approval:批准时发出,记录owner地址向approved批准了tokenId号代币ApprovalForAll:管理第三方权限时发出,记录owner地址将第三方operator地址的管理权限设置为approved 由于合约中含有tokenId,所以每个代币都是不尽相同的,这正是非同质化的含义。ERC721和ERC20在设计思路上没有太大差别,只不过由于ERC721的代币是非同质化的,所以既可以通过tokenId进行单个批准,也可以将owner地址的代币全部进行批准,而ERC20只能批准固定数量。 在实际使用中,不一定需要把九个函数全部实现,这里是ERC721合约的一种实现方式。尾记 知道了ERC20和ERC721有什么用呢? 知道了标准,我们就可以通过ERC标准提供的接口直接操作各类代币和NFT,例如,无聊猿是NFT,那么他的合约肯定也符合ERC721标准。 可以通过以太坊浏览器,直接调用ownerOf接口查看2022号无聊猿的拥有者(当然使用代码调用接口也可以,只是以太坊浏览器比较直观) 我们再在最大的NFT交易市场OpenSea上查看一下2022号无聊猿,发现其拥有者确实是这个B44618开头的账户 事实上,OpenSea这类应用,正是通过调用ERC标准提供的各种接口来实现交易的,当我们完全了解ERC标准之后,完全可以自己编写应用来进行代币的交易。 今天就到这里,再见。 参考文章 https:ethereum。orgzhdevelopersdocsstandardstokenserc20 https:ethereum。orgzhdevelopersdocsstandardstokenserc721 https:eips。ethereum。orgEIPSeip165