2026-07-08 16:25:20 +02:00
2026-06-26 17:32:43 +02:00
2026-05-25 21:55:02 +02:00
2026-05-16 18:00:24 +02:00
2026-06-22 22:25:49 +02:00
2026-05-26 21:45:35 +02:00
2026-05-24 16:27:52 +02:00
2026-05-16 18:00:24 +02:00
2026-06-26 17:32:43 +02:00
2026-05-23 23:22:05 +02:00
2026-06-22 22:25:49 +02:00
2026-05-16 18:00:24 +02:00
2026-05-18 23:18:26 +02:00
2026-06-26 17:32:43 +02:00
2026-07-08 16:25:20 +02:00
2026-05-18 23:13:23 +02:00
2026-05-16 18:09:11 +02:00
2026-06-26 17:32:43 +02:00

descro

A decentralized escrow protocol on Solana for physical goods trading. Fully permissionless and resolver-agnostic — any wallet or program that implements the resolver interface can adjudicate disputes.

🌍 Vision & Concept

Buying and selling physical goods peer-to-peer runs on trust — and today that trust is either placed in a centralized platform that takes a cut and can freeze your funds, or in nothing at all, leaving buyers and sellers to hope the other side follows through. descro removes that single point of control: funds sit in an on-chain vault that only releases according to rules enforced by the protocol itself, not by a company.

Instead of building one monolithic marketplace, descro splits the problem into a minimal protocol layer (escrow logic + a resolver registry) and lets anyone build the application layer on top — from a slick, KYC'd consumer app to a raw wallet-to-wallet trade between two people who've never met.

  • ⚖️ Resolver-agnostic by design — disputes aren't adjudicated by descro itself. Any wallet or program that implements the resolver interface can be plugged in: a single trusted authority, a multisig, a jury DAO, or an algorithmic (MAD-style) resolver.
  • 🔓 Fully permissionless — no whitelist, no gatekeeping. Anyone can create an escrow, register as a resolver, or build a client against the protocol.
  • 🔒 Non-custodial by construction — SOL lives in a program-owned vault, not a company's balance sheet. Nobody, including descro itself, can move funds without satisfying the on-chain rules.
  • 🧩 Progressive decentralization — a central platform (own resolver, KYC, familiar UX) can onboard mainstream users first, while the same trades quietly build up a decentralized backend anyone can tap into directly, with free choice of resolver, once critical mass is reached.
  • Built for Solana — sub-cent transaction fees and ~400ms finality mean the on-chain plumbing can stay invisible to end users while still being fully verifiable.
  • 🧱 Minimal, composable core — the escrow program only knows about escrow state and SOL; dispute resolution is entirely external via CPI, so the protocol doesn't need to be trusted to "get justice right," only to enforce the interface correctly.
  • 🛡️ Trust-minimized stats — resolver reputation (fee, resolution history) lives in an on-chain registry that only the escrow program can update, so it can't be gamed by a resolver inflating its own track record.

Overview

APPLICATION LAYER
  Central Platform (own resolver, KYC, normal UX)
  Decentralized Clients (raw protocol access, free resolver choice)
        │
PROTOCOL LAYER
  ┌─────────────────┐     ┌──────────────────────┐
  │  Escrow Program │────▶│  Resolver Registry   │
  │   (descro)      │ CPI │  (descro_ext_res.)   │
  └─────────────────┘     └──────────────────────┘

The protocol only defines the interface. Any resolver that implements it is compatible — from a single authority wallet to a jury DAO voting contract.

Programs

Program ID
descro DjVR4EuYV6USMJFfsGZwhZ3y8rtWsmG8EvDY96GTqqi3
descro_ext_resolvers GwUPAKs3HHzCpj8uhet4NAnxk9GWNwfrYbpihu5DyFp

Escrow Program (descro)

Holds trade state and SOL. Two PDAs per escrow:

  • EscrowAccount ["escrow", seller_pubkey, escrow_id_le_bytes] — trade state
  • Vault ["vault", escrow_account_pubkey] — system-owned, holds SOL only

Instruction flow:

create_escrow (seller)
  └─▶ deposit (buyer)
        ├─▶ complete (buyer)          → SOL released to seller
        └─▶ dispute (buyer | seller)
              └─▶ resolve (resolver)  → SOL released to winner
cancel (seller, only from AwaitingDeposit)

The dispute_resolver field in the escrow can be any pubkey — a wallet signing directly or a program calling resolve() via CPI. The check is identical either way.

Emergency resolve: After 14 days in Disputed state with no resolution, either party can call emergency_resolve to unlock funds.

Resolver Registry (descro_ext_resolvers)

An on-chain directory for resolvers. Resolvers register with metadata (name, type, fee, URI); resolution stats are auto-incremented by the escrow program via CPI and cannot be manipulated externally.

update_stats is callable only by the escrow program — enforced via an ["escrow_authority"] PDA that only the escrow program can sign for.

Resolver types: CentralAuthority, JuryDAO, MAD, Algorithmic, Multisig

Repository Structure

programs/
├── descro/                    — Escrow Program (Rust/Anchor)
└── descro_ext_resolvers/      — Resolver Registry (Rust/Anchor)
sdk/                           — @descro/sdk TypeScript client
├── src/
│   ├── idl/                   — Anchor-generated IDL JSON
│   ├── escrow.ts              — EscrowClient (instruction builders + fetchers)
│   ├── registry.ts            — RegistryClient
│   ├── listener.ts            — WebSocket subscriptions
│   ├── pda.ts                 — PDA derivation helpers
│   ├── types.ts               — TypeScript types matching on-chain state
│   └── index.ts               — Re-exports + DescroSdk convenience class
app/                           — Next.js + Tamagui playground
├── src/app/                   — App Router pages + providers
├── src/components/            — EscrowDetail, ResolverPanel, …
└── src/hooks/                 — useEscrows, useEscrowDetail

Getting Started

Prerequisites

  • Rust + cargo-build-sbf
  • Solana CLI
  • Node.js + Yarn

Build

Programs must be built in order — the escrow program depends on the registry:

cargo build-sbf --manifest-path programs/descro_ext_resolvers/Cargo.toml
cargo build-sbf --manifest-path programs/descro/Cargo.toml

Install JS dependencies from the repo root:

yarn install

Test

Tests load the compiled .so files via include_bytes!, so programs must be built first:

cargo test --manifest-path programs/descro/Cargo.toml
cargo test --manifest-path programs/descro_ext_resolvers/Cargo.toml

Run a single test:

cargo test --manifest-path programs/descro/Cargo.toml -- test_create_escrow
cargo test --manifest-path programs/descro/Cargo.toml --test test_resolve

App (dev server)

yarn workspace descro-app run dev

SDK Usage

The SDK is consumed as raw TypeScript via transpilePackages in the Next.js config — no build step needed.

import { DescroSdk } from "@descro/sdk";

const sdk = new DescroSdk(provider);

// Create escrow
await sdk.escrow.createEscrow({ amount, disputeResolver, escrowId });

// Fetch all escrows for a seller
const escrows = await sdk.escrow.fetchEscrowsBySeller(sellerPubkey);

// Subscribe to state changes
sdk.listener.onEscrowUpdate(escrowPubkey, (account) => { ... });

Security Properties

Property Mechanism
Nobody can take SOL without consent Network enforces signature requirement at protocol level
Vault can only be drained by the escrow program Vault owner = system_program, only accessible via invoke_signed with correct seeds
Wrong resolver cannot call resolve() require!(signer.key() == escrow.dispute_resolver)
PDAs cannot be spoofed Program verifies seeds on-chain for every instruction
Registry stats cannot be manipulated update_stats only callable via CPI from the escrow program

Architecture Notes

  • Anchor 1.0.x: UncheckedAccount<'info> with /// CHECK: doc comments; #[derive(InitSpace)] + #[max_len(N)] for strings.
  • @coral-xyz/anchor@0.32.x: Use new Program(idl, provider) — the IDL's address field provides the program ID. The 3-argument form is broken in 0.32.x.
  • Yarn workspaces: nodeLinker: node-modules (not PnP) — required for Next.js Turbopack compatibility.
  • LiteSVM tests: each tests/common/mod.rs provides setup(), PDA helpers, send()/try_send(), ix_* builders, and read_* deserializers. test_resolve_with_registry.rs loads both .so files to test the full CPI flow.
Description
No description provided
Readme 597 KiB
Languages
TypeScript 75.6%
Rust 24.4%