Skip to content
Draft
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
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
* [1Sat Provenance Remittance for Basket `1sat`](./tokens/0150.md)
* [1Sat Ordinals — Single-Satoshi Tokens and Origin Tracking](./tokens/0159.md)
* [1Sat Ordinals — Inscription Envelopes](./tokens/0160.md)
* [1Sat Fungible Basket Profile for BRC-46 / BRC-100](./tokens/0175.md)
* [Miner-Enforced Resale-Royalty Covenant Tokens (OP_PUSH_TX)](./tokens/0226.md)

## Overlays
Expand Down
2 changes: 2 additions & 0 deletions tokens/0147.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,13 @@ Normative fine-grained asset permission schemes remain [BRC-99](../wallet/0099.m
* Wallets that do not implement this profile MUST still store and forward unknown baskets’ `customInstructions` and tags unchanged ([BRC-37](../outpoints/0037.md)).
* This profile does not conflict with BRC-99 `p ` baskets; future permission-wrapped variants MAY wrap `1sat` semantics under a `p <scheme> …` name without invalidating this profile for the plain `1sat` basket.
* Marketplaces (e.g. OrdLock), BSV-20/21, and mint APIs are out of scope.
* **[BRC-175](./0175.md) fungibles** share the bare P2PKH tip-move shape with this profile. Chain-scan / instant-ingest MUST NOT place an output in basket `1sat` solely because its creating transaction spends a 1-sat input. Importers SHOULD require an inscribed non–`1sat-ft` ancestor (or equivalent remittance / provenance) before painting a collectable. An ancestor with content-type `application/1sat-ft+json` MUST NOT yield eligibility for this profile.

## Security considerations

* **Tag / metadata spoofing** — Without provenance verification, a sender can attach another inscription’s `origin` and `name`. See [BRC-150](./0150.md). A forged `content` only mis-points display media; it does not prove tip→origin.
* **Basket pollution** — Placing non-1-sat or non-ordinal outputs in `1sat` confuses list UIs; receivers should re-check `satoshis` and inscription rules.
* **Fungible misfile** — Auto-importing every bare 1-sat that spends a 1-sat parent will file [BRC-175](./0175.md) transfer tips into `1sat`. Those tips then look burnable as junk NFTs. See Compatibility above.
* **Burn** — Per 1Sat Ordinals, packing a sat into a multi-sat output ends that origin trail. Do not continue `origin:` claims across a burn.
* **Indexer trust** — Display media URLs and collection metadata often come from indexers; this profile does not make indexers authoritative for tip→origin binding. Forwarding `content` reduces indexer dependence for derivative media.

Expand Down
266 changes: 266 additions & 0 deletions tokens/0175.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
# BRC-175: 1Sat Fungible Basket Profile for BRC-46 / BRC-100

Brandon Cryderman / HandCash (brandongcryderman@gmail.com)

## Abstract

This BRC defines the **fungible** application basket profile for 1Sat under [BRC-46](../wallet/0046.md) / [BRC-100](../wallet/0100.md). A fungible 1Sat token is a set of **1-satoshi tips that share one origin**. Token identity is that origin outpoint. Each tip carries a face value **`amt`** (token units). **Balance** is the sum of `amt` on bound tips held. Transfers **spend tip UTXOs and create new 1-sat tips** (recipients and change), funded with ordinary BSV dust — the same custody class as collectables ([BRC-147](./0147.md)), not a split of one physical satoshi across payees.

**Locked supply is optional:** the origin MAY set `supply: "locked"` with `max` (**total units**). When omitted, tips still bind via tip→origin rules with face-value `amt`; wallets MUST NOT invent a lock. Offline tip→origin proof reuses [BRC-150](./0150.md). Mint-batch attestation MAY bind same-tx genesis siblings until a transfer creates a 150 path. A tip with omitted `amt` MUST be treated as `amt = 1` (tip-count legacy).

This BRC does not redefine 1Sat origin theory ([BRC-159](./0159.md)) or inscription envelopes ([BRC-160](./0160.md)).

## Motivation

Collectables already interoperate as tip→origin assets with offline proof ([BRC-147](./0147.md), [BRC-150](./0150.md)). Fungible balances that re-inscribe protocol JSON each hop do not share that transfer path and typically depend on indexers for discovery and settlement. Counting tips as units (without face-value `amt`) does not scale: moving *N* units costs *O(N)* tips.

Wallets and future **token markets** need a shared contract so that:

1. Markets and wallets identify a token by **origin** (one id forever).
2. Inventory is a set of **tip UTXOs** (listable, lockable, settleable like collectables).
3. Large balances MAY sit in **one tip** (`amt` large); sends **split/merge** with change.
4. Fungible tips are not filed into NFT basket `1sat`.
5. Supply policy is readable from the **origin tip** without an indexer census.
6. Custody never depends on a market overlay or indexer being online.

## Specification

### Basket identifier

* The storage basket name is the UTF-8 string `1sat-ft`.
* After [BRC-46](../wallet/0046.md) normalization (trim + lowercase), conforming use MUST use exactly `1sat-ft`.
* This identifier does **not** use the [BRC-99](../wallet/0099.md) `p ` prefix.
* Outputs for this profile MUST NOT be placed in basket `1sat` ([BRC-147](./0147.md)).
* Writers and readers MUST use `1sat-ft` (no legacy basket alias).

### Eligibility

An output SHOULD be placed in basket `1sat-ft` only when **all** hold:

1. `satoshis === 1`.
2. The tip is a carrier for fungible units of a token whose identity is a shared origin outpoint.
3. The tip **binds** to that origin under §Binding (below).
4. The tip carries a valid first `ord` envelope ([BRC-160](./0160.md)). Genesis and mint-batch tips MUST. **New transfer colour tips MUST** (see §Transfer inscription). Legacy bare leftovers MAY exist; they bind only via lineage walk and MUST NOT invent `amt`.

Wallets MUST NOT place ordinary payment change or multi-sat outputs into `1sat-ft`.
**Autodetect is not “any 1-sat output”:** `satoshis === 1` is necessary; basket + binding are required before counting units.

### Token identity and units

* **Token id** = origin outpoint (`txid_vout` after normalize; same rules as [BRC-147](./0147.md)).
* **Carrier** = 1-sat tip UTXO. Face value is **not** the satoshi amount.
* **`amt`** = positive integer token units on that tip (decimal string in JSON).
* **Balance** = sum of `amt` over bound tips held for that origin.
* Missing `amt` ⇒ treat as `"1"` (legacy tip-count rows).
* **`max`** (locked) = total units at genesis, **not** required tip count.
* **Decimals** — Origin MAY reserve `dec`; readers that do not implement decimals MUST treat `amt` as integer units and MUST NOT invent fractional balances.

### Origin inscription (normative policy surface)

The **origin tip** (outpoint = token id) MUST carry an `ord` envelope whose body is UTF-8 JSON:

```json
{
"p": "1sat-ft",
"v": 1,
"amt": "1000",
"sym": "GOLD",
"name": "optional",
"supply": "locked",
"max": "1000"
}
```

| Field | Requirement | Meaning |
|-------|-------------|---------|
| `p` | MUST | Profile id `1sat-ft`. |
| `v` | MUST | Origin schema version. This BRC defines `1`. |
| `amt` | MUST | Face value of **this** tip (genesis tip often holds the full issued amount). |
| `supply` | MAY | `locked` freezes total units. Omit when no cap. `open` means uncapped (no local max). |
| `max` | MUST when `supply` is `locked` | Total units. Decimal string of a positive integer. |
| `sym` | SHOULD | Short symbol (≤ 32). |
| `name` | MAY | Display name (≤ 80). |
| `dec` | RESERVED | Future decimal places; ignore if unimplemented. |
| `issuer` / `auth` | RESERVED | Future open-mint authority; ignore until defined. |

Unknown fields MUST be preserved by wallets that round-trip remittance ([BRC-37](../outpoints/0037.md) spirit) and MUST be ignored for validation unless this BRC defines them.

**Authority:** When locked, the origin inscription is the sole durable supply policy. Remittance MUST NOT contradict it (`supply` / `max` on tips SHOULD echo the origin when present; on conflict, **origin wins**). Wallets MUST NOT write `supply: locked` unless the origin defined it. Child tips MUST NOT claim `amt` that violates §Conservation.

### Supply (optional lock)

| State | Meaning |
|-------|---------|
| *(omitted)* / `open` | No declared unit cap. Hold/send still use `amt` + binding + conservation. |
| `locked` | Genesis defines total units `max`. No further mint against this origin. |

Conforming **locked mints** MUST:

1. Create one or more 1-sat tips in the genesis transaction whose **`amt` values sum to `max`**, and
2. Set origin `supply` to `locked` with that `max`.

A single genesis tip with `amt = max` is the preferred compact locked mint. Unlocked mints MAY omit `supply`/`max` and issue any positive genesis `amt`.

Conforming **receivers** MUST accept a tip only if it binds under §Binding. When the origin is locked, mint-batch / local holdings MUST respect `max`. Holders are **not** required to enumerate global circulating supply via an indexer. Markets MAY show indexer stats as convenience only (grade C).

### Mint batch (genesis siblings)

Optional. Genesis MAY create the origin tip and additional siblings in the **same transaction** (`randomizeOutputs: false` recommended so origin is `txid_0`).

Sibling at `txid_vout` binds when:

* same txid as origin,
* remittance includes `"mint": { "batch": true, "vout": <vout> }`,
* `origin` matches the genesis origin outpoint,
* each sibling has a positive `amt`,
* sum of all genesis tip `amt` values equals origin `max`, and
* each output is 1 sat with a valid first `ord` envelope on genesis outputs.

After the first transfer of a tip, senders SHOULD attach [BRC-150](./0150.md) provenance; receivers MUST prefer a verifying 150 package over mint-batch attestation alone.

### Conservation (split / merge)

Token units are conserved across spends:

1. Select one or more **input tips** bound to the same origin.
2. Let `S` = sum of input `amt`.
3. Create one or more **output tips** (1 sat each), funded with ordinary BSV for dust + fees.
4. Let `T` = sum of output `amt` for that origin in the same action.
5. Receivers / wallets MUST require `T === S`. Change is an output tip back to the sender (or another allowed destination) with the residual `amt`.

There is **no** requirement that one physical satoshi be “split” among recipients. The input tip UTXO(s) are spent; new 1-sat carriers are created. Multi-recipient pays = multiple new tips in one (or more) transactions.

Merging (many inputs → fewer outputs) and splitting (few inputs → more outputs) use the same conservation rule.

### Binding (when a tip counts)

A tip **binds** to origin `O` if any of the following hold (checked in order):

1. **Genesis** — tip outpoint equals `O`, and origin inscription parses as this profile.
2. **Transfer inscription** — this tip’s first `ord` envelope is `application/1sat-ft+json` with a positive integer `amt`, and the spend-chain / BRC-150 walk binds to `O`. `amt` is taken from this envelope.
3. **BRC-150** — `customInstructions.provenance` verifies per [BRC-150](./0150.md) v2 to origin `O`.
4. **Mint batch** — same-tx sibling attestation as above.
5. **Parent hop** — remittance `parent` names a tip that itself binds to `O` (inductive), and this tip’s `amt` is consistent with a conserving spend of that parent (wallets SHOULD verify when parent spend data is available). Wallets MUST depth-limit inductive walks and MUST fail closed on cycles, missing parents, or parents that do not themselves bind. A `parent` claim alone MUST NOT bind.

`mint.extend` without a future auth rule does **not** bind.

### Tags

| Tag | Requirement | Meaning |
|-----|-------------|---------|
| `1sat-ft` | SHOULD | Profile marker. |
| `ordinal` | SHOULD | 1-sat ordinal tip. |
| `origin:<outpoint>` | SHOULD when known | Claimed origin. |
| `name:<string>` / `sym:<string>` | MAY | Display claims. |
| `id:` / `outid:` | SHOULD for held rows | Local list key ([BRC-164](../wallet/0164.md) practice). |

Unknown tags MUST be preserved.

### Custom instructions (per tip)

```json
{
"p": "1sat-ft",
"origin": "<txid_vout>",
"amt": "400",
"sym": "<optional echo>",
"supply": "locked",
"max": "<echo when locked>",
"mint": { "batch": true, "vout": 3 },
"parent": "<optional prior tip>",
"provenance": { }
}
```

| Field | Requirement | Meaning |
|-------|-------------|---------|
| `p` / `origin` | SHOULD / MUST when known | Profile + token id. |
| `amt` | MUST when known | Face value of this tip (decimal string). Omit only for legacy `amt = 1`. |
| `supply` / `max` | SHOULD when origin locked | Echo origin policy only — do not invent. |
| `mint` | MAY | Genesis batch attestation. |
| `parent` | MAY | Prior tip for inductive bind. |
| `provenance` | SHOULD when buildable | BRC-150 v2 object. |

### Transfer inscription

Conforming senders MUST inscribe each new colour tip (payee and change) as `application/1sat-ft+json` over P2PKH. Body is UTF-8 JSON:

```json
{
"amt": "9000"
}
```

| Field | Requirement | Meaning |
|-------|-------------|---------|
| `amt` | MUST | Face value of **this** tip (decimal string). |

Origin is **not** written on the leftover. Identity is the spend-chain / [BRC-150](./0150.md) walk to the mint, same as [BRC-147](./0147.md). `amt` is on this tip so a split can be verified before the wallet shows it as true.

Other 1-sat outputs in the same transaction are **not** carriers unless they carry this envelope.

Remittance (`customInstructions`) MAY repeat `origin` + `amt` to speed import, same as 147. When remittance `amt` and the inscription disagree, **the inscription wins**. A tip with no envelope is legacy: scanners MUST walk spend-chain to an inscribed ancestor and MUST NOT invent `amt`.

### Transfer

1. Select input tip(s) bound to the same origin with sufficient Σ `amt`.
2. Build output tip(s): payee amounts + change; enforce §Conservation.
3. Spend inputs; create new 1-sat outputs (BSV funds dust + fees).
4. **Inscribe** each colour tip per §Transfer inscription.
5. File under basket `1sat-ft` with tags + CI including `amt` (fast path).
6. Attach BRC-150 when a path exists; else set `parent` to a spent tip and echo origin policy.

### Chain scan and basket separation

Address / UTXO scan MAY surface 1-sat outs. Conforming wallets:

* An output whose own first `ord` envelope is `application/1sat-ft+json` MUST be this profile. Read `amt` from the body. Origin comes from the 150 / spend-chain walk. Remittance is a fast path only.
* MUST NOT place a 1-sat output in basket `1sat` ([BRC-147](./0147.md)) solely because the creating transaction spends a 1-sat input.
* MUST NOT place an output in basket `1sat-ft` until it **binds** under §Binding. Unbound 1-sat outs SHOULD be held (not swept, not painted as collectables).
* When walking legacy bare-tip lineage, an ancestor whose first `ord` envelope content-type is `application/1sat-ft+json` MUST be treated as this profile — not as a collectable mint. Do not invent `amt` for that leftover.

### Peer capability (optional)

Senders MAY advertise support for basket `1sat-ft` / this profile via identity or handle-resolve metadata, and MAY warn or refuse bare-address sends to peers that do not advertise it. Remittance is a fast path for identified peers; the inscription is custody. Capability bits are **not** a custody requirement.

### Provenance scope

The BRC-150 v2 **object schema and verification rules** apply unchanged when present. Conforming wallets MUST accept 150 packages for `1sat-ft` tips. A future BRC-150 errata MAY list basket `1sat-ft` explicitly; until then this BRC imports the format by reference.

### Open mint (reserved)

Post-genesis mint via `mint.extend` is **not binding** without a future **auth** rule on the origin. Uncapped (`supply` omitted / `open`) is not the same as free extend — new tips still need genesis, mint-batch, BRC-150, or a proven parent hop.

### Market / overlay notes (informative)

| Concern | Approach |
|---------|----------|
| Token identity in a catalog | Origin outpoint |
| Seller inventory | Bound tips in `1sat-ft` (UTXOs) with `amt` |
| Listing lock | Existing OrdLock / marketplace patterns on tip UTXOs |
| Settlement | Conserving tip spends to buyer (same as wallet send) |
| Discovery / volume charts | Optional overlays (grade C) — never custody |
| Scaling | Transfer cost ≈ tips spent/created, not unit count; prefer compact `amt` |

## Security considerations

* **Tag / CI spoofing** — Without binding (§Binding), identity is unproven. Markets MUST NOT treat unproven tips as inventory of origin `O`.
* **`amt` inflation** — Receivers MUST enforce §Conservation when parent spend data is available; unbound or non-conserving tips MUST NOT increase spendable balance.
* **Mint-batch weaker than 150** — Prefer 150 after first hop. Genesis envelopes + `max` + Σ `amt` bound the batch.
* **Locked vs lying minter** — Origin `max` does not stop extra 1-sat outputs on-chain; conforming wallets **reject** tips that do not bind / conserve for that token id.
* **Open mint** — Deferred precisely because unbounded extend claims are forgeable.
* **Basket mix-up** — Do not file fungibles into `1sat` or collectables into `1sat-ft`.
* **Legacy bare leftovers** — Older sends may be bare P2PKH. A bare 1-sat that spends a 1-sat parent is **not** a collectable. Walk lineage; FT mime ancestor ⇒ this profile, and do not invent `amt`. New conforming sends inscribe origin + amt so a scan can read the tip without remittance. Pre–BRC-175 clients that treat unknown `ord` mimes as collectables may still misfile inscribed tips; that is an old-client bug, not a reason to omit the envelope.

## Relationship to other BRCs

| BRC | Relationship |
|-----|----------------|
| [BRC-147](./0147.md) | Collectables / NFT basket `1sat`. Remittance is a fast path on both profiles; see §Chain scan. |
| [BRC-150](./0150.md) | Provenance format for lineage hops. |
| [BRC-159](./0159.md) / [BRC-160](./0160.md) | Origin theory / envelopes. |
| [BRC-165](./0165.md) | P1Sat permissions for collectables; fungible scopes MAY follow. |

## Copyright

Copyright (c) Brandon Cryderman / HandCash. Licensed under the Open BSV License.
1 change: 1 addition & 0 deletions tokens/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ BRC | Standard
150 | [1Sat Provenance Remittance for Basket `1sat`](./0150.md)
159 | [1Sat Ordinals — Single-Satoshi Tokens and Origin Tracking](./0159.md)
160 | [1Sat Ordinals — Inscription Envelopes](./0160.md)
175 | [1Sat Fungible Basket Profile for BRC-46 / BRC-100](./0175.md)
226 | [Miner-Enforced Resale-Royalty Covenant Tokens (OP_PUSH_TX)](./0226.md)