- Scope
- The whole codebase — contracts, deployment, validation and QA scripts, invariant harnesses, the frontend, and the governing documents — assessed against both a Sepolia redeploy and mainnet readiness.
- Method
- A manual pre-mainnet review merged with an adversarial red-team fleet whose findings were each put to a refuter panel, then a 24-lens full-codebase register with executable proof-of-concept reproduction, then two go/no-go re-audits of the resulting fix diff.
- Internal report
- audit-reports/CONSOLIDATED_PRE_MAINNET_AUDIT_2026-07-20.md, PRE_MAINNET_SECURITY_REVIEW_2026-07-20.md, FULL_CODEBASE_AUDIT_2026-07-21.md, FINAL_FIX_AUDIT_2026-07-22.md, REAUDIT_H5_DELTA_2026-07-22.md
C-1HighRemediated
Queue settlement could burn an entire queued position for exactly zero assets
Filed Critical, reproduced seven times. Under a fully-marked unrealized impairment the conservative NAV clamp could price a queued position at zero, and settlement burned it anyway. This was the Round 2 sub-wei dust item escalated: the conservative-NAV change destroyed the premise that made it immaterial, and its original recommendation had never been implemented. Confirmed no longer reproducing in the 22 July re-audit.
H-1HighRemediated
Treasury-directed funding plus permissionless reconciliation inflated backing
Reproduced with 1,500,000 units of unbacked supply measured. Deployment could name the treasury as its own funding recipient, and the then-bidirectional reserve reconciliation converted that into backing. Confirmed no longer reproducing; the reconciliation primitive is now monotone-downward only.
H-2HighRemediated
Partial recovery followed by write-off stranded the impairment pool permanently
Reproduced three times, with no reachable terminal state. Confirmed no longer reproducing: all pools return to zero and stay there across a full-year warp.
H-3HighRemediated
Re-pricing the yield vesting period could claw back vested yield and open a dilution mint
Reproduced three times. Fixed by crystallizing before re-pricing, then tightened again when the first entry guard was shown to still leave most of the stream skimmable. Confirmed dead in the 22 July re-audit.
H-4HighRemediated
The mint gate proved attestations existed but not that they attested to the facility's terms
Receivable classes had no on-chain binding between the attested bundle and the facility's economic terms. A terms hash is now bound and re-checked on the funding path as well as at origination.
H-5HighRemediated
Nothing on-chain forced a receivable to be marked down between a missed payment and a servicer default
Redesigned rather than patched, across two rounds. Past-due marking is now a permissionless but reversible accounting flag that cannot set the defaulted state, cannot freeze the curator, and cannot de-gate the loss cascade — the attested default declaration remains the only path to those. A residual in which a cured facility kept a stale mark was closed by a repayment hook wired into both performing branches of the waterfall.
H-6HighDeferred
Absorbed junior capital has no on-chain claim on later recoveries
Accepted in principle and deferred on-chain by owner decision: handled off-chain while Forest Road is the curator, with the on-chain recovery leg a required build before a junior tranche or a third-party curator. The architecture document was corrected because it had promised an on-chain leg the code does not implement.
PM-H-01HighRemediated
Revoking a valuation permitted rollback to an older signed mark
A monotonic high-watermark now survives revocation. The direct reset lever was subsequently removed entirely by owner decision, leaving recovery to a timelocked upgrade.
PM-H-02HighRemediated
The points loss-freeze was bypassable by a permissionless checkpoint
Closed in source with regression coverage.
PM-H-03HighRemediated
The conservative redemption NAV was specified but not implemented
Implemented across the engine, the resolve hook, the vault and the queue, with fifteen tests and two new stateful invariants.
PM-H-04HighRemediated
The production deployment path was not mainnet ready
Resolved by the dedicated mainnet deployment, configuration and validation scripts. Preparing that path is not authorization to use it.
PM-H-05HighRemediated
The frontend was hardwired to testnet and mock-stable assumptions
The build is now chain-pinned at build time and a production build fails closed unless it can verify its deployment receipt.
PM-H-06HighRemediated
A global recovery assessment survived a changed impairment book
Assessments are now bound to an impairment revision that invalidates them when the book moves. Deployed and exercised on Sepolia.
PM-R-11HighRemediated
The conservative NAV under-marked impairment after partial backstop coverage
Externally reported and reproduced with a 150,000-unit under-mark measured, because the NAV subtracted global backstop capacity while coverage is capped and consumed per event. Coverage consumption is now recorded per default and released per facility, deliberately aggregated so the result may over-mark but never under-mark.
PM-M-01MediumAccepted
Concentration exposure could drift above the configured limit after a decrease
Reclassified as a disclosed admission-control posture: drift is published on-chain and a breached dimension cannot be grown further. Remains an economic and governance item for sign-off.
PM-M-02MediumSuperseded
Frontend approval handling assumed standard-return stablecoins
Scoped out rather than fixed: mainnet v1 is canonical USDC only. Any second stablecoin requires new testing and a new audit.
PM-M-03MediumRemediated
The documentation route rendered repository markdown as raw HTML
The renderer now discards raw HTML and applies a safe URL transform, with regression tests. This is the route these audit pages are served from.
PM-M-04MediumRemediated
The production frontend had no content-security or framing protection
Content security policy, frame-ancestors, strict transport, nosniff, referrer and permissions policies are now set and asserted by the frontend test suite.
PM-M-05MediumRemediated
The queue interface hid older claimable positions
Resolved by direct request-identifier lookup and claim, so a position outside the scan window is still reachable.
PM-R-02MediumRemediated
The reserve pause did not cover the debt-service reserve primitives
Pause scope widened to the outflow primitives it had omitted.
PM-R-09MediumRemediated
Mint-gate attestation masks were not validated as exact known-bit masks
Governance can no longer set a mask bit outside the known set, so a future attestation kind cannot be accepted by governance while remaining unread by the gate.
R4-AC1MediumAccepted
The realized-loss magnitude is chosen by the servicer rather than bound to an attestation
Confirmed real and pre-existing; accepted and folded into the documented attestation and servicer trust model. Constraining it is a counsel decision, not a code decision.
PM-R-01MediumOpen
The Sepolia deployment is deliberately testnet-shaped and must not be copied to production
Open by design, and the reason a testnet result is not a production result: the testnet stack retains bootstrap administrative privileges, uses a mock stablecoin, and runs with concentration limits open for ramp testing. The production validator refuses each of those postures.
PM-R-04MediumRemediated
No fresh coverage measurement existed for the current tree
Declared a test-rigor blocker at the time. A source-only coverage gate now reports every source-defined contract function and line entered.
PM-R-05LowRemediated
The redemption-queue request layout was fresh-deploy-only
Resolved by the clean-v1 fresh-deployment-only path.
PM-R-07LowRemediated
The backstop per-event coverage cap was enforced per call
Coverage is now snapshotted and tracked per event rather than per call.
PM-R-08LowRemediated
Streaming rewards with no stakers stranded them
Notifying rewards with a zero staked supply now reverts rather than silently stranding the stream. This closes one leg of the Round 1 reward-dust finding.
PM-R-10MediumRemediated
The deployed testnet queue was stale relative to the redesigned cooldown
Resolved by redeploying. The validator correctly failed loudly on the stale manifest rather than passing it.
What this round was
This was the largest and most adversarial campaign run against the protocol, and the one
that found the most serious defects. It ran in four connected stages over six days:
- A manual pre-mainnet review of contracts, frontend, deployment configuration,
invariants and fork validation, producing the readiness register.
- An adversarial red-team fleet — per-contract, specialist and protocol-wide reviewers
attacking independently on isolated local forks. Every submitted finding was put to a
panel of independent refuters before it was accepted; of fifty-six submissions, thirty-six
were refuted and roughly nine distinct findings survived deduplication. The severities
published here are the panel-adjudicated values, not the values as filed.
- A twenty-four-lens full-codebase register in which each lens attacked independently
and was forbidden to run the test suite, followed by a reproduction phase that turned
forty-three findings into executable proofs. Every entry was labelled as reproduced or
reasoning-only.
- Two go/no-go re-audits of the resulting fix diff, each run with the explicit posture
that another incomplete fix should be assumed until disproven, and each requiring the
original defect to be re-run and shown dead rather than argued dead.
What it found
The headline result was a Critical: under a fully-marked unrealized impairment, queue
settlement could burn an entire queued position and pay out exactly zero. It was reproduced
seven times.
Its history is the most instructive thing in this whole audit record. The same mechanism had
already been filed a week earlier, in Round 2, as an Informational item — a queued request
could become sub-wei dust and burn for nothing — and closed on the reasoning that an amount
below one wei was immaterial. Its recommendation was never implemented. When the conservative
redemption NAV was introduced days later, that change destroyed the premise: the clamp could
price a whole position at zero, not at a sub-wei residual, and the burn proceeded anyway.
An Informational finding was accepted on an argument about magnitude rather than a bound in
the code, and a later change falsified the argument while the code stayed as it was. That is
the failure mode this campaign exists to catch, and it is why findings on this site record
the premise of an acceptance rather than only its outcome.
Five further High findings concerned backing inflation through treasury-directed funding, a
permanently stranded impairment pool after partial recovery, a dilution mint opened by
re-pricing the yield vesting period, a mint gate that proved attestations existed without
proving they attested to the facility's terms, and the absence of any on-chain force to mark
a receivable down between a missed payment and a servicer default. All five are recorded
closed, each by re-running the original reproduction rather than by inspection.
The campaign also recorded that a first round of parallel fixes was rejected in its entirety
— every one reviewed as incomplete, nothing applied — with upgrade-safety blindness and
knowingly-red test suites named as the two systemic causes.
What it did not close
Two findings were deferred rather than fixed, and both remain live commitments:
- Absorbed junior capital has no on-chain claim on later recoveries. Accepted in
principle, handled off-chain while Forest Road is itself the curator, and identified as a
required build before a junior tranche or any third-party curator exists. The architecture
document was corrected because it had described an on-chain leg the code does not
implement.
- The realized-loss magnitude is chosen by the servicer rather than bound to an
attestation. Confirmed real, pre-existing, and folded into the documented attestation and
servicer trust model. Constraining it is a counsel decision rather than a code decision.
One further item is open by design and is the single most important caveat on any testnet
result reported anywhere on this site: the testnet deployment is deliberately
testnet-shaped. It retains bootstrap administrative privileges, uses a mock stablecoin
with no value, and runs with concentration limits open for ramp testing. The production
validator refuses every one of those postures. A green result on that stack is evidence
about the code, not evidence about a production configuration.
Method note on the numbers
Severities here are adjudicated, and several moved during adjudication — two findings filed
High were reduced to Medium, one filed High was reduced to Low, and one was raised. Findings
that were reproduced with an executable proof are distinguished throughout the internal
reports from those established by reasoning alone; roughly a third of the full-codebase
register was reasoning-only and is marked as such there.
Fourteen further reported claims were refuted outright and recorded as refuted, so that a
later round would not re-derive them and count them again.
Why these reports are not published in full
The underlying reports for this campaign are held internally rather than published, and the
reason is specific rather than reflexive. Several of them contain step-by-step, measured
exploitation recipes for defects whose fix status is stated in a different document; the
operational posture of the live testnet stack in enough detail to target it; and local
filesystem and endpoint detail from the reviewers' own environments. Publishing an
exploitation recipe alongside an incomplete statement of what is fixed would be worse than
publishing nothing.
What is published is the finding, its adjudicated severity, and its current disposition —
which is the part a reader needs in order to judge the protocol.
Limitations
The full-codebase register explicitly recorded what it did not cover: nothing was executed
by the lenses themselves, coverage was not measured in that round, the handover script was
unread, and economic calibration, most of the frontend, individual test files, manifest
drift, observability, servicer-outage liveness, and gas, static-analysis and storage-layout
diffs were all out of scope. Two of its findings concerned false greens in the test and
invariant layers, both reproduced by mutation — a reminder that a passing suite is evidence
only to the extent its assertions bind.
An independent external audit remains a required production gate.