Build a Multi-Token Game Economy with ERC-1155

Want to understand how Enjin gaming assets, Gods Unchained cards, or OpenSea shared collections work? Build your own multi-token contract.
In 90-120 minutes, you'll deploy a contract managing unlimited token types: fungible currencies, unique items, and everything in between. One contract powering an entire game economy. You'll see why developers call ERC-1155 the multi-tool of token standards and how batch operations can save 50-80% on gas costs.
Note: This guide builds on concepts from the ERC-721 guide. If you haven't completed it, you'll still be able to follow along, but some concepts will be more familiar if you've worked with NFTs before.
What You'll Learn
This guide goes beyond basic token creation. You'll understand the architecture powering blockchain gaming:
Why one contract can replace dozens - ERC-20 needs one contract per token. ERC-721 needs one per collection. ERC-1155 manages unlimited token types in a single deployment.
How batch operations slash gas costs - Minting 10 different items in one transaction instead of 10 separate ones. The savings add up fast.
What "semi-fungible" actually means - Concert tickets for the same event but different seats. Game items that start identical but become unique through use.
The
{id}metadata pattern - How one base URI serves metadata for thousands of token types without storing thousands of strings on-chain.
What You Need
MetaMask wallet
Holds test funds and signs the deployment transaction that creates your contract
Sepolia test ETH
Pays for gas fees (~$0 in real value, but required for test network)
Alchemy RPC URL
Your connection point to Ethereum. Like an API key for blockchain access.
alchemy.com (free tier)
Pinata account
Hosts your token images and metadata on IPFS, the decentralized storage layer"
pinata.cloud (free tier)
Understanding What You're Building
ERC-1155 solves a problem that becomes obvious once you think about game economies.
Imagine building a blockchain game. You need:
Gold coins - Players earn and spend millions of these. Fungible, like ERC-20.
Health potions - Common items, maybe 10,000 exist. Semi-fungible.
Legendary Sword of Fire - Only one exists. Non-fungible, like ERC-721.
Event tickets - 500 for the same tournament, but each has a seat number.
With previous standards, you'd deploy separate contracts: one ERC-20 for gold, one ERC-721 for the sword, another ERC-721 for potions … Managing dozens of contracts, each with deployment costs, each requiring separate approvals for marketplaces.
ERC-1155 consolidates everything into one contract. Each token type gets an ID:
1
Gold Coin
1,000,000
Fungible
2
Health Potion
10,000
Semi-fungible
3
Legendary Sword
1
Non-fungible
4
Tournament Ticket
500
Semi-fungible
The key insight: fungibility is determined by supply, not by the standard. Token ID 3 with supply of 1 behaves like an NFT. Token ID 1 with supply of 1,000,000 behaves like a currency. Same contract, same interface, different configurations.
Time to build.
Project Setup With Hardhat
We'll create a new Hardhat project for your multi-token contract.
The setup process is identical to the ERC-721 guide. Please see that guide for detailed explanations of each step.
1. Initialize Your Project
Select:
Version: Hardhat 3 Beta
Project location:
my-game-itemsProject type: TypeScript + Viem
Dependencies: Confirm with
Y
2. Install OpenZeppelin Contracts
3. Create Your Contract File
Smart Contract Development
We'll build your multi-token contract step by step, inheriting from OpenZeppelin's ERC1155 and Ownable. Unlike ERC-721 which needed URIStorage for per-token metadata, ERC-1155 handles this differently with a base URI pattern.
1. Initial Imports and Contract Structure
Open contracts/GameItems.sol and add the foundation:
What's different from ERC-721:
ERC1155: The multi-token standard. One contract, unlimited token types. Each token ID can have any supply.No
URIStorageextension: ERC-1155 uses a base URI with{id}substitution instead of storing URIs per token.Constructor takes a URI string (we'll set it properly later).
2. State Variables and Token Configuration
Add the state variables that define your token economy. In contracts/GameItems.sol:
Key differences from ERC-721:
_totalSupplymapping: Tracks supply PER token ID. Token ID 1 might have 1,000,000 minted, token ID 2 might have just 5.maxSupplymapping: Optional cap PER token ID. Token ID 3 (legendary sword) has max 1. Token ID 1 (gold) might be unlimited (0).mintPricemapping: Different prices for different items. Legendary items cost more than common ones.tokenExists: Prevents minting unconfigured tokens. Owner must set up a token type before anyone can mint it.
3. Token Type Configuration
Before tokens can be minted, the owner must configure each token type. Add this to contracts/GameItems.sol:
Why this pattern:
Real game economies don't let anyone create arbitrary token types. The owner (game developer) defines what items exist:
Token ID 1: Gold coins, unlimited supply, can't be bought directly
Token ID 2: Health potion, max 10,000, costs 0.001 ETH
Token ID 3: Legendary sword, max 1, costs 0.1 ETH
This mirrors how actual games work. Developers control the item catalog.
4. Public Mint Function
The core minting logic, with payment and supply validation. Add to contracts/GameItems.sol:
The power of batch operations:
mintBatch is where ERC-1155 shines. Instead of:
You get:
For games where players acquire multiple items at once (loot drops, shop purchases), this adds up fast.
5. Owner Mint Functions
Free minting for the game owner: initial distribution, rewards, airdrops. Add to contracts/GameItems.sol:
Same pattern as ERC-721's ownerMint, but with batch capability. Useful for:
Initial token distribution at game launch
Tournament rewards (batch mint prizes to winners)
Airdrops to community members
6. Helper Functions
Utility functions for querying and managing the contract. Add to contracts/GameItems.sol:
The uri() function explained:
ERC-1155's metadata pattern differs from ERC-721:
ERC-721: Store unique URI per token (
tokenURI[tokenId] = "ipfs://Qm.../1.json")ERC-1155: One base URI, dynamically construct per-token URI
If _baseURI is "ipfs://QmMeta.../":
uri(1)returns"ipfs://QmMeta.../1.json"uri(42)returns"ipfs://QmMeta.../42.json"uri(1000)returns"ipfs://QmMeta.../1000.json"
This saves gas (no storage writes for URIs) and scales to unlimited token types.
Your multi-token contract is complete. It handles fungible currencies, unique items, and everything in between. Batch operations, configurable supplies, and dynamic pricing make up the same architecture powering blockchain games worth billions.
Writing Tests
Your multi-token contract is more complex than ERC-721. It handles multiple token types with different configurations, batch operations with payment calculations, and supply tracking per token ID. More moving parts means more potential bugs.
We'll test with the same dual approach: Solidity unit tests for individual functions, TypeScript integration tests for complete user flows.
Solidity Unit Tests
1. Setup
Create the test file:
Add the test contract with setup. Open contracts/GameItems.t.sol:
Setup notes:
Three token types configured: unlimited free gold, 10k potions at 0.001 ETH, unique sword at 0.1 ETH
This mirrors a real game economy with currency, consumables, and rare items
2. Test Deployment and Configuration
3. Test Single Minting
4. Test Batch Minting
5. Test Owner Minting
6. Test Withdrawals
7. Test URI Generation
8. Run Solidity Tests
TypeScript End-to-End Tests
1. Setup
Create the TypeScript test file:
Add the test structure. Open test/GameItems.ts:
2. Implement Complete Game Economy Test
3. Run TypeScript Tests
ERC-1155 uses a different metadata pattern than ERC-721. Instead of storing a unique URI for each token, it uses a base URI with {id} substitution.
For detailed Pinata setup instructions, see ERC-721: Setting Up Pinata.
The {id} Pattern
ERC-721 stores individual URIs per token:
ERC-1155 constructs URIs dynamically from a base:
Why this matters: No storage writes for URIs. Scales to unlimited token types. Gas savings compound as your game grows.
Create a folder structure:
Metadata JSON structure (same as ERC-721, but with game-specific properties):
1.json (Gold Coin - Fungible):
2.json (Health Potion - Semi-fungible):
3.json (Legendary Sword - Non-fungible):
Upload Process
Upload images folder to Pinata → Get Images CID
Update metadata JSON files with Images CID in the
"image"fieldUpload metadata folder to Pinata → Get Metadata CID
Use Metadata CID as your contract's base URI:
ipfs://YOUR_METADATA_CID/
The contract's uri() function will append the token ID and .json automatically.
Setting Up for Deployment
1. Setting Up Environment Variables
Same process as ERC-721. Set your RPC URL and private key in Hardhat's keystore:
2. Create the Deployment Script
Create the deployment file:
Add the deployment configuration. Open ignition/modules/GameItems.ts:
3. Deploy Your Contract
Save your deployed contract address!
Interacting with Your Contract
Configure Token Types
After deployment, configure your token types. Create scripts/configureTokens.ts:
Run with:
Mint Tokens
Create scripts/mint.ts:
Viewing on Rarible
Rarible supports ERC-1155 collections. To view your tokens:
Visit testnet.rarible.com
Connect your MetaMask wallet (Sepolia network)
Navigate to your profile
Your tokens should appear with their quantities
ERC-1155 tokens display differently than ERC-721; specifically, you'll see quantities like 'x5' for fungible/semi-fungible tokens.
Conclusion
You've built a complete multi-token game economy. Let's recap what you accomplished:
Built a production-ready ERC-1155 contract with configurable token types, batch operations, supply caps, and dynamic pricing. This is the same architecture powering Enjin and other blockchain gaming platforms.
Understood the multi-token paradigm where fungibility is determined by configuration, not by the standard. One contract managing currencies, items, and unique collectibles.
Implemented batch operations that can save 50-80% on gas costs for complex transactions like loot drops or shop purchases.
Mastered the
{id}metadata pattern for scalable, gas-efficient metadata serving unlimited token types.Deployed and configured a live contract on Sepolia, minting tokens that appear on Rarible.
What You Built vs. Production Games
Your contract contains the core mechanics of blockchain gaming:
Multi-token management: One contract for entire economies
Batch operations: Gas-efficient mass distributions
Configurable supplies: Fungible currencies to unique legendaries
Payment handling: Item shop functionality built-in
What production games add:
Crafting/burning: Combine items to create new ones
Staking mechanics: Lock items for rewards
Royalties (ERC-2981): Earn from secondary sales
Access control: Multiple admin roles, not just owner
Explore advanced features: Add crafting (burn X potions to create Y), implement staking for passive rewards, or integrate ERC-2981 royalties.
Build a game frontend: Connect your contract to a web interface where players can view inventory, trade items, and interact with the economy.
Study production implementations: Read Enjin's contracts, examine Gods Unchained's architecture, understand how Loot (for Adventurers) structured their drops.
You've moved from understanding individual token types to managing entire economies. That's the foundation of blockchain gaming.
Last updated

