FoundrySolidityLayer 2
7.25 ETH
View results
Submission Details
Impact: medium
Likelihood: low
Invalid

Blacklisted claimant is permanently denied self-claim with no redirect

Root + Impact

Description

  • Describe the normal behavior in one or more sentences

  • Explain the specific issue or problem in one or more sentences

`claimSurvived()` pays the caller directly. `claimAttackerBounty()` pays the moderator-fixed `attacker`. Neither exposes a redirect target.
```solidity
if (!claimsStarted) claimsStarted = true;
stakeToken.safeTransfer(msg.sender, payout);
emit ClaimSurvived(msg.sender, userEligible, bonusShare);
```
```solidity
if (payout > 0) {
corruptedReserve -= payout;
if (!claimsStarted) claimsStarted = true;
stakeToken.safeTransfer(attacker, payout);
}
```
If the stake token uses a per-recipient denylist, a blacklisted staker or whitehat makes `safeTransfer` revert on every claim attempt. USDC is a plausible allowlisted stake token. The recipient can never receive their owed funds.
The pool itself recovers. After the 180-day windows, `sweepUnclaimedBonus` and `sweepUnclaimedCorrupted` route the stranded funds to `recoveryAddress`. The legitimate recipient loses the full value to the sponsor.
The factory allowlist and DESIGN.md only exclude tokens that freeze the pool's own balance and only warn about fee-on-transfer and rebasing. Per-recipient denylists are not covered, so this is not a design-accepted limitation.

Risk

Likelihood:

  • Reason 1 // Describe WHEN this will occur (avoid using "if" statements)

  • Reason 2

Impact:

  • Impact 1

  • Impact 2

Proof of Concept

Recommended Mitigation

Add a claimant-controlled redirect so a blacklisted recipient can route their payout to a clean address.
```diff
- function claimSurvived() external nonReentrant {
+ function claimSurvived(address recipient) external nonReentrant {
+ if (recipient == address(0)) revert InvalidAmount();
if (outcome != PoolStates.Outcome.SURVIVED) revert OutcomeNotSet();
if (hasClaimed[msg.sender]) revert InvalidAmount();
...
- stakeToken.safeTransfer(msg.sender, payout);
+ stakeToken.safeTransfer(recipient, payout);
emit ClaimSurvived(msg.sender, userEligible, bonusShare);
}
```
Apply the same redirect parameter to `claimAttackerBounty`, still gating eligibility on `msg.sender`. If a redirect is not added, document that stakers and whitehats must verify their address is not blacklisted by the stake token before depositing.
Updates

Lead Judging Commences

inallhonesty Lead Judge 22 days ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
inallhonesty Lead Judge 22 days ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!