Run locally
Clone the monorepo, install, and run the web app, contracts, and tests.
Maren is a single pnpm monorepo: five Solidity contracts, one shared TypeScript SDK, the web app, the iOS app, and the relayer, orchestrated with Turborepo. This is how to run it.
Prerequisites
The workspace pins pnpm@10.19.0 via packageManager and requires Node 22 or newer.
Corepack ships pnpm with Node. corepack enable picks up the pinned version.
forge and cast for the contracts and for on-chain verification.
Clone and install
# The Maren monorepo is private during the grant review.
# Reviewers: request access at exorbilabs@gmail.com and you will be added within a day.
git clone https://github.com/SeventhOdyssey71/marenfinance.git
cd marenfinance
Run each part
pnpm --filter @maren/web dev
# Next.js on http://localhost:3000, live reads against matsnet
The web app reads live from matsnet contracts. The write path is wired and exercised on testnet.
/app is served in local development only. It is switched off on
marenfinance.vercel.app, where /app/* returns 404 by design while the launch is
mobile-first — the iOS TestFlight beta is the shipping client. The documentation site is the
public surface today. The dev script also pins port 3000; pass --port to next dev
directly if that port is taken.
The test suites
| Suite | Count | Runs against |
|---|---|---|
| Contract unit and property tests | 313 | Foundry, including the redemption splitter and the audit regressions |
| Fork tests | 11 | The real MUSD contracts on matsnet, including a driven redemption. Needs MEZO_TESTNET_RPC_URL, else they skip |
| Relayer | 299 | Four adversarial review rounds, plus packaging and nonce serialisation |
| Web behaviour suite | 104 | The built app, live matsnet, read-only signer. Run with node apps/web/scripts/verify-behaviour.mjs against a running pnpm --filter @maren/web start |
| Web unit tests | 141 | Preflight, revert decoding, the relayer client and its routing |
The fork tests run Maren's contracts against the actual deployed MUSD system rather than a mock, so a divergence between MUSD's documentation and its bytecode breaks a test instead of a user. The behaviour suite drives the real interface against the real chain with a signer that structurally cannot sign, and reads the account nonce before and after to prove no signature was ever requested.
The CI=true note
A guard in this codebase fails closed. One of the rules inherited from a real audit is that a
gate reading if (FLAG !== "false") return true is a pass-through whenever the variable is
unset. Maren's equivalent has a test that boots with empty configuration and asserts the service
refuses to operate. When running the full suite in a CI-shaped environment, set CI=true so the
environment-sensitive tests take the CI path. Note also that GitHub CI currently shows a known
account-billing failure at startup that is unrelated to the code.
The em-dash guard
Product copy in this repo does not use em dashes, and a scanner enforces it. Run it before shipping copy changes:
node tools/copy/em-dash-scan.mjs
# scans apps/web and apps/ios; exits non-zero on a prose em dash
The fix for a flagged dash is to rewrite the sentence, not delete the glyph. A lone dash glyph used as a "no value" placeholder is exempt.
