> ## Documentation Index
> Fetch the complete documentation index at: https://docs.immutable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ERC-20 (In-Game Currencies)

ERC-20 tokens are fungible—each unit is identical and interchangeable. Use them for in-game currencies, reward points, governance tokens, or any divisible asset.

## Why Use ERC-20?

<AccordionGroup>
  <Accordion title="True Ownership" icon="key">
    Players own their currency on-chain. They keep it even if they stop playing your game.
  </Accordion>

  <Accordion title="Tradability" icon="arrow-right-arrow-left">
    List on DEXes or enable peer-to-peer trading. Players can buy/sell currency with real market prices.
  </Accordion>

  <Accordion title="Cross-Game Value" icon="link">
    Same token can work across multiple games. Build partnerships and shared economies.
  </Accordion>

  <Accordion title="Transparent Economics" icon="eye">
    All supply, distribution, and transactions are verifiable on-chain. Players trust what they can verify.
  </Accordion>
</AccordionGroup>

## Deploy via Hub

<Card title="Deploy Contracts" icon="file-contract" href="/docs/products/hub/deploy-contracts">
  Deploy ERC-20 contracts in Hub
</Card>

## Deploy via Code

```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract GameCurrency is ERC20, Ownable {
    constructor() ERC20("Gold Coins", "GOLD") Ownable(msg.sender) {
        _mint(msg.sender, 1000000 * 10 ** decimals());
    }

    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
    }
}
```

## Distribution Patterns

### Achievement Rewards

```typescript theme={null}
const REWARDS = {
  'first_kill': 100n * 10n ** 18n,
  'level_10': 500n * 10n ** 18n,
  'boss_defeated': 1000n * 10n ** 18n,
};

async function grantAchievement(player: string, achievement: string) {
  const reward = REWARDS[achievement];
  if (reward) await currencyContract.mint(player, reward);
}
```

### Daily Login

```typescript theme={null}
async function claimDailyReward(player: string) {
  const lastClaim = await getLastClaimTime(player);
  if (Date.now() - lastClaim < 24 * 60 * 60 * 1000) {
    throw new Error('Already claimed today');
  }
  
  await currencyContract.mint(player, 50n * 10n ** 18n);
  await setLastClaimTime(player, Date.now());
}
```

## Spending Currency

### In-Game Purchases

```typescript theme={null}
async function purchaseItem(player: string, itemId: string, price: bigint) {
  // Transfer from player to treasury
  await currencyContract.transferFrom(player, TREASURY, price);
  
  // Grant the item
  await grantItem(player, itemId);
}
```

### Approval Flow

Players must approve your contract to spend their tokens:

```typescript theme={null}
// Frontend: Request approval
async function approveSpending(amount: bigint) {
  const signer = await ethersProvider.getSigner();
  const currency = new ethers.Contract(CURRENCY_ADDRESS, ERC20_ABI, signer);
  await currency.approve(GAME_CONTRACT, amount);
}
```

## Balance Queries

```typescript theme={null}
// Direct contract call
const balance = await currencyContract.balanceOf(playerAddress);
console.log(`${ethers.formatEther(balance)} GOLD`);

// Via Indexer API
const tokens = await indexer.listTokensByAccountAddress({
  chainName: 'imtbl-zkevm-mainnet',
  accountAddress: playerAddress,
});
```

See [Indexer API](/docs/products/indexer/overview) for querying token balances.

## Economy Design

<AccordionGroup>
  <Accordion title="Control Inflation" icon="chart-line-down">
    * Set maximum supply caps
    * Implement burning mechanics (consumables, fees)
    * Balance earn rates with spending sinks
  </Accordion>

  <Accordion title="Multiple Currencies" icon="coins">
    * **Soft currency**: Earned through gameplay, unlimited
    * **Hard currency**: Purchased or rare, limited supply
    * **Seasonal currency**: Resets each season
  </Accordion>

  <Accordion title="Anti-Bot Measures" icon="robot">
    * Rate limit claims per wallet
    * Require game actions, not just API calls
    * Monitor for suspicious patterns
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Deploy Contracts" icon="rocket" href="/docs/products/hub/deploy-contracts">
    Deploy via Hub
  </Card>

  <Card title="Indexer" icon="database" href="/docs/products/indexer/overview">
    Query token balances
  </Card>

  <Card title="Contracts Overview" icon="file-contract" href="/docs/products/asset-contracts/overview">
    Explore other contract types
  </Card>

  <Card title="Deploy with Hardhat" icon="code" href="/docs/products/asset-contracts/deploy-contracts-with-hardhat">
    Deploy programmatically
  </Card>
</CardGroup>
