D1 — On-chain blacklist registry
Statement of Work: Deliverable 1 · Target: Week 1 (7–13 Sep) · Status: Complete and closed
A Soroban contract that replaces the hardcoded demo deny-list baked into the wallet's scanner. A list inside one wallet's bundle protects one wallet's users; a contract any wallet or dApp can read protects everyone.
Evidence
| SOW §6.1 evidence | Where | What it shows | Status |
|---|---|---|---|
| stellar.expert testnet contract page | CBJWD6SA…G623F |
The deployed contract, its WASM hash, creation time, storage entries, and a history of report and set_status calls from several accounts |
Present |
| WASM hash published in the README | README — Testnet smart contracts | 40fd37718c3fbc7f849c4d414364cdd86c01b4db9ab86be9099007ba5be23783, identical on the published and sandbox instances and to a fresh local build |
Present |
| Sample on-chain report transaction with the fee routed to the treasury | 81fa64a6…8ed8 |
One transaction carrying the write, the attribution and the 1 XLM transfer reporter → treasury; the smoke script asserts the treasury delta equals the fee | Present |
| Recordings (registry end to end; captioned terminal capture) | TODO: link | Report → fee lands → address reads flagged → admin disputes → warning stops, on the public explorer; then the same loop from the command line | Pending link |
| Evidence decks | TODO: link | Proof of Deliverables (7 slides) and Technical Documentation & Demo Evidence (8 slides) | Pending link |
What a user can do when this is done
Anyone can report a Stellar address as a scam by paying a small fee, and anyone — a wallet, a dApp, a script — can ask whether an address has been reported, by whom, why, and how many times, without owning an account, signing anything or paying. A reported address raises a warning in every wallet that reads the registry, not just the one where it was reported. An administrator can mark an entry Disputed or Revoked so a wrongful report stops raising a warning while the record of it survives.
Traceability
| SOW clause | Change | Evidence | Status |
|---|---|---|---|
| A registry contract on Soroban with a data model for reports | 22de070 — crate scaffold, nine-field entry, storage schema, constructor |
Contract page; reference: data model | Evidenced |
Fee-gated report() with the fee routed to a treasury in the same transaction |
072c336 |
Report tx 81fa64a6…; smoke script asserts +1 XLM on the treasury |
Evidenced |
| Admin status transitions (Active / Disputed / Revoked) and config management | 76edfba |
set_status transactions on the contract history; sandbox tx ae57d189… |
Evidenced |
Public read API (is_flagged, get, count, list) |
4d7b093 |
Interface tab on the contract page; unit tests with committed snapshots | Evidenced |
| Fee-free read path for per-signature screening | 3bcfc4e — deterministic ledger key + getLedgerEntries |
scripts/hot-read-blacklist-registry.mjs prints FLAGGED for the demo address with no account and no signature; the worked example in the reference is re-derived by the test suite |
Evidenced |
| Continuous integration for the contract | 619214a — fmt, clippy -D warnings, tests, wasm build, vendored-artifact check |
Contracts lane | Evidenced |
| Deployed to testnet with the evidence the SOW names | 96c4713 — re-runnable deploy script that refuses an unverifiable hash; smoke script |
Contract page; README row; report tx | Evidenced |
| Documented end to end | 7983bd3 — full ABI, error table, data model, events, both read paths |
docs/blacklist-registry.md |
Evidenced |
| §3.9 — no secrets in the repository | Admin and treasury are local stellar keys identities; deploy script documents that real secrets live in environment secrets |
Repository grep; CI | Evidenced |
Scope notes
- The registry informs a warning; it does not gate a transaction on its own. Attribution (who reported) is stored so a consumer can weight the claim; an auto-block on one stranger's word was deliberately not built.
- Evidence is a 32-byte hash. The material itself never goes on chain.
- The wallet did not read the registry in Week 1; that wiring is Deliverable 2's Screen stage (done) and Deliverable 3's pre-sign screen.
Implementation choices
- Two instances of the same bytecode. The published deployment is the one named in the README and the reference; a separate QA sandbox instance (
CDPEFCHA…53F4N) lets a tester hold the admin key and exercise the admin paths without touching the published one. Same WASM hash on both. - The deploy script is the runbook. Testnet is periodically reset; the script re-creates identities only if absent, prints every value the README needs, and aborts rather than publish a WASM hash it cannot reproduce locally.
- Documentation coupled to code. The reference document's worked example is parsed by the test suite and re-derived, so a half-finished re-deployment fails the tests instead of shipping a document that lies.
