Forge
ERC-1155 Token-Composition




Tier composition
Atomic burn/mint paths for forged token IDs (Forge README).
Overview
ERC-1155 crafting loops need supply rules users cannot route around: inputs burned and outputs minted together, and no way to mint or burn outside the recipes.
Forge splits FToken (ledger) from Forge (rules). Composite IDs 3–6 use burnBatch + mint in a single tx; basic mints are cooldown-gated; the Next.js and TypeScript UI syncs via Alchemy WebSockets and TanStack Query invalidation.
Technical Architecture
Forge is an experiment in keeping composition rules and supply mutations honest on ERC-1155. The ledger (FToken) stays supply-focused; the rules (Forge) encode cooldowns, recipes, trade constraints, and burn permissions. Every supply change routes through Forge, which is the immutable owner of FToken after deploy. For forged token IDs 3–6, Forge.mint calls burnBatch then mint in one call. Because FToken has no public mint or burn, users cannot mint or burn outside these recipes. Basic mints (0–2) are cooldown-gated; the Next.js and TypeScript UI listens to Forge events over Alchemy WebSockets with wagmi and invalidates TanStack Query keys instead of polling.
Key features
- On-Chain Crafting System (ERC-1155): Players mint basic tokens and forge composite items by burning combinations, enforced entirely by Solidity logic.
- Re-entry Cannot Skip the Cooldown: Basic mint writes userCoolDownTimer before the external I_TOKEN.mint call, so re-entering through
onERC1155Receivedcannot skip the cooldown or double-mint. For forged IDs 3–6, mint performs burnBatch then mint in one call and keeps no state of its own. - Logic / Asset Contract Separation: Forge deploys FToken in its own constructor and is its immutable owner (a custom check, not OpenZeppelin
Ownable, with no ownership transfer), so ownership cannot be misconfigured or change. FToken mint, burn and burnBatch accept only that owner. Forge burns users' tokens withoutsetApprovalForAllbecause the owner path skips ERC-1155 approvals; it only ever burnsmsg.sender's tokens and is not upgradeable. - Cooldown-Based Minting: Per-address cooldown (15 s) on basic mints (IDs 0–2) slows minting on-chain; it is not Sybil-resistant, since a new wallet starts fresh.
- Event-Driven UI Updates: Mint, burn, forge and trade events over Alchemy WebSockets invalidate the balance queries for the token IDs the event touched; separate HTTP and WebSocket wagmi configs, cookie-based SSR.
- Foundry Tests: 38 tests (32 Forge, 6 FToken) that run the real deploy script in
setUp, with a throwaway key so CI needs no secrets, and assert exact custom-error selectors and events. There are no fuzz or invariant tests yet, andtradehas a single happy-path test.
Technologies Used
- Next.js
- TypeScript
- Solidity
- Foundry
- OpenZeppelin
- viem
- wagmi
- RainbowKit
- IPFS
- Alchemy
- React
- TanStack Query
- React Hook Form
- Zod
- shadcn/ui
- Tailwind CSS
- Solidity + Foundry: Implements ERC-1155 minting, forging, burning and trading logic, with custom errors carrying context and an indexed event per action.
- Next.js + TypeScript + wagmi: Frontend framework with wallet integration, event listeners, and reactive state management.
- Alchemy WebSockets: Mint, forge, burn and trade events refetch the balances for the affected token IDs.
- ERC-1155 Architecture: Multi-token setup supporting crafting rules; metadata pinned on IPFS through the contract's
uri. - OpenZeppelin: ERC-1155 base implementation behind FToken; minting and burning are guarded by a custom immutable-owner check (no
Ownable, no ownership transfer).
Challenges and Learnings
Encoding recipes, cooldowns, and trade/burn rules so they stay readable in Solidity without hiding edge cases. Testing each custom-error revert in Forge.sol and FToken.sol with its exact selector, through the real deploy script. Event-driven UI updates required TanStack Query keys per token ID, so a Forge event invalidates only the balances for the IDs it touched.
Outcome
Forge on Sepolia shows atomic ERC-1155 composition with verified contracts and a small single-page Next.js and TypeScript client: a focused case study, not a shipped game economy.
Key Metrics
- Tests: 38 Foundry unit tests; a local
forge coveragerun reported 100% of lines (95/95), statements, branches (21/21) and functions across Forge.sol, FToken.sol and the deploy scripts - Sepolia addresses: Forge · FToken
- Architecture: Forge is immutable owner of FToken; only Forge mutates supply; forged IDs use burnBatch + mint in one tx
Transferable patterns: On-chain cooldowns as simple rate limits, ERC-1155 batch operations for atomic multi-token updates.
Known limitations
- Admin can stop basic mints:
setCoolDownDelayhas no bounds and the owner is a single EOA: a huge value overflows the timer so every basic mint reverts, and 0 turns the cooldown off. - Recipes are hard-coded: the maximum token ID is a constructor parameter while recipes stop at 6; a deploy with a higher maximum would let ID 7 mint for free (the live deploy uses 6).
- Trade rules:
tradedoes not bound-check the ID to burn and allows basic-to-basic swaps with no cooldown. - UI cooldown is local: the countdown starts from the browser clock and never reads
userCoolDownTimer, so after a refresh it can show ready while the chain still reverts. - Event filtering: the event watchers do not filter by user and read only the first log, so another user's event triggers a refetch and a multi-log batch is only partly handled.
- Single network: Sepolia deployment for learning; no mainnet or multi-chain story in this repo.
- Cooldown model: One global delay for basic mints (IDs 0–2); no per-token issuance curves yet.
- Marketplace: No secondary marketplace integration beyond the on-chain trade helper into basics.
Roadmap
- L2 comparison: Deploy the same Forge/FToken pattern to an L2 testnet and compare gas on burnBatch + mint paths vs Sepolia.
- Bounded admin: Cap
setCoolDownDelayand derive recipes fromI_MAX_TOKEN_ID(or fix it at 6). - Progressive cooldowns: Per-id or tiered cooldown tuning instead of the single
coolDownDelay. - Marketplace hooks: Pair the contracts with standard ERC-1155 marketplace flows.