Summary
The _clampWeights()
calculates the weights incorrectly.
Vulnerability Details
In _clampWeights()
, it normalizes the weights that the sum is ONE
and each weight is between absoluteMin
and absoluteMax
.
function _clampWeights(
int256[] memory _weights,
int256 _absoluteWeightGuardRail
) internal pure returns (int256[] memory) {
unchecked {
uint weightLength = _weights.length;
if (weightLength == 1) {
return _weights;
}
int256 absoluteMin = _absoluteWeightGuardRail;
int256 absoluteMax = ONE -
(PRBMathSD59x18.fromInt(int256(_weights.length - 1)).mul(_absoluteWeightGuardRail));
int256 sumRemainerWeight = ONE;
int256 sumOtherWeights;
for (uint i; i < weightLength; ++i) {
if (_weights[i] < absoluteMin) {
_weights[i] = absoluteMin;
sumRemainerWeight -= absoluteMin;
} else if (_weights[i] > absoluteMax) {
_weights[i] = absoluteMax;
sumOtherWeights += absoluteMax;
}
}
if (sumOtherWeights != 0) {
int256 proportionalRemainder = sumRemainerWeight.div(sumOtherWeights);
for (uint i; i < weightLength; ++i) {
if (_weights[i] != absoluteMin) {
_weights[i] = _weights[i].mul(proportionalRemainder);
}
}
}
}
return _weights;
}
But while calculating sumOtherWeights
, it's not updated when the weight is between absoluteMin
and absoluteMax
.
So sumOtherWeights
will be smaller than the expected sum. (sum of all elements except for the min weights)
After applying the proporation, the weight sum will be larger than ONE
.
Impact
The _weights
will be calculated incorrectly in _clampWeights()
.
Recommendations
Recommend modifying like this.
for (uint i; i < weightLength; ++i) {
if (_weights[i] < absoluteMin) {
_weights[i] = absoluteMin;
sumRemainerWeight -= absoluteMin;
} else if (_weights[i] > absoluteMax) {
_weights[i] = absoluteMax;
sumOtherWeights += absoluteMax;
}
+ else {
+ sumOtherWeights += _weights[i];
+ }
}