The fee-pool solvency counter can be driven to zero by any caller
tally accepts a non-existent case ID and runs the quorum-failure branch, which decrements the active-case counter. Any caller can drive the counter to zero and disable the floor that keeps juror compensation solvent.
Description
withdrawFeePool refuses to draw the balance below a floor derived from activeCaseCount:
uint256 floor = activeCaseCount * PANEL_SIZE_ROUND1 * tierFeeExpertCommercial;
tally(caseId) performs no existence check on its argument and carries no modifiers. For an
unused caseId the default Case has phase == Evidence (enum 0) and commitDeadline == 0, so
the auto-advance at #L716-L718 fires; the phase gate passes; revealDeadline == 0 clears the
reveal-window check; the empty juror loop yields totalRevealed == 0; and the quorum-failure
branch executes if (activeCaseCount > 0) activeCaseCount--;. Repeating with fresh bytes32
values drives the counter to zero while genuine cases are live and their panels are seated.
Vulnerable Scenario:
- A genuine dispute is opened and a three-juror panel is seated.
activeCaseCount == 1. - The owner attempts to withdraw the fee pool; the floor correctly refuses it.
- Any address calls
tallywith an arbitrary unusedcaseId. The counter falls to zero. - The same withdrawal now succeeds and the fee pool is emptied.
- The genuine panel reaches a ruling and each winning juror is paid nothing.
Impact
The guard that keeps juror compensation solvent can be disabled by any external caller at negligible cost. Realising the loss additionally requires the owner to withdraw the newly exposed balance, so the counter forgery alone is a griefing precondition rather than a completed theft. Escrow principal, juror stake and appeal deposits are separately accounted and are not reachable by this path, and withdrawal goes to a fixed treasury address, which bounds the severity.
Recommendation
Reject an absent case: tally should revert when cases[caseId].escrowContract == address(0)
rather than falling through its default-value branches, and activeCaseCount should be adjusted
only on validated phase transitions.
Resolution
Fixed. A tally against a nonexistent case now reverts instead of decrementing the counter.
Affected files
ArbitrationPool.sol#L442-L450(withdrawFeePool)ArbitrationPool.sol#L713-L796(tally)