ERC-1155 多代币标准
ERC-1155 多代币标准
本页内容正在整理中,欢迎贡献。
概述
ERC-1155 是一种多代币标准,单个合约可以管理无限种类型的代币——既可以是同质化的(如游戏货币),也可以是非同质化的(如独特道具)。批量操作使 Gas 消耗大幅降低,特别适合区块链游戏和多资产项目。
主要内容
ERC-1155 vs ERC-721 vs ERC-20
| 特性 | ERC-20 | ERC-721 | ERC-1155 |
|---|---|---|---|
| 代币类型数 | 1 种 | 1 种 | 无限种 |
| 同质化 | ✅ | ❌ | ✅(部分 ID) |
| 非同质化 | ❌ | ✅ | ✅(供应量=1) |
| 批量转移 | ❌ | ❌ | ✅ |
| 部署成本 | 低 | 低 | 低(多资产共用) |
| 单次转账 Gas | 中 | 中 | 低(批量时) |
基础实现
// SPDX-License-Identifier: MITpragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";import "@openzeppelin/contracts/access/Ownable.sol";import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
contract GameItems is ERC1155, ERC1155Supply, Ownable { // Token ID 常量定义 uint256 public constant GOLD = 0; // 同质化:游戏金币 uint256 public constant SILVER = 1; // 同质化:银币 uint256 public constant SWORD = 2; // 半同质化:剑(可多把) uint256 public constant RARE_SWORD = 3; // NFT:稀有剑(只有1把) uint256 public constant SHIELD = 4;
// 每种 Token 的最大供应量(0 = 无限) mapping(uint256 => uint256) public maxSupply;
constructor() ERC1155("https://api.mygame.xyz/items/{id}.json") Ownable(msg.sender) { maxSupply[RARE_SWORD] = 1; // 稀有剑只有 1 把 }
// 铸造 function mint( address to, uint256 id, uint256 amount, bytes memory data ) external onlyOwner { if (maxSupply[id] > 0) { require(totalSupply(id) + amount <= maxSupply[id], "Exceeds max supply"); } _mint(to, id, amount, data); }
// 批量铸造 function mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) external onlyOwner { _mintBatch(to, ids, amounts, data); }
// 设置元数据 URI function setURI(string memory newuri) external onlyOwner { _setURI(newuri); }
// 覆盖 supportsInterface function supportsInterface(bytes4 interfaceId) public view override(ERC1155, ERC1155Supply) returns (bool) { return super.supportsInterface(interfaceId); }
function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal override(ERC1155, ERC1155Supply) { super._update(from, to, ids, values); }}批量转移
// 批量转移多种代币(一笔交易)function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public override { super.safeBatchTransferFrom(from, to, ids, amounts, data);}// 前端批量转移await writeContract({ address: GAME_ITEMS_ADDRESS, abi: ERC1155_ABI, functionName: "safeBatchTransferFrom", args: [ fromAddress, toAddress, [0n, 1n, 2n], // Gold, Silver, Sword [100n, 50n, 1n], // 数量 "0x", ],});元数据格式
ERC-1155 元数据 URI 中的 {id} 会被替换为十六进制 token ID(64 位,零填充):
URI 模板: "https://api.example.com/tokens/{id}.json"tokenId 0: "https://api.example.com/tokens/0000000000000000000000000000000000000000000000000000000000000000.json"元数据 JSON:
{ "name": "Gold Coin", "description": "游戏中的黄金货币", "image": "https://api.example.com/images/gold.png", "decimals": 0, "properties": { "type": "currency", "rarity": "common" }}接收回调
接收 ERC-1155 的合约需实现:
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
contract ItemVault is IERC1155Receiver { // 接收单个 Token function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external override returns (bytes4) { return this.onERC1155Received.selector; }
// 接收批量 Token function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external override returns (bytes4) { return this.onERC1155BatchReceived.selector; }
function supportsInterface(bytes4 interfaceId) external view override returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId; }}典型使用场景
| 场景 | Token ID 设计 |
|---|---|
| 区块链游戏 | 0=金币(FT),1-999=武器(SFT),1000+=独特道具(NFT) |
| 数字藏品 | 每个系列一个 ID,supply=版次数量 |
| 活动票务 | 每场活动一个 ID,supply=座位数 |
| 多合约替代 | 将原来需要多个 ERC-20/721 的项目合并 |