aldabra/aiken-escrow/README.md

65 lines
2.9 KiB
Markdown

# aiken-escrow
> ⚠️ **UNAUDITED.** No third-party security review has been performed.
> Internal review only. Treat as use-at-own-risk for high-value flows
> until external audit lands.
Two-party agreement-with-veto escrow validator (Plutus V3, Aiken
v1.1.21). The off-chain (Rust) side lives in `crates/aldabra-dao` and
is wired into the MCP tool surface via `aldabra-mcp`.
## State machine
```
Open ──(both sign Agree)──▶ Agreed{at} ──(lock_period elapsed, no veto)──▶ Settle (→ recipient)
│ │
│ └──(A or B fires Veto)─────────────▶ Refund (per-contributor)
└──(open_deadline passed, no agreement)─────────────────────────▶ Refund (per-contributor)
```
## Build
```bash
cd aiken-escrow
aiken check # type check + tests
aiken build # produces plutus.json blueprint
```
The blueprint at `plutus.json` is consumed by aldabra's escrow builders
to construct script addresses + spending witnesses.
## Threat model — known gaps (out-of-scope for v1)
These are KNOWN gaps the validator does not protect against:
- **Datum CBOR canonicality.** The Deposit redeemer compares
`cbor.serialise(expected) == cbor.serialise(new.deposits)`. If the
Aiken stdlib's CBOR encoder is non-canonical for any input shape
(e.g. map ordering), an attacker could submit a continuing output
with the same logical content but byte-different and bypass the
check. Mitigated by using `List<Deposit>` (not Map) which has
deterministic order, but external review should re-confirm.
- **Stake credential preservation on refund outputs.** Refund outputs
are derived from contributor PKHs as null-stake base addresses. If a
contributor's wallet uses a custom stake credential, refund value
bypasses their stake-delegation pool. Acceptable v1 tradeoff.
- **Min-utxo per refund leg.** Validator does not enforce min-utxo
per refund output — assumes the off-chain builder has already
ensured each deposit cleared min-utxo at deposit time. A pathological
multi-asset deposit that splits below min-utxo on refund would brick
the escrow until manual recovery.
- **Multi-script-input attack.** If a single tx spends multiple escrow
UTxOs simultaneously with overlapping signers, the per-UTxO
validator runs independently. Cross-UTxO consistency is not enforced.
## Status
- Validator compiles cleanly (`aiken build` produces `plutus.json`).
- Off-chain codecs in `aldabra-dao::agora::escrow`.
- Off-chain unsigned-tx builders for all 6 paths (open / deposit /
agree / veto / settle / refund-timeout) implemented + unit-tested.
- MCP tool wrappers exposed under `escrow_*` prefix.
- Lifecycle paths exercised end-to-end on preprod (settle / veto /
refund-timeout).
- **Outstanding:** external third-party audit before mainnet release.