aldabra/aiken-escrow
Kayos 45954f3f75 chore: scrub internal session-log narrative from code comments
Wide sweep across the codebase to remove leftover artifacts of internal
development sessions, internal entity naming, and audit-code references
that point at non-public docs. The technical reasoning for each piece
of code stays; the "Caught 2026-05-XX while debugging XYZ at preprod"
narrative goes.

Categories scrubbed:
- Dated session-log comments ("Caught/Surfaced/Discovered 2026-05-XX")
  → rewritten as neutral technical reasoning.
- Internal audit codes (AUDIT-H2, AUDIT-C2, AUDIT-M2, AUDIT-H5, etc.)
  referencing a non-public audit doc → labels stripped, fix reasoning
  kept.
- Internal-entity names in code comments (Sulkta-specific, Sulkta runs
  X, Terrapin/TRP as gov-token names) → generic phrasing.
- Test fixture helper `sulkta_cfg` → `test_dao_cfg`; test DAO name
  string `"sulkta"` → `"test-dao"`. On-chain addresses in test fixtures
  kept (they're real-world wire-byte test data on public chain).
- Cross-references to memory files / non-public audit docs
  (`audit-sulkta-agora-2026-05-05.md`, `audits/2026-05-09-escrow-spec.md`)
  → reasoning inlined or removed.
- Test names renamed: `decodes_sulkta_live_governor_datum` →
  `decodes_live_governor_datum`, `decodes_sulkta_live_proposal_zero` →
  `decodes_live_finished_proposal`, etc.

Kept (legitimate):
- Cross-references to in-repo audit docs (audits/2026-05-09-escrow-
  internal-audit.md, audits/2026-05-09-escrow-e2e.md) — they ARE the
  public artifacts being referenced.
- HIGH-1/HIGH-2/MED-2/LOW labels on escrow fixes — these correspond to
  findings in the in-repo audit doc.
- TODO markers — legitimate work-still-to-do.
2026-05-10 21:29:40 -07:00
..
validators chore: scrub internal session-log narrative from code comments 2026-05-10 21:29:40 -07:00
.gitignore feat(escrow_wip): aiken validator + plutus.json blueprint 2026-05-09 11:38:45 -07:00
aiken.toml feat(escrow_wip): aiken validator + plutus.json blueprint 2026-05-09 11:38:45 -07:00
plutus.json fix(escrow_wip): apply 2026-05-09 internal audit findings 2026-05-09 14:06:17 -07:00
README.md docs: rewrite for users — drop internal infra context 2026-05-10 20:56:25 -07:00
validator.cbor.hex fix(escrow_wip): apply 2026-05-09 internal audit findings 2026-05-09 14:06:17 -07:00

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

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) — findings in audits/.
  • Outstanding: external third-party audit before mainnet release.