ERC-1155 - OpenZeppelin 文档

本文介绍了ERC-1155代币标准,它是一种新型代币标准,旨在从以前的标准中吸取精华,以创建与同质化无关且具有gas效率的代币合约。ERC-1155使用单个智能合约来同时表示多个代币,从而节省了gas,并简化了多代币项目的部署和操作。文章还提供了构造ERC-1155代币合约的示例,并讨论了如何向合约发送代币。

ERC-1155

ERC-1155 是一种新颖的 token 标准,旨在从以前的标准中吸取精华,创建一个 fungibility-agnosticgas-efficienttoken 合约

ERC-1155 从 ERC-20, ERC-721, 和 ERC-777 中借鉴了想法。如果你不熟悉这些标准,请在继续之前查阅它们的指南。

Multi Token Standard

ERC-1155 的显著特点是它使用单个智能合约来同时表示多个 token。这就是为什么它的 balanceOf 函数与 ERC-20 和 ERC-777 的不同:它有一个额外的 id 参数,用于标识你想查询余额的 token。

这与 ERC-721 的做法类似,但在该标准中,token id 没有余额的概念:每个 token 都是非同质化的,要么存在,要么不存在。ERC-721 的 balanceOf 函数指的是一个账户拥有多少个不同的 token,而不是每种 token 有多少个。另一方面,在 ERC-1155 中,账户对每个 token id 都有不同的余额,而非同质化 token 的实现方式仅仅是铸造一个。

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

Batch Operations

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

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

Constructing an ERC-1155 Token Contract

我们将使用 ERC-1155 来跟踪我们游戏中的多个物品,每个物品都有自己独特的属性。我们将所有物品铸造给合约的部署者,我们稍后可以将这些物品转移给玩家。玩家可以自由地保留他们的 token,或者与其他玩家进行交易,就像他们在区块链上交易任何其他资产一样!

为简单起见,我们将在构造函数中铸造所有物品,但你可以向合约添加铸造功能,以便按需铸造给玩家。

有关铸造机制的概述,请查看创建 ERC-20 供应

这是一个 token 化物品的合约示例:

// contracts/GameItems.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC1155} from "@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() 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。

另请注意,与 ERC-20 不同,ERC-1155 缺少 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 架构

你会注意到该物品的信息包含在元数据中,但该信息不在链上!因此,游戏开发者可以更改底层元数据,从而更改游戏规则!
如果你想将所有物品信息放在链上,你可以扩展 ERC-721 来做到这一点(尽管这将非常昂贵),方法是提供一个带有编码的 JSON 模式的 Base64 数据 URI。你还可以利用 IPFS 来存储 URI 信息,但这些技术超出了本概述指南的范围

Sending Tokens to Contracts

使用 safeTransferFrom 时的一个主要区别是,向其他合约转移 token 可能会因以下自定义错误而恢复:

ERC1155InvalidReceiver("<ADDRESS>")

这是一件好事!这意味着接收合约尚未将自己注册为知道 ERC-1155 协议,因此禁用了向其的转移,以防止 token 永远被锁定。例如,Golem 合约目前持有超过 35 万个 GNT token,并且缺乏将它们从那里取出的方法。这种情况几乎发生在每个 ERC20 支持的项目中,通常是由于用户错误造成的。

为了让我们的合约接收 ERC-1155 token,我们可以继承便捷合约 ERC1155Holder,它会为我们处理注册。但是,我们需要记住实现允许 token 从我们的合约转移出去的功能:

// contracts/MyERC115HolderContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";

contract MyERC115HolderContract is ERC1155Holder {}

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

← ERC-721

ERC-4626 →

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

0 条评论

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