Skip to content

[Audit] Round 6 Summary — Deep-dive on REVLoans, suckers, UniV4, reentrancy, permissions, decimals, 721/banny #87

@mejango

Description

@mejango

Audit Seed

Deep dive / All subsystems / All personas / 7 parallel deep-dive strategies

Round 6 Strategies

# Strategy Target Result
1 REVLoans deep audit Loan math, liquidation, flash loans, collateral valuation Clean — flash loans confirmed safe, cross-chain staleness accepted risk
2 Sucker bridge Merkle deep dive Merkle proofs, claim bitmaps, state machine, emergency hatch Clean — claim bitmap correct, emergency hatch safe, leaf hash adequate
3 Uniswap V4 integration TWAP oracle, V4 hook callbacks, LP positioning, swap-vs-mint MEV Clean — all concerns documented in RISKS.md
4 Reentrancy exhaustive trace Every external call in JBMultiTerminal — CEI verification CLEAN — no CEI violations found across all flows
5 Permission & access control ROOT/wildcard, cross-project, privilege escalation, ERC-2771 CLEAN — no exploitable permission bugs
6 Decimals/currency edge cases Fixed-point truncation, currency confusion, mulDiv rounding, unchecked CLEAN — all arithmetic consistent, all unchecked blocks safe
7 721 NFT hook + Banny retail Tier manipulation, credit system, supply accounting, outfit system Clean — supply accounting correct, credit system sound

Findings Submitted: 0

No findings from Round 6 warranted individual issues. All candidates were either:

  • Documented/accepted design decisions (TWAP warmup, pool pre-init, cross-chain staleness, discount cash-out weight)
  • Theoretical but impractical (Merkle leaf domain separation, uint32 currency collision)
  • Confirmed safe (reentrancy, permissions, flash loans, credit system, decimals)

Notable Positive Confirmations

Reentrancy (JBMultiTerminal): Exhaustive trace of every external call in pay(), cashOutTokensOf(), sendPayoutsOf(), useAllowanceOf(), migrateBalanceOf(), addToBalanceOf(), processHeldFeesOf(). CEI pattern correctly followed throughout despite no nonReentrant modifier. Store state (balanceOf, usedPayoutLimitOf, usedSurplusAllowanceOf) always updated before external calls.

Permissions: ROOT cannot be escalated by operators. Wildcard permissions properly gated (only account owner can set). JBDirectory and JBControlled use raw msg.sender (immune to ERC-2771 spoofing). Self-call patterns (executePayout, executeProcessFee) use msg.sender == address(this).

Decimals/Arithmetic: All mulDiv uses floor rounding consistently. Fee rounding favors payers (safe direction). Bonding curve rounding prevents dust extraction (concave curve + floor = splitting cashouts unprofitable). All 30+ unchecked blocks across core, revnet, and buyback repos verified safe.

Flash Loans (REVLoans): Collateral tokens are burned on deposit and re-minted on repayment. Flash-borrowed tokens cannot be returned after burning — makes flash loan attacks economically irrational.

Claim Bitmap (Suckers): OpenZeppelin BitMaps used correctly. Bitmap set before proof validation and claim handling (CEI). No off-by-one errors. Emergency hatch correctly blocks leaves with index < numberOfClaimsSent.

Credit System (721 Hook): Credits tracked per beneficiary, not per payer. Cannot be double-spent. cantBuyWithCredits correctly enforced against fresh payment value.

Areas With Documented Design Tradeoffs (Not Bugs)

  • TWAP spot fallback during warmup: Uses slot0 when <2 observations. amountOutMin provides backstop. Documented in RISKS.md.
  • TWAP estimate lacks price impact: Systematically overquotes V4 for large trades. Documented.
  • Cross-chain surplus staleness in REVLoans: Stale sucker snapshots can inflate borrowable amount. localSurplus cap mitigates. Accepted risk.
  • Swap sucker minAmountOut: 0: TWAP sigmoid curve provides protection. Documented.
  • _tryPayFee failure in REVLoans: Gifts 1% REV fee to borrower on terminal failure. Liveness tradeoff.
  • Discount mints inflate cash-out weight: Full-price weight for discounted NFTs. Documented governance risk.
  • Banny accessories travel with body: Equipped outfits transfer with the body NFT. Accepted UX risk.

Cumulative Audit Coverage (Rounds 1-6)

Round Focus Issues Filed
1 Deep dive / personas 15 findings, 1 valid (known)
2 Component decomposition #73-#76 (3 verified)
3 Cross-cutting attack chains #77 (1 verified)
4 8 strategies (test coverage, V5→V6 diff, stupid bugs, composability, economic extremes) #79-#80 (2 verified)
5 Under-explored repos, ecosystem sequences, random walker, gas #84-#85 (2 verified)
6 REVLoans, suckers, UniV4, reentrancy, permissions, decimals, 721/banny 0 (all clean)

Total verified findings across 6 rounds: 8 (#73, #74, #75, #77, #79, #80, #84, #85)
Currently open: 3 (#84, #85, #86)
Closed as fixed: 3 (#75, #77, #80)
Closed as by-design: 2 (#74, #79)

Assessment

After 6 rounds of intensive auditing with 40+ specialized agents, the Juicebox V6 ecosystem demonstrates strong security posture. The codebase shows:

  • Correct CEI patterns throughout (no reentrancy guard needed)
  • Proper permission escalation prevention
  • Consistent arithmetic with safe rounding direction
  • Well-documented design tradeoffs in RISKS.md
  • Appropriate fail-open vs fail-closed decisions per subsystem

The diminishing return in finding count (3→1→2→2→0 verified findings) suggests the codebase has been thoroughly stress-tested. Remaining areas of attention are operational: deployment wiring (Resume.sol Tempo support, #84) and gas optimization (#85).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions