function _decrementWeightUntilFree(address user, uint256 weight) internal {
uint256 userFreeWeight = balanceOf(user) - getUserWeight[user];
// early return if already free
if (userFreeWeight >= weight) return;
// cache totals for batch updates
uint256 userFreed;
uint256 totalFreed;
// Loop through all user gauges, live and deprecated
address[] memory gaugeList = _userGauges[user].values();
// Free gauges until through entire list or under weight
uint256 size = gaugeList.length;
for (
uint256 i = 0;
i < size && (userFreeWeight + userFreed) < weight;
) {
address gauge = gaugeList[i];
uint256 userGaugeWeight = getUserGaugeWeight[user][gauge];
if (userGaugeWeight != 0) {
userFreed += userGaugeWeight;
_decrementGaugeWeight(user, gauge, userGaugeWeight);
// If the gauge is live (not deprecated), include its weight in the total to remove
if (!_deprecatedGauges.contains(gauge)) {
totalTypeWeight[gaugeType[gauge]] -= userGaugeWeight;
totalFreed += userGaugeWeight;
}
@> //@audit
unchecked {
++i;
}
}
}
totalWeight -= totalFreed;
}
As seen, in the loop of function, the position of ++i is wrong, this is cause whenever userGaugeWeight == 0 the i is not incremented which would lead to a infinite loop
Impact
Since the position of ++i is wrong, this could lead to an infinite loop when the if condition is met since the i isn't going to be incremented.
Recommended Mitigation Steps
Apply these changes:
function _decrementWeightUntilFree(address user, uint256 weight) internal {
uint256 userFreeWeight = balanceOf(user) - getUserWeight[user];
// early return if already free
if (userFreeWeight >= weight) return;
// cache totals for batch updates
uint256 userFreed;
uint256 totalFreed;
// Loop through all user gauges, live and deprecated
address[] memory gaugeList = _userGauges[user].values();
// Free gauges until through entire list or under weight
uint256 size = gaugeList.length;
for (
uint256 i = 0;
i < size && (userFreeWeight + userFreed) < weight;
) {
address gauge = gaugeList[i];
uint256 userGaugeWeight = getUserGaugeWeight[user][gauge];
if (userGaugeWeight != 0) {
userFreed += userGaugeWeight;
_decrementGaugeWeight(user, gauge, userGaugeWeight);
// If the gauge is live (not deprecated), include its weight in the total to remove
if (!_deprecatedGauges.contains(gauge)) {
totalTypeWeight[gaugeType[gauge]] -= userGaugeWeight;
totalFreed += userGaugeWeight;
}
- unchecked {
- ++i;
- }
}
+ unchecked {
+ ++i;
+ }
}
totalWeight -= totalFreed;
}
Lines of code
https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/2376d9af792584e3d15ec9c32578daa33bb56b43/src/tokens/ERC20Gauges.sol#L500-L539
Vulnerability details
Proof of Concept
Take a look at ERC20Gauges.sol#L500-L539
As seen, in the loop of function, the position of
++i
is wrong, this is cause wheneveruserGaugeWeight == 0
thei
is not incremented which would lead to a infinite loopImpact
Since the position of
++i
is wrong, this could lead to an infinite loop when theif
condition is met since thei
isn't going to be incremented.Recommended Mitigation Steps
Apply these changes:
Assessed type
Loop