Inspiration On every exchange — centralized or not — an order is a promise. The venue holds your funds, the market maker can renege, and each hop between you and the trade is a party you have to trust. We wanted an order that simply cannot break: where the order isn't a promise about a coin, but a property of the coin itself.
Liquid gives you confidential assets and Taproot; Simplicity gives you transaction introspection — a coin that can read the transaction trying to spend it. Put those together and an order can become a single coin that enforces its own trade. That was the idea worth building.
What it does Mosaik is a covenant DEX on the Liquid Network. Every order is a Tessera — one Liquid UTXO governed by a Simplicity covenant — with two doors:
SETTLE — spendable by anyone, but only by a transaction that pays the maker exactly what the offer asks. The taker can't take the locked asset without paying; the coin refuses. REFUND (keyless) — after a timeout, anyone can sweep the coin, but only back to the maker. No key, no signature — the maker can stay offline forever. The result: trustless, atomic asset swaps with no exchange, no matching engine, no maker server, and no custody. Offers are discovered over a Nostr orderbook, and a browser wallet lets a maker and a taker fund, make, fill, and reclaim offers — and even attack the covenant to watch it reject fraud. It supports L-BTC/asset, asset/L-BTC, and asset/asset swaps in either direction.
How we built it A Rust workspace of four crates:
tessera — the covenant in SimplicityHL, parameterised per offer and compiled to a Commitment Merkle Root, with Taproot address derivation and witness assembly. mosaik-core — offer types, multi-asset Elements transaction construction, the SETTLE and keyless-REFUND builders, and the Elements JSON-RPC client. mosaik-relay — the Nostr orderbook: offers published as addressable Nostr events, discoverable with no server in the path. mosaik-cli + webapp — the mosaik command and a single-file browser wallet UI. Settlement is enforced on-chain by a Simplicity-capable elementsd (from the smplx toolchain); covenant witnesses are assembled with hal-simplicity. The whole thing runs end-to-end on a local Elements regtest, with integration tests that fund real covenant UTXOs and verify settlement on-chain. Challenges we ran into Running Simplicity at all. Stock Elements rejects a covenant spend — leaf version 0xbe is non-standard. We had to source a Simplicity-capable elementsd, and on macOS ad-hoc-sign the unsigned binaries to stop them being SIGKILL-ed. Witness encoding. hal-simplicity documents the witness as hex but emits it as base64; the program and witness must both be base64, and the witness stack order is witness before program. Each of those cost a debugging session. The "Program has FAIL node" wall. An embedded covenant program must be pruned against the exact spending transaction first, or the node rejects the dead branch. The free-option problem. We explored oracle pricing, RFQ, and signed quotes — and discovered our quote covenant had a real binding flaw (a quote wasn't tied to the coin it spent). That exploration led us to drop signed refunds entirely. Confidential vs explicit outputs. A covenant settlement needs explicit outputs; mixing a blinded input quietly unbalances the transaction. Accomplishments that we're proud of A covenant that is enforced on real chain state — not simulated. The Simplicity node executes it and rejects any underpaying spend. The keyless REFUND: we redesigned the covenant so it has no maker key and no signatures at all — pure transaction introspection. It made the covenant smaller and deleted our most fragile code (sighash, genesis binding, signing). The "attack the covenant" demo — deliberately fraudulent fills (underpay, wrong recipient, hidden output), each a well-formed transaction, each rejected by the covenant. Watching the coin stop a thief is the moment that makes Simplicity's value concrete. A complete, honest end-to-end demo: a Nostr orderbook, a browser wallet, multi-asset swaps, and reclaim — all on the simple, proven covenant. What we learned Transaction introspection is the real Simplicity superpower — a covenant that enforces a counter-payment is the thing Bitcoin Script genuinely cannot do. The free option is fundamental. Any async swap where one side commits and the other completes hands someone an option. Covenants bound it; they don't eliminate it. The honest fix is short expiries and a spread, or co-signing when both parties are online. Keyless beats signed. Removing the maker key didn't weaken the refund — the covenant enforces the destination itself, and the result is simpler, offline-friendly, and griefing-proof. Simpler covenants win. Our best design decisions were deletions: fewer parameters, no signatures, one covenant instead of two. What's next for Mosaik Partial fills — a maker funds a grid of covenant UTXOs; a taker sweeps several in one transaction. Depth and partial execution with no covenant change. Recursive vault — a SETTLE re-locks the remainder into a fresh covenant: fund once, fill many times. Cross-L2 legs — a hash-preimage branch lets a Tessera be one leg of an atomic swap with Lightning or RGB. Confidential v2 — covenant settlement that verifies a blinded maker output, restoring Liquid's confidential amounts. Mosaik — the order is the coin. No exchange, no matching engine, no custody.
Log in or sign up for Devpost to join the conversation.