# ERC-6909: Minimal Multi-Token Interface

Source: https://www.eipsfordesigners.com/standards/ERC-6909
Agent brief: https://www.eipsfordesigners.com/standards/ERC-6909/agent.md
Machine-readable JSON: https://www.eipsfordesigners.com/api/standards/ERC-6909
Last reviewed: 2026-05-25
Last updated: 2026-05-25

| Field | Value |
| --- | --- |
| Status | Final |
| Chain | both |
| Category | NFT Capabilities |
| Journey stages | Asset Discovery & Display |
| Detailed guide | Yes |
| Official specification | https://eips.ethereum.org/EIPS/erc-6909 |
| Discussion search | https://ethereum-magicians.org/search?q=ERC-6909 |

## UX Impact

Streamlined multi-token with granular per-token-type approvals and no mandatory callbacks — simpler than ERC-1155. Design implications: show per-token-type allowance amounts (like ERC-20), remove batch transfer UI complexity if not needed, design approval UIs that distinguish 'approve specific amount' from 'operator access to all'. Design decisions: whether to expose the simpler approval model to users or abstract it, tradeoff between gas savings (no callbacks) vs safety checks that callbacks provided.

## Summary

Streamlined multi-token with granular per-token-type approvals and no mandatory callbacks — simpler than ERC-1155.

## For Designers

- You can show per-token-type allowance rows mirroring ERC-20 revoke.cash patterns.
- Your approval modal can distinguish Approve 50 of this type from Allow app to manage all types.
- You can skip ERC-1155 batch UI when the contract only needs simple per-id transfers.

## Applicability

### When to Use

- One contract emits many fungible-like token types.
- You need ERC-20-style allowances without ERC-1155 callbacks.
- Gas-efficient multi-token vaults or game currencies.

### When to Avoid

- True batch NFT transfers with mixed metadata are required.
- Contract is ERC-1155-only with existing indexer support.
- Users never need granular approvals — operator suffices.

## Problems It Solves

### ERC-1155 approval UX too coarse

Impact: high

Old way: setApprovalForAll for entire contract

New way: Per-type amount allowances like ERC-20

### Multiple contracts clutter wallet

Impact: medium

Old way: One ERC-20 per game currency

New way: Single 6909 contract with typed balances

### Callback gas and reentrancy concerns

Impact: medium

Old way: ERC-1155 onReceived hooks

New way: No mandatory callbacks — simpler transfer path

## Anti-Patterns

### Defaulting to operator approval

Severity: critical

Grants unlimited access across all types

Instead: Default amount approval with scary operator path

### Showing only contract address without type

Severity: high

Users send wrong token type

Instead: Type name in every confirmation step

### ERC-1155 batch UI on 6909 contract

Severity: medium

Unnecessary complexity

Instead: Simple single-type transfer and approve flows

## Design Decisions

### Expose token type ids to users?

Recommendation: Show friendly names; tuck numeric id behind advanced.

Rationale: Ids are implementation detail unless debugging.

### Default approval style?

Recommendation: Amount approval per action; operator requires extra confirmation.

Rationale: Operator equals unlimited across types — high risk.

### Use batch transfer UI?

Recommendation: Skip unless contract exposes batch; prefer simple single-type flows.

Rationale: 6909 value is simplicity over 1155 batch complexity.

## States to Design

### Sufficient balance — type selected

Trigger: User picks type and amount.

User need: Confirm correct type before send.

Design response: Type name prominent in confirmation; id in advanced.

### Approval required

Trigger: Spender lacks allowance.

User need: Grant minimum needed access.

Design response: Suggest exact amount approval, not operator by default.

### Operator fully approved

Trigger: User previously granted operator.

User need: Audit and revoke if unintended.

Design response: Show in permissions dashboard with high-risk badge.

### Insufficient type balance

Trigger: Amount exceeds id balance.

User need: Fix amount without guessing.

Design response: Inline max available for this type.

### Revoked approval

Trigger: User revokes spender.

User need: Confirm app may break until re-approved.

Design response: Success toast with Re-approve if needed link.

## Vocabulary

- Use "Token type" instead of "Token id 8472": Friendly naming unless advanced view.

- Use "Spending limit" instead of "Allowance mapping": ERC-20 familiar terms.

- Use "Manage all types" instead of "Operator set true": Plain permission language.

## What to Prototype First

### Multi-type balance sheet

Users must see each token type balance distinctly.

Covers: Multiple ids, Zero balance types, Single type

- Type name
- Balance
- Token id disclosure in advanced

### Approve specific amount

ERC-20 mental model is the anchor.

Covers: Amount approval, Unlimited toggle, Revoke

- Amount input
- Spender address
- Current allowance row

### Operator approval warning

Full operator access is high risk.

Covers: Operator grant, Revoke operator

- Scary unlimited copy
- List affected types
- Confirm checkbox

### Transfer type picker

Sending requires choosing which type.

Covers: Single type send, Insufficient balance

- Type selector
- Amount
- Recipient
- Preview

## Mental Model

### Token type ID

Each id is a distinct balance lane inside one contract address.

### Amount approval

Spender can move up to N of one type — like ERC-20 allowance.

### Operator approval

Spender can move all types — like ERC-1155 setApprovalForAll.

### Single contract

One address on chain; UI must label types clearly to avoid confusion.

### No callbacks

Transfers won't auto-notify receivers — apps track balance via events.

## Seen in the Wild

- Uniswap V4: Multi-token vault patterns inform typed balance display. (https://uniswap.org/)

- Revoke.cash: Allowance management UX applies per-type approvals. (https://revoke.cash/)

- OpenSea: Multi-token inventory patterns for id-based assets. (https://opensea.io/)

## On Monad

### Multi-type transfers

Ethereum: Many approvals add gas

Monad: Lower fees enable granular per-type approvals

Design implication: Prefer amount approvals over operator on Monad.

### Balance refresh

Ethereum: Multi-id indexing lag

Monad: Fast blocks need snappy balance updates per type

Design implication: Refresh all types after any transfer event.

## UX Patterns

### Per-Type Allowance Row

ERC-20-style allowance display per token id.

Components: AllowanceRow, RevokeButton, AmountLabel

User flow:

- User opens permissions
- Sees per-type allowances
- Revokes or edits
- Spender updated

Mockup registry key: `concept/nft-gallery` (React UI on the live standard page).

### Type Picker Transfer

Send flow with explicit token type selection.

Components: TypeSelector, AmountInput, ConfirmSheet

User flow:

- User taps Send
- Picks type
- Enters amount
- Confirms

Mockup registry key: `concept/permit-approval` (React UI on the live standard page).

## Related Standards

- ERC-1155: Multi-token alternative with callbacks

- ERC-20: Approval mental model per token type

## Technical Notes

ERC-6909 uses per-id allowances; treat operator approval as high-risk unlimited grant.
