README + supporting docs were written for ourselves (deployment paths,
internal product comparisons, internal task lists, build pipeline
artifacts) instead of for users of the software. This pass refocuses
them on what the software is, how to install, configure, and use it.
- README.md: full rewrite. New shape — What it does / Architecture /
Build / Run / Configuration / MCP tools / Security model / Status /
License / Dependencies. Drops the internal "why we built it"
narrative, drops phase-status claims that drifted stale, drops
internal deployment paths.
- ROADMAP.md: deleted. Was an internal task-list with [x]/[ ] items
showing incremental private development. The README's Status
section now communicates what's actually shipped.
- docs/architecture.md: scrub cross-project comparisons referencing
unrelated internal Sulkta codebases.
- aiken-escrow/README.md: drop reference to a non-existent spec file;
rewrite the Status checklist to reflect what's actually done
rather than what was open at the time of writing.
- audits/2026-05-09-escrow-e2e.md: scrub internal image names +
container paths; the audit findings (chain hashes, validator hash,
what each tx proved) are the public-useful part and stay.
- audits/2026-05-09-escrow-internal-audit.md: drop references to
feature-flag-gated branches that no longer exist.
- Dockerfile: drop the dead `escrow_wip surface` phrase from comments.
- Cargo.toml: drop the cross-project comparison comment that named
an unrelated internal service.
- crates/aldabra-{core,dao}: scrub internal preprod-test naming from
source comments — same technical content, generic phrasing.
Settle path (4 txs):
- open a878900c09022381f332ca2cea1b4624202ebdbd6f3a83fd9de07475bb98bd6b
- bob deposit ef8910101e88b63abb28ec9b511616e3465075b8d34d5eeb9703efe1876a62bf
- agree bbfd57c3acb68ddb76d6b92c0dbe8ba9cb21ca88ad6370d19f00822c3b69d655
- settle 4b52312ce264dba74a6fde6c2ccb597696022c8919470f23670e2746db10d1ff
agreed_at_ms=1778381375000 + lock_period_ms=1_800_000 = 1778383175000
earliest_settle. Tip at settle submit: 1778383733000 (558s past).
recipient (bob) receives 10 ADA at enterprise address. Settle requires
no party signer — preprod drove as fee-payer only.
Validator's Settle branch executed cleanly: state==Agreed check,
strict-> time gate, recipient payout via value_geq_value(paid, in_value).
MED-2/3 fix (slot-derived validity_lower_ms) held a second time under
different timing. Total escrow value cycled through validator across all
three E2E paths: 5+10+10 = 25 tADA, 9 successful txs across 6 distinct
validator branches (open as no-script, deposit, agree, veto, settle,
refund). Zero failed txs, zero collateral burns.
Code surface complete. Next: drop escrow_wip flag (task #48) per Cobb's
2026-05-09 directive — replace compile-time gate with runtime
"use at own risk" note when an agent calls escrow_open.
5 of 6 builders proven on chain on preprod_test2 against the
post-audit validator (a8081acef26935d9b5f44b92052178e17301b6d6e6808c91c5b56f5d).
Veto path (4 builders):
- open 0972963e8eb46597b37dfa7e1fa15c97fea4e39d55b29c54f723ba1b155bc7cb
- deposit 0519cb7dbb8c2c1632db5baee90d5440d2905c151f910a085c78d9050c2d6175 ← first Plutus V3 spend on chain
- agree f6664079d96c453e1a6333c33c65744984953c474e57cdb331e78ad3e5429cc7
- veto 14a4be9f233ab02e518356e5963d30517986984f6fd3520151c924057db9c661 ← HIGH-2 fix proven
Refund-timeout path (5th builder):
- open(short) 0669ef61b8695bedcb4eb4c38fda2bd66c68c9384b57839329a01a745db75305
- refund 41590ac6ed069586e650da58858436cfe6be51a865069a7a4b40f795dfcdbff9 ← strict-> time gate proven, MED-2/3 fix held
Settle deferred — needs 30-min lock_period_ms wait. Builder + validator
branch unit-tested (5/5 tests pass), on-chain validation in next session.
Both HIGH validator fixes from the 2026-05-09 internal audit confirmed
running on chain. Multi-party signing flow + slot↔ms boundary math
both held up under real preprod chain race conditions.
Two HIGH validator-side bugs + several MED/LOW off-chain issues found
in the subagent-driven audit on this branch. New validator hash:
a8081acef26935d9b5f44b92052178e17301b6d6e6808c91c5b56f5d.
## HIGH-1: Deposit redeemer let depositors drain tokens
aiken-escrow/validators/escrow.ak Deposit branch now requires
`value_geq_value(new_value, in_value)` before computing net_added.
Previously net_added could carry negative quantities (when new_value
< in_value component-wise), letting a depositor write a matching
new_d.deposits with reduced values and pocket the difference as
wallet change. Latent under v1 ADA-only MCP usage but the validator
must hold against all callers.
## HIGH-2: Empty/partial deposits enabled funds drain via Veto/Refund
Veto and Refund branches now require
`value_eq(deposits_to_value(d.deposits), in_value)` — the tracked
deposits must account for the full locked value. Previously
`refund_outputs_satisfy(_, [])` was vacuously true on empty deposits,
so a driver could fire Veto/Refund on an escrow opened with
`initial_contributor=None` (deposits=[], in_value>0) and pocket the
input's lovelace as change.
Defense in depth: escrow_open builder now refuses
`initial_contributor=None`. New helper `deposits_to_value` folds
deposit FlatValues into a Value via `assets.add` for the equality
check.
## MED: off-chain fixes
- escrow_open min-utxo bumped 1M → 2M (Conway-era inline-datum
+ script-address outputs need ~1.4-1.7 ADA, NOT the 1 ADA default).
- escrow_settle_unsigned + escrow_refund_timeout_unsigned now derive
`validity_lower_ms` via slot_to_posix_ms(network, slot) instead of
Koios's `block_time*1000` — the chain reconstructs `lower` from the
slot, so Koios's ~1s drift could pass off-chain preflight while the
chain rejects at the strict-`>` boundary.
- escrow_open_unsigned MCP tool no longer accepts (and silently
discards) `fee_lovelace` — the unsigned-tx builder auto-estimates.
## LOW: defensive depth
- escrow_veto + escrow_refund_timeout: `qty as u64` → `u64::try_from`
so a corrupt or adversarial datum with negative i128 qty can't slip
through with a wraparound.
## Tests
- 36 escrow builder tests pass (added rejects_no_initial_contributor)
- 132 dao tests pass under --features escrow_wip
- aldabra-mcp release build clean
## Infra
- Validator artifact files (plutus.json, validator.cbor.hex)
regenerated. Dockerfile already wired to bake them at
/etc/aldabra/escrow/ for MCP tools' validator_script_path arg.
- Internal audit findings written up at
audits/2026-05-09-escrow-internal-audit.md including the v2-deferred
items (multi-asset spend-input, lovelace-not-cross-checked, etc.)
Third-party audit still required before any mainnet deployment.