Vulnerability Details
When increasing lock amount, it will increasing lock of user first before calculate new power:
function increase(uint256 amount) external nonReentrant whenNotPaused {
@> _lockState.increaseLock(msg.sender, amount);
_updateBoostState(msg.sender, locks[msg.sender].amount);
LockManager.Lock memory userLock = _lockState.locks[msg.sender];
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
@> userLock.amount + amount,
userLock.end
);
uint256 newPower = uint256(uint128(newBias));
_checkpointState.writeCheckpoint(msg.sender, newPower);
raacToken.safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender, newPower - balanceOf(msg.sender));
emit LockIncreased(msg.sender, amount);
}
In increaseLock function, locking amount is already increased, but it is increased again when calling calculateAndUpdatePower()function:
function increaseLock(
LockState storage state,
address user,
uint256 additionalAmount
) internal {
Lock storage lock = state.locks[user];
if (!lock.exists) revert LockNotFound();
if (lock.end <= block.timestamp) revert LockExpired();
if (lock.amount + additionalAmount > state.maxLockAmount) revert AmountExceedsLimit();
@> lock.amount += additionalAmount;
state.totalLocked += additionalAmount;
emit LockIncreased(user, additionalAmount);
}
Which lead to voting power is double-counted, more power is increased that it should be.
Recommendations
Update to:
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
- userLock.amount + amount,userLock.end);
+ userLock.amount);