This plan covers only the MiHashport-Contract repo: the Soroban smart
contracts that back "Chat. Build. Pay. On Stellar." Every contract here
exists to let the backend
turn a WhatsApp message into a signed Stellar operation, without ever putting
a raw phone number on-chain.
Phases are ordered so the project is demoable as early as possible: Phase 1 already gives the backend team something to integrate against (resolve a phone hash to an address), and each later phase adds one user-facing verb from the pitch (send/receive → swap → deploy).
The six phases are grouped into three sections for issue-tracking and milestone purposes. Each section is a coherent, independently demoable slice of the system:
| Section | Phases | Theme | Contract(s) |
|---|---|---|---|
| 1. Identity Foundation | 1–2 | Resolve a WhatsApp identity to a Stellar address, safely | identity-registry |
| 2. Money Movement | 3–4 | Send, receive, and swap value by phone number | payments, swap |
| 3. Build & Launch | 5–6 | Deploy user contracts from chat; get mainnet-ready | factory, mainnet hardening |
Issues on GitHub are labeled section-1, section-2, or section-3 to
match this grouping. Section 1 is fully issued first — see the 130 issues
tracked under the section-1 label for the granular breakdown of Phases 1
and 2.
Goal: stand up the workspace and ship the identity primitive every other contract depends on.
Scope:
- Cargo workspace layout (
contracts/<name>, sharedrust-toolchain.toml). identity-registrycontract: register / resolve / update / unregister aphone_hash -> Addressbinding, admin-initialized.- CI (build + test on every push/PR to
main). - Repo docs (README, CONTRIBUTING, AGENTS, this plan).
Checklist:
- Cargo workspace +
identity-registryskeleton compiles forwasm32v1-noneandcargo testpasses. - GitHub Actions CI (build + test).
- README / CONTRIBUTING / AGENTS / issue & PR templates.
- Publish the
identity-registryWASM hash in the README once deployed to testnet, so backend can pin against it. - Add a
scripts/deploy-testnet.sh(or documentedstellar contract deployinvocation) for repeatable testnet deploys. - Share the testnet contract ID with the backend team and confirm they
can call
resolvefrom their Soroban RPC client.
Dependencies: none — this phase unblocks everything else.
Definition of done: identity-registry is deployed to testnet, its
contract ID and WASM hash are documented in the README, and the backend repo
has confirmed it can call register/resolve against it.
Goal: make the identity primitive safe enough for real funds to be routed through it.
Scope:
- Admin-mediated recovery (re-bind a phone hash without the old key when a user loses their device, gated by an admin/multisig or timelock).
- Storage TTL management (
extend_ttlfor persistent entries) so bindings don't expire unexpectedly. - Fuzzing/property tests for register/update/unregister invariants.
- Contract upgradability (admin-gated
upgradeentrypoint usingenv.deployer().update_current_contract_wasm).
Checklist:
- Design and implement admin-gated recovery flow with its own error variants and events.
- Add
bump_ttl/ TTL-extension entrypoint and a CI/test check that catches entries expiring in tests. - Add
upgrade(new_wasm_hash)admin entrypoint + test. - Add property-based tests (e.g. via
proptestor repeatedtestutilscases) for register/update/unregister invariants. - Document the recovery flow and admin key custody expectations in README.
- Re-deploy to testnet and confirm backward compatibility with Phase 1 bindings (or document the migration).
Dependencies: Phase 1's identity-registry deployed on testnet.
Definition of done: recovery, TTL extension, and upgrade paths are implemented, tested, and documented; redeployed to testnet.
Goal: let a chat user send Stellar assets to another chat user by phone number, including to someone not yet on MiHashport.
Scope:
paymentscontract that resolves a phone hash viaidentity-registrythen moves a token (native XLM or SAC) from sender to recipient.- Escrow path: if the phone hash isn't registered yet, funds are held in the
contract and released on first
registercall (claimable transfer). - Reference/memo field so the backend can correlate a WhatsApp message with an on-chain transfer.
- Reclaim path for the sender if an escrowed transfer is never claimed (after a configurable timeout).
Checklist:
- Define
paymentscontract skeleton + storage keys (pending escrows keyed by phone hash). - Implement
send(from, phone_hash, token, amount, memo). - Implement direct-transfer path when the recipient is already registered.
- Implement escrow-and-claim path when the recipient is not registered,
auto-releasing on the recipient's next
identity-registry.register. - Implement sender-side
reclaimafter timeout. - Tests covering: direct send, escrowed send + later claim, reclaim after timeout, double-claim rejection.
- Deploy to testnet; document integration contract for backend (expected call sequence for a WhatsApp "send $5 to +234..." message).
Dependencies: Phase 1/2 identity-registry (resolve/register
callable cross-contract); backend must be able to submit a Soroban invoke
transaction from a WhatsApp-triggered flow.
Definition of done: direct and escrowed sends work end-to-end on testnet, with backend able to trigger both paths and observe emitted events.
Goal: let a chat user swap one asset for another ("swap $10 XLM to USDC") from inside the chat.
Scope:
swapcontract exposing a quote function and a swap entrypoint with slippage protection (min_out).- Integration with a Soroban AMM/liquidity-pool interface (either a minimal constant-product pool implemented here for testnet, or a client interface to an existing Soroban DEX contract if one is available on the target network).
- Phone-hash-aware wrapper so a swap can be requested by phone number and the result routed back to the requester's registered address.
Checklist:
- Decide and document integration approach: own minimal AMM vs. calling an existing Soroban DEX contract (record the decision and why).
- Define
swapcontract skeleton:quote(in_token, out_token, amount),swap(from, in_token, out_token, amount_in, min_out). - Implement the chosen pricing/execution path.
- Add slippage protection tests (reject when
min_outnot met). - Add tests for quote accuracy against a known pool state.
- Deploy to testnet with at least one funded test pool/pair.
- Document the swap flow for backend and frontend (what a "quote" call returns, expected latency, failure modes).
Dependencies: Phase 3 payments (reuses its token-transfer plumbing);
identity-registry for resolving the requester's address.
Definition of done: a testnet swap between two test tokens executes with correct slippage enforcement, and quote/swap are documented for the backend team to wire into the chat flow.
Goal: deliver on "deploy contracts" — let a chat user spin up a pre-audited contract (e.g. a simple token, a savings pot, a shared wallet) from a WhatsApp conversation.
Scope:
factorycontract holding an allow-list of approved WASM hashes (templates) an admin can add/remove.deploy(template_id, init_args, owner)entrypoint that deploys a new instance viaenv.deployer(), setsowner(resolved from the caller's phone hash) as the initial admin of the new contract.- At least one real template wired end-to-end (start with a minimal token or savings-pot contract) to prove the factory works, not just compiles.
Checklist:
- Define
factorycontract skeleton + allow-list storage (template_id -> wasm_hash). - Implement admin
add_template/remove_template. - Implement
deployusingenv.deployer().with_current_contract(...)(or address-generated deployer), returning the new contract's address. - Build one starter template contract (e.g.
savings-pot: lock funds, withdraw after a time or goal condition) as the first deployable. - Tests: deploying an allow-listed template succeeds and initializes correctly; deploying a non-allow-listed hash fails.
- Deploy factory + starter template to testnet; document the deploy
flow (what init args the backend must collect from chat before
calling
deploy).
Dependencies: Phase 1/2 identity-registry (owner resolution); a real
template contract to deploy (built as part of this phase).
Definition of done: a chat-triggered deploy call on testnet produces a
working new contract instance owned by the requester's registered address.
Goal: get the contract suite from "works on testnet" to "safe to hold real user funds on mainnet."
Scope:
- Full test coverage review across all contracts (unit + integration + adversarial cases: reentrancy-shaped call patterns, auth bypass attempts, storage exhaustion).
- Gas/storage cost review and optimization pass.
- External or community security review, with findings triaged and fixed.
- Versioned deployment records (which WASM hash is live on which network) and a documented upgrade/rollback procedure.
- Mainnet deployment runbook.
Checklist:
- Adversarial test pass on every contract (unauthorized calls, double-spend/double-claim attempts, boundary values).
- Gas/fee cost report for each entrypoint; optimize any outliers.
- Open the repo for a focused external/community security review pass and track findings as issues.
- Write
docs/DEPLOYMENTS.mdrecording every network's live contract IDs and WASM hashes, kept current going forward. - Write a mainnet deployment + upgrade runbook.
- Execute (or dry-run, if not yet ready for real funds) the mainnet deployment following the runbook.
Dependencies: Phases 1–5 all deployed and stable on testnet with real usage from the backend/frontend for at least one full send → swap → deploy cycle.
Definition of done: all contracts have documented gas costs, a completed security review pass with findings resolved, and a mainnet deployment runbook that has been exercised at least once (testnet dry run acceptable if mainnet launch is still pending business sign-off).