Lucene search

K
code423n4Code4renaCODE423N4:2021-12-POOLTOGETHER-FINDINGS-ISSUES-74
HistoryDec 12, 2021 - 12:00 a.m.

Can claim epoch > 255 repeatedly due to bitshift truncation

2021-12-1200:00:00
Code4rena
github.com
6

Handle

gzeon

Vulnerability details

Can claim epoch > 255 repeatedly due to bitshift truncation

Impact

TwabRewards contract store user claimed reward in a _claimedEpochs bitmap.
<https://github.com/pooltogether/v4-periphery/blob/b520faea26bcf60371012f6cb246aa149abd3c7d/contracts/TwabRewards.sol#L371&gt;

    function _isClaimedEpoch(uint256 _userClaimedEpochs, uint256 _epochId)
        internal
        pure
        returns (bool)
    {
        return (_userClaimedEpochs &gt;&gt; _epochId) & uint256(1) == 1;
    }

even in solidity ^8.0.0, bitshifts are unsafe.
_userClaimedEpochs >> _epochId will truncate to 0 for any _epochId > 255.
<https://github.com/pooltogether/v4-periphery/blob/b520faea26bcf60371012f6cb246aa149abd3c7d/contracts/TwabRewards.sol#L350&gt;

    function _updateClaimedEpoch(uint256 _userClaimedEpochs, uint256 _epochId)
        internal
        pure
        returns (uint256)
    {
        return _userClaimedEpochs | (uint256(1) &lt;&lt; _epochId);
    }

uint256(1) << _epochId will also truncate to 0 for any _epochId > 255

Also note that while _numberOfEpochs is uint8, _epochIds is uint256 and there are no checks to make sure _epochId < _numberOfEpochs in claimRewards.

These combined allows an attacker to drain the promotion reward.

#Proof of Concept

When block.timestamp > startTimestamp + startTimestamp * 255, attacher can drain the remaining reward in the contract when block.timestamp > startTimestamp + startTimestamp * 255, for any value of _numberOfEpochs set in the promotion, by calling claimRewards with _epochIds = [256,256,256,…]

Recommended Mitigation Steps

  1. Make _epochIds uint8

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

All reactions