Summary
对于ERC20和ERC721来说,每个合约对应的都只有一个独立代币或者NFT,对于大型项目来说可能会有上千种代币,那么如果要部署和管理这上千份合约,那是非常麻烦的,所以有了ERC1155,允许一个合约包含多个同质化和非同质化代笔。
ERC1155和ERC721类似,ERC721有tokenId用来作为唯一标识,而在ERC1155中,每一种代币都有一个id作为唯一标识符,每个id对应一种呆逼,这样代币种类就可以非同质的在同一个合约中管理了,并且每一种代币都有一个网址uri来存储元数据,类似ERC721中的tokenURI。
Interface
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/AmazingAng/WTFSolidity/blob/main/34_ERC721/IERC165.sol";
/**
 * @dev ERC1155标准的接口合约,实现了EIP1155的功能
 * 详见:https://eips.ethereum.org/EIPS/eip-1155[EIP].
 */
interface IERC1155 is IERC165 {
    /**
     * @dev 单类代币转账事件
     * 当`value`个`id`种类的代币被`operator`从`from`转账到`to`时释放.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
    /**
     * @dev 批量代币转账事件
     * ids和values为转账的代币种类和数量数组
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );
    /**
     * @dev 批量授权事件
     * 当`account`将所有代币授权给`operator`时释放
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);
    /**
     * @dev 当`id`种类的代币的URI发生变化时释放,`value`为新的URI
     */
    event URI(string value, uint256 indexed id);
    /**
     * @dev 持仓查询,返回`account`拥有的`id`种类的代币的持仓量
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);
    /**
     * @dev 批量持仓查询,`accounts`和`ids`数组的长度要想等。
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);
    /**
     * @dev 批量授权,将调用者的代币授权给`operator`地址。
     * 释放{ApprovalForAll}事件.
     */
    function setApprovalForAll(address operator, bool approved) external;
    /**
     * @dev 批量授权查询,如果授权地址`operator`被`account`授权,则返回`true`
     * 见 {setApprovalForAll}函数.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);
    /**
     * @dev 安全转账,将`amount`单位`id`种类的代币从`from`转账给`to`.
     * 释放{TransferSingle}事件.
     * 要求:
     * - 如果调用者不是`from`地址而是授权地址,则需要得到`from`的授权
     * - `from`地址必须有足够的持仓
     * - 如果接收方是合约,需要实现`IERC1155Receiver`的`onERC1155Received`方法,并返回相应的值
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;
    /**
     * @dev 批量安全转账
     * 释放{TransferBatch}事件
     * 要求:
     * - `ids`和`amounts`长度相等
     * - 如果接收方是合约,需要实现`IERC1155Receiver`的`onERC1155BatchReceived`方法,并返回相应的值
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}
如何区分
如果某个id对应的代币总量为1,那么它就是非同质化代币,类似ERC721;如果某个id对应的代币总量大于1,那么他就是同质化代币,因为这些代币都分享同一个id,类似ERC20。
Receive ERC1155 Token
要求接受合约实现IERC1155Receiver并且实现两个接受函数:
- onERC1155Received():单币转账接收函数,接受- ERC1155安全转账- safeTransferFrom需要实现并返回自己的选择器- 0xf23a6e61.
- onERC1155BatchReceived():多币转账接收函数,接受- ERC1155安全多币转账- safeBatchTransferFrom需要实现并返回自己的选择器- 0xbc197c81.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/AmazingAng/WTFSolidity/blob/main/34_ERC721/IERC165.sol";
/**
 * @dev ERC1155接收合约,要接受ERC1155的安全转账,需要实现这个合约
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev 接受ERC1155安全转账`safeTransferFrom` 
     * 需要返回 0xf23a6e61 或 `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);
    /**
     * @dev 接受ERC1155批量安全转账`safeBatchTransferFrom` 
     * 需要返回 0xbc197c81 或 `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}
Refer
https://ethereum.org/zh/developers/docs/standards/tokens/erc-1155/