ERC1155

多代币标准

简介

用于多种代币管理的合约标准接口。 单个部署的合约可以包括同质化代币、非同质化代币或其他配置(如半同质化代币)的任何组合。

多代币标准是什么?

它的目的很单纯,就是创建一个智能合约接口,可以代表和控制任何数量的同质化和非同质化代币类型。 这样一来,ERC-1155 代币就具有与 ERC-20 和 ERC-721 代币相同的功能,甚至可以同时使用这两者的功能。 它改进了 ERC-20 和 ERC-721 标准的功能,提升了效率并纠正了实现中的明显错误。

功能

批量传输

通过一次合约调用传输多种资产

就是不单是一种代币可以传输,很多种代币都可以传输

来看看,他与ERC20传输合约的比较

// ERC-20
function transferFrom(address from, address to, uint256 value) external returns (bool);

// ERC-1155
function safeBatchTransferFrom(
address _from,
address _to,
uint256[] calldata _ids,
uint256[] calldata _values,
bytes calldata _data
) 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
function balanceOf(address owner) external view returns (uint256);

// ERC-1155
function balanceOfBatch(
address[] calldata _owners,
uint256[] calldata _ids
) external view returns (uint256[] memory);

调用余额查询更简单的是,我们可以在单次调用中获取多个余额。 参数中传递所有者帐户数组和代币的 id 数组。

例如,对于给出的 _ids=[3, 6, 13] 和 _owners=[0xbeef…, 0x1337…, 0x1111…],返回值将为:

[
balanceOf(0xbeef...),
balanceOf(0x1337...),
balanceOf(0x1111...)
]

批量审批

审批同一地址的所有代币

还是来看一下ERC115

// ERC-1155
function setApprovalForAll(
address _operator,
bool _approved
) external;

function isApprovedForAll(
address _owner,
address _operator
) external view returns (bool);

审批过程与 ERC-20 略有不同。 这里不是批准特定金额,而是通过 setApprovalForAll 函数设置操作帐户为已批准或未批准。

查看当前的审批状态可以通过 isApprovedForAll 完成。 如你所见,要么全部批准,要么不批准。 不能定义要批准代币的数量,甚至代币类型。

这是考虑到简洁性而故意设计的。 你只能批准一个地址的所有代币。

接受钩子

接受钩子的代币函数

function onERC1155BatchReceived(
address _operator,
address _from,
uint256[] calldata _ids,
uint256[] calldata _values,
bytes calldata _data
) external returns(bytes4);

基于 EIP-165(opens in a new tab) 的协议支持,ERC-1155 只支持智能合约的接收钩子函数。 钩子函数必须返回一个事先预定义的 4 字节值,这个值被指定为:bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
当接收合约返回这一值时,意味着合约知道如何处理 ERC-1155 代币并接受转账。 太好了,代币不会再卡在合约中了!(这里可能会是漏洞,比如点击这个题就是使用到了钩子,让代币困在合约中)

安全转账

现在我们来看一下最重要的规则:

1,调用者必须获得批准才能从 _from 的帐户地址消费代币,或者调用者帐户地址必须与 _from 的帐户地址相同。
2,在以下情况下,转账调用将回退

  • _to 地址为 0;
  • _ids 的长度与 _values 的长度不同;
  • _ids 中代币持有者的任何余额低于发送给接收者的相应 _value 金额。出现任何其他错误。

    注意:包括钩子在内的所有批处理函数也均作为非批处理的版本存在。 这样做是为了提高燃料效率,考虑到只转移一种资产可能仍然是最常用的方式。 简洁起见,我们没有在这里介绍这些非批处理的版本,包括安全转账规则。 名称是相同的,只需移除 ‘Batch’。

接口

IERC1155接口,接口中定义了六个函数

  • balanceOf():单币种余额查询,返回account拥有的id种类的代币的持仓量。
  • balanceOfBatch():多币种余额查询,查询的地址accounts数组和代币种类ids数组的长度要相等。
  • setApprovalForAll():批量授权,将调用者的代币授权给operator地址。。
  • isApprovedForAll():查询批量授权信息,如果授权地址operator被account授权,则返回true。
  • safeTransferFrom():安全单币转账,将amount单位id种类的代币从from地址转账给to地址。如果to地址是合约,则会验证是否实现了onERC1155Received()接收函数。
  • safeBatchTransferFrom():安全多币转账,与单币转账类似,只不过转账数量amounts和代币种类ids变为数组,且长度相等。如果to地址是合约,则会验证是否实现了onERC1155BatchReceived()接收函数。(重点)

如果ERC1155TOKEN的接收者receiver是一个合约地址,那么接收者必须要实现该接口。

该接口有两个函数:(前提是接收者是合约地址):

  • onERC1155Received:这个函数是在调用 ERC1155的 safeTransferFrom()和 _mint()时,接收者的该函数会被调用,并按要求返回指定的值 bytes4(keccak256(“onERC1155Received(address,address,uint256,uint256,bytes)”))。
  • onERC1155BatchReceived:这个函数时在调用 ERC1155的 safeBatchTransferFrom()时,接收者的该函数会被调用,并按要求返回指定的值 bytes4(keccak256(“onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)”))

如果我们不按要求返回一个指定值,那么代币就会转移不出来,困在合约中。