| Section | Description | Result |
|---|---|---|
| R1.1–R1.4 | MCP award_job + award_token regression | PASS |
| R2.1–R2.3 | prepare_escrow amount enforcement regression | PASS |
| H1 | Full XRP happy path (0.1 XRP) end-to-end | PASS |
| D1 | DEX / RLUSD quote tooling | OPEN |
| A1–A4 | Adversarial edge cases (fee skip, replay, limits, role checks) | PASS |
| K1 | Signature-free address claims | DOCUMENTED |
award_token) and escrow prepare amount checksaward_job FixAn earlier probe the same day found MCP award_job was not passing award_token to the REST endpoint, causing every award attempt to return HTTP 403. This test confirms the fix.
| ID | Test | Expected | Actual | Verdict |
|---|---|---|---|---|
| R1.1 | post_job (buyer) | posted + award_token | Job JOB-AUDIT-20260926-R1 posted; token returned | PASS |
| R1.2 | submit_bid (seller) | bid submitted | Bid BID-8D997268, proposed_xrp=0.1 | PASS |
| R1.3 | MCP award_job with correct token | awarded, no 403 | status=awarded, worker=seller, agreed_xrp=0.1 | PASS |
| R1.4 | award_job with wrong token | HTTP 403 | MCP: not_authorized / "Invalid award_token"; REST HTTP 403 | PASS |
prepare_escrow Amount EnforcementEarlier behaviour silently accepted a mismatched amount, which could allow signing an EscrowCreate for a different value than the registered vault. This test confirms the fix.
| ID | Test | Expected | Actual | Verdict |
|---|---|---|---|---|
| R2.1 | create_escrow_vault 0.1 XRP + fee | vault created | AT-AUDIT-R2-20260926 LOCKED | PASS |
| R2.2 | prepare_escrow with amount 0.01 (wrong) | HTTP 400 | {"detail":"amount_xrp 0.01 does not match the registered vault amount 0.1 XRP."} | PASS |
| R2.3 | prepare_escrow with correct amount 0.1 | signable EscrowCreate | Amount: "100000" drops — ready to sign | PASS |
Full end-to-end lifecycle: post job → bid → award → lock escrow → submit work → AI verdict → on-chain EscrowFinish → seller credited.
| Step | Detail |
|---|---|
| Job posted | JOB-AUDIT-20260926-H1 |
| Bid submitted | BID-A7484B4B, proposed_xrp=0.1 |
| Job awarded | MCP award_job with token — agreed_xrp=0.1 |
| Protocol fee | 0.065789 XRP → 196DAC5B…975C57 |
| EscrowCreate | 0.1 XRP locked → 971DCB71…3AB05A — tesSUCCESS |
| Work evaluated | AI verdict: PASS (score 100), auto_finish_queued=true |
| EscrowFinish | 0.1 XRP released → 6454258D…2878F5 — tesSUCCESS |
| Vault status | RELEASED, submission_count=1 |
| Seller balance | 1.137174 XRP → 1.237174 XRP (+0.1 XRP confirmed on-chain) |
MCP get_dex_quote arguments did not match the REST endpoint, returning HTTP 422. RLUSD-denominated escrow is separately unavailable pending Ripple enabling lsfAllowTrustLineLocking.
get_dex_quote MCP tool updated to send xrp_amount + worker_address, matching the REST endpoint. RLUSD escrow remains on the roadmap pending Ripple.
| ID | Test | Expected | Actual | Verdict |
|---|---|---|---|---|
| A1 | Create vault without fee_hash (trust score < 25) | HTTP 402 | MCP + REST HTTP 402 with x402 payment-required envelope | PASS |
| A2 | Reuse a spent fee_hash | HTTP 403 | REST HTTP 403: "payment hash already used" | PASS |
| A3 | max_submissions=2 → exhaust → purchase extra attempt → PASS | limit enforced; EscrowFinish on PASS | Limit enforced; extra attempt purchased; EscrowFinish 5ED7B51E…374433 | PASS |
| A4 | Evaluate from unauthenticated caller on live vault | Document response | Accepted — evaluation ran and returned FAIL (consumed an attempt slot) | DOCUMENTED |
Finding: POST /evaluate accepted submissions from any caller who knew the escrow_id, allowing attempt-slot burning without being the awarded worker.
Mitigations already present: award_token on job award; single-use fee_hash; the EscrowCreate transaction requires the buyer's private key to lock funds on-chain; EscrowFinish is performed by the referee after PASS — an attacker could not redirect escrowed XRP without the buyer signing the EscrowCreate.
A one-time evaluate_token is now generated at vault creation and returned to the buyer, who shares it with the worker. POST /evaluate returns HTTP 403 if the token is missing or invalid. Existing vaults are unaffected (backwards-compatible).
| Purpose | XRP | Tx Hash |
|---|---|---|
| R2 create fee | 0.065789 | CC567667…F9E2B7 |
| H1 create fee | 0.065789 | 196DAC5B…975C57 |
| H1 EscrowCreate | 0.1 locked | 971DCB71…3AB05A |
| H1 EscrowFinish | 0.1 released | 6454258D…2878F5 |
| A3 create fee | 0.065789 | BC7A35E1…0091B8 |
| A3 EscrowCreate | 0.05 locked | F4BD1615…F5EA77 |
| A3 extra attempt 1 | 0.032895 | 869CD018…DE54E3 |
| A3 extra attempt 2 | 0.032895 | C49A53E5…0E20B9 |
| A3 EscrowFinish | 0.05 released | 5ED7B51E…374433 |
| Wallet | XRP after audit | Spendable |
|---|---|---|
Buyer r4oLry…wTqr | 2.859368 | ~1.859 |
Seller rfxMVo…TcN | 1.221364 | ~0.221 |
Seller net: +0.084 XRP ≈ +0.1 (H1) + 0.05 (A3) − 2×0.033 (extra attempts) − ledger fees.
| ID | Issue | Status |
|---|---|---|
| D1 | MCP get_dex_quote schema drift — wrong arg names, HTTP 422 | Fixed v2.8.0 |
| — | RLUSD escrow unavailable until Ripple enables lsfAllowTrustLineLocking | Roadmap |
| K1/A4 | Evaluate could be called by anyone with escrow_id, burning attempt slots | Fixed v2.8.0 |
| — | s1/s2.ripple.com removed from server; production exclusively uses xrplcluster.com | Fixed v2.8.0 |
https://mcp.cryptovault.co.uk/mcp/. Private keys were used only in-process to sign transactions and are not included in this report.