Assessment reports>Nibiru>High findings>Large ,rewardSpread, due to miscalculation
Category: Coding Mistakes

Large rewardSpread due to miscalculation

High Severity
Medium Impact
Medium Likelihood

Description

The oracle module uses the rewardSpread to check if the price data from the validator is within an acceptable range from the chosen price.

func Tally(ballots types.ExchangeRateBallots, rewardBand sdk.Dec, validatorPerformances types.ValidatorPerformances) sdk.Dec {
	sort.Sort(ballots)

	weightedMedian := ballots.WeightedMedianWithAssertion()
	standardDeviation := ballots.StandardDeviation(weightedMedian)
	rewardSpread := weightedMedian.Mul(rewardBand.QuoInt64(2))

	if standardDeviation.GT(rewardSpread) {
		rewardSpread = standardDeviation
sum := sdk.ZeroDec()
for _, v := range pb {
	deviation := v.ExchangeRate.Sub(median)
	sum = sum.Add(deviation.Mul(deviation))
}

The standard deviation for the ballots is used directly as the rewardSpread if it is greater than the calculated rewardSpread.

if standardDeviation.GT(rewardSpread) {
	rewardSpread = standardDeviation

The StandardDeviation function, however, does not ignore negative votes. This could allow a malicious validator to submit abstaining votes with very large negative values and increase the rewardSpread.

Impact

Two malicious validators could collude to repeatedly submit prices outside the acceptable price band. They can do this without being slashed due to rewardSpread having a very high value. If eventually the attacker succeeds in publishing an invalid price, they could profit by liquidating strong postions through the perp module.

Recommendations

Abstained votes should be ignored when calculating the standard deviation for the ballots.

Remediation

This issue has been acknowledged by Nibiru, and a fix was implemented in commit 908571f0.

Zellic © 2024Back to top ↑