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:
for (uint256 i = 0; i < 50; i++) {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
Was this helpful?