A Soroban smart contract on Stellar that enables trustless milestone-based escrow between a client, freelancer, and arbiter.
This contract allows a client to fund a job broken into milestones. Funds are locked in the contract and released per milestone only when the client approves delivery. Disputes can be raised by either party and resolved by a designated arbiter.
| Function | Caller | Description |
|---|---|---|
initialize |
Anyone | Set up job with parties, token, and milestone amounts |
fund |
Client | Deposit total amount into contract |
mark_delivered |
Freelancer | Mark a milestone as delivered |
approve_milestone |
Client | Release funds for a delivered milestone |
raise_dispute |
Client or Freelancer | Freeze a milestone for arbitration |
resolve_dispute |
Arbiter | Release to freelancer or refund to client |
get_job |
Anyone | View current job state |
Pending → Delivered → Released
↓
Disputed → Released (arbiter favors freelancer)
→ Refunded (arbiter favors client)
- https://rustup.rs/ 1.79+
- https://developers.stellar.org/docs/smart-contracts/getting-started/setup
- wasm32 target: rustup target add wasm32-unknown-unknown
From the repository root:
cargo build --release --target wasm32-unknown-unknown -p milestone-escrowFrom the repository root:
cargo test -p milestone-escrow- Contract implementation completed in
contracts/milestone-escrow - Includes milestone delivery, approval, dispute, and arbitration flows
- Initialize now rejects empty milestone lists, zero/negative amounts, zero addresses, and zero auto-release windows with explicit contract errors
raise_disputenow performs zero-address check,require_auth, and identity validation before writing the re-entrancy lock (issue #566), matching the authorization pattern used byfund,approve_milestone, andresolve_dispute; includes the five precondition guard assertions present in all other mutating functionslock_escrow_interest_yieldnow rejects unauthorized callers withUnauthorizedand an illegal source state withInvalidStatusbefore it reads or writes the ledger entry (issue #464); authorization runs first viarequire_admin_from_instance, so a non-admin cannot probe whether an escrow is locked, and an already-locked configuration is refused rather than silently re-locked- Contract tests and snapshots are provided under
contracts/milestone-escrow/test_snapshots
soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/milestone_escrow.wasm \
--network testnet \
--source <your-account>MIT
| Network | Contract ID |
|---|---|
| Testnet | CDD5WKK3WT3QVKXMXTJNDIXE4T73FK6GGXDSD6UTJAH6YYZU52SQ4MUH |
Explorer: https://stellar.expert/explorer/testnet/contract/CDD5WKK3WT3QVKXMXTJNDIXE4T73FK6GGXDSD6UTJAH6YYZU52SQ4MUH