Skip to content

Latest commit

 

History

History
100 lines (83 loc) · 6.11 KB

062.md

File metadata and controls

100 lines (83 loc) · 6.11 KB

Rough Brick Meerkat

Medium

Rewards computation affected by setting a new delegatee score eligibility threshold

Summary

The call to function setDelegateeScoreEligibilityThreshold in the BinaryEligibilityOracleEarningPowerCalculator contract should be accompanied by updating each and every Delegatee’s Score, eligibility and the earning power as all these are linked to the threshold. Not doing these causes the contract to keep running with the stale values of these thereby affecting the rewards also.

Vulnerability Detail

The call to function setDelegateeScoreEligibilityThreshold in the BinaryEligibilityOracleEarningPowerCalculator contract should be accompanied by updating each and every Delegatee’s Score, eligibility and the earning power as all these are linked to the threshold. Not doing these causes the contract to keep running with the stale values of these thereby affecting the rewards also.

The function setDelegateeScoreEligibilityThreshold can only be called by the contract owner to set a new delegatee score eligibility threshold.

  function _setDelegateeScoreEligibilityThreshold(uint256 _newDelegateeScoreEligibilityThreshold)
    internal
  {
    emit DelegateeEligibilityThresholdScoreSet(
      delegateeEligibilityThresholdScore, _newDelegateeScoreEligibilityThreshold
    );
    delegateeEligibilityThresholdScore = _newDelegateeScoreEligibilityThreshold;
  }
}

This value is used to determine the eligibility of the delegatee for the earning power. Only when the delegatee score is equal or above this threshold, the delegate will get 100% earning power, otherwise the earning power is ‘0’. i.e.

Earning power = staked amount if delegatee score >= delegateeEligibilityThresholdScore

and

Earning power = 0 if delegatee score < delegateeEligibilityThresholdScore

Refer https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/BinaryEligibilityOracleEarningPowerCalculator.sol#L130-L137

  function getEarningPower(uint256 _amountStaked, address, /* _staker */ address _delegatee)
    external
    view
    returns (uint256)
  {
    if (_isOracleStale() || isOraclePaused) return _amountStaked;
    return _isDelegateeEligible(_delegatee) ? _amountStaked : 0;
  }

and https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/BinaryEligibilityOracleEarningPowerCalculator.sol#L282-L284

  function _isDelegateeEligible(address _delegatee) internal view returns (bool) {
    return delegateeScores[_delegatee] >= delegateeEligibilityThresholdScore;
  }

The earning power of the delegate and the totalEarningPower are used in the reward calculations as well. Refer, for example, https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/GovernanceStaker.sol#L303-L308

  function rewardPerTokenAccumulated() public view virtual returns (uint256) {
    if (totalEarningPower == 0) return rewardPerTokenAccumulatedCheckpoint;


    return rewardPerTokenAccumulatedCheckpoint
      + (scaledRewardRate * (lastTimeRewardDistributed() - lastCheckpointTime)) / totalEarningPower;
  }

and https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/GovernanceStaker.sol#L522-L525

  function _scaledUnclaimedReward(Deposit storage deposit) internal view virtual returns (uint256) {
    return deposit.scaledUnclaimedRewardCheckpoint
      + (deposit.earningPower * (rewardPerTokenAccumulated() - deposit.rewardPerTokenCheckpoint));
  }

Impact

Assume the case where delegateeEligibilityThresholdScore = 300 eth; a. Number of stakers with staked amount 70 eth = 500; Total amount 35000 eth b. Number of stakers with staked amount 150 eth = 250; Total amount 37500 eth c. Number of stakers with staked amount 225 eth = 100; Total amount 22500 eth d. Number of stakers with staked amount 350 eth = 600; Total amount 210000 eth e. Number of stakers with staked amount 500 eth = 300; Total amount 150000 eth

Under this condition(not using the scalefactors), eventhough totalStaked = 455000 eth, totalEarningPower = 360000 as only the stakes at ‘d’ and ‘e’ qualify for the earning power. For the stakes at a, b and c, earning power = 0.

If the delegateeEligibilityThresholdScore, which is presently 300 eth is altered to 200 eth or 400 eth, it will affect the earning power of some of these stakes, and consequently the rewards due.

In the cases where the delegateeEligibilityThresholdScore is reduced, Bumper(s) may call function bumpEarningPower in the GovernanceStaker contract and collect fees for it. Alternatively, the stakers themselves have to call the function updateDelegateeScore in the BinaryEligibilityOracleEarningPowerCalculator.sol to update their earning power. The stakers who become ineligible when the delegateeEligibilityThresholdScore is increased, will not take any action as it impacts them negatively.

The process can be easily automated in the contract with fair deal to every staker in the event of either increase or decrease of the delegateeEligibilityThresholdScore.

Code Snippet

https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/BinaryEligibilityOracleEarningPowerCalculator.sol#L325-L333 https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/BinaryEligibilityOracleEarningPowerCalculator.sol#L130-L137 https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/BinaryEligibilityOracleEarningPowerCalculator.sol#L282-L284 https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/GovernanceStaker.sol#L303-L308 https://github.com/sherlock-audit/2024-11-tally/blob/b125d1f2b52170a3789b1060a52fc6609e6e2262/staker/src/GovernanceStaker.sol#L522-L525

Tool used

Manual Review

Recommendation

The call to function setDelegateeScoreEligibilityThreshold should be accompanied by updating each and every Delegatee’s Score, eligibility and the earning power as all these are linked to the threshold.