31399 - [SC - High] RewardDistributor claims can be DoSed through e...
Submitted on May 18th 2024 at 03:47:27 UTC by @jecikpo for Boost | Alchemix
Report ID: #31399
Report type: Smart Contract
Report severity: High
Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/RewardsDistributor.sol
Impacts:
Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
Permanent freezing of unclaimed royalties
Description
Brief/Intro
A malicious user can DoS (permanently lock) veALCX token owner's claims, by creating certain amount of userPointHistory
entries by calling VotingEscrow.depositFor()
on a target token multiple times.
Vulnerability Details
RewardDistributor
claims are calculated in the _claimable()
function. The calculation first involves finding the last userPoint
which was taken before the last weekCursor
. This is done through a for
loop that cycles from the last userEpoch
until it finds one. The loop can cycle up to 50 times:
hence if there are more userPoints
than 50 the _claimable()
function will return 0 as toDistribute
.
A malicious user can call the VotingEscrow.depositFor()
on the attacked veALCX token multiple times and can deposit minimum amount tokens (1 wei is enough), this way he can create the userPoints
that will DoS the function.
The solution would be to use binary search like in other places in the system.
Impact Details
Te veALCX token holder loses irreversibly all claims.
References
https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/RewardsDistributor.sol#L365
Proof of Concept
paste the following code into Minter.t.sol
:
We can see in the output that the tokenId1
that was attacked is returning 0 of claimable amount, while the tokenId2
returns the correct amount:
Last updated