ConfidencePool calculates k=2 scores using checked uint256 products over raw token balances
and absolute Unix timestamps. A standard high-decimal ERC20 can therefore admit a stake that is
safe when deposited and when the risk window opens, but overflows at the later expiry timestamp.
After a zero-stake account mechanically finalizes the pool, all real staker claims revert and the
entire principal plus bonus is permanently trapped.
The final Math.mulDiv does not protect the earlier products:
For riskStart < expiry, choose a raw stake in this interval:
The risk window opens safely. Any account can then contribute one raw token unit so
snapshotTotalBonus != 0. At expiry, a caller with no stake can execute claimExpired(); it sets
outcome = EXPIRED and claimsStarted = true, then returns before _bonusShare(). Every staker's
later claim evaluates expiry * expiry * rawStake and reverts.
Recovery is unavailable: withdraw() rejects a resolved outcome, claimsStarted prevents
moderator re-flagging, and sweepUnclaimedBonus() reserves all outstanding principal and bonus.
The same unsafe timestamp-squared representation also exists in _markRiskWindowStart(),
_clampUserSums(), and stake().
Occurs when governance allowlists a standard ERC20 whose raw-unit scale permits balances above the timestamp-squared capacity.
Occurs when aggregate stake falls inside the safe-earlier/unsafe-at-expiry interval.
Occurs when any account contributes at least one raw bonus unit before permanent-lock finalization.
Occurs when the token otherwise follows standard ERC20 transfer semantics; no fee-on-transfer, rebasing, or callbacks are required.
Occurs when the allowlisted token uses an uncommon raw-unit scale, which is why likelihood is Low.
All affected stakers permanently lose access to principal and earned bonus.
No normal pool entry point can recover the reserved balance after mechanical finalization.
The maximum loss is the complete token balance of each affected pool.
Use the primary PoC embedded below. If the reviewer wants to run it, save the code as test/poc/CodexRebuilt_20260712_RawScoreOverflowLocksClaims.t.sol in the target repository and run:
Observed at commit 58e8ba4ce3f3277866e4926f3140e597f9554a1e:
The PoC proves that a one-unit bonus activates the unsafe score path, a non-staker finalizes
without evaluating it, all staker claims then overflow, all tokens remain in the clone, bonus sweep
fails, withdrawal fails, and moderator correction fails. The active-risk observation overflow variant is supporting coverage for the same root cause and is not a separate finding.
File: CodexRebuilt_20260712_RawScoreOverflowLocksClaims.t.sol
Refactor scoring to use bounded relative durations rather than absolute timestamp squares. As a
minimal guard for the current representation, cap aggregate raw stake against the worst-case
intermediates before accepting a deposit:
Apply the same invariant to every timestamp-squared path and add boundary tests covering a one-unit
bonus and non-staker finalization.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.