Cosmic Bull

Rendered from pearl/r/service_market/DISCOVERY.md at commit f191063fd89d in the project repository. The committed file is the source of truth; this page is a rendering of it.

Discovery — service_market

Search date: 2026-09-22 Objective: a decentralized service marketplace — providers register services, customers purchase with on-chain payment, completed work is resolved, and escrowed payment is released to the provider only after successful resolution. Must resist unauthorized settlement, double payment, and stuck funds.

This record follows docs/DISCOVERY_AND_REUSE.md. It is the gate, not a summary written afterwards.


1. What was searched

StepSourceMethod
1Cosmic Bull catalogcatalog/README.md, catalog/applications.md, catalog/primitives.md read in full
2Cosmic Bull /p/ and /r/ sourcesall 33 .gno files under pearl/p/ and pearl/r/ read as source, not via catalog summaries
3On-chain pearl-1exhaustive enumeration, 500 packages at height 626979 — 167 under /p/, 333 under /r/
4Public Gno / GitHubpinned examples tree (all 1,503 .gno files; 144 kept + 180 quarantined package dirs); GitHub code search; gnolang/tx-exports by keyword

The chain listing exceeds the query tool's single-response budget, so step 3 was run as an alphabet slice — gno.land/p/{a..z}, gno.land/r/{a..z}, and gno.land/r/g1{0..9,a..z} for the address-namespace bulk. No prefix was left unqueried. vm/qpaths is HEAD-only, so this is a snapshot at that height.

Two properties were treated as the decisive filter, because they are the heart of the objective:

  1. Real coin custody — a chain/banker and an OriginSend envelope, versus accounting that only moves integers.
  2. A resolution step gating payout — value that stays immobile across transactions until a separate resolving act releases it.

2. Relevant implementations found

Cosmic Bull's own portfolio

PackageCustodyResolution gateClassification
r/marketreal (coinio+feeledger)noneRELATED
r/bounty_panelreal, pooled openTotalyes (M-of-N panel)RELATED
r/grantsreal, pooledyes (funder selects)RELATED
r/bountiesreal, pooledyes (funder awards)RELATED
r/service_registrynonen/aRELATED (complementary)
p/coinioREUSABLE PRIMITIVE
p/feeledgerREUSABLE PRIMITIVE
p/duebook, p/permbookREUSABLE, not needed (see §4)

External, live on pearl-1

PackageClassificationConcrete reason it is not reused
r/samcrew/escrow_v3RELATED — closest functional neighbourGenuinely custodial and resolution-gated, with timeout valves. But it is a bilateral contract, not a marketplace: CreateContract(cur realm, freelancer address, …) means the client names the freelancer, so there is no provider registration and no service catalog — no discoverable supply side, and no standing offer a customer can purchase against. Authority is a hardcoded AdminAddress with no rotation function, and that key is simultaneously sole dispute arbiter, a unilateral ReleaseFunds path, and a permanent Pause() kill switch over every fund path. It derives identity via unsafe.PreviousRealm() inside crossing functions rather than cur.Previous() (security.md Class 2 shape). It hard-imports r/samcrew/memba_market_config, so adopting it means inheriting a third party's live DAO fee spine.
r/samcrew/agent_registry_v2RELATEDProvider registration + prepaid credits, genuinely custodial — but settlement is provider-asserted: UseCredit is callable by the agent creator, so the provider unilaterally debits the customer. That is precisely the unauthorized-settlement property this objective must resist.
r/samcrew/memba_nft_market_v3_2, nsmarket/v1–v4 (×3 namespaces), g1hx4z2k…/nftmarket* (28 realms), gnomads_market, memba_token_otc_v2RELATEDAll settle a transferable token asset atomically against coins. There is no delivery phase, so there is no resolution step to gate. nsmarket/v4's own package doc is explicit that holding either side "is a different kind of business".
r/g16m0r7…/{escrow, bountyboard, subscription, orderbook, splitpayment}, r/g1nyjym92…/escrowRELATEDTwo disqualifying defects throughout. No custody: no chain/banker import anywhere in the family; Payout returns a formatted string and moves nothing. Designation forgery (security.md Class 2): Approve(caller, dealID string), Resolve(arbiter, …), Claim(hunter, …) take the actor's claimed identity as a string parameter, so any address can act as any party. g1nyjym92…/escrow additionally lets a caller-supplied id overwrite an existing deal.
r/moul/x/daily/escrow/v1RELATEDIts own doc says it: "Accounting only: no funds move." Models the mutual-confirmation handshake correctly and derives identity correctly, but with no custody it cannot resist double payment or stuck funds — there are no funds.

Public ecosystem

r/demo/defi/atomicswap (HTLC, hashlock-gated rather than acceptance-gated), p/demo/subscription, r/jjoptimist/eventix (instant delivery, and carries an in-source SECURITY XXX note that its paymentToken any is unvalidated) — all RELATED, and none of the three is deployed on pearl-1.


3. The delta

No package found combines all four of: provider registration, an open catalog a customer purchases against, real coin custody, and an acceptance-gated release.

Stated precisely: every existing Cosmic Bull escrow realm escrows funder-first — the party who will later decide escrows their own money and then solicits work. This objective requires customer-first escrow against a standing provider offer. Four consequences follow, and they are the new work:

  1. A standing offer that survives N orders. market's listing is single-shot (Active → Sold is terminal), so one listing is one sale. A service offering must be purchasable repeatedly.
  2. Escrow on the purchase path. No existing package has both pay-against-a-pre-existing-offer and hold-pending-resolution.
  3. A per-order state machinePurchased → Delivered → Released, with escrow immobile until the acceptance edge.
  4. Valve polarity inverts. Existing valves refund the funder on inaction. Here, after delivery, customer silence must eventually release to the provider — otherwise a non-responsive customer traps completed work. Copying an existing valve unchanged would ship a live griefing vector.

4. Reuse decisions

Imported as-is:

PackageContribution
p/g1ut6…/coinioReceive (escrow-in at purchase), Payout (release), Sweep (surplus), HeldAt. Honours the once-per-transaction Receive contract and debit-before-payout.
p/g1ut6…/feeledgerClaimable balances and fee pot after resolution; guarantees credited + fee == amount; overflow-checked.
gno.land/p/nt/avl/v0Ordered service/order trees with deterministic Iterate for Render.
gno.land/p/nt/markdown/sanitize/v0InlineText over provider-supplied titles and descriptions — the service_registry Y5 fix, live-verified.

All four confirmed present on pearl-1 by live enumeration. A §7a closure check proves byte equivalence separately; path existence is not byte equivalence.

Adopted as a pattern, with credit, not as a dependency:

Considered and not used:

PackageReason
p/duebookIts consume-then-act Claim would make a timeout replay-proof, but the realm's own terminal status transitions already give that property without a second state store to keep consistent. Its cross-realm consumption path also has no live consumer yet (audit Y1).
p/permbookRoles are not in scope. Per-order buyer and seller identity must come from cur.Previous().Address() directly, never from a permission set.
r/service_registryDeliberately not used to resolve providers. Its INTEGRATOR CONTRACT states that a name is not an authorization and must not route a payment.
p/samcrew/memba_market_core_v2SplitProceedsBPS is clean money math, but it is three-way NFT-shaped and frozen to the Memba generation. feeledger covers the two-way split without coupling to a third party's live config realm.
p/nt/treasury/v0Heavier multi-banker dispatch surface, marked v0 Unaudited; coinio is the minimal guard-trio contract already audited and pearl-validated here.

5. Novelty statement

"No relevant existing implementation was found in the searched sources."

This is bounded by §6 and is deliberately not a claim that nobody has built this.


6. Search-confidence limits

Exhaustive: pearl-1 package paths at height 626979 (500 packages, every prefix queried); the pinned examples tree by filename and by content keyword; the coin-custody set in that tree (banker.NewBanker/SendCoins/OriginSend, 28 files) enumerated and reviewed by path.

Sampled, not exhaustive: GitHub code search — escrow extension:gno alone reports ~980 results; roughly 40 were read by relevance and 6 in full. GitHub code search indexes incompletely and ranks opaquely. gnolang/tx-exports was searched by keyword, not enumerated.

Not searched at all: AmozPay/gbnty (GitHub API rate limit exhausted before it could be read — an unresolved gap); non-GitHub hosts; the Gno Playground corpus; forum- and chat-posted code. Other chains — sapphire-1 and local — were not enumerated; this is pearl-1 only.

Depth limit: most external classifications rest on outlines plus targeted full reads. Per the skill's own warning, an outline is navigation, not evidence; names and doc comments are realm-authored claims. escrow_v3, g16m0r7…/escrow, and market were read in full because they were load-bearing.

A correction recorded against this search's own reliability. One search strand reported samcrew/escrow_v3 as existing only on topaz, and its dependency memba_market_config as absent from pearl-1. Both claims were wrong — a direct gno_packages query on gno.land/r/samcrew/ returns both. Had that gone uncorrected, the closest functional neighbour on the target chain would have been dismissed as not deployed. The lesson is the standing one: a negative deployment claim is only as good as the query that produced it, and the query is cheap enough that it should always be run.