ERC1155 - OpenZeppelin 文档

本文介绍了 ERC1155 token 标准,它借鉴了 ERC20、ERC721 和 ERC777 的优点,实现了fungibility-agnostic 和 gas-efficient 的代币合约。ERC1155 允许在一个智能合约中表示多种类型的代币,通过批量操作和单一合约状态管理,可以节省大量 gas 费用。

你当前阅读的不是此文档的最新版本。5.x 是当前版本。

ERC1155

ERC1155 是一种新型的 token 标准,旨在吸取先前标准的优点,以创建一种与同质化无关gas 高效token 合约

ERC1155 从 ERC20ERC721ERC777 中汲取了想法。 如果你不熟悉这些标准,请在继续之前查看其指南。

Multi Token Standard

ERC1155 的独特之处在于,它使用单个智能合约一次表示多个 token。 这就是为什么它的 balanceOf 函数与 ERC20 和 ERC777 的不同:它有一个额外的 id 参数,用于标识你要查询余额的 token。

这与 ERC721 的工作方式类似,但在该标准中,token id 没有余额的概念:每个 token 都是非同质化的,存在或不存在。 ERC721 balanceOf 函数指的是一个账户拥有多少个不同的 token,而不是每个 token 有多少个。 另一方面,在 ERC1155 中,账户对于每个 token id 都有不同的余额,并且非同质化 token 通过简单地铸造一个来实现。

对于需要多个 token 的项目,这种方法可以节省大量 gas。 无需为每种 token 类型部署新的合约,单个 ERC1155 token 合约就可以保存整个系统状态,从而降低部署成本和复杂性。

Batch Operations

由于所有状态都保存在单个合约中,因此可以在单个交易中非常有效地处理多个 token。 该标准提供了两个函数balanceOfBatchsafeBatchTransferFrom,这使得查询多个余额和转移多个 token 更加简单且减少 gas 消耗。

本着该标准的精神,我们还在非标准函数中包含了批量操作,例如 _mintBatch

Constructing an ERC1155 Token Contract

我们将使用 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 模式

你会注意到物品的信息包含在元数据中,但是该信息不在链上! 因此,游戏开发人员可以更改基础元数据,从而更改游戏规则!

Sending Tokens to Contracts

使用 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 {
}

我们还可以使用 onERC1155ReceivedonERC1155BatchReceived 函数来实现更复杂的场景。

Preset ERC1155 contract

有一个预设的 ERC1155 可用,ERC1155PresetMinterPauser。 它是预设为允许 token 铸造(创建) - 包括批量铸造,停止所有 token 转移(暂停)并允许持有者燃烧(销毁)他们的 token。 该合约使用 访问控制 来控制对铸造和暂停功能的访问。 部署合约的帐户将被授予铸币者和暂停者角色,以及默认管理员角色。

该合约已准备好部署,无需编写任何 Solidity 代码。 它可以按原样用于快速原型设计和测试,但也适用于生产环境。

← ERC777

Gas Station Network →

  • 原文链接: docs.openzeppelin.com/co...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。