发布时间:2023-05-16 11:00
ERC20是可替代型通证,ERC721则是不可替代型通证。这意味着每个通证是完全不同的, 并且每个通证对不同的用户都有不同的价值。 这种类型通证最具有代表性的应用就是CryptoKittes,每一个数字猫都是独立的,因为每只猫各有千秋,而且由于不同辈分的稀缺性不同,市场价格也差异巨大。。
如果说ERC20实现了“币”,那么ERC721就实现了“货”。如果说ERC20协议本身只能发行可替代性通证(fungible token),用其来代表各种可替代性事物(如钱,证劵,积分,代币等等)。那么现实生活中大部分的事物的不可替代性(任何一个物理商品,IP,版权以及身份)就可以通过ERC721来实现。
pragma solidity ^0.4.20;
interface ERC721 /* is ERC165 */ {
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
balanceOf():返回由_owner 持有的NFTs的数量。
ownerOf():返回tokenId代币持有者的地址。
approve():授予地址_to具有_tokenId的控制权,方法成功后需触发Approval 事件。
setApprovalForAll():授予地址_operator具有所有NFTs的控制权,成功后需触发ApprovalForAll事件。
getApproved()、isApprovedForAll():用来查询授权。
safeTransferFrom():转移NFT所有权,一次成功的转移操作必须发起 Transer 事件。
transferFrom(): 用来转移NFTs, 方法成功后需触发Transfer事件。
这里需要注意的有以下几点:
1、由于每一个NFT都是独一无二的,所以与ERC20的代币不同,ERC721的每一个NFT都有其固定的拥有者,通过一个map(uint256=>address)储存起来,通过ownerOf()来获得持有者的地址。
2、safeTransferFrom()要转移NFT所有权,首先要做以下的检查:1)调用者msg.sender就是当前tokenId的所有者或者得到了授权的地址 2)_from必须是当前tokenId的所有者地址 3)_tokenId必须是当前合约所监测的NFTs中的一个 4)_to的地址不能为0 5)如果_to是一个合约,那么它必须实现ERC721TokenReceiver接口。
3、transferFrom()也要在实现的时候检查以上前四条,与safeTransferFrom()不同之处在于调用者必须自己确认_to地址能正常接收NFT,否则将丢失此NFT。
4、使用setApprovalForAll()
函数来批准一个地址来传输和处理由特定地址拥有的所有令牌,因为我们有一个全局变量operatorApprovals
,其中所有者的地址映射到批准的支票地址,然后映射到布尔。 默认设置为0或false,但通过使用setApprovalForAll()
我们可以将此映射设置为true,并允许地址处理所有ERC721的拥有。
interface ERC721TokenReceiver {
/// @return `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
}
一个可以接受NFT的合约,必须实现 ERC721TokenReceiver 接口,转让NFT的合约应该调用其onERC721Received方法,并检查其返回值。如果返回值不为bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))
抛出异常。
interface ERC721Metadata /* is ERC721 */ {
function name() external pure returns (string _name);
function symbol() external pure returns (string _symbol);
function tokenURI(uint256 _tokenId) external view returns (string);
}
ERC721Metadata 接口用于提供合约的元数据:name , symbol 及 URI(NFT所对应的外部资源)。
ERC721Enumerable的主要目的是提高合约中NTF的可访问性,其接口定义如下:
interface ERC721Enumerable /* is ERC721 */ {
function totalSupply() external view returns (uint256);
function tokenByIndex(uint256 _index) external view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}
totalSupply(): 返回NFT总量
tokenByIndex(): 通过索引返回对应的tokenId
tokenOfOwnerByIndex(): 所有者可以一次拥有多个的NFT, 此函数返回_owner拥有的NFT列表中对应索引的tokenId
上面的四个接口中,前两个是必须实现的,后面两个可以选择性的实现。
在标准的接口中,挖矿、销毁并不是标准的一部分,但是在实际使用中,还是要尽量实现。
同样,OpenZeppelin完成了完整的ERC721的实现,感兴趣的可以去看源码:https://openzeppelin.org/
【区块链实战】什么是 hash 函数,区块链用 hash 函数来干什么
(二)docker使用——2 DockerFile和docker-compose.yml区别
SSM框架基于JavaWeb在线投票系统的设计与实现源码+论文+ppt+代码讲解视频+安装视频(包安装)
c语言字节数分配,【C语言】结构体占用字节数及储存与空间分配
【论文翻译|KDD19】IntentGC:一种融合异构信息用于推荐的可扩展图卷积框架
机器学习(3)--正则化及python源码(附练习数据资源文件百度云)
华为鸿蒙harmonyos 2.0下载,鸿蒙2.0正式版下载_华为鸿蒙2.0系统下载(HarmonyOS 2.0)_易玩网...
人工智能 | ShowMeAI资讯日报 #2022.06.05
Java Web 利用 session 实现简单的购物车(数量可以累加)