Build a Solana Escrow Program for Service Marketplaces (Anchor Blueprint)
A lot of teams want “something useful” on Solana and immediately jump to tokenomics. A better first product is usually boring and profitable: escrow.
If you run a service marketplace (design, consulting, dev gigs, AI tasks), you need one hard guarantee:
- buyer funds are reserved,
- seller gets paid only after acceptance,
- disputes and timeouts are deterministic.
Solana is a good fit for this because transaction costs are small and execution is fast enough for normal product UX.
This article gives you a production-oriented blueprint using Anchor.
1. Product Scope (What This Program Should Do)
Keep v1 narrow:
- Create escrow for one order
- Fund escrow in stablecoin (for example USDC)
- Mark work delivered
- Buyer accepts and releases payment
- Optional timeout-based cancellation
Do not start with arbitration marketplaces, reputation staking, and fee tokenomics in the same release.
2. Account Model
A clean account model removes most future pain.
#[account]
pub struct Escrow {
pub escrow_id: u64,
pub buyer: Pubkey,
pub seller: Pubkey,
pub mint: Pubkey,
pub amount: u64,
pub fee_bps: u16,
pub created_at: i64,
pub delivery_deadline: i64,
pub status: EscrowStatus,
pub bump: u8,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone, PartialEq, Eq)]
pub enum EscrowStatus {
Created,
Funded,
Delivered,
Released,
Cancelled,
Disputed,
}
Design notes:
- Use a PDA escrow vault authority, never a private key wallet for custody.
- Keep
statustransitions explicit. - Store all critical participants and amounts on-chain; do not trust off-chain payloads.
3. Instruction Set
A minimal but complete instruction set:
create_escrow(escrow_id, seller, amount, deadline, fee_bps)fund_escrow()mark_delivered(proof_hash)accept_and_release()cancel_after_timeout()raise_dispute(reason_hash)
This is enough to ship real transactions and iterate safely.
4. Critical Security Invariants
These invariants should hold in every instruction:
- Funds move only from escrow vault to allowed recipients.
- Only buyer can call
accept_and_release. - Only seller can call
mark_delivered. - Timeout cancellation requires
Clock::get()?.unix_timestamp > delivery_deadline. - State transitions are one-way and validated (
Funded -> Delivered -> Releasedetc.). - Arithmetic on fees and payouts is checked (no overflow, no negative logic).
If any of these fail, you get real money bugs, not cosmetic bugs.
5. Example Release Flow
pub fn accept_and_release(ctx: Context<AcceptAndRelease>) -> Result<()> {
let escrow = &mut ctx.accounts.escrow;
require!(escrow.status == EscrowStatus::Delivered, EscrowError::InvalidStatus);
require!(ctx.accounts.buyer.key() == escrow.buyer, EscrowError::Unauthorized);
let fee = (escrow.amount as u128)
.checked_mul(escrow.fee_bps as u128)
.ok_or(EscrowError::MathOverflow)?
/ 10_000u128;
let seller_amount = (escrow.amount as u128)
.checked_sub(fee)
.ok_or(EscrowError::MathOverflow)?;
// Transfer seller payout from vault ATA -> seller ATA
// Transfer fee from vault ATA -> platform fee ATA
// (Use token program CPI with PDA signer seeds)
escrow.status = EscrowStatus::Released;
Ok(())
}
This example omits CPI boilerplate, but shows the core discipline:
- strict status check,
- strict caller check,
- checked math,
- state update only after valid transfer path.
6. Off-Chain Services You Still Need
Smart contracts are not enough for a production marketplace.
You still need:
Order APIfor business rules and metadataIndexer/workerthat tracks escrow account changes and signaturesReconciliation DBmapping on-chain escrow IDs to platform order IDsNotification servicefor delivery, acceptance, timeout warnings
The program secures value transfer. Your backend secures operability.
7. Testing Matrix (Do Not Skip)
Unit and integration tests should cover:
- Happy path: create -> fund -> deliver -> release
- Unauthorized calls by wrong signer
- Double execution attempts
- Deadline edge conditions
- Fee rounding behavior on small amounts
- Token account mismatch attempts
If your tests do not try to steal funds, they are incomplete.
8. Rollout Plan
A pragmatic rollout:
- Internal beta with capped amounts
- Mainnet limited cohort and allowlisted sellers
- Automated alerts for failed releases and stuck escrows
- Controlled expansion of amount limits
Treat this as payment infrastructure. Rollout discipline matters more than adding fancy features quickly.
9. Why This Is a Strong First Solana Product
Escrow gives immediate business value:
- trust layer for marketplace transactions,
- lower operational reconciliation overhead,
- clear path to platform fees.
And technically, it trains your team on the hard parts that matter later:
- account design,
- signer and authority safety,
- deterministic state machines,
- production monitoring around on-chain flows.
Final Take
If you want a serious Solana use case, build escrow before chasing speculative mechanics.
You will get a useful product, real transaction volume, and a codebase your team can evolve into more advanced programs later.
Related posts
Solana in 2026: Use Cases That Actually Ship
A practical map of real Solana use cases in 2026: stablecoin payments, embedded Actions, and operations patterns teams can implement this quarter.
Architecture as Code: ADR, C4 Diagrams and CI Quality Gates
A complete guide to implementing living documentation using Architecture Decision Records, C4 model, and CI/CD pipeline automation.
Protobuf Event Evolution: Why buf breaking Isn't Enough
How to safely evolve Protobuf schemas in event-driven systems. Rules for .proto files, upcaster pattern and backward compatibility.
Architectural Linting: Automated Protection Against Spaghetti Code
How to enforce architectural rules in CI/CD. Dependency Cruiser for JS/TS, ArchUnit for Java, and practical configuration examples.
Cite this article
If you reference this post, please link to the original URL and credit the author.