本文介绍了 ERC1155 token 标准,它借鉴了 ERC20、ERC721 和 ERC777 的优点,实现了fungibility-agnostic 和 gas-efficient 的代币合约。ERC1155 允许在一个智能合约中表示多种类型的代币,通过批量操作和单一合约状态管理,可以节省大量 gas 费用。
你当前阅读的不是此文档的最新版本。5.x 是当前版本。
ERC1155 是一种新型的 token 标准,旨在吸取先前标准的优点,以创建一种与同质化无关且gas 高效的 token 合约。
ERC1155 从 ERC20,ERC721 和 ERC777 中汲取了想法。 如果你不熟悉这些标准,请在继续之前查看其指南。 |
ERC1155 的独特之处在于,它使用单个智能合约一次表示多个 token。 这就是为什么它的 balanceOf
函数与 ERC20 和 ERC777 的不同:它有一个额外的 id
参数,用于标识你要查询余额的 token。
这与 ERC721 的工作方式类似,但在该标准中,token id
没有余额的概念:每个 token 都是非同质化的,存在或不存在。 ERC721 balanceOf
函数指的是一个账户拥有多少个不同的 token,而不是每个 token 有多少个。 另一方面,在 ERC1155 中,账户对于每个 token id
都有不同的余额,并且非同质化 token 通过简单地铸造一个来实现。
对于需要多个 token 的项目,这种方法可以节省大量 gas。 无需为每种 token 类型部署新的合约,单个 ERC1155 token 合约就可以保存整个系统状态,从而降低部署成本和复杂性。
由于所有状态都保存在单个合约中,因此可以在单个交易中非常有效地处理多个 token。 该标准提供了两个函数balanceOfBatch
和 safeBatchTransferFrom
,这使得查询多个余额和转移多个 token 更加简单且减少 gas 消耗。
本着该标准的精神,我们还在非标准函数中包含了批量操作,例如 _mintBatch
。
我们将使用 ERC1155 来跟踪我们游戏中的多个物品,每个物品都将具有其自己的独特属性。 我们将所有物品都铸造给合约的部署者,以后我们可以将其转移给玩家。 玩家可以自由保留其 token 或与其他玩家进行交易,就像他们在区块链上交易任何其他资产一样!
为简单起见,我们将在构造函数中铸造所有物品,但是你可以将铸造功能添加到合约中,以便按需铸造给玩家。
有关铸造机制的概述,请查看 创建 ERC20 供应。 |
以下是 token 化物品的合约可能如下所示:
// contracts/GameItems.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
contract GameItems is ERC1155 {
uint256 public constant GOLD = 0; // 黄金
uint256 public constant SILVER = 1; // 白银
uint256 public constant THORS_HAMMER = 2; // 索尔之锤
uint256 public constant SWORD = 3; // 剑
uint256 public constant SHIELD = 4; // 盾
constructor() public ERC1155("https://game.example/api/item/{id}.json") {
_mint(msg.sender, GOLD, 10**18, "");
_mint(msg.sender, SILVER, 10**27, "");
_mint(msg.sender, THORS_HAMMER, 1, "");
_mint(msg.sender, SWORD, 10**9, "");
_mint(msg.sender, SHIELD, 10**9, "");
}
}
请注意,对于我们的游戏物品,黄金是一种同质化 token,而索尔之锤是一种非同质化 token,因为我们只铸造了一个。
ERC1155
合约包括可选扩展 IERC1155MetadataURI
。 这就是 uri
函数的来源:我们使用它来检索元数据 uri。
另请注意,与 ERC20 不同,ERC1155 缺少 decimals
字段,因为每个 token 都是不同的并且不能被划分。
部署后,我们将能够查询部署者的余额:
> gameItems.balanceOf(deployerAddress,3)
1000000000
我们可以将物品转移到玩家帐户:
> gameItems.safeTransferFrom(deployerAddress, playerAddress, 2, 1, "0x0")
> gameItems.balanceOf(playerAddress, 2)
1
> gameItems.balanceOf(deployerAddress, 2)
0
我们还可以将物品批量转移到玩家帐户并获取批量余额:
> gameItems.safeBatchTransferFrom(deployerAddress, playerAddress, [0,1,3,4], [50,100,1,1], "0x0")
> gameItems.balanceOfBatch([playerAddress,playerAddress,playerAddress,playerAddress,playerAddress], [0,1,2,3,4])
[50,100,1,1,1]
可以获得元数据 uri:
> gameItems.uri(2)
"https://game.example/api/item/{id}.json"
uri
可以包含字符串 {id}
,客户端必须将其替换为实际的 token ID,以小写十六进制(没有 0x 前缀)表示,并用前导零填充到 64 个十六进制字符。
对于 token ID 2
和 uri https://game.example/api/item/{id}.json
,客户端将 {id}
替换为 0000000000000000000000000000000000000000000000000000000000000002
以在 https://game.example/api/item/0000000000000000000000000000000000000000000000000000000000000002.json
处检索 JSON。
token ID 2 的 JSON 文档可能如下所示:
{
"name": "Thor's hammer",
"description": "Mjölnir, the legendary hammer of the Norse god of thunder.", // 姆乔尔尼尔,挪威雷神的传奇锤子。
"image": "https://game.example/item-id-8u5h2m.png",
"strength": 20
}
有关元数据 JSON 模式的更多信息,请查看 ERC-1155 元数据 URI JSON 模式。
你会注意到物品的信息包含在元数据中,但是该信息不在链上! 因此,游戏开发人员可以更改基础元数据,从而更改游戏规则! |
使用 safeTransferFrom
时,一个关键区别在于,将 token 转移到其他合约可能会恢复,并显示以下消息:
ERC1155: transfer to non ERC1155Receiver implementer // ERC1155:转移到非 ERC1155Receiver 实现者
这是一件好事! 这意味着接收合约尚未将自身注册为知晓 ERC1155 协议,因此禁用向其的转移,以防止 token 永远被锁定。 作为一个例子,Golem 合约目前持有超过 35 万个 GNT
token,价值数万美元,并且缺乏将其取出的方法。 这几乎发生在每个 ERC20 支持的项目中,通常是由于用户错误。
为了使我们的合约能够接收 ERC1155 token,我们可以从便捷合约 ERC1155Holder
继承,该合约为我们处理注册。 尽管我们需要记住实现允许 token 从我们的合约中转移出去的功能:
// contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "@openzeppelin/contracts/token/ERC1155/ERC1155Holder.sol";
contract MyContract is ERC1155Holder {
}
我们还可以使用 onERC1155Received
和 onERC1155BatchReceived
函数来实现更复杂的场景。
有一个预设的 ERC1155 可用,ERC1155PresetMinterPauser
。 它是预设为允许 token 铸造(创建) - 包括批量铸造,停止所有 token 转移(暂停)并允许持有者燃烧(销毁)他们的 token。 该合约使用 访问控制 来控制对铸造和暂停功能的访问。 部署合约的帐户将被授予铸币者和暂停者角色,以及默认管理员角色。
该合约已准备好部署,无需编写任何 Solidity 代码。 它可以按原样用于快速原型设计和测试,但也适用于生产环境。
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!