stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: medium
Valid

Users on secondary chains might lose their funds and boosts if the `LinearBoostController` parameters are updated

Summary

The SDLPoolSecondary._executeQueuedLockUpdates function doesn't update startTime, duration, or amount and sets boostAmount to zero when boostAmountDiff < 0. While this behavior is fine in the case of unlocking, it could be dangerous when the LinearBoostController parameters, particularly maxLockingDuration and maxBoost, are updated. In such cases, boostAmountDiff might be negative, but the values of startTime, duration, and amount could change, and the new boostAmount might not necessarily be zero.

Vulnerability Details

  1. Let's consider the following parameters of the LinearBoostController:

maxBoost = 1
maxLockingDuration = 100
  1. Suppose a user has a lock with the following parameters:

amount = 100
startTime = timestamp #1
duration = 100
boostAmount = 100 * 1 * 100 / 100 = 100
  1. The owner updates the maxLockingDuration by setting it to 200

  2. The user increases their lock amount by 50 and increases the duration by 4, the adjusted lock parameters would be:

amount = 150
startTime = timestamp #2
duration = 104
boostAmount = 150 * 1 * 104 / 200 = 78
  1. Despite a negative boostAmountDiff, this is not an unlock case. The new values of amount, startTime, and duration are greater than before, and boostAmount remains positive. However, with the existing implementation, amount, startTime, and duration would not be updated, and boostAmount would be reset to zero.

As a result, the user loses 50 tokens in amount and will also receive fewer rewards due to the resetting of boostAmount. It's worth mentioning that the owner is not expected to act maliciously in this scenario. If the protocol ever decides to reduce the max boost or to increase the max locking period, this issue could arise.

Impact

Users might lose their funds and receive fewer rewards than they are entitled to if the parameters of the LinearBoostController are updated in an unfortunate manner.

Tools Used

Manual Review

Recommendations

Consider replacing the unlock condition:

boostAmountDiff < 0

with

curLockState.expiry == 0 && updateLockState.expiry > 0

Additionally, modify the code in the else block to accommodate negative totalDiff as follows:

int256 totalDiff = int256(baseAmountDiff + boostAmountDiff);
if (totalDiff > 0) {
effectiveBalances[_owner] += uint256(totalDiff);
totalEffectiveBalance += uint256(totalDiff);
} else if (totalDiff < 0) {
effectiveBalances[_owner] -= uint256(-1 * totalDiff);
totalEffectiveBalance -= uint256(-1 * totalDiff);
}
Updates

Lead Judging Commences

0kage Lead Judge
over 1 year ago
0kage Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

negative boostdiff

negative boost diff caused by lowering max boost or increasing max duration can trigger unlocks

Support

FAQs

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