You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Updating participation will break core functionalities
Summary
The updateParticipation function in the Launch contract incorrectly uses currencyAmount and userToken amounts, which are from different tokens, causing faulty accounting. This primarily impacts the cancellation of non-finalized launch group participations, making the core functionality of cancelling participation non-executable.
Root Cause
In the following code section of the updateParticipation function there is a "conceptual issue", that the currencyAmount (refund and additional) is used for setting and comparing with the userToken amount, which are the values from two different tokens.
if (prevInfo.currencyAmount > newCurrencyAmount) {
// Calculate refund amountuint256 refundCurrencyAmount = prevInfo.currencyAmount - newCurrencyAmount;
// Validate user new requested token amount is greater than min token amount per userif (userTokenAmount - refundCurrencyAmount < settings.minTokenAmountPerUser) {
revertMinUserTokenAllocationNotReached(
request.launchGroupId, request.userId, userTokenAmount, request.tokenAmount
);
}
// Update total tokens requested for user for launch group
userTokens.set(request.userId, userTokenAmount - refundCurrencyAmount);
// Transfer payment currency from contract to userIERC20(request.currency).safeTransfer(msg.sender, refundCurrencyAmount);
} elseif (newCurrencyAmount > prevInfo.currencyAmount) {
// Calculate additional payment amountuint256 additionalCurrencyAmount = newCurrencyAmount - prevInfo.currencyAmount;
// Validate user new requested token amount is within launch group user allocation limitsif (userTokenAmount + additionalCurrencyAmount > settings.maxTokenAmountPerUser) {
revertMaxUserTokenAllocationReached(
request.launchGroupId, request.userId, userTokenAmount, request.tokenAmount
);
}
// Update total tokens requested for user for launch group
userTokens.set(request.userId, userTokenAmount + additionalCurrencyAmount);
// Transfer payment currency from user to contractIERC20(request.currency).safeTransferFrom(msg.sender, address(this), additionalCurrencyAmount);
}
Specifically these lines, will mostly affect the cancelation of the participation which is core functionality of the lauchGroup with the finalizesAtParticipation parameter set to false:
State of the Launch contract: minAmountPerUser: 500 maxAmountPerUser: 3000 tokenPriceBps: 2
Attack path for cancelation:
User joins launchGroup with request of 800 tokenAmount, so the currency amount is 1600
User updates participation, so the request for the tokenAmount is 700 launchToken
Due to incorrect accounting, wrong value is accounted as userTokens value and instead of 700, it will be 600
If user tries to cancel participation it will fail, because userTokenAmout - info.tokenAmount will underflow, because userTokenAmount is 600 and info.tokenAmount is 700, and the cancelation will revert
Impact
If update of participation is done, the cancelation of the participation will fail, which is breaking core functionality, since it is intended by protocol, that the lauchGroups that are not finalized at participation should be cancelable (could loose currency tokens paid if get finalized, which will lead in getting launch tokens that user didn't want since he wanted to cancel participation). Furthermore, if the duration of the lauchGroup is long enough (longer than 1 week), then one more problem will arise, and that's that the users could have their funds locked for longer than a week.
PoC
No response
Mitigation
Consider using the request.tokenAmount in:
checks weather the token amount is greater or not then min and max amount
and when calling userTokens.set()
The text was updated successfully, but these errors were encountered:
Bumpy Tiger Hawk
Medium
Updating participation will break core functionalities
Summary
The updateParticipation function in the Launch contract incorrectly uses currencyAmount and userToken amounts, which are from different tokens, causing faulty accounting. This primarily impacts the cancellation of non-finalized launch group participations, making the core functionality of cancelling participation non-executable.
Root Cause
In the following code section of the
updateParticipation
function there is a "conceptual issue", that thecurrencyAmount
(refund and additional) is used for setting and comparing with theuserToken
amount, which are the values from two different tokens.Specifically these lines, will mostly affect the cancelation of the participation which is core functionality of the lauchGroup with the
finalizesAtParticipation
parameter set tofalse
:https://github.com/sherlock-audit/2025-02-rova/blob/53fb6d71d253676bfbd00926e8f217f40c62d8c5/rova-contracts/src/Launch.sol#L361
https://github.com/sherlock-audit/2025-02-rova/blob/53fb6d71d253676bfbd00926e8f217f40c62d8c5/rova-contracts/src/Launch.sol#L374
Internal Pre-conditions
For Cancelation revert:
TokenPriceBps
!= 1External Pre-conditions
/
Attack Path
State of the Launch contract:
minAmountPerUser
: 500maxAmountPerUser
: 3000tokenPriceBps
: 2Attack path for cancelation:
Impact
If update of participation is done, the cancelation of the participation will fail, which is breaking core functionality, since it is intended by protocol, that the lauchGroups that are not finalized at participation should be cancelable (could loose currency tokens paid if get finalized, which will lead in getting launch tokens that user didn't want since he wanted to cancel participation). Furthermore, if the duration of the lauchGroup is long enough (longer than 1 week), then one more problem will arise, and that's that the users could have their funds locked for longer than a week.
PoC
No response
Mitigation
Consider using the
request.tokenAmount
in:userTokens.set()
The text was updated successfully, but these errors were encountered: