Skip to main content

erc1155-patterns

Use when building multi-token contracts with ERC-1155. Covers batch operations, URI handling, supply tracking, hybrid fungible and non-fungible patterns, and game item architectures.

설치로 이동

소스 정보

저장소
ccashwell/evm-cortex
최근 소스 활동
2026년 4월 10일 16:31
감지된 SKILL.md 언어
영어
스타
131
포크
18

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
erc1155-patterns
description
Use when building multi-token contracts with ERC-1155. Covers batch operations, URI handling, supply tracking, hybrid fungible and non-fungible patterns, and game item architectures.
# ERC-1155 Multi-Token Patterns ## Standard Interface ```solidity interface IERC1155 { function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address account, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; } ``` ## Implementation Pattern ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import {ERC1155Supply} from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import {ERC1155URIStorage} from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract GameItems is ERC1155, ERC1155Supply, ERC1155URIStorage, Ownable { // Token type constants uint256 public constant GOLD = 0; // fungible uint256 public constant SILVER = 1; // fungible uint256 public constant SWORD = 2; // non-fungible (supply = 1 each) uint256 public constant SHIELD = 3; // semi-fungible uint256 private _nextUniqueId = 1000; mapping(uint256 tokenId => uint256 maxSupply) public caps; constructor(string memory baseUri) ERC1155(baseUri) Ownable(msg.sender) { caps[GOLD] = type(uint256).max; caps[SILVER] = type(uint256).max; caps[SWORD] = 100; caps[SHIELD] = 500; } function mintFungible(address to, uint256 id, uint256 amount) external onlyOwner { require(totalSupply(id) + amount <= caps[id], "Cap exceeded"); _mint(to, id, amount, ""); } function mintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts) external onlyOwner { for (uint256 i = 0; i < ids.length; i++) { require(totalSupply(ids[i]) + amounts[i] <= caps[ids[i]], "Cap exceeded"); } _mintBatch(to, ids, amounts, ""); } function mintUnique(address to, string calldata tokenUri) external onlyOwner returns (uint256) { uint256 tokenId = _nextUniqueId++; caps[tokenId] = 1; _mint(to, tokenId, 1, ""); _setURI(tokenId, tokenUri); return tokenId; } function uri(uint256 tokenId) public view override(ERC1155, ERC1155URIStorage) returns (string memory) { return super.uri(tokenId); } function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal override(ERC1155, ERC1155Supply) { super._update(from, to, ids, values); } } ``` ## URI Handling ERC-1155 uses a single URI template with `{id}` substitution: ``` https://api.example.com/tokens/{id}.json ``` The `{id}` is replaced with the lowercase hex token ID, zero-padded to 64 characters: `https://api.example.com/tokens/0000000000000000000000000000000000000000000000000000000000000001.json` For per-token URIs, use `ERC1155URIStorage`: ```solidity _setURI(tokenId, "ipfs://QmUniqueHash"); // Emits URI(value, tokenId) ``` ## Batch Operations Batch transfers save significant gas compared to individual transfers: ```solidity // Transfer multiple token types in one tx uint256[] memory ids = new uint256[](3); uint256[] memory amounts = new uint256[](3); ids[0] = GOLD; amounts[0] = 100; ids[1] = SILVER; amounts[1] = 50; ids[2] = SWORD; amounts[2] = 1; gameItems.safeBatchTransferFrom(alice, bob, ids, amounts, ""); ``` Gas savings: batch of 10 transfers costs ~60% of 10 individual transfers. ## Receiver Interface Contracts receiving ERC-1155 tokens must implement: ```solidity interface IERC1155Receiver { function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); } ``` ## Hybrid Fungible + Non-Fungible Pattern Use ID ranges to distinguish token types: ```solidity // IDs 0-999: fungible tokens (can have supply > 1) // IDs 1000+: unique NFTs (supply == 1) function isFungible(uint256 id) public pure returns (bool) { return id < 1000; } function isNonFungible(uint256 id) public view returns (bool) { return id >= 1000 && totalSupply(id) == 1; } ``` ## ERC-1155 vs ERC-721 Decision | Factor | ERC-721 | ERC-1155 | |--------|---------|----------| | Token types | One per contract | Many per contract | | Batch transfers | Not native | Built-in | | Gas (deploy) | Lower | Higher | | Gas (batch ops) | Higher | Much lower | | Marketplace support | Universal | Growing | | Fungible support | No | Yes | Choose ERC-1155 when: multiple token types, game items, mixed fungible/non-fungible, batch operations needed. ## Security Checklist - [ ] Implement both `onERC1155Received` and `onERC1155BatchReceived` in receiver contracts - [ ] Validate array lengths match in batch operations - [ ] Track supply with `ERC1155Supply` if caps are needed - [ ] Use `_update` hook for custom transfer logic (not `_beforeTokenTransfer`) - [ ] Test `supportsInterface` for ERC-1155 and ERC-165 - [ ] Guard against reentrancy (safe transfers call external code)
GitHub에서 보기