code-423n4 / 2023-01-popcorn-findings

0 stars 0 forks source link

MultiStakingReward.sol assumes all RewardTokens are in 18 decimal places #800

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/utils/MultiRewardStaking.sol#L406

Vulnerability details

Impact

Calculation of accrued rewards will be affected.

Proof of Concept

The function _accrueRewards is called anytime rewards needs to be accrued. The variable supplyTokens is the total supply of the reward token. deltaIndex is calculated by taking the accrued * 10** decimals() / supplyTokens, and rounded down. decimals() calculates the decimals of the staking Token.

  function _accrueRewards(IERC20 _rewardToken, uint256 accrued) internal {
    uint256 supplyTokens = totalSupply();
    uint224 deltaIndex;
    if (supplyTokens != 0)
      deltaIndex = accrued.mulDiv(uint256(10**decimals()), supplyTokens, Math.Rounding.Down).safeCastTo224();

If the decimal places of the staking token and reward token is different, ie DAI (18 decimals) and USDC (6 decimals) for staking and reward respectivevly, then the deltaIndex will be calculated incorrectly. It should take the decimals of the reward token instead of the staking token.

    _name = string(abi.encodePacked("Staked ", IERC20Metadata(address(_stakingToken)).name()));
    _symbol = string(abi.encodePacked("pst-", IERC20Metadata(address(_stakingToken)).symbol()));
    _decimals = IERC20Metadata(address(_stakingToken)).decimals();

  function decimals() public view override(ERC20Upgradeable, IERC20Metadata) returns (uint8) {
    return _decimals;
  }

Tools Used

VSCode

Recommended Mitigation Steps

Calculate using the decimals of the rewardToken instead of the staking token.

  function _accrueRewards(IERC20 _rewardToken, uint256 accrued) internal {
    uint256 supplyTokens = totalSupply();
    uint224 deltaIndex;
    if (supplyTokens != 0)
-      deltaIndex = accrued.mulDiv(uint256(10**decimals()), supplyTokens, Math.Rounding.Down).safeCastTo224();
+     deltaIndex = accrued.mulDiv(uint256(10**IERC20Metadata(address(_rewardToken)).decimals()), supplyTokens, Math.Rounding.Down).safeCastTo224();
c4-sponsor commented 1 year ago

RedVeil marked the issue as sponsor confirmed

c4-judge commented 1 year ago

dmvt marked the issue as unsatisfactory: Insufficient quality