ERC-1155 多代币标准
上次修改时间: @mdranger(opens in a new tab), 2023年8月15日
介绍
用于多种代币管理的合约标准接口。 单个部署的合约可以包括同质化代币、非同质化代币或其他配置(如半同质化代币)的任何组合。
多代币标准是什么?
它的目的很单纯,就是创建一个智能合约接口,可以代表和控制任何数量的同质化和非同质化代币类型。 这样一来,ERC-1155 代币就具有与 ERC-20 和 ERC-721 代币相同的功能,甚至可以同时使用这两者的功能。 它改进了 ERC-20 和 ERC-721 标准的功能,提升了效率并纠正了实现中的明显错误。
EIP-1155(opens in a new tab) 中对 ERC-1155 代币进行了全面的描述。
前提条件
为了更好地理解这一页面的内容,我们建议你先阅读代币标准、ERC-20 和 ERC-721。
ERC-1155 的功能和特点:
- 批量传输:通过一次合约调用传输多种资产。
- 批量余额:在一次调用中获取多个资产的余额。
- 批量审批:审批同一地址的所有代币。
- Hook:接收代币的钩子函数。
- 支持非同质化代币:如果供应量仅为 1,将其作为非同质化代币处理。
- 安全转账规则:安全转账规则集。
批量传输
批量传输与常规 ERC-20 传输非常相似。 让我们看看常规 ERC-20 transferFrom
函数:
1// ERC-202function transferFrom(address from, address to, uint256 value) external returns (bool);34// ERC-11555function safeBatchTransferFrom(6 address _from,7 address _to,8 uint256[] calldata _ids,9 uint256[] calldata _values,10 bytes calldata _data11) external;显示全部复制
ERC-1155 中唯一的区别是我们将值作为数组传递,同时也传递了 ids 数组。 例如,给出 ids=[3, 6, 13]
和 values=[100, 200, 5]
,传输结果将是
- 将 id 3 的 100 个代币从
_from
传输到_to
。 - 将 id 6 的 200 个代币从
_from
传输到_to
。 - 将 id 13 的 5 个代币从
_from
转移到_to
。
在 ERC-1155 中,我们只有 transferFrom
,没有 transfer
。 要像常规的 transfer
一样使用它,只需将 "from" 地址设为调用该函数的地址。
批量余额
相应的 ERC-20 balanceOf
调用同样具有支持批处理的相应函数。 作为对比,这是 ERC-20 版本:
1// ERC-202function balanceOf(address owner) external view returns (uint256);34// ERC-11555function balanceOfBatch(6 address[] calldata _owners,7 uint256[] calldata _ids8) external view returns (uint256[] memory);复制
调用余额查询更简单的是,我们可以在单次调用中获取多个余额。 参数中传递所有者帐户数组和代币的 id 数组。
例如,对于给出的 _ids=[3, 6, 13]
和 _owners=[0xbeef..., 0x1337..., 0x1111...]
,返回值将为:
1[2 balanceOf(0xbeef...),3 balanceOf(0x1337...),4 balanceOf(0x1111...)5]复制
批量审批
1// ERC-11552function setApprovalForAll(3 address _operator,4 bool _approved5) external;67function isApprovedForAll(8 address _owner,9 address _operator10) external view returns (bool);显示全部复制
审批过程与 ERC-20 略有不同。 这里不是批准特定金额,而是通过 setApprovalForAll
函数设置操作帐户为已批准或未批准。
查看当前的审批状态可以通过 isApprovedForAll
完成。 如你所见,要么全部批准,要么不批准。 不能定义要批准代币的数量,甚至代币类型。
这是考虑到简洁性而故意设计的。 你只能批准一个地址的所有代币。
接收钩子
1function onERC1155BatchReceived(2 address _operator,3 address _from,4 uint256[] calldata _ids,5 uint256[] calldata _values,6 bytes calldata _data7) external returns(bytes4);复制
基于 EIP-165(opens in a new tab) 的协议支持,ERC-1155 只支持智能合约的接收钩子函数。 钩子函数必须返回一个事先预定义的 4 字节值,这个值被指定为:
1bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))复制
当接收合约返回这一值时,意味着合约知道如何处理 ERC-1155 代币并接受转账。 太好了,代币不会再卡在合约中了!
支持非同质化代币
当供应量仅为 1 时,代币本质上就是一个非同质化的代币 (NFT)。 按照 ERC-721 的标准,你可以定义一个元数据网址。 客户端可以读取并修改网址,请参阅这里(opens in a new tab)。
安全转账规则
在前面的解释中,我们已经提到过一些安全转账规则。 现在我们来看一下最重要的规则:
- 调用者必须获得批准才能从
_from
的帐户地址消费代币,或者调用者帐户地址必须与_from
的帐户地址相同。 - 在以下情况下,转账调用将回退
_to
地址为 0;_ids
的长度与_values
的长度不同;_ids
中代币持有者的任何余额低于发送给接收者的相应_value
金额。- 出现任何其他错误。
注意:包括钩子在内的所有批处理函数也均作为非批处理的版本存在。 这样做是为了提高燃料效率,考虑到只转移一种资产可能仍然是最常用的方式。 简洁起见,我们没有在这里介绍这些非批处理的版本,包括安全转账规则。 名称是相同的,只需移除 'Batch'。
延伸阅读
- EIP-1155:多代币标准(opens in a new tab)
- ERC-1155:OpenZeppelin 文档(opens in a new tab)
- ERC-1155: GitHub Repo(opens in a new tab)
- Alchemy NFT API(opens in a new tab)