Test matrix
Generated by scripts/src/gen-docs.ts from proof/local/forge-test-results.json (2026-10-07T15:27:11Z). Environment for every contract row: contracts (Perpl bytecode harness), LOCAL_REPRODUCTION. Commit: none (no commits authorized yet).
| ID | Requirement | Tests | Expected | Actual | Status | Evidence |
|---|---|---|---|---|---|---|
| I-01 | Trader cannot withdraw pool principal | AttacksTest::test_lp_cannotWithdrawDeployedPrincipal<br>AttacksTest::test_unauth_poolMoneyPathsRequireRegisteredDesk<br>PoolInvariantTest::invariant_cashBasisIdentity | pass | pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-02 | Every order receives the policy stamp | DeskPolicyTest::test_orderType_stampIsAlwaysImmediate<br>DeskPolicyTest::test_stamp_negPnlAndExecutionBlock | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-03 | Leverage cannot exceed the limit | DeskPolicyTest::test_leverage_exactlyAtCapAccepted<br>DeskPolicyTest::test_leverage_oneUnitOverCapRejected<br>DeskPolicyTest::testFuzz_leverage_aboveCapAlwaysRejected | pass | pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-04 | Only allowlisted markets | DeskPolicyTest::test_market_notAllowlistedRejected | pass | pass | PASS | proof/local/forge-test-results.json |
| I-05 | Only IOC/FOK orders | DeskPolicyTest::test_orderType_stampIsAlwaysImmediate<br>DeskPolicyTest::test_orderType_fokStampedAndRevertsAtomicallyWithoutLiquidity<br>DeskPolicyTest::test_orderType_iocWithoutLiquidityLeavesNoPosition | pass | pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-06 | Price within the band | DeskPolicyTest::test_priceBand_exactlyAtBandAccepted<br>DeskPolicyTest::test_priceBand_oneTickOutsideRejected<br>DeskPolicyTest::test_priceBand_appliesToClosesToo<br>DeskPolicyTest::testFuzz_priceBand | pass | pass, pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-07 | maxNegPnlCollatBPS enforced | DeskPolicyTest::test_stamp_negPnlAndExecutionBlock<br>DeskPolicyTest::test_negPnlStamp_perplRejectsFillFarFromMarkWithinBand<br>DeskPolicyTest::test_negPnlStamp_venueRefusesAddingToUnderwaterPosition | pass | pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-08 | lastExecutionBlock stamped | DeskPolicyTest::test_stamp_negPnlAndExecutionBlock | pass | pass | PASS | proof/local/forge-test-results.json |
| I-09 | Equity floor before/after trade | DeskPolicyTest::test_floor_breachedDeskRejectsNewRiskAndReduce<br>DeskPolicyTest::test_floor_postTradeBreachRevertsWholeTransaction | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-10 | Invalid order reverts atomically | DeskPolicyTest::test_floor_postTradeBreachRevertsWholeTransaction<br>DeskPolicyTest::test_orderType_fokStampedAndRevertsAtomicallyWithoutLiquidity | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-11 | Signed order cannot replay | AttacksTest::test_relay_validSignedOrderExecutesOnce | pass | pass | PASS | proof/local/forge-test-results.json |
| I-12 | Nonce strictly increases | AttacksTest::test_relay_lowerNonceRejected | pass | pass | PASS | proof/local/forge-test-results.json |
| I-13 | Deadline enforced | AttacksTest::test_relay_expiredDeadlineRejected | pass | pass | PASS | proof/local/forge-test-results.json |
| I-14 | Stale mark prevents new risk | DeskPolicyTest::test_staleMark_refusesNewRiskAllowsReduceOnly | pass | pass | PASS | proof/local/forge-test-results.json |
| I-15 | Reduce-only possible during stale state | DeskPolicyTest::test_staleMark_refusesNewRiskAllowsReduceOnly | pass | pass | PASS | proof/local/forge-test-results.json |
| I-16 | claim() rejects with an open position | DeskLifecycleTest::test_fullLifecycle_demoCohort_graduateTradeClaimClose<br>DeskSettlementTest::test_claim_unrealizedProfitCannotBeWithdrawn | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-17 | claim() distributes only realized profit | DeskSettlementTest::test_claim_unrealizedProfitCannotBeWithdrawn<br>SettlementMathTest::testFuzz_claimSplit_conservesGross | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-18 | HWM cannot be double claimed | DeskSettlementTest::test_claim_hwmPreventsReclaimAfterLossAndRecovery<br>DeskLifecycleTest::test_fullLifecycle_demoCohort_graduateTradeClaimClose | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-19 | Fees accrue only during exposure | DeskSettlementTest::test_fees_exposedIntervalAccruesExactlyOnceDespitePositionsAndCheckpoints<br>DeskSettlementTest::test_fees_chunkedCheckpointsCannotRoundFeesAway | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-20 | Flat desks accrue zero new fees | DeskSettlementTest::test_fees_flatFundedDeskAccruesNothingForAMonth<br>DeskSettlementTest::test_fees_evaluationDeskAccruesNothing | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-21 | Fee cap enforced | DeskSettlementTest::test_fees_capStopsAccrualAndNewRiskButAllowsReduceAndEnforce<br>SettlementMathTest::testFuzz_accrue_neverExceedsCap | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-22 | Fee cap cannot consume principal | DeskSettlementTest::test_fees_capStopsAccrualAndNewRiskButAllowsReduceAndEnforce<br>SettlementMathTest::testFuzz_waterfall_conservesCashAndOrdersPriority | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-23 | Fee write-offs explicit | SettlementMathTest::testFuzz_waterfall_conservesCashAndOrdersPriority<br>PoolInvariantTest::invariant_feeSubledgerAndCap | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-24 | Settlement reconciles actual cash | DeskSettlementTest::test_enforce_breachSettlesWaterfallAndPaysKeeperOnce<br>ReferenceVectorsTest::test_vectors_settlements | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-25 | Keeper bounty paid at most once | DeskSettlementTest::test_enforce_breachSettlesWaterfallAndPaysKeeperOnce | pass | pass | PASS | proof/local/forge-test-results.json |
| I-26 | Voluntary close has no keeper bounty | DeskSettlementTest::test_close_voluntaryPaysNoKeeperAndRequiresFlat | pass | pass | PASS | proof/local/forge-test-results.json |
| I-27 | Partial closure cannot prematurely settle | DeskSettlementTest::test_enforce_partialCloseDoesNotSettleAndPaysNothing | pass | pass | PASS | proof/local/forge-test-results.json |
| I-28 | Pool exposure cap cannot be bypassed | AttacksTest::test_caps_grossCapAcrossDesksCannotBeBypassed<br>AttacksTest::test_caps_increaseIsTimelocked | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-29 | Per-desk notional cap cannot be bypassed | AttacksTest::test_caps_perDeskNotionalCap<br>AttacksTest::test_unauth_deskCannotUnderReportExposure | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-30 | Pause cannot block closes/claims | DeskSettlementTest::test_graduation_pausedPoolBlocksButCloseStillWorks<br>DeskSettlementTest::test_factoryPause_blocksNewDesksOnly | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-31 | Unauthorized addresses cannot move pool funds | AttacksTest::test_unauth_poolMoneyPathsRequireRegisteredDesk<br>AttacksTest::test_unauth_deskCannotDrawCreditForAnotherDesk<br>AttacksTest::test_unauth_operatorCannotMoveFunds | pass | pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-32 | Reentrancy protections work | ReentrancyTest::test_reentry_claimDuringTrade<br>ReentrancyTest::test_reentry_enforceDuringTrade<br>ReentrancyTest::test_reentry_tradeDuringTrade<br>ReentrancyTest::test_reentry_closeDuringTrade<br>ReentrancyTest::test_reentry_graduateDuringTrade | pass | pass, pass, pass, pass, pass | PASS | proof/local/forge-test-results.json |
| I-33 | Unexpected external calls fail safely | AttacksTest::test_venue_haltedExchangeBlocksTradingButEnforceStatePersists<br>DeskSettlementTest::test_enforce_bankruptPositionWithoutVenueInsuranceStaysEnforcing | pass | pass, pass | PASS | proof/local/forge-test-results.json |
| I-34 | Perpl errors surfaced | AttacksTest::test_venue_perplErrorsSurfaceNamed | pass | pass | PASS | proof/local/forge-test-results.json |
| I-35 | Indexer cannot authorize money movement | n/a | pass | n/a | BY DESIGN | design: no contract reads the indexer; web/keeper read chain (docs/ARCHITECTURE.md) |
| I-36 | UI cannot authorize money movement | AttacksTest::test_relay_signedOrderStillPolicyChecked | pass | pass | PASS | proof/local/forge-test-results.json plus web e2e: blocked order sent to contract is rejected onchain |
| I-37 | Relayer cannot alter signed order | AttacksTest::test_relay_alteredFieldsRejected | pass | pass | PASS | proof/local/forge-test-results.json plus relayer/test/relayer.test.ts |
| I-38 | Relayer cannot replay signed order | AttacksTest::test_relay_validSignedOrderExecutesOnce | pass | pass | PASS | proof/local/forge-test-results.json plus relayer/test/relayer.test.ts |
| I-39 | Keeper cannot enforce a healthy desk | DeskSettlementTest::test_enforce_healthyDeskRejected<br>AttacksTest::test_keeper_cannotGraduateIneligibleOrEnforceHealthy | pass | pass, pass | PASS | proof/local/forge-test-results.json plus keeper/test/decide.test.ts |
| I-40 | Testnet deployment matches compiled bytecode | scripts/src/sync-deployment.ts | pass | pass | TESTNET VERIFIED | proof/receipts/deployments/testnet-*.json (runtime bytecode matches the build on two RPCs) |
Services, model and browser
| ID | Requirement | Test | Runner |
|---|---|---|---|
| S-01 | Core accounting, verification state machine, evidence rules | packages/core/test/core.test.ts | vitest |
| S-02 | Relayer: malicious signer, altered fields, replay, stale deadline, quota, gas cap | relayer/test/relayer.test.ts | vitest |
| S-03 | Keeper: healthy/breach/fee cap/partial/settled/stale decisions | keeper/test/decide.test.ts | vitest |
| S-04 | Reference model agrees with contract outputs | proof/reference_model/run_reference.py | python |
| S-05 | Web pages render, testnet banner, no overflow 320-1920 px, no console errors | web/e2e/*.spec.ts | playwright |
| S-06 | Live testnet fork: real Perpl account and book fill | contracts/test/perpl/TestnetFork.t.sol | forge (FORK_TESTNET=true), SIMULATED |
Run everything with pnpm test, pnpm proof:local and pnpm --filter @imprest/web e2e.