# ERC1155 和 ERC721 有什么区别

By [Cat](https://paragraph.com/@cat-24) · 2022-04-21

---

![ERC1155 和 ERC721 区别](https://storage.googleapis.com/papyrus_images/a3e667ad0d869471c71d6d6d07faf472c4cc12cbcec8885987c5881c64466bb2.jpg)

ERC1155 和 ERC721 区别

简单来说，ERC1155是ERC721的升级版，ERC1155在ERC721的基础上，主要增加或改善了如下功能：

*   同时支持**可替换代币（同质化代币）和不可替换代币（非同质化代币）**；
    
*   在 ERC-1155 中，智能合约链接到多个 URI，并且**不存储额外的元数据**（例如文件名）。相比之下，ERC-721 仅支持直接存储在智能合约上的每个代币 ID 的静态元数据，增加了部署成本并限制了灵活性。
    
*   ERC-1155 的智能合约支持**无限数量的代币**，而 ERC-721 需要为每种类型的代币创建一个新的智能合约。
    
*   **批量转账**：仅需要一次智能合约调用，就可以转账多种代币资产；
    
*   **批量查询余额**：一次智能合约调用可以查询多种代币余额数据；
    
*   **批量授权**：一次智能合约调用可以向指定地址授权多种代币的使用权；
    

用人话来说，就是一张ERC1155智能合约，里面可以同时包含类似USDT这种代币，和类似MekaVerse，无聊猿等这种独一无二的NFT代币。

传统的ERC721合约，如果要转移NFT，必须一个一个操作，没有办法做到批量转账。而ERC1155，则加入了类似「购物车」的概念，可以一堆代币一次过转移。不要小看这个「批量」功能，要知道每次和内存块链交互，都要消耗gas，如果有某些应用场景需要大量，频繁转移资产，那ERC1155相比ERC721则能节约大量的gas成本。

试想一下，假如现在想要创作一款区块链游戏，里面有类似USDT的可替换同质化代币以进行金融操作，也需要有各种游戏装备，英雄角色等独一无二不可替换代币来进行游戏，这两种代币也需要透过一定的机制进行交易互换，这个场景，使用ERC1155则可以完美实现。

对比一下ERC721和ERC1155合约的规范接口：

ERC721

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

ERC1155

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

由上的代码块可以看出，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);
    }
    

其他相关的更新
-------

### ERC721R

ERC721R 是为了ERC721 和 ERC1155 标准打造的**退款功能**。在NFT智能合约中增加了去信任的退款协议设计，允许铸造在给定的期限内退还按成本铸造的NFT，并且收获相应的退款。

当用户在 ERC721R 集合中铸造 NFT 时，资金由购买时的智能合约持有。该智能合约可以设置特定时间区间，在该时间范围内，用户随时可将NFT发送给合约并获取自己的初始购买资金，合约在该时间内也不能提走用户的购买资金。

例如：一份含有ERC721R的智能合约，该合约设置了NFT购买的可退款时间为10天内，用户在该合约中花费 0.5 ETH 购买了1枚NFT，两天之后，用户想拿回自己的ETH，随后在该合约归还NFT，获取自己的初始购买资金0.5ETH。本次操作中用户只会损失交易的 gas 成本。

**ERC721R的优势**

> 对于买家：
> 
> *   低风险购买（可以退款，只承担手续费）
>     
> *   防止项目跑路
>     
> *   迫使创作者承担更大的责任来交付
>     
> 
> 对于卖家：
> 
> *   与买家建立信任
>     
> 
> 对双方都有好处：
> 
> *   在退款开放期间，项目底价不太可能跌破新币价格。
>     
> *   短期恐惧提前离开项目，留下完整的高质量核心。
>     

**ERC721R 可能存在的安全风险**

> *   风险一：用户退款至管理员，管理员可获取合约中所有ERC20资金。
>     
>     *   假如有10个用户购买了该合约的NFT，当其中一个用户退款后，该用户的NFT会转移至refundAddress地址，也就是管理员地址，之后refundAddress管理员调用refund方法，将自己所属的NFT进行退款，由于现在transferFrom方法中的发送者和接收者均为自己，所以NFT归属者不受影响，但转移NFT后会进行ERC20资金发送，所以此时管理员可以一直进行NFT退款操作，得到合约内部所有的ERC20资金。
>         
> *   风险二：管理员铸造NFT，利用该NFT获取合约中所有ERC20资金。
>     
>     *   假如有10个用户购买了该合约的NFT，在规定时间区间内也未归还，管理员可以铸造一个NFT，之后进行循环退款，取走合约内部ERC20资金，也就是上述风险1中的描述。
>         

**ERC721R 或许可改进**

*   建议对合约中管理员地址进行区别。
    
*   建议设置退款之后的NFT流动限制。
    

**如下是ERC721R合约的代码，可以参考。**

[https://github.com/CatBosss/ERC721R](https://github.com/CatBosss/ERC721R)

**参考资料：**

[https://www.frank.hk/blog/nft-erc1155/](https://www.frank.hk/blog/nft-erc1155/)

[https://www.anquanke.com/post/id/272039](https://www.anquanke.com/post/id/272039)

`随便叭叭`

`技术本身不值钱，重要的都是思想。`

`代码是诚实的，难以捉摸的是人心。`

---

*Originally published on [Cat](https://paragraph.com/@cat-24/erc1155-erc721)*
