Lucene search

K
code423n4Code4renaCODE423N4:2023-02-MALT-FINDINGS-ISSUES-6
HistoryFeb 18, 2023 - 12:00 a.m.

LinearDistributor.declareReward: previouslyVested may update incorrectly, which will cause some rewards to be lost

2023-02-1800:00:00
Code4rena
github.com
3
lineardistributor
reward loss
netvest
balance
mitigation

Lines of code

Vulnerability details

Impact

In LinearDistributor.declareReward , distributed represents the reward to distribute and is calculated using netVest(currentlyVested - previouslyVested).
At the same time, distributed cannot exceed balance, which means that if balance < linearBondedValue * netVest / vestingBondedValue, part of the rewards in netVest will be lost.

    uint256 netVest = currentlyVested - previouslyVested;
    uint256 netTime = block.timestamp - previouslyVestedTimestamp;

    if (netVest == 0 || vestingBondedValue == 0) {
      return;
    }

    uint256 linearBondedValue = rewardMine.valueOfBonded();

    uint256 distributed = (linearBondedValue * netVest) / vestingBondedValue;
    uint256 balance = collateralToken.balanceOf(address(this));

    if (distributed &gt; balance) {
      distributed = balance;
    }

At the end of the function, previouslyVested is directly assigned to currentlyVested instead of using the Vested adjusted according to distributed, which means that the previously lost rewards will also be skipped in the next distribution.

    previouslyVested = currentlyVested;
    previouslyVestedTimestamp = block.timestamp;

Also, in the next distribution, bufferRequirement will be small because distributed is small, so it may increase the number of forfeits.

    if (netTime &lt; buf) {
      bufferRequirement = (distributed * buf * 10000) / netTime / 10000;
    } else {
      bufferRequirement = distributed;
    }

    if (balance &gt; bufferRequirement) {
      // We have more than the buffer required. Forfeit the rest
      uint256 net = balance - bufferRequirement;
      _forfeit(net);
    }

#Proof of Concept

Tools Used

None

Recommended Mitigation Steps

Consider adapting previouslyVested based on distributed

    uint256 linearBondedValue = rewardMine.valueOfBonded();

    uint256 distributed = (linearBondedValue * netVest) / vestingBondedValue;
    uint256 balance = collateralToken.balanceOf(address(this));

    if (distributed &gt; balance) {
      distributed = balance;
+    currentlyVested = distributed * vestingBondedValue / linearBondedValue + previouslyVested;
    }  

The text was updated successfully, but these errors were encountered:

All reactions