-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gauge weight reduction via GaugeController.change_gauge_weight()
breaks global accounting, potentially causing both outsized reward distribution and loss of user rewards
#386
Comments
slope and bias math issue |
OpenCoreCH marked the issue as sponsor confirmed |
Very good catch, the math in the PoC seems valid to me. I have to think about how to fix this, one way might be to calculate the new t-intercept (based on the updated bias) and update the slope changes such that they take this into consideration. |
Just noticed that this and #206 probably should be duplicates. While they address the problem from a different view point, both point out the same underlying problem that |
Fixed in mkt-market/canto-neofinance-coordinator#4 As the warden mentioned, this is not that easy to fix because one gauge may have contributed to many different |
alcueca marked the issue as duplicate of #206 |
alcueca marked the issue as satisfactory |
Lines of code
https://github.com/code-423n4/2023-08-verwa/blob/main/src/GaugeController.sol#L185-L206
https://github.com/code-423n4/2023-08-verwa/blob/main/src/LendingLedger.sol#L145-L182
https://github.com/code-423n4/2023-08-verwa/blob/main/src/GaugeController.sol#L173-L183
https://github.com/code-423n4/2023-08-verwa/blob/main/src/GaugeController.sol#L146-L161
https://github.com/code-423n4/2023-08-verwa/blob/main/src/GaugeController.sol#L124-L132
Vulnerability details
Impact
Users may be given outsized rewards; therefore it is possible for
LendingLedger
's CANTO balance to drop below the reward amount of a valid user claim, in which case that claim will fail. Furthermore, gauge decay accounting is made inaccurate.Proof of Concept
Note the below code and inline comments for
GaugeController.change_gauge_weight()
:We see here that the weight (bias) is updated for both the global state and the individual gauge, while slope is not updated at all. Consider the following: let the equation$f(t) = b - mt$ represent the gauge's decay equation before the weight is reduced by some amount $k$ . (Note that $m$ , or slope, is always positive in the protocol's code.) After the weight is reduced by calling $f(t) = -k + b -mt$ . The slope is unchanged, but the t-axis intercept has changed from $t_{before} = b/m$ to $t_{after} = (-k + b)/m$ , the latter of which is a smaller value. Now, because global "slope changes" (slope values that should be subtracted from the global slope upon their decay equations equaling zero) are stored in the $t_1 - t_2$ during which the previous slope changes applied to the global state by user calls to
change_gauge_weight()
, the equation becomeschanges_sum
timestamp to slope mapping, which is not modified bychange_gauge_weight()
, there is a time period with length determined by the value ofvote_for_gauge_weights()
remain applied even though they should have been subtracted at the start of the aforementioned time period.This results in the global weight being less than the sum of the weights of all the individual gauges, which is an accounting error. Thus when
LendingLedger.claim()
callsGaugeController.gauge_relative_weight_write()
on the affected time period, the calculated relative weight will be inflated, andLendingLedger.claim()
will disburse outsized rewards. If the magnitude of the outsized rewards is large enough, then theLendingLedger
contract may lose enough funds to where theclaim()
function starts to fail. Furthermore, it's also possible for the global weight to reach zero before the weight of all gauges reaches zero, possibly resulting in active gauges receiving zero rewards.Note that this issue only applies once a gauge's weight has decayed to zero. This is guaranteed to occur at the next epoch if a gauge (having nonzero bias, nonzero slope, and t-intercept greater than the current time plus two weeks) is removed with
GaugeController.remove_gauge()
.Finally, reducing the weight of a gauge makes its decay equation inaccurate, as can be seen from the t-intercept changes discussed.
Tools Used
Manual Review
Recommended Mitigation Steps
This issue is difficult to fix without losing functionality in
change_gauge_weights()
due to the way that slope changes are calculated by the contract; the accounting logic in GaugeController may need to be changed significantly. The issue can be easily fixed by not allowing governance to reduce gauge weights.Assessed type
Math
The text was updated successfully, but these errors were encountered: