# Fixed Denomination Tokens

The ERC-20 Fixed Denomination protocol creates fungible tokens where balances move in fixed batches (denominations) tied to NFT "notes."

{% hint style="info" %}
Fixed Denomination Tokens are an **AppChain-only** feature. They require smart contract execution on the L2.
{% endhint %}

## Overview

Unlike standard ERC-20 tokens where users can transfer arbitrary amounts, fixed denomination tokens:

* Move in **fixed batches** (the denomination)
* Are tied to **NFT notes** that represent the token amount
* Transfer **automatically** when the note transfers

This creates a unique hybrid between fungible and non-fungible tokens.

## How It Differs from Standard ERC-20

| Feature          | Standard ERC-20       | Fixed Denomination           |
| ---------------- | --------------------- | ---------------------------- |
| Transfer amounts | Arbitrary             | Fixed denomination only      |
| Transfer method  | `transfer()` function | Transfer the NFT note        |
| Divisibility     | Yes                   | No (whole notes only)        |
| Balance tracking | Single balance        | Balance = sum of owned notes |

## Deploy a Token

Create an ethscription with JSON content to deploy a new token:

```json
{"p":"erc-20-fixed-denomination","op":"deploy","tick":"mytoken","max":"1000000","lim":"1000"}
```

As a Data URI:

```
data:application/json,{"p":"erc-20-fixed-denomination","op":"deploy","tick":"mytoken","max":"1000000","lim":"1000"}
```

{% hint style="warning" %}
**Strict JSON Format**: The JSON must be minified (no whitespace), use exact key order as shown, and contain no extra fields. The legacy protocol name `"p":"erc-20"` is also accepted for backward compatibility.
{% endhint %}

### Deploy Parameters

| Field  | Description                         | Constraints                                                |
| ------ | ----------------------------------- | ---------------------------------------------------------- |
| `tick` | Token symbol                        | Lowercase alphanumeric, max 28 chars                       |
| `max`  | Maximum total supply                | uint256, **must be divisible by `lim`** (`max % lim == 0`) |
| `lim`  | Amount per mint note (denomination) | uint256, must divide evenly into `max`                     |

{% hint style="warning" %}
**Constraint**: `max` must be evenly divisible by `lim`. For example, `max=1000` and `lim=100` is valid (10 notes), but `max=1000` and `lim=300` is invalid.
{% endhint %}

## Mint Notes

After deployment, create notes by minting:

```json
{"p":"erc-20-fixed-denomination","op":"mint","tick":"mytoken","id":"1","amt":"1000"}
```

As a Data URI:

```
data:application/json,{"p":"erc-20-fixed-denomination","op":"mint","tick":"mytoken","id":"1","amt":"1000"}
```

### Mint Parameters

| Field  | Description                              | Constraints                                     |
| ------ | ---------------------------------------- | ----------------------------------------------- |
| `tick` | Token symbol (must match deployed token) | Must be a deployed token                        |
| `id`   | Unique note identifier within the token  | **Must be ≥ 1** (IDs start at 1, not 0)         |
| `amt`  | Token amount for this note               | **Must equal `lim`** from deploy (`amt == lim`) |

{% hint style="warning" %}
**Constraints**:

* `id` must be ≥ 1 (note IDs start at 1)
* `amt` must exactly equal the token's `lim` value
  {% endhint %}

Each mint creates:

1. An **ethscription** (the mint inscription)
2. An **NFT note** representing the token amount
3. **ERC-20 balance** credited to the minter

## Transfer Mechanics

Transferring tokens works differently than standard ERC-20:

### Standard ERC-20 (disabled)

```solidity
// This does NOT work for fixed denomination tokens
token.transfer(recipient, amount);
```

### Fixed Denomination (how it works)

Transfer the **ethscription** (the mint inscription) to move tokens:

```
To: 0xRecipient
Value: 0 ETH
Data: 0x<mint-inscription-txhash>
```

When the ethscription transfers:

1. The inscription moves to the new owner
2. The NFT note automatically transfers
3. The ERC-20 balance automatically moves

All three are synchronized atomically.

## Example Flow

### 1. Deploy Token

Alice deploys "mytoken" with max supply 10,000 and denomination 100:

```json
{"p":"erc-20-fixed-denomination","op":"deploy","tick":"mytoken","max":"10000","lim":"100"}
```

### 2. Mint Notes

Alice mints note #1:

```json
{"p":"erc-20-fixed-denomination","op":"mint","tick":"mytoken","id":"1","amt":"100"}
```

Alice now has:

* 1 mint inscription (ethscription)
* 1 NFT note (tokenId = 1)
* 100 "mytoken" ERC-20 balance

### 3. Transfer

Alice transfers the mint inscription to Bob:

```
To: Bob's address
Data: 0x<alice-mint-txhash>
```

Result:

* Mint inscription → Bob
* NFT note #1 → Bob
* 100 "mytoken" balance: Alice → Bob

## Querying Balances

### ERC-20 Balance

```javascript
const balance = await tokenContract.balanceOf(address);
```

### Note Ownership

```javascript
const owner = await tokenContract.ownerOf(noteId);
```

### Notes Owned

Each note's `amount` contributes to the holder's ERC-20 balance. The total balance equals the sum of all owned notes' amounts.

## Use Cases

### Collectible Tokens

Each note is a unique collectible that also carries fungible value.

### Batch Transfers

Transfer multiple notes to move large amounts efficiently.

### Marketplace Trading

Notes can be traded on NFT marketplaces while carrying their token value.

### Fair Distribution

Fixed denominations ensure equal distribution - everyone gets the same sized "bills."

## Technical Details

### Contract Architecture

* **ERC20FixedDenominationManager** - Handles deploy/mint operations
* **ERC20FixedDenomination** - Individual token contract (ERC-20 + ERC-721 hybrid)

### Storage

Each token stores:

* Token metadata (tick, max supply, denomination)
* Note registry (id → ethscription mapping)
* Balances (derived from note ownership)

### Events

```solidity
event TokenDeployed(string tick, uint256 maxSupply, uint256 denomination);
event NoteMinted(string tick, uint256 noteId, address owner, uint256 amount);
event NoteTransferred(string tick, uint256 noteId, address from, address to);
```

## Limitations

* Cannot transfer partial amounts (only whole notes)
* Cannot combine notes
* Cannot split notes
* Direct ERC-20 transfers are disabled

## Security Considerations

1. **Atomic transfers** - ERC-20 and NFT always move together
2. **No double-spending** - Note ownership enforced on-chain
3. **Immutable denomination** - Cannot change after deployment
4. **Supply cap** - Cannot exceed max supply
