What it is: A
did:t3nautonomous escrow agent. A client funds a milestone, then both freelancer and client sign cryptographic attestations. When both match (or a deadline/arbiter rule fires), a Rust β WASM contract automatically releases the payout. No single partyβnot even Escrowa itselfβcan move the funds unilaterally.
- π¬ Demo Video: youtu.be/WzEVJwG1ebQ
- π Live Demo Console: escrowa.edycu.dev
- π DoraHacks BUIDL Page: dorahacks.io/buidl/44352
- π₯ Best Agent Auth SDK ($300) (Primary): A production-ready least-privilege
agent-authimplementation. - π Bug & Documentation Bounty ($200): Real ADK developer feedback detailed in BUGS.md.
cd contract && cargo test # Run 18 Rust contract state tests
cd ../board && npm run ci # Run ESLint, typecheck & 73 Vitest tests (100% coverage)
npm run e2e # Run 10 Playwright E2E tests (auto-starts dev server)
npm run dev # Launch local dev server at http://localhost:3000| Core Concern | Technical Implementation / File Reference |
|---|---|
| Agent-Auth Enforcement | Scoped functions + allowedHosts allowlist configured in agentAuth.ts and enforced natively via T3nClient.ts |
| Escrow State Machine | Core dual-consent, deadline, and arbiter logic written in Rust in lib.rs |
| Decentralized Identity | Identity resolution and mapping configured in didRegistry.ts |
| Comprehensive Test Suite | 91 total tests (73 Vitest frontend tests + 18 Cargo contract tests) |
| Documentation & Playbook | Walkthrough playbook in DEMO.md and architecture layout in ARCHITECTURE.md |
Important
Honest Hackathon Scope & Simulation Context: The Rust β WASM contract logic and secp256k1 cryptographic signatures are real. The TEE enclave, host interfaces, and blockchain settlement are locally simulated using the T3 Agent Development Kit (ADK) and @bytecodealliance/jco. This architecture is production-ready for real Intel TDX hardware when the T3N mainnet launches. Full details are in the Hackathon Simulation Context section below.
The Flow: Priya delivers the milestone β signs a cryptographic attestation β client approves β TEE enclave verifies signatures and triggers the in-enclave
signingkey to sign the payout βoutboxdelivers the payout idempotently.
β
Mutual release (m1) |
β° Deadline fallback (m2) |
βοΈ Arbiter refund (m3) |
|---|---|---|
![]() |
![]() |
![]() |
| Both parties attest β released | Client ghosts β auto-release at deadline | Disputed β arbiter refunds the client |
Priya shipped the final milestone of a 6-week remote development contract. The client said "looks great," went silent, and she's still chasing $4,200 three months later. Traditional escrow requires trusting a third-party custodian with both the funds and the release decision. On-chain escrow usually means trusting a hot wallet or an opaque, unverified smart contract. No platform offers a neutral, secure environment that releases payment only when both sides agree without exposing the private keys to any single human or software agent.
Escrowa is an autonomous escrow agent. The funds are locked under conditional logic compiled for a Trusted Execution Environment (TEE).
- Mutual Consent: Payout occurs automatically when the freelancer's "delivered" and the client's "approved" cryptographic signatures match.
- Hardware-Gated Custody: The signing keys are generated and held inside the enclave under
cluster CEK. The agent never sees the raw private keys, preventing unilateral draining of the escrow. - Fail-Safe Fallbacks: Includes customizable ghost/deadline rules (automatic release if a client vanishes) and arbiter-gated resolution paths.
Note
Hackathon Simulation Context: For this DoraHacks submission, the TEE hardware environment is simulated locally using the T3 Agent Development Kit (ADK) and @bytecodealliance/jco. The core logic (contract/src/lib.rs) compiles to a standard wasm32-wasip2 T3 component, but the host cryptographic functions (like sign-secp256k1) are simulated locally via ethers.js in board/src/wasm/host.ts. This ensures the code is production-ready for real Intel TDX hardware when the T3 network launches, without misleading about current hardware utilization.
flowchart LR
C[Client] -->|"fund milestone"| ESC
F[Freelancer] -->|"attest: delivered (sig)"| ESC
C -->|"attest: approved (sig)"| ESC
subgraph ESC["Escrowa agent (did:t3n)"]
API["REST API"]
CLI["T3nClient.executeAndDecode"]
end
subgraph T3["T3N TEE (Intel TDX / Wasmtime)"]
DISP["escrow contract: dispatch"]
COND["release conditions"]
SIGN["signing: per-wallet secp256k1"]
OUT["outbox: idempotent payout"]
end
API --> CLI -->|"execute fn"| DISP --> COND
COND -->|"delivered AND approved -> sign release"| SIGN --> OUT -->|"tokens -> freelancer"| TX[("settlement")]
ESC -. "did:t3n" .-> REG["did-registry / agent-registry"]
OUT --> DASH["Audit dashboard"]
- Fund: Client locks test tokens in the contract.
- Attest: Freelancer signs
delivered, client signsapproved. - Evaluate: Enclave contract verifies signatures against
did:t3nregistry. - Sign & Settle: Enclave
signingsigns payout;outboxposts it idempotently.
We use six distinct Terminal 3 host capability interfaces:
signing(contract/src/lib.rs:224): Generates secp256k1 signatures for release payouts inside the TEE. Keys never leave the enclave.outbox(contract/src/lib.rs:239): Posts payouts to the settlement system exactly-once (prevents double-spending).kv-store(contract/src/lib.rs:83): Stores namespace-isolated milestone states securely.did-registry&agent-registry(board/src/sdk/didRegistry.ts, wired inboard/src/app/api/seed/route.ts): Links each party's authenticator to itsdid:t3nidentity and publishes the Escrowa agent URI.agent-auth(board/src/sdk/agentAuth.ts, enforced inboard/src/sdk/T3nClient.ts): Provisions Escrowa a least-privilege scope (allowed functions +allowedHostsegress allowlist) and the host blocks any call outside it β an out-of-scope function fails withhost/agent.function_deniedand an unauthorized host withhost/http.egress_denied.- TEE Attestation (Intel TDX): Enforces execution of compiled WASM logic inside hardware-secured VMs.
The demo provisions these identities via the did-registry / agent-registry (see board/src/app/api/seed/route.ts). DIDs are did:t3n:<authenticator-address>.
| Role | Authenticator address | DID |
|---|---|---|
| Client | 0x1111111111111111111111111111111111111111 |
did:t3n:0x1111111111111111111111111111111111111111 |
| Freelancer (Priya) | 0x2222222222222222222222222222222222222222 |
did:t3n:0x2222222222222222222222222222222222222222 |
| Arbiter | 0x3333333333333333333333333333333333333333 |
did:t3n:0x3333333333333333333333333333333333333333 |
| Escrowa agent | β | did:t3n:escrowa-agent (URI https://escrowa.edycu.dev/.well-known/agent) |
The Escrowa agent is granted a least-privilege agent-auth scope: functions create-milestone, submit-attestation, resolve-milestone; egress allowlist api.terminal3.io (see board/src/sdk/agentAuth.ts).
These are deterministic demo identities for the simulated build. A real deployment would obtain its
did:t3nand developer key from the claim page (set asT3N_API_KEY).
- Node.js β₯ 20
- Rust & Cargo (with
wasm32-wasip2target) - npm
- Clone the repository:
git clone https://github.com/edycutjong/escrowa.git cd escrowa - Build the Rust WASM contract:
cd contract rustup target add wasm32-wasip2 cargo build --target wasm32-wasip2 --release cd ..
- Install frontend dependencies:
cd board npm install - Configure the Environment Variables:
Open
cp .env.example .env.local
.env.localand add your Terminal 3 API Token (claimable here):T3_API_KEY=0x_your_terminal3_api_key_here
- Run the local dev server:
Open
npm run dev
http://localhost:3000to view the Escrowa Dashboard.
We enforce a rigorous test harness verifying the entire escrow state machine.
# Run unit tests
cd board
npm run test| Suite | Focus | Status |
|---|---|---|
| Key Custody Test | Asserts that generated keys are restricted to TEE memory and never leak to disk/env/logs | β Passing |
| Happy Path Suite | Verifies create -> attest:delivered -> attest:approved -> released |
β Passing |
| Deadline Fallback | Verifies deadline timeout automatically triggers release/refund | β Passing |
| Arbiter Dispute | Verifies arbiter-only decision resolution | β Passing |
| Replay Protection | Asserts duplicate attestation requests are rejected | β Passing |
| Agent-Auth Scope | Asserts out-of-scope functions (host/agent.function_denied) and non-allowlisted egress (host/http.egress_denied) are blocked |
β Passing |
We ran 200 full lifecycle evaluations of our release-condition check, signing, and outbox posting inside the TEE simulator.
Run the benchmarks:
./scripts/bench.py- Mean Latency: ~3.4 ms
- p50 (Median): ~2.3 ms
- p95 Latency: ~8.6 ms
MIT Β© 2026 Edy Cu




