Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions versioned_docs/version-0.14/reference/protocol/asset.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ In Miden, assets serve as the primary means of expressing and transferring value
All data structures following the Miden asset model that can be exchanged.
:::

Native assets adhere to the Miden `Asset` model (encoding, issuance, storage). Every native `Asset` is encoded using 32 bytes, including both the [ID](./account/id) of the issuing account and the `Asset` details.
Native assets adhere to the Miden `Asset` model (encoding, issuance, storage). In an account vault each native `Asset` is stored as an `ASSET_KEY` plus an `ASSET_VALUE` (two words / 64 bytes) that together carry the issuing faucet [ID](./account/id), callback metadata, and asset payload — see [Encoding](#encoding).

### Issuance

Expand All @@ -46,11 +46,11 @@ Faucets can issue either fungible or non-fungible assets as defined at account c

#### Fungible asset

Fungible assets are encoded with the amount and the `faucet_id` of the issuing faucet. The amount is always $2^{63}-1$ or smaller, representing the maximum supply for any fungible `Asset`. Examples include ETH and various stablecoins (e.g., DAI, USDT, USDC).
Fungible assets are encoded with the amount, the issuing `faucet_id`, and the per-asset callback flag (see [Encoding](#encoding) and [Callbacks](#callbacks)). Units merge in a vault only when both the faucet id **and** the callback flag match; the amount is always $2^{63}-2^{31}$ or smaller. Examples include ETH and various stablecoins (e.g., DAI, USDT, USDC).

#### Non-fungible asset

Non-fungible assets are encoded by hashing the `Asset` data into 32 bytes and placing the `faucet_id` as the second element. Examples include NFTs like a DevCon ticket.
Non-fungible assets are encoded from a 4-limb `DATA_HASH` of the NFT payload plus the issuing `faucet_id` and callback metadata (see [Encoding](#encoding)). Each NFT has a distinct vault key derived from `DATA_HASH[0..2]`; that does **not** imply a distinct SMT leaf — NFTs from the same faucet can share a leaf. Examples include NFTs like a DevCon ticket.

### Storage

Expand Down Expand Up @@ -123,6 +123,49 @@ A callback is not invoked in any of these cases:

This means assets with callbacks enabled can still be used even if the faucet has not (yet) registered a callback procedure.

## Encoding

Every native asset occupies two words (64 bytes): an `ASSET_KEY` (vault key) that identifies the asset in an account vault SMT, and an `ASSET_VALUE` that carries the asset payload.

### `ASSET_KEY` / `AssetVaultKey` layout

The vault key is a [`Word`](https://docs.rs/miden-protocol) with this limb order (matching `AssetVaultKey::to_word()` in v0.14):

```text
[
asset_id_suffix, // Felt
asset_id_prefix, // Felt
faucet_id_suffix_and_metadata, // Felt
faucet_id_prefix // Felt
]
```

Where `faucet_id_suffix_and_metadata` packs:

```text
[ faucet_id_suffix (56 bits) | 7 zero bits | callbacks_enabled (1 bit) ]
```

The low byte of the faucet account-id suffix is reserved for metadata (it is zero in a bare faucet id). The least-significant bit of that byte is the [`AssetCallbackFlag`](#callbacks): `0` disabled, `1` enabled.

### Fungible vs non-fungible keys

| Kind | `asset_id_*` limbs | Meaning |
| --- | --- | --- |
| Fungible | both zero | Units that share the same faucet id **and** callback flag occupy one vault entry and merge by amount. Different callback flags are distinct assets (see [Callbacks](#callbacks)). |
| Non-fungible | taken from `DATA_HASH[0..2]` | Each NFT has a distinct vault key. Distinct keys from the same faucet may still share an SMT leaf — leaf identity is not 1:1 with vault keys. |

### `ASSET_VALUE` layout

| Kind | Value word |
| --- | --- |
| Fungible | `[amount, 0, 0, 0]` — `amount ≤ 2⁶³−2³¹` |
| Non-fungible | full 4-limb `DATA_HASH` of the NFT payload |

### Stdlib helpers

When building assets from arbitrary code (not as the faucet itself), use `miden::protocol::asset::create_fungible_asset` / `create_non_fungible_asset`. Both take an `enable_callbacks` flag so the metadata bit is set explicitly — see [Protocol library](./protocol_library.md#asset-procedures-midenprotocolasset).

## Alternative asset models

:::note
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,4 @@ Asset procedures provide utilities for creating fungible and non-fungible assets
| Procedure | Description | Context |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `create_fungible_asset` | Builds a fungible asset for the specified fungible faucet and amount.<br/><br/>**Inputs:** `[enable_callbacks, faucet_id_suffix, faucet_id_prefix, amount]`<br/>**Outputs:** `[ASSET_KEY, ASSET_VALUE]` | Any |
| `create_non_fungible_asset` | Builds a non-fungible asset for the specified non-fungible faucet and data hash.<br/><br/>**Inputs:** `[faucet_id_suffix, faucet_id_prefix, DATA_HASH]`<br/>**Outputs:** `[ASSET_KEY, ASSET_VALUE]` | Any |
| `create_non_fungible_asset` | Builds a non-fungible asset for the specified non-fungible faucet and data hash.<br/><br/>**Inputs:** `[enable_callbacks, faucet_id_suffix, faucet_id_prefix, DATA_HASH]`<br/>**Outputs:** `[ASSET_KEY, ASSET_VALUE]` | Any |