前言
在之前的文章中,我们了解了ERC-20代币,ERC-20是一个Token标准,ERC-721同样是一个Token标准。之前很火的那个以太坊加密猫就是基于ERC-721创造出来的.
什么是ERC-721
ERC721官方简要解释是Non-Fungible Tokens,简写为NFTs,多翻译为不可互换的Token。ERC721 是由Dieter Shirley 在2017年9月提出。Dieter Shirley 正是加密猫CryptoKitties背后的公司Axiom Zen的技术总监。加密猫也是第一个实现了ERC721 标准的去中心化应用。
如何理解NFTs
NFTs(Non-Fungible Tokens),翻译过来是不可互换的Token。以加密猫为例,每只加密猫实质上都是ERC-721的Token,每只加密的基因是不一样的(实质上是拥有不同属性的Token),猫之间是不能置换的。这种独特性使得某些稀有猫具有收藏价值,也因此受到追捧。
ERC20代币是可置换的,也就是说所有的ERC-20Token都是一样的。我手中的ERC-20Token和你手中的ERC-20Token本质上是一样的,是可以互相转换的,在使用的时候,我们只关心余额,而不关心Token之间的区别。而ERC-721的Token是不可置换的。仍然以加密猫为例子,加密猫这个游戏中的Token就是加密猫,每个人的加密猫是不一样的。ERC721的Token或虚拟物品具有收藏价值的属性
ERC-721适用于什么场景
ERC-721 Token是不可互换的,比如上面讲的加密猫。所以它适用于那些具有稀缺性或者不可替换的资源的场景,比如创造一些稀缺的虚拟物品(这些物品和现实世界中的那些古玩收藏品一样),尤其在加密货币收藏和网络游戏领域拥有巨大的潜力。ERC-721 Token虽然不可互换,但是它可以通过交易,去置换ERC-20 Token,比如一个加密猫可以价值几百个ETH。
此外,将来它还能实现物理资产,如:房屋、土地等上链,用ERC-721 对这些资产确权。
ERC721标准
ERC721最为一个合约标准,提供了在实现ERC721代币时必须要遵守的协议,要求每个ERC721标准合约需要实现ERC721及ERC165接口,接口定义如下:
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 事件。函数的实现需要做一下几种检查:
1、调用者msg.sender应该是当前tokenId的所有者或被授权的地址
2、_from 必须是 _tokenId的所有者
3、_tokenId 应该是当前合约正在监测的NFTs 中的任何一个
4、_to 地址不应该为 0
5、如果_to 是一个合约应该调用其onERC721Received方法, 并且检查其返回值,如果返回值不为bytes4(keccak256("onERC721Received(address,uint256,bytes)"))抛出异常。
一个可接收NFT的合约必须实现ERC721TokenReceiver接口:
interface ERC721TokenReceiver {
/// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
}
- transferFrom(): 用来转移NFTs, 方法成功后需触发Transfer事件。调用者自己确认_to地址能正常接收NFT,否则将丢失此NFT。此函数实现时需要检查上面条件的前4条。
参考:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
https://www.jianshu.com/p/47457d149f9d