The issue is applied differently based on how change_gauge_weight works.
An attacker can front-run change_gauge_weight transaction to manipulate slope which can result in reverts in the future in getting the gauge weight
Vote does not have effect before change_gauge_weight is called once.
function _get_weight(address _gauge_addr) private returns (uint256) {
uint256 t = time_weight[_gauge_addr];
if (t > 0) {
// time_weight[_gauge_addr] is updated here
...
} else {
return 0;
}
}
In _get_weight function, time_weight is updated to next_time when original value is set.
The time_weight for a gauge is initialized only through change_gauge_weight.
So when vote_for_gauge_weights is called before time_weight is initialized, _get_weight always return zero and time_weight also remains zero.
Thus, updating points_weight has no effect but changes_weight has effect.
function _get_weight(address _gauge_addr) private returns (uint256) {
uint256 t = time_weight[_gauge_addr];
if (t > 0) {
...
if (pt.bias > d_bias) {
pt.bias -= d_bias;
uint256 d_slope = changes_weight[_gauge_addr][t];
pt.slope -= d_slope; // <-- where issue happens
} else {
pt.bias = 0;
pt.slope = 0;
}
...
} else {
return 0;
}
}
Assuming there are some vote transactions that are front-run before change_gauge_weight is called, at some point in the future, _get_weight can be reverted on the line mentioned above.
Because, points_weight is not changed so pt.bias > d_bias will be true, but inside it, pt.slope will be smaller than d_slope since there had been changes made to changes_weight.
This will cause revert, once this is reverted, the GaugeController will not work anymore.
Manual Review
There can be more than one ways to resolve this issue as follows:
function add_gauge(address _gauge) external onlyGovernance { // @audit-ok
require(!isValidGauge[_gauge], "Gauge already exists");
_change_gauge_weight(_gauge, 0);
isValidGauge[_gauge] = true;
emit NewGauge(_gauge);
}
points_weight[_gauge_addr][next_time].bias = Math.max(old_weight_bias + new_bias, old_bias) - old_bias;
points_sum[next_time].bias = Math.max(old_sum_bias + new_bias, old_bias) - old_bias;
time_weight[_gauge_addr] = next_time; // <-- add this line
if (pt.bias > d_bias) {
pt.bias -= d_bias;
uint256 d_slope = changes_weight[_gauge_addr][t];
// update like this
if (pt.slope > d_slope) {
pt.slope -= d_slope;
} else {
pt.slope = 0;
}
} else {
pt.bias = 0;
pt.slope = 0;
}
Appling one of these would resolve the issue, but appling all of them would make it perfect!
DoS
The text was updated successfully, but these errors were encountered:
All reactions