Implementation status
This build runs on a local chain and on Monad testnet, with scripts for each. The economic review in simulation/MODEL_REVIEW.md still applies.
Component boundaries
| Directory | Content |
|---|---|
contracts/ | Solidity market, collateral, session permissions, and test oracle |
packages/shared/ | Contract interfaces, signed action types, and input schemas |
services/ | Transaction relay, event index, read API, and keeper commands |
web/ | Next.js trading terminal, portfolio page, and demo page |
scripts/ | Local and testnet deployment and scripted market actions |
simulation/ | Python accounting reference and research tools |
integration/ | ABI tests, the smoke check, the Python reference script, and the browser layout check |
docs/ | This documentation site |
Each market holds its own collateral. The relayer submits signed actions. It does not select execution prices or change signed orders. Contracts do the matching. The event index supports reads and history. Contract state stays authoritative.
What is implemented
| Area | State |
|---|---|
| Order book | Limit and IOC orders, partial fills, cancellation, expiry, self-trade prevention, and parametric maker ladders |
| Funding | Capped squared returns, fixed charge, funding index, and delayed activation |
| Risk | Initial and maintenance margin, position limit, IOC liquidation against book depth |
| Sessions | Market-scoped session keys with expiry, exposure limit, nonces, and revocation |
| Queue | QueuedMarket with an on-chain IOC queue and combined quote calls |
| Services | Relayer, JSON event index, REST API, SSE notices, and the local shock route |
| Web | Trade page, portfolio page, account dialog, and the LP hedge panel with the shock bar |
| Scripts | Local demo loop with calm noise and shocks, testnet operator, fast testnet operator, and gas estimates |
Differences from the reference model and the target design
| Topic | This build | Reference or target |
|---|---|---|
| Oracle | Test oracle with one signer | Pyth with one valid price for each boundary |
| Funding cash | Funding goes directly to cash when an account syncs | The Python model keeps a separate pending balance until its settlement clock |
| Self trade | The contract cancels the resting self order | The Python model skips the self order |
| Margin constants | The two markets use the same constants | Separate calibration for each asset. The Python MON demo uses a higher initial mark floor. |
| Transport | REST polling and SSE notices | WebSocket |
| Persistence | One atomic JSON file | A database |
| Relayer fallback | Direct contract calls are possible, but the web application has no automatic fallback | Automatic fallback to main-wallet orders |
| Bad debt | A deficit stays visible | A rule for loss allocation |
Tests compare total cash and equity between the contract and the Python model, not each intermediate cash field.
Amounts and permissions
Market quotes, sizes, and cash use 18 decimal places. Token transfers use the 6 decimal places of the test USDC token. JSON messages encode large integers as strings. The web application converts these units at the display boundary.
Session permissions apply to one account and one market. Each permission has an expiry and an exposure limit. A session can place and cancel orders. It cannot withdraw collateral or grant a session permission. Main-wallet actions stay separate from signed session actions.
Gas measurements
Not a Monad benchmark
The values below are Foundry measurements and RPC estimates. None of them is a measured Monad throughput or a measured hourly cost.
| Measurement | Value | Source |
|---|---|---|
| Quote and one-contract fill on testnet, existing position | 168,548 gas (estimate) | pnpm testnet:estimate-onchain, recorded in the root file TESTNET.md |
| Quote and fill with an observation | 246,169 gas (estimate) | The same |
| One random taker order on the MON market | 228k to 323k gas (estimate) | The root file TESTNET.md |
| Enqueue and clear one queued order | About 288,000 gas together | The root file TESTNET.md |
| Enqueue and clear four queued orders | About 730,000 gas together | The root file TESTNET.md |
| Largest match of the earlier array book: 128 live orders, 32 fills | 16,441,705 gas in a warmed Foundry call | contracts/README.md. The book structure changed after this measurement. |
The relayer has a default gas cap of 5,000,000 and rejects an action above it. A user can send a smaller order or a lower match limit.
Run the current Foundry gas tests with:
forge test --root contracts --match-path 'test/MarketGas.t.sol' -vvContract size
In the build artifacts of 13 October 2026, the runtime code of Market is 31,482 bytes and the runtime code of QueuedMarket is 35,868 bytes. These sizes are above the 24,576-byte contract size limit of Ethereum mainnet. The script pnpm local:chain starts Anvil with --disable-code-size-limit. The Monad testnet deployments in the deployment record have contract code at their addresses.
Work before a funded release
- Select and validate the sampling interval and the price source separately for MON and ETH.
- Resolve observation omission and the difference between source time and receipt time.
- Validate the price of a retained funding claim.
- Define recovery when the book cannot form a valid mark after a jump.
- Define loss allocation when liquidation and market collateral are not sufficient.
- Complete a contract security review and measure gas at the maximum workload.
The seven-day horizon, the observation cap, the margin buffers, and the demo maker policies are test inputs. They are not approved launch parameters.
Verification baseline
Before the implementation, all 54 Python tests passed. The Python demo produced an LP loss from moves of 528.98 USDC and a hedge profit of 513.75 USDC after costs. Its shock inputs are log returns of -0.04 and +0.03. These are not exact simple returns of -4% and +3%.
The fixed Python scenario in integration/reference.py matches the Solidity test within 1e-6 USDC for funding, fees, and final equity. This tolerance applies to that scenario. It is not a global rounding bound and not a solvency result.
See the verification record for the checks of the implementation run.