code-423n4/2023-06-lybra-findings

Incorrect use of `token.decimals()` leads to error in rewards calculation and distribution

code423n4 opened this issue · 2 comments

Lines of code

https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/ProtocolRewardsPool.sol#L209-L211
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/ProtocolRewardsPool.sol#L235-L236

Vulnerability details

token.decimals() is used for scaling up and scaling down amounts instead of 10 ** token.decimals(). So instead of scaling, it messes up all calculations.

Impact

There are two impacts related to this issue:

  • Users receive much less rewards than they should via ProtocolRewardsPool::getReward().
  • ProtocolRewardsPool::notifyRewardAmount() hugely increases the reward per token stored when external stablecoins are notified as rewards.

Proof of Concept

token.decimals() is used for scaling up and scaling down amounts instead of 10 ** token.decimals(). This leads to calculation with huge errors. For example, if the stable token has 18 decimals, it would translate to total = amount * 18 vs total = amount * 1e18.

In getReward(), it is used to calculate the tokenAmount of rewards that the user will receive. In this case token.decimals() is much lower than 10 ** token.decimals(), so they will receive an insignificant amount of rewards:

    ERC20 token = ERC20(configurator.stableToken());
    uint256 tokenAmount = (reward - eUSDShare - peUSDBalance) * token.decimals() / 1e18;
    token.transfer(msg.sender, tokenAmount);

ProtocolRewardsPool.sol#L209-L211

In the case of notifyRewardAmount(), it calculates the rewardPerTokenStored that will be later used for distributing rewards. Here, it divides by token.decimals(). This means it will divide by a very small number, leading to a huge result:

    ERC20 token = ERC20(configurator.stableToken());
    rewardPerTokenStored = rewardPerTokenStored + (amount * 1e36 / token.decimals()) / totalStaked();

ProtocolRewardsPool.sol#L235-L236

Tools Used

Manual Review

Recommended Mitigation Steps

Escale amounts using 10 ** token.decimals() instead of token.decimals().

Assessed type

Math

JeffCX marked the issue as duplicate of #501

0xean marked the issue as satisfactory