When a pool resolves to SURVIVED or EXPIRED, stakers are entitled to claim their principal plus their share of the bonus. The sweepUnclaimedBonus function is intended to allow the sponsor to sweep "excess" tokens (like direct donations or dust) while strictly reserving the snapshotTotalBonus - claimedBonus amount for the stakers.
Due to a catastrophic logic error, sweepUnclaimedBonus calculates the exact amount of bonus owed to the stakers, and then transfers that exact amount to the sponsor's recoveryAddress. This not only steals the stakers' yields, but because the contract balance is depleted, all subsequent claimSurvived or claimExpired calls will revert due to insufficient funds, permanently locking the stakers' principal.
Likelihood:
Any caller can trigger this function immediately after flagOutcome(SURVIVED) or claimExpired() resolves the pool. It requires no malicious admin, just a standard protocol state transition.
Impact:
The sponsor instantly receives 100% of the stakers' bonus yields.
The contract is drained below its liabilities. When stakers attempt to claim, stakeToken.safeTransfer(msg.sender, payout) reverts, permanently trapping their principal in the contract.
Rewrite sweepUnclaimedBonus to calculate the total reserved liabilities (unclaimed principal + unclaimed bonus) and only sweep the balance that exceeds those liabilities.
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.