Audit
33Labs, an independent security research group, reviewed the source of Recoup's lender pool and the contracts wired beside it, 7-26 September 2026. It made 13 findings, none rated critical. 11 are fixed, each fix verified by the reviewers, and the other 2 are accepted risks, set out in full below.
The lender pool, where lenders' money sits, is independently audited.
Six source files of the public repository thedelph/recoup-contracts at commit b66023d: the lender pool's accounting and withdrawals, the protocol wiring, the liquidity source, fee routing, configuration bounds and loan-to-value maths. The fixes were reviewed on main, from f6893cb through 566a9eb.
By 0x23r0 and PhantomOz of 33Labs ↗.
Lenders' USDC is held and accounted for in the lender pool, and an independent audit is the gate in front of any outside lender's money. So the review went where that money sits: the pool itself, and the contracts wired beside it.
The pool is open to outside lenders up to a deposit cap, which Recoup's governance timelock sets by hand, each change public for 48 hours before it takes effect. See Lend for where it stands.
13 found. 11 fixed.
None rated critical. 2 accepted as risks, set out in full below.
- FIXED · 11
- ACCEPTED RISK · 2
Statuses are the report's own: its remediation review classified 11 findings as fixed and 2 as acknowledged and accepted risk. The report judged them on the code, the regression tests, the public risk disclosures and the maintainer and reviewer discussion, not on whether a GitHub issue is open. Pick a group of blocks to filter the findings.
FINAL REPORT · 29 SEP 2026SHA-256 83d9…562aCHECK THE HASH, THEN READ IT- HighH-01Borrower-keyed recovery provenance redirects an earlier workout's recoveryFixed#45
- HighH-02Auction replacement orphans a closed workout's recovery legFixed#46
- HighH-03Repeated request service converts more than a requester's pro-rata cash into senior claimsFixed#47
- HighH-04Manager migration strands post-close loss recoveries with no unblocked repair pathFixed#53
- MediumM-01Permissionless yield sweep can confiscate an open workout's borrower yieldFixed#48
- MediumM-02Realised open-workout yield bypasses the dedicated sweep protectionFixed#49
- MediumM-03First clean workout close captures shared residual yieldFixed#50
- MediumM-04Uncapped stream duration plus gross entry pricing lets a timed flush overcharge new lendersFixed#51
- MediumM-05A lender-yield backlog above the deposit-cap ceiling can never be deliveredFixed#52
- MediumM-06A request serviced down to one share-wei keeps the rest of its cash floor (maintainer-reported)Fixed#64
- LowL-01Permissionless settle discards a borrower's sub-unit yield accrualFixed#54
- LowL-02After a raw cash loss, the request floors can lock the whole remaining cash until a repayment or a cancelAccepted risk#61
- LowL-03A paused or blacklisting USDC shuts every bond door, because the farm pays its pending USDC inside the same call (maintainer-reported)Accepted risk#68
- RATED CRITICAL
- None
- MAINTAINER-REPORTED
- 2
- PUBLIC GITHUB ISSUES
- 13
TABLE VIEW · 13 rows
| ID | FINDING | SEVERITY | STATUS | ISSUE |
|---|---|---|---|---|
| H-01 | Borrower-keyed recovery provenance redirects an earlier workout's recoveryHighFixed | High | Fixed | #45 |
| H-02 | Auction replacement orphans a closed workout's recovery legHighFixed | High | Fixed | #46 |
| H-03 | Repeated request service converts more than a requester's pro-rata cash into senior claimsHighFixed | High | Fixed | #47 |
| H-04 | Manager migration strands post-close loss recoveries with no unblocked repair pathHighFixed | High | Fixed | #53 |
| M-01 | Permissionless yield sweep can confiscate an open workout's borrower yieldMediumFixed | Medium | Fixed | #48 |
| M-02 | Realised open-workout yield bypasses the dedicated sweep protectionMediumFixed | Medium | Fixed | #49 |
| M-03 | First clean workout close captures shared residual yieldMediumFixed | Medium | Fixed | #50 |
| M-04 | Uncapped stream duration plus gross entry pricing lets a timed flush overcharge new lendersMediumFixed | Medium | Fixed | #51 |
| M-05 | A lender-yield backlog above the deposit-cap ceiling can never be deliveredMediumFixed | Medium | Fixed | #52 |
| M-06 | A request serviced down to one share-wei keeps the rest of its cash floor (maintainer-reported)MediumFixed | Medium | Fixed | #64 |
| L-01 | Permissionless settle discards a borrower's sub-unit yield accrualLowFixed | Low | Fixed | #54 |
| L-02 | After a raw cash loss, the request floors can lock the whole remaining cash until a repayment or a cancelLowAccepted risk | Low | Accepted risk | #61 |
| L-03 | A paused or blacklisting USDC shuts every bond door, because the farm pays its pending USDC inside the same call (maintainer-reported)LowAccepted risk | Low | Accepted risk | #68 |
Issue numbers are on the public repository's tracker, where each finding was filed and answered.
What the reviewers verified for each fix
For each of the 11 fixed findings, the report names what the reviewers verified and on which commit:
- H-01the fix, on 68c0c26
- H-02the fix, on 68c0c26
- H-03the original High-severity routes, on 68c0c26
- H-04the migration-recovery regression, on 68c0c26
- M-01the fix, on 68c0c26
- M-02the fix and its regression coverage, on 68c0c26
- M-03the fix, on 68c0c26
- M-04the capped 30-day stream and newcomer full-value recovery, on 29af396
- M-05successive partial backlog delivery and the preserved below-ceiling anti-capture behaviour, on 29af396
- M-0672 of 72 fix-focused tests and 104 of 104 #61-preservation tests passing, on 35f0a58
- L-01that repeated non-count-changing settlement preserves the same 41,254-base-unit accrual as a single settlement, on 29af396
L-02 and L-03 are accepted risks, with no fix to verify.
These two are accepted rather than fixed. Both are disclosed in full here and in the public repository, and if either happens, lenders and borrowers carry it.
- L-02 · Low#61After a loss of the pool's own cash, queued withdrawal floors can lock all the remaining cash until a borrower repays or a floor holder cancels, with no guaranteed time. Kept by design: writing the floors down instead would make every queued lender permanently lose part of the amount she was quoted.
- L-03 · Low#68If Circle pauses USDC or blacklists the custody adapter while any farm reward is pending, bond deposits, withdrawals and harvests fail for as long as it lasts, because DexFi's farm pays out pending USDC inside the same call. Liquidation clocks keep running meanwhile. Rated Low because no one in the protocol can cause a Circle pause or blacklist.
- AUDITEDLender
Pool - AUDITEDCredit
Wiring - AUDITEDTreasury
Liquidity Source - AUDITEDProtocol
Fee Splitter - AUDITEDConfig
- AUDITEDLtv
Math - OUT OF SCOPECollateral
Vault - OUT OF SCOPECredit
Manager - OUT OF SCOPELiquidation
Auction - OUT OF SCOPEEpoch
Harvester - OUT OF SCOPENAVOracle
- OUT OF SCOPERisk
Params - OUT OF SCOPEDirect
Call Adapter - OUT OF SCOPEMint
Attempt Receiver - OUT OF SCOPEReferral
Registry - OUT OF SCOPEBond
Deposit Consent Gate - OUT OF SCOPEAdapter
Consent Gate
- The other 11 contracts, which handle borrowing, bond custody, pricing, harvests, auctions and the joint consent some governance calls need, were outside this review. Some findings trace paths from the pool into CreditManager and LiquidationAuction, and some fixes landed there, so the reviewers read parts of those two; this page still does not call them audited.
- The audit is a review of source code, not of any deployment. The audited contracts on mainnet were deployed from the reviewed source, fixes included.
- A review cannot prove there are no bugs left. The report says so itself, quoted below.
“A smart contract security review cannot prove the complete absence of vulnerabilities. This assessment was bounded by the agreed scope, review period, available documentation, and referenced commits. Additional review, deployment verification, monitoring, and a public bug bounty are recommended before production use.”
“M-06 is fixed: its independently reviewed remediation was merged into main through PR #69. L-02 is the accepted post-raw-loss withdrawal-floor lock, and L-03 documents the accepted external paused/blacklisted-USDC custody dependency. Before accepting third-party capital, 33Labs recommends retaining M-06's regression and #61-preservation coverage, publishing the L-03 incident runbook, retaining the activation gate, and verifying deployment/source parity.”
From the report's conclusion. #61 is L-02's public issue.
Download the report (PDF, 2.87 MB) - “Recoup Security Audit Report”, 33Labs, September 2026.
file 33labs-recoup-final-report-2026-09-29.pdf bytes 2,870,881 sha256 83d9b929c481cf2fbf730c53b71d7f681d926fd52c58f3764e4ea7f091f0562a
To check your copy, run sha256sum 33labs-recoup-final-report-2026-09-29.pdf and compare the output with the hash above. Or drop it on the box, where it is hashed in your browser and never uploaded.