```javascript
@> function claimCorrupted() external nonReentrant {
if (outcome != PoolStates.Outcome.CORRUPTED) revert OutcomeNotSet();
if (goodFaith && bountyClaimed < bountyEntitlement) revert MustClaimBountyFirst();
uint256 toSweep = stakeToken.balanceOf(address(this));
if (toSweep == 0) revert NothingToSweep();
corruptedReserve = toSweep <= corruptedReserve ? corruptedReserve - toSweep : 0;
if (!goodFaith) {
bountyClaimed = bountyEntitlement;
}
if (!claimsStarted) claimsStarted = true;
stakeToken.safeTransfer(recoveryAddress, toSweep);
emit ClaimCorrupted(msg.sender, recoveryAddress, toSweep);
}
@> function sweepUnclaimedCorrupted() external nonReentrant {
if (outcome != PoolStates.Outcome.CORRUPTED) revert OutcomeNotSet();
if (!goodFaith) revert NotGoodFaithCorrupted();
if (block.timestamp <= corruptedClaimDeadline) revert ClaimWindowNotExpired();
uint256 amount = stakeToken.balanceOf(address(this));
if (amount == 0) revert NothingToSweep();
corruptedReserve = 0;
bountyClaimed = bountyEntitlement;
if (!claimsStarted) claimsStarted = true;
stakeToken.safeTransfer(recoveryAddress, amount);
emit UnclaimedCorruptedSwept(msg.sender, recoveryAddress, amount);
}
@> function sweepUnclaimedBonus() external nonReentrant {
if (outcome != PoolStates.Outcome.SURVIVED && outcome != PoolStates.Outcome.EXPIRED) {
revert OutcomeNotEligibleForSweep();
}
uint256 reserved;
if (totalEligibleStake != 0) {
reserved = totalEligibleStake;
if (riskWindowStart != 0) {
reserved += snapshotTotalBonus - claimedBonus;
}
}
uint256 freeBalance = stakeToken.balanceOf(address(this));
uint256 amount = freeBalance > reserved ? freeBalance - reserved : 0;
if (amount == 0) revert NothingToSweep();
if (totalEligibleStake == 0 || riskWindowStart == 0) {
totalBonus -= amount <= totalBonus ? amount : totalBonus;
}
stakeToken.safeTransfer(recoveryAddress, amount);
emit BonusSwept(msg.sender, recoveryAddress, amount);
}
```
* Add the `onlyOwner` modifier to these functions
```diff
- function claimCorrupted() external nonReentrant {
+ function claimCorrupted() external nonReentrant onlyOwner {
if (outcome != PoolStates.Outcome.CORRUPTED) revert OutcomeNotSet();
if (goodFaith && bountyClaimed < bountyEntitlement) revert MustClaimBountyFirst();
// aderyn-fp-next-line(reentrancy-state-change)
uint256 toSweep = stakeToken.balanceOf(address(this));
if (toSweep == 0) revert NothingToSweep();
// Clamp the decrement — `toSweep` can exceed the original reserve when post-resolution
// donations have inflated the balance.
corruptedReserve = toSweep <= corruptedReserve ? corruptedReserve - toSweep : 0;
if (!goodFaith) {
bountyClaimed = bountyEntitlement;
}
if (!claimsStarted) claimsStarted = true;
stakeToken.safeTransfer(recoveryAddress, toSweep);
emit ClaimCorrupted(msg.sender, recoveryAddress, toSweep);
}
```
```diff
- function sweepUnclaimedCorrupted() external nonReentrant {
+ function sweepUnclaimedCorrupted() external nonReentrant onlyOwner {
if (outcome != PoolStates.Outcome.CORRUPTED) revert OutcomeNotSet();
if (!goodFaith) revert NotGoodFaithCorrupted();
if (block.timestamp <= corruptedClaimDeadline) revert ClaimWindowNotExpired();
// aderyn-fp-next-line(reentrancy-state-change)
uint256 amount = stakeToken.balanceOf(address(this));
if (amount == 0) revert NothingToSweep();
corruptedReserve = 0;
bountyClaimed = bountyEntitlement;
if (!claimsStarted) claimsStarted = true;
stakeToken.safeTransfer(recoveryAddress, amount);
emit UnclaimedCorruptedSwept(msg.sender, recoveryAddress, amount);
}
```
```diff
- function sweepUnclaimedBonus() external nonReentrant {
+ function sweepUnclaimedBonus() external nonReentrant onlyOwner {
if (outcome != PoolStates.Outcome.SURVIVED && outcome != PoolStates.Outcome.EXPIRED) {
revert OutcomeNotEligibleForSweep();
}
// Reserve principal still owed to non-claimers plus any bonus they're entitled to. When
// `riskWindowStart == 0` (no observable risk), `_bonusShare` returns 0 for everyone, so
// the bonus is not owed to any staker and the entire snapshotTotalBonus is sweepable.
uint256 reserved;
if (totalEligibleStake != 0) {
reserved = totalEligibleStake;
if (riskWindowStart != 0) {
reserved += snapshotTotalBonus - claimedBonus;
}
}
// aderyn-fp-next-line(reentrancy-state-change)
uint256 freeBalance = stakeToken.balanceOf(address(this));
uint256 amount = freeBalance > reserved ? freeBalance - reserved : 0;
if (amount == 0) revert NothingToSweep();
// Bonus is only unreserved when no staker is owed it (no risk window, or no stakers left).
// In that case the sweep removes it from the pool, so drop it from the live `totalBonus`
// too — keeping the accounting honest for any later re-snapshot. Clamp to `totalBonus` so
// swept donations/dust (never counted in it) can't over-decrement or underflow.
if (totalEligibleStake == 0 || riskWindowStart == 0) {
totalBonus -= amount <= totalBonus ? amount : totalBonus;
}
// Intentionally does NOT set claimsStarted. A direct-transfer donation of as little as 1
// wei would otherwise let anyone flip the flag post-flagOutcome and block the moderator's
// documented pre-claim re-flag window. Genuine reliance only comes from claim entrypoints.
stakeToken.safeTransfer(recoveryAddress, amount);
emit BonusSwept(msg.sender, recoveryAddress, amount);
}
```