Repository navigation
Description
Objective
Implement a clean-room, multi-instrument token in Daml that is interface-faithful to CIP-0056 (the CN Token Standard) and structurally faithful to Amulet, with no economics.
Rationale
Demos and sandboxes need a token that a standard-compliant wallet or CLI can read and transact against without special-casing. Building against the splice-api-token-* interfaces only, never splice-amulet, keeps the package small and proves those interfaces are sufficient on their own. Mirroring Amulet's structure (a rules/factory host, two-template locking, two-step transfer, allocations) means the behavior transfers to real deployments, while dropping decay, fees, mining rounds, rewards, and DSO governance keeps it teachable.
Scope
In scope:
TokenandLockedTokenholdings implementing theHoldinginterfaceTokenRegistryandInstrumentConfig, the host for the transfer, allocation, and burn-mint factories- Free, admin-authorized minting plus a per-instrument faucet
- Direct and two-step transfers, transfer preapproval, locking and unlocking
- DvP allocations with execute, withdraw, and cancel
- Propose-accept instrument registration gated by the operator
- Amulet's owner-co-signed authority model
Out of scope:
- Any economics: decay, fees, mining rounds, rewards, DSO governance
- A
splice-amuletdependency - The registry HTTP service, which is its own epic
Architecture & technical considerations
- Daml SDK 3.4.11, LF target 2.1, built with
dpm. LF 2.1 has no contract keys, so on-ledger lookups are passed through the choice context (ExtraArgs.context) rather than fetched by key. - Factories are
interface instances on the admin-signedInstrumentConfig, our analog of Amulet'sExternalPartyAmuletRules, delegating to top-level*Implfunctions. - Holdings are
signatory admin, owner, and locks additionally require the holders, so the admin alone cannot move a party's funds. - Daml authorization is enforced at runtime during script execution, not by the compiler. A signatory change type-checks fine and fails only when a script exercises it.
- Design doc:
docs/superpowers/specs/2026-07-01-canton-token-forge-design.md
Dependencies
Requires the vendored splice-api-token-* interface DARs (bash scripts/fetch-dep.sh). Blocks the registry HTTP service epic, which reads and writes these templates.
Issue breakdown
-
Scaffold the Daml project on the splice-api-token interface DARs #24 Scaffold the Daml project on the splice-api-token interface DARs (feat(scaffold): initialize canton-token-forge on splice-api-token interfaces #1)
-
Implement core token holding, registry, mint, and direct transfer #25 Implement core token holding, registry, mint, and direct transfer (feat(token): core token holding, registry, mint, and direct transfer #2)
-
Add token locking and two-step transfers with preapproval #26 Add token locking and two-step transfers with preapproval (feat(transfer): add token locking and two-step transfers with preapproval #3)
-
Add DvP allocations, a per-instrument faucet, and burn-mint #27 Add DvP allocations, a per-instrument faucet, and burn-mint (feat(token): add DvP allocations, per-instrument faucet, and burn-mint #4)
-
Gate instrument registration behind operator propose-accept #28 Gate instrument registration behind operator propose-accept (feat(registry): gate instrument registration behind operator propose-accept #5)
-
Align holdings and locking with Amulet's owner-co-signed authority model #29 Align holdings and locking with Amulet's owner-co-signed authority model (feat(token): align holdings, locking, transfer, and allocation with Amulet's authority model #6)
-
Amounts are not validated against the instrument's declared decimals #47 Amounts are not validated against the instrument's declared decimals
-
Transfer and allocation aborts fail when the escrow was already reclaimed by lock expiry #48 Reclaiming an escrow by lock expiry leaves an orphaned transfer instruction
-
Transfer instruction accept consumes an unchecked escrow, and the deadline guards have no tests #49 Transfer instruction accept lacks defensive amount and owner asserts
The last three are low-priority correctness polish carried as sub-issues of this epic.
Acceptance criteria
- Every CIP-0056 interface is implemented: holding, transfer-instruction, allocation, allocation-instruction, burn-mint
-
npm testis green across holding, registration, mint, direct and two-step transfer, lock/unlock/expire, allocation execute/withdraw/cancel, faucet, burn-mint, and multi-instrument isolation - No
splice-amuletdependency and no economics anywhere in the package - Instrument creation is propose-accept only, with no direct registration path
- The admin cannot mint, move, or lock a party's holdings without that party's signature
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity