本文以基础概念结合代码层分析简单讲解ERC721和ERC1155的区别。

一、基础概念

1.1同质与非同质

  • ERC-721:仅限于非同质。
  • ERC-1155:允许同质和非同质,允许像半同质代币这样的新概念币,例如,同质代币可以“转化”为非同质代币,反之亦然。

1.2批量传输

  • ERC-721:只支持每次传输一个代币。
  • ERC-1155:支持在单个交易中批量传输多个代币ID。
  • (由于每个以太坊交易大约要15-30秒的时间,因此ERC-721需要花很长时间来传输代币,而ERC-1155可以在一个区块中发送数百个不同的代币)
  • ERC-1155用了一种新的方式来定义代币,物品将被储存的一个中央智能合约,并占用极少的空间仅用来互相区分。任何物品Token都可以被合并打包成一个"Token包",Token包也有自己独立的id(减少区块链上大量的冗余字节码)。

1.3数据层

  • ERC-721:要求为每种新型代币部署一个新的智能合约(例如,创建一个CryptoKitties的合约,再另外创建一个CryptoCuties的合约等)。
  • ERC-1155:一个智能合约可容纳无数类型的代币。
  • 无法将ERC-1155锁定在不支持ERC-1155的合约中。只能将代币发送给符合ERC-1155的合约!从而防止意外的代币丢失。如果收件人拒收ERC-1155代币,系统会立即恢复你的代币。

1.4发送代币触发智能合约

  • 向智能合约发送ERC-1155代币可触发区块链上的一系列函数和事件。例如,交易所允许用户直接发送代币,自动瞬时地在链上交换其他代币。
  • 由于这些代币严格遵循“onERC1155Received”规则,因此ERC-1155百分百可靠。

1.5本地化

  • ERC-721:只支持一种语言。
  • ERC-1155:支持将所有元数据(例如代币名称、说明、甚至代币图像)语言本地化,使所有代币都通用。

1.6遗留元数据

  • ERC-721:保留了像“symbol”和“name”这样的遗留元数据,但这对于许多现代代币来说是不必要的。
  • ERC-1155:将所有元数据保存到web或IPFS上的URI(“统一资源标识符”的简称)中。

1.7ID替换

  • ERC-721:由于只支持静态元数据,因此每个代币ID必须由智能合约存储和管理其元数据URI。
  • ERC-1155:合约可以指向无数的代币URI,无需在链上存储任何额外的数据。甚至可以用来指向一个web服务,该服务为数据库中的每个代币动态生成代币JSON。

二、合约规范接口对比

2.1ERC721

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);

2.2ERC1155

function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
function balanceOf(address _owner, uint256 _id) external view returns (uint256);
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
function setApprovalForAll(address _operator, bool _approved) external;
function isApprovedForAll(address _owner, address _operator) external view returns (bool);

2.3结论

  • 可以明显看到,ERC1155 在原有 ERC721 基础上增加了很多 batch 的接口。再看看 OpenZeppelin 中的 ERC1155 实现,其中的 mint function 增加了 amount 参数, 不难想象,如果 amount = 1, 则代表这个代币总共只发行一个,那这个代币就是类似 ERC721 的 NFT 了。
function _mint(
    address account,
    uint256 id,
    uint256 amount,
    bytes memory data
) internal virtual {
    require(account != address(0), "ERC1155: mint to the zero address");
    address operator = _msgSender();
    _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);
    _balances[id][account] += amount;
    emit TransferSingle(operator, address(0), account, id, amount);
    _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
}

看完啦,动动小手点个赞吧!