Skip to content

NUTs for prediction markets#337

Open
joemphilips wants to merge 8 commits into
cashubtc:mainfrom
joemphilips:nuts_for_prediction_markets
Open

NUTs for prediction markets#337
joemphilips wants to merge 8 commits into
cashubtc:mainfrom
joemphilips:nuts_for_prediction_markets

Conversation

@joemphilips

@joemphilips joemphilips commented Feb 7, 2026

Copy link
Copy Markdown

This is my ongoing attempt to support encoding Prediction Market Token with cashu.
My primary motivation is to

There have been previous attempts to support DLCs on Cashu, for example:
#128

The purpose of those attempts was essentially to emulate a two-party DLC transaction using eCash tokens.

This approach is completely different. Each outcome is encoded as a separate token, and the mint is agnostic to the oracles. I believe this is a more natural representation of a prediction-market security token and enables a more liquid market.

This PR contains three NUTs

  • NUT-CTF: Conditional token redemption via oracle-attested outcome keysets
  • NUT-CTF-split-merge: Conditional token split and merge for trading positions
  • NUT-CTF-numeric: Numeric outcome conditions with digit decomposition

Done self-reviewing, it is now ready for review from others. I will try to have a reference implementation ready when I have time. I may update the spec based on what I've learn during implementation.

It is possible to split CTF.md (Conditional Token Framework) into an independent PR if the maintainer wishes. Since this is quite a huge PR.

Reference implementation: cashubtc/cdk#1666

@github-project-automation github-project-automation Bot moved this to Backlog in nuts Feb 7, 2026
@joemphilips joemphilips force-pushed the nuts_for_prediction_markets branch from 2657a60 to 3f6850a Compare February 15, 2026 14:10
@joemphilips joemphilips marked this pull request as ready for review February 15, 2026 14:11
@joemphilips joemphilips changed the title WIP: NUTs for prediction markets NUTs for prediction markets Feb 15, 2026
@joemphilips

joemphilips commented Feb 17, 2026

Copy link
Copy Markdown
Author

Reference implementation in CDK(WIP)
and cashu-ts

@joemphilips joemphilips force-pushed the nuts_for_prediction_markets branch 2 times, most recently from ee15247 to 63af400 Compare February 18, 2026 01:18
@lescuer97

Copy link
Copy Markdown
Contributor

@joemphilips have you taken a look at this PR: #128? its a previous standard for DLCs in cashu. you might want to take a look

@joemphilips

Copy link
Copy Markdown
Author

Hi @lescuer97, thanks for pointing it out. Yes, I've read it.

I didn't go into detail because the approach is quite different from mine. IIUC, PR #128 proposes an
ecash-native DLC framework, using the mint as a blind intermediary for two-party conditional
contracts.

My concern with that approach is that it's primarily suited for bilateral contracts (two parties
locking funds against a predefined outcome tree), whereas CTF is designed for prediction markets
where you need liquidity, composable positions, and the ability to enter/exit freely before
settlement. The two have different scopes:

  • DLC is for "Contract" - enforce a pre-agreed bilateral payout when an oracle attests to an
    outcome.
  • CTF (this PR) is for "Market" - represent outcome exposure as tradeable tokens, enabling open market
    participation.

They're not in conflict. In fact, both can share the same oracle infrastructure (DLC oracle
announcements/attestations), which could benefit the broader ecosystem. But I believe CTF is the
more appropriate primitive for prediction markets within Cashu's trust model.

@joemphilips

Copy link
Copy Markdown
Author

In case anyone's interested, I've been building a PoC application based on this protocol.

Comment thread CTF.md
[22]: 22.md
[CTF-split-merge]: CTF-split-merge.md
[CTF-numeric]: CTF-numeric.md
[NIP-88]: https://github.com/nostr-protocol/nips/pull/1681

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link should be replaced with an actual NIP after nostr-protocol/nips#1681 gets merged.

Add NUT-CTF (Conditional Token Framework), NUT-CTF-split-merge (split/merge operations), and NUT-CTF-numeric (numeric outcome conditions) specs with test vectors, supplementary material, error codes, and README entries.

Squashed from 9 commits after rebasing onto upstream/main to resolve NUT-28/29 filename conflicts (upstream now uses those numbers for P2BK and Batched Mint).
@joemphilips joemphilips force-pushed the nuts_for_prediction_markets branch from f94f19e to 618bf78 Compare April 6, 2026 09:20
@joemphilips

Copy link
Copy Markdown
Author

squashed and rebased

Comment thread CTF.md Outdated

## Terminology

- **Condition**: A question with defined outcomes, resolved by an oracle. Identified by a `condition_id`. Equivalent to "condition" in the [Gnosis Conditional Token Framework](https://docs.gnosis.io/conditionaltokens/).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Gnosis Conditional Token Framework link appears to be broken.
It currently shows a "Page Not Found" page.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. It seems like the website is not well maintained. Perhaps I should link to the contract itself (https://github.com/gnosis/conditional-tokens-contracts)

Or referencce the Polymarket's version (https://github.com/Polymarket/ctf-exchange-v2) but this one has slightly different terminology so I must be careful. Let me think

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broken link fixed.
It seems to be referencing Polymarket version CTF is not a good idea for now since it has a much broader scope than this (off-chain CLOB matching, UMA oracle, etc.)

The docs.gnosis.io/conditionaltokens/ URL returns 404. Replace with the official readthedocs site (rendered from the same gnosis/conditional-tokens-contracts repo) and link the contracts repo alongside as a stable fallback. Add Polymarket as a real-world production example of the same model in CTF.md's Terminology section.
Silexperience210 pushed a commit to Silexperience210/hunch that referenced this pull request May 29, 2026
…SPIKE-02)

SPIKE-02 resolved by pivot: NUT-CTF (cashubtc/nuts#337) is still draft/WIP and was
the only blocker left in the Phase 2 backend. It isn't needed. A Hunch outcome token
is a vanilla NUT-11 P2PK proof locked to L = B + S_X (bettor key + oracle outcome
signature point). The spend key b + s_X exists only after the oracle attests X, so
the token is spendable iff the outcome occurred. The mint enforces only NUT-11 — no
custom NUT, builds on shipping CDK. Refund/INVALID maps to NUT-11 locktime+refund tags.

- token.rs: build_outcome_token (NUT-11 secret with lock + refund + locktime),
            redeem_spend_secret, verify_token_unlock
- 3 tests against the real oracle attestation path: YES attestation redeems the YES
  token only; wrong bettor can't redeem; secret carries lock/refund/locktime
- spikes/nut-ctf/SPIKE-02-RESOLUTION.md documents the pivot, math, safety, and the
  HIP-3 update needed

Remaining mint work (CDK issuance, LDK Lightning, DLC funding tx) is standard
engineering on stable primitives — no longer blocked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace POST /v1/ctf/split and /v1/ctf/merge with a single POST /v1/ctf/convert that performs any payoff-preserving rebalance of conditional positions within one condition at one nesting level. Split, merge, recombine, and negative-risk-style conversion all become special cases.

Core rule: for every outcome o in Omega, out(o) == in(o) - F, valid only if in(o) >= F, where F = ceil(sum input_fee_ppk / 1000). The flat fee is retained non-contingently on every outcome (real collateral the mint keeps regardless of the attested outcome), which bounds free operations.

Collateral is the reserved map key '*' (regular keyset at root, parent conditional keyset when nested). Coverage is computed from registered keyset metadata, not request map keys. Canonical collection encoding fixed (enum: announcements[0] outcome index; numeric: [HI,LO]). Partitions must have >=2 elements with no full-set conditional collection. Issuance invariant: every conditional token backed by >= its face in collateral. Adds error codes 13041/13042/13043; updates CTF.md, CTF-numeric.md, error_codes, suppl, and test vectors accordingly.

Design and post-implementation passes adversarially reviewed via Codex (verdict: sound to merge).
Remove partition registration from the CTF specs and describe condition-time keyset creation, managed default policies, root-only convert scope, and updated numeric behavior.
Add NUT-08-style blank outputs and change signatures for condition registration fees so mints retain only the authoritative required fee.
Use a distinct 13047 error for invalid registration fee change outputs and disambiguate the idempotency cross-reference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

3 participants