recoveryAddress via a single unconditional safeTransfer, with no pull-based fallback if that transfer can revert. If the stake token can blacklist addresses and recoveryAddress gets blacklisted, all CORRUPTED/bonus-sweep payouts revert and pool funds are frozen until the owner calls setRecoveryAddress to repoint — a temporary, owner-recoverable denial of service, not a fund loss.The protocol's compatibility statement supports "standard ERC20"; USDC/USDT are standard, non-fee,
non-rebasing tokens whose only non-vanilla behavior is an issuer-controlled blacklist. Blacklisting
of an address is a plausible, real-world token behavior that a token-accepting contract must tolerate.
The CORRUPTED resolution and both sweep helpers move the entire relevant balance to recoveryAddress
in a single push transfer. If that address is blacklisted by the token, the transfer reverts and the
resolution cannot complete.
recoveryAddress pattern appears insweepUnclaimedCorrupted (L468)sweepUnclaimedBonus (L506).Likelihood:
Low-to-medium. It requires (a) the pool's stake token to be a blacklistable token — very likely if
USDC/USDT are allowlisted — and (b) the specific recoveryAddress to be blacklisted, which is
uncommon but does happen (OFAC actions, compromised-address freezes). No attacker action is needed;
it is an availability/robustness gap rather than an exploit.
Impact:
Impact is a temporary freeze of funds, not a loss. Because recoveryAddress is owner-controlled
via setRecoveryAddress, the owner can repoint it to a non-blacklisted address and re-run the sweep,
so the funds are always recoverable. The blocked destination is the sponsor's own recovery target, so
the party inconvenienced is largely the sponsor themselves.
Create the next file `test/TestRecoveryBlacklistDoS.sol` paste the next file and run `forge test --mc MockBlacklistERC20`
Prefer a pull-over-push pattern for the recovery destination, or wrap the sweep so a blacklisted
destination does not brick the call. A minimal, low-risk mitigation is to document the owner's
obligation to keep recoveryAddress transfer-eligible and to expose the repoint as the sanctioned
remediation (already possible via setRecoveryAddress). A stronger fix converts the recovery payout
into a credit the recovery address pulls:
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.