gzeon
TwabRewards contract store user claimed reward in a _claimedEpochs bitmap.
<https://github.com/pooltogether/v4-periphery/blob/b520faea26bcf60371012f6cb246aa149abd3c7d/contracts/TwabRewards.sol#L371>
function _isClaimedEpoch(uint256 _userClaimedEpochs, uint256 _epochId)
internal
pure
returns (bool)
{
return (_userClaimedEpochs >> _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>
function _updateClaimedEpoch(uint256 _userClaimedEpochs, uint256 _epochId)
internal
pure
returns (uint256)
{
return _userClaimedEpochs | (uint256(1) << _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.
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,…]
The text was updated successfully, but these errors were encountered:
All reactions