TSP-1 — Coin Standard
The maintained executable protocol is PLUMB v2. The v1 layouts below are historical design references and are incompatible with v2 witnesses.
PLUMB implementation for divisible assets. See PLUMB for the shared token framework.
Conservation law: sum(balances) = supply.
See the Gold Standard for design rationale and skill architecture.
Account Leaf — 10 field elements
leaf = hash(account_id, balance, nonce, auth_hash, lock_until,
controller, locked_by, lock_data, 0, 0)
| Field | Type | Description |
|---|---|---|
account_id |
Field | Unique account identifier (pubkey hash) |
balance |
Field | Token balance (U32 range) |
nonce |
Field | Monotonic counter |
auth_hash |
Field | Hash of authorization secret |
lock_until |
Field | Timestamp lock (0 = unlocked) |
controller |
Field | Program ID that must co-authorize operations (0 = owner only) |
locked_by |
Field | Program ID that locked this account (0 = not program-locked) |
lock_data |
Field | Program-specific lock data (position ID, collateral ratio, etc.) |
| reserved | Field x2 | Extension space |
Controller Field
When controller != 0, every operation requires a composed proof from
the controller program in addition to normal auth. Enables
program-controlled accounts (fund collateral, escrow, protocol
treasuries).
Locked-by Field
When locked_by != 0, tokens are committed to a specific program. The
lock_data field carries program-specific state. Only a proof from the
locked_by program can unlock the account. Unlike lock_until
(time-based), this is program-based locking.
Token Config
See PLUMB Config for the shared 10-field config model (5 authorities + 5 hooks) and authority semantics.
Token Metadata — 10 field elements
Standalone on-chain commitment, independent of config. Does not affect circuit business logic directly.
metadata = hash(name_hash, ticker_hash, teaser_hash, site_hash, custom_hash,
price_oracle, volume_oracle, 0, 0, 0)
| Field | Type | Description |
|---|---|---|
name_hash |
Field | Hash of token name string |
ticker_hash |
Field | Hash of ticker symbol |
teaser_hash |
Field | Hash of token description/teaser |
site_hash |
Field | Content hash of token website/frontend |
custom_hash |
Field | Hash of arbitrary custom metadata |
price_oracle |
Field | Reference to external price oracle program (0 = none) |
volume_oracle |
Field | Reference to external volume oracle program (0 = none) |
Merkle Tree
See PLUMB Merkle Tree.
Global Public State
| Field | Type | Description |
|---|---|---|
state_root |
Digest | Merkle root of all accounts |
supply |
Field | Sum of all balances |
config_hash |
Digest | Token configuration commitment |
metadata_hash |
Digest | Token metadata commitment |
current_time |
Field | Block timestamp for time-lock checks |
Operations
All operations follow the PLUMB proof envelope.
Op 0: Pay
Transfer amount tokens from sender to receiver.
Public I/O: op, old_root(5), new_root(5), supply, current_time, amount, config(5)
Constraints:
- Config verified,
pay_authandpay_hookextracted - Sender leaf verifies against
old_root hash(secret) == sender.auth_hash- If
pay_auth != 0, dual auth required current_time >= sender.lock_untilsender.balance >= amount(range check viaas_u32)- Sender:
balance -= amount,nonce += 1 - Receiver:
balance += amount - New leaves produce
new_root - Supply unchanged
Op 1: Lock(time)
Lock an account's tokens until a future timestamp.
Public I/O: op, old_root(5), new_root(5), supply, lock_until_time, config(5)
Constraints:
- Config verified,
lock_authandlock_hookextracted - Account auth required
- If
lock_auth != 0, dual auth required lock_until_time >= leaf.lock_until(extend only)- Leaf:
lock_until = lock_until_time,nonce += 1 - Merkle root updated, supply unchanged
Op 2: Update
Update token configuration (authorities, hooks). Setting admin_auth = 0
in the new config permanently renounces authority.
Public I/O: op, old_root(5), new_root(5), supply, old_config(5), new_config(5)
Constraints:
old_root == new_root(state unchanged)- Old config verified,
update_hookextracted hash(admin_secret) == old_config.admin_authadmin_auth != 0(not renounced)- New config fields hash to
new_config - Supply unchanged
Op 3: Mint
Create amount new tokens for a recipient.
Public I/O: op, old_root(5), new_root(5), old_supply, new_supply, amount, config(5)
Constraints:
- Config verified,
mint_authandmint_hookextracted hash(mint_secret) == config.mint_auth(always required, 0 = disabled)new_supply == old_supply + amount- Recipient:
balance += amount - Merkle root updated
Op 4: Burn
Destroy amount tokens from an account.
Public I/O: op, old_root(5), new_root(5), old_supply, new_supply, current_time, amount, config(5)
Constraints:
- Config verified,
burn_authandburn_hookextracted - Account auth required
- If
burn_auth != 0, dual auth required current_time >= leaf.lock_untilleaf.balance >= amount(range check)new_supply == old_supply - amount- Leaf:
balance -= amount,nonce += 1 - Merkle root updated
Hooks
See PLUMB Hook System for the shared hook model. All 5 hook slots are available. See Skill Reference for standard hook programs.
Security Properties
All PLUMB framework security properties apply. Additional TSP-1 properties:
- No negative balances —
as_u32()range check on all balance arithmetic - Supply conservation —
supplyis public I/O, enforced per Mint/Burn operation