The Construction Escrow Program is a Solana smart contract built with the Anchor framework.
It manages escrow accounts between buyers and sellers of construction materials, ensuring funds are only released after verified delivery.
It supports milestones, multi-oracle verification, time-locks, retention (holdbacks), NFT receipts, and dispute resolution.
A comprehensive TypeScript test suite is included to demonstrate account setup, PDA derivation, and step-by-step validation.
Note: This project was developed as a proof of concept for a client researching how construction escrow systems could be implemented on blockchain, specifically leveraging the Solana ecosystem. The goal was to explore transparency, automation, and trustless settlement for large-scale material contracts.
MAX_ORACLES = 8β maximum number of oracles/verifiers per project.MAX_MILESTONES = 10β maximum number of payment milestones.QUORUM_MIN = 1β minimum quorum for oracle verification.
Holds global configuration for the protocol.
Fields:
authorityβ current admin authority of the market.pending_authorityβ new authority waiting to be accepted.treasuryβ PDA that collects protocol fees.insurance_treasuryβ PDA that collects insurance fees.fee_bpsβ base protocol fee (basis points).insurance_bpsβ insurance fund fee (basis points).retention_bpsβ % held back as retention until warranty ends.warranty_daysβ warranty period in days.quorum_mβ required quorum (M-of-N) for oracle verification.arbiterβ designated dispute resolver.
Represents a construction project escrow account.
Fields:
project_idβ unique identifier.buyer,sellerβ counterparties.mintβ SPL token used for payment.configβ reference to Config PDA.amountβ total escrowed amount.fee_bps,insurance_bps,retention_bpsβ copied from Config at creation.late_penalty_bpsβ optional penalty for late delivery.price_snapshot_1e6β price snapshot (USD notional, 6 decimals).quorum_mβ quorum required for verification.oraclesβ array of oracle pubkeys.stateβ escrow state machine:OpenVerifiedPartiallyReleasedReleasedRefundedDispute
created_ts,verified_ts,released_tsβ lifecycle timestamps.verify_by_ts,deliver_by_tsβ deadlines.warranty_end_tsβ timestamp when retention can be released.milestonesβ fixed array of milestone structs.last_evidence_hashβ SHA-256 evidence (docs, photos).attestations_countβ number of attestations attached.cancel_requested_byβ if cancel was requested, stores who requested.dispute_openβ flag for dispute state.nft_enabledβ whether to issue an NFT receipt.receipt_nft_mintβ mint address for NFT receipt.in_transferβ reentrancy guard.retention_releasedβ true once retention is paid out.
Represents a stage payment.
Fields:
idβ milestone index.amountβ payment amount.verifiedβ true once verified by oracles.releasedβ true once funds are released.verify_tsβ timestamp when verified.evidence_hashβ SHA-256 hash of delivery evidence.
Maps project_id β escrow PDA for quick lookups.
Represents an external attestation (e.g., inspector note).
Fields:
escrowβ escrow it belongs to.attesterβ signer.hashβ SHA-256 evidence hash.uri96β optional URI prefix (truncated to 96 bytes).tsβ timestamp.
init_configβ initialize Config PDA.update_fee_splitsβ update fee % and insurance %.transfer_market_authority_proposeβ propose new authority.transfer_market_authority_acceptβ accept authority transfer.
-
create_escrow(project_id, buyer, seller, amount, oracles, quorum_m, price_snapshot, nft_enabled)
Creates a new escrow, transfers buyerβs tokens to a PDA vault. -
set_deadlines(verify_by_ts, deliver_by_ts)
Set verification and delivery deadlines. -
mark_in_progress()
Seller marks project as started. -
expire_and_refund()
Refund buyer if verification not done by deadline.
-
verify_delivery(project_id)
Verifies delivery using M-of-N oracle signatures. -
add_milestone(amount, evidence_hash)
Add a milestone with supporting evidence. -
verify_milestone(milestone_id)
Verify a milestone with oracle quorum. -
release_for_milestone(milestone_id)
Release funds for a verified milestone (fees + penalties applied). -
release_payment()
Release all remaining funds (minus retention). -
release_retention()
Release retention after warranty ends.
request_cancel()β buyer/seller requests cancel.approve_cancel()β counterparty approves cancel β buyer refunded.open_dispute(reason_code, evidence_hash)β open a dispute.resolve_dispute(outcome, seller_pct_bps)β arbiter resolves dispute (refund, release, split).
attach_evidence(hash, uri)β attach evidence to escrow.add_attestation(hash, uri)β add inspector or third-party attestation.
init_receipt_nft()β mint a soulbound NFT as buyerβs receipt.finalize_receipt_nft(burn: bool)β burn or unfreeze NFT at final release.
update_oracles(new_oracles, new_quorum_m)β update oracle set.update_seller_dest(new_seller)β update seller payout destination.
process_timeouts(limit)β cron-friendly function to auto-refund expired escrows.
The test suite demonstrates:
-
Mint & ATA setup
- Creates SPL mint and funds buyer.
- Ensures all ATAs exist.
-
Config initialization
- Creates
ConfigPDA with fees, retention, warranty.
- Creates
-
Escrow creation
- Derives PDAs (
escrow,vault_authority,project_index). - Transfers buyer tokens into vault.
- Derives PDAs (
-
Milestone flow
- Adds milestone, verifies with oracle quorum.
- Releases funds, applying fees + insurance cut.
-
Final release & retention
- Releases payment to seller.
- Holds retention until warranty ends, then releases.
-
Failure case
- Tries to release before verification β fails with expected error logs.
β
Each step uses assertions and console logs to confirm state transitions and balances.
β
Program Derived Addresses (PDAs) are derived exactly as in Rust using seeds.
β
Errors are captured with try/catch and full transaction logs printed for debugging.
- Reentrancy Guard β prevents double-spending during transfers.
- Quorum Verification β requires multiple oracle signatures.
- Retention β ensures buyer protection after delivery.
- Dispute Resolution β arbiter can refund, release, or split funds.
- Timeout Refunds β auto-refunds if deadlines expire.
-
π Buyer funds escrow.
-
π¦ Seller marks project in progress.
-
π§Ύ Oracles verify delivery (or milestones).
-
πΈ Funds released (fees + insurance deducted).
-
β³ Retention held until warranty ends.
-
πͺͺ Buyer receives NFT receipt.
-
βοΈ If dispute, arbiter resolves with refund/release/split.
This program is a robust escrow system for construction projects.
It combines milestone-based payments, oracle verification, retention, NFT receipts, and dispute resolution.
The provided TypeScript test shows full setup, execution, and debugging flow on Solana Playground.