Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

WETH Blacklist Griefing Attack on Reward Distribution System

Description

A malicious user can exploit WETH blacklisting to permanently disrupt the protocol's reward distribution mechanism, affecting all stakers in the vault and causing protocol-wide economic impact.

The vault's staking reward system has a critical vulnerability where a blacklisted WETH address can permanently lock their staking position and manipulate reward rates for all other users due to the requirement that users must claim all rewards before unstaking.

function unstake(uint128 vaultId, uint256 shares) external {
Distribution.Data storage wethRewardDistribution = vault.wethRewardDistribution;
// Get claimable rewards
UD60x18 amountToClaimX18 = vault.wethRewardDistribution.getActorValueChange(actorId).intoUD60x18();
// Critical check - prevents unstaking with unclaimed rewards
if (!amountToClaimX18.isZero()) revert Errors.UserHasPendingRewards(actorId, amountToClaimX18.intoUint256());
// ... rest of unstaking logic
}

Attack Scenario

  1. Attacker stakes a significant amount in the vault

  2. Accumulates WETH rewards over time

  3. Gets their address blacklisted by WETH

  4. Cannot claim rewards due to blacklist

  5. Cannot unstake due to non-zero rewards check

  6. Position remains locked, continuing to accumulate rewards

Impact

The attack triggers a systemic failure in the protocol's reward distribution mechanism, starting with the permanent locking of the attacker's staked position. This locked stake continues to participate in reward accumulation, creating an ever-widening distortion in the protocol's economics as rewards are continuously allocated to an irretrievable position. The impact cascades through the entire staking system, diluting rewards for legitimate participants and permanently skewing the protocol's distribution mathematics, with no existing mechanism to rectify or mitigate the compromised state. This architectural flaw effectively transforms a single locked position into a persistent drain on the protocol's reward efficiency.

Proof of Concept

contract RewardGriefingAttack {
function execute(address vault, uint128 vaultId) external {
// 1. Stake significant amount
vault.stake(vaultId, LARGE_AMOUNT);
// 2. Wait for rewards to accumulate
// time passes...
// 3. Get blacklisted on WETH
// external action...
// 4. Position now permanently locked
// - Cannot claim rewards (WETH transfer fails)
// - Cannot unstake (requires zero pending rewards)
}
}

Recommended Fixes

  1. Implement emergency unstake mechanism for blacklisted addresses

  2. Separate reward claiming from unstaking logic

  3. Add protocol admin function to handle stuck positions

  4. Consider implementing reward forfeiture mechanism for edge cases

function emergencyUnstake(uint128 vaultId, uint256 shares) external {
// Allow unstaking without claiming rewards
// Optionally forfeit or lock accumulated rewards
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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