Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large _epochId value impacts rewards calculation #122

Closed
code423n4 opened this issue Dec 12, 2021 · 2 comments
Closed

Large _epochId value impacts rewards calculation #122

code423n4 opened this issue Dec 12, 2021 · 2 comments
Assignees
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate This issue or pull request already exists

Comments

@code423n4
Copy link
Contributor

Handle

sirhashalot

Vulnerability details

Impact

The _epochId value is a uint256 that can be provided by the user in the _epochIds array in the important claimRewards and getRewardsAmount functions. The epochId value should be between 0 and 255, as evidenced by the bit shifting of a uint256 type in the functions _updateClaimedEpoch and _isClaimedEpoch. However, while the epochId value will not be negative because it is an unsigned integer, the edge case of epochId > 255 is not handled well. A user may submit an epochId of 300, or 300000, which can result in the following unexpected situations:

  • In the _calculateRewardAmounts function, the _epochStartTimestamp may be greater than the _epochEndTimestamp (note that no casting overflow is required for this to occur, but a casting overflow in this same code is submitted as a separate finding)
  • The current code relies on getAverageBalanceBetween() function in the out of scope Ticket.sol contract to properly handle _epochStartTimestamp > _epochEndTimestamp
  • _isClaimedEpoch returns false for epochId values over 255
  • _userClaimedEpochs array in the _updateClaimedEpochs function would remain unchanged for epochId values over 256

In summary, the case of epochId > 255 results in unexpected edge cases which allow a user to manipulate the rewards calculation in unexpected ways, especially if further code modifications do not examine this edge case. Edge case complexity would be substantially reduced if epochId is required to be <= 255 in the TwabRewards.sol file.

Proof of Concept

Two external functions of TwabRewards.sol allow a user to provide epochId values.

  1. The claimRewards function:
    https://github.com/pooltogether/v4-periphery/blob/b520faea26bcf60371012f6cb246aa149abd3c7d/contracts/TwabRewards.sol#L162-L191
  2. The getRewards function:
    https://github.com/pooltogether/v4-periphery/blob/b520faea26bcf60371012f6cb246aa149abd3c7d/contracts/TwabRewards.sol#L209-L222

However, the _epochId value has cascading impact due to external function calls and the impact can extend to other pooltogether contracts. For example, the call flow for the claimRewards function is:
claimRewards() → _calculateRewardAmount() → Ticket.getAverageBalanceBetween (out of current scope)→ TwabLib.getAverageBalanceBetween (out of current scope)

Recommended Mitigation Steps

  • In the two for loops that iterate over the user provided _epochIds array, or in the _calculateRewardAmount() function, add the following bounds check for the epochId value:
    require(epochIds[index] <= 255);
  • Alternatively, a more gas-efficient solution is for the epochIds[] array to have type uint8, which inherently limits values to <= 255.
  • Another alternative is to add require(_epochEndTimestamp > _epochStartTimestamp); to line 299, next to the existing require statement and before the uint64 casting operations, to prevent this type of manipulation
@code423n4 code423n4 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Dec 12, 2021
code423n4 added a commit that referenced this issue Dec 12, 2021
@PierrickGT
Copy link
Member

This will be fixed in the following issue by casting _epochIds to uint8: #3

@PierrickGT
Copy link
Member

Duplicate of #3

@PierrickGT PierrickGT marked this as a duplicate of #3 Dec 13, 2021
@PierrickGT PierrickGT self-assigned this Dec 13, 2021
@PierrickGT PierrickGT added the duplicate This issue or pull request already exists label Dec 13, 2021
@dmvt dmvt added 3 (High Risk) Assets can be stolen/lost/compromised directly and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Jan 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

3 participants