31080 - [SC - Insight] DoS in startCooldown when users want start cool...
Submitted on May 12th 2024 at 11:24:32 UTC by @Lastc0de for Boost | Alchemix
Report ID: #31080
Report type: Smart Contract
Report severity: Insight
Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol
Impacts:
Permanent freezing of unclaimed yield
Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
Temporary freezing of funds for 12 hours
Description
Brief/Intro
There will be a one-epoch cooldown
period between unlocked tokens and being able to claim them to the user’s wallet. Locked tokens can become eligible for unlocks by burning Flux tokens. When the user wants to withdraw his/here locked tokens, he/she must start the cooldDown
mechanism before withdrawing, otherwise he will not be able to withdraw.
Activating this process is possible in two ways:
1- lock period is expired
2- lock period is not expired
There is a vulnerability in model 2 that allows a malicious user to freeze the activation of this process for a short or long time for users who want to use the second method ( Denial-of-Service).
Vulnerability Details
Vulnerable contract is
VotingEscrow.sol
:
https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol
Vulnerable function is
startCooldown()
: https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L778C1-L804C6
When a user want withdraw his/here locked amounts before do that should start coold down process. Above we can see the function that activates this process. When a user who wish to unlock their veALCX early, should burn Flux Tokens this means that should buy Flux Token of other users
Deep dive
AUDIT-1 For this, the
VotingEscrow.sol
first calculates Amount of FLUX required toragequit
by calling theamountToRagequit()
function: https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L345C1-L356C6
AUDIT-1-A In the first line of this function, the amount of flux earned in one epoch is obtained by calling the
claimableFlux
function: https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L377C1-L385C6
AUDIT-1-A-a This line calculate and return Amount of flux claimable is percent of the balance
as you can see this function calculate returned value by percent of the balance so by deposit for a
tokenId
can manipulate this value.
We can do this by calling the depositFor()
function: https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L667C1-L678C1
but what is the problem?
So we go to the beginning of the report to see AUDIT-2
:
AUDIT-2 :
require(IFluxToken(FLUX).balanceOf(msg.sender) >= fluxToRagequit, "insufficient FLUX balance");
If the balance of the Flux Token for user is less than the calculated value meaning fluxToRagequit
, the user cannot call this function for a while, so the user must increase the balance of Flux tokens in his wallet, and this is only possible by buying tokens from other users.
Secnario
For example, Bob wants to withdraw his tokens before the lock time done.
1- Bob knows for do this should buy 5 Flux Token
2- Bob buyed 5 Flux Token
3- Alex knows Bob Want withdraw his locked tokens (Ex:front-running)
4- Alex before Bob make call depositFor() - for Bob tokenId with small amount
5- Bob cant start coold down because he does not have enough tokens for this
6- Bob should buy more Flux Token
7- A malicious user can do this for a long time and prevent the withdrawal of other users' tokens
Impact Details
Attacker can Freeze this function for users so users for short -or long time cant withdraw his/here locked tokens
References
https://alchemixfi.medium.com/vealcx-update-272e8900ac5a
Proof of Concept
1- Add this function in VotingEscrow.t.sol
file :
2- Runing test
Last updated