Closed code423n4 closed 2 years ago
WatchPug
For ended promotions, _getCurrentEpochId() may return a epochId larger than numberOfEpochs.
_getCurrentEpochId()
epochId
numberOfEpochs
As a result, _getRemainingRewards() will revert at _promotion.numberOfEpochs - _getCurrentEpochId(_promotion).
_getRemainingRewards()
_promotion.numberOfEpochs - _getCurrentEpochId(_promotion)
https://github.com/pooltogether/v4-periphery/blob/0e94c54774a6fce29daf9cb23353208f80de63eb/contracts/TwabRewards.sol#L331-L336
function _getRemainingRewards(Promotion memory _promotion) internal view returns (uint256) { // _tokensPerEpoch * _numberOfEpochsLeft return _promotion.tokensPerEpoch * (_promotion.numberOfEpochs - _getCurrentEpochId(_promotion)); }
https://github.com/pooltogether/v4-periphery/blob/0e94c54774a6fce29daf9cb23353208f80de63eb/contracts/TwabRewards.sol#L276-L279
function _getCurrentEpochId(Promotion memory _promotion) internal view returns (uint256) { // elapsedTimestamp / epochDurationTimestamp return (block.timestamp - _promotion.startTimestamp) / _promotion.epochDuration; }
Consider checking if block.timestamp > _promotionEndTimestamp in getRemainingRewards() and return 0 for ended promotions.
block.timestamp > _promotionEndTimestamp
getRemainingRewards()
0
The promotion will be inactive, so it will revert before calculating the remaining rewards. For this reason, I have disputed the issue. Relevant code:
Agree with sponsor's explanation
Handle
WatchPug
Vulnerability details
For ended promotions,
_getCurrentEpochId()
may return aepochId
larger thannumberOfEpochs
.As a result,
_getRemainingRewards()
will revert at_promotion.numberOfEpochs - _getCurrentEpochId(_promotion)
.https://github.com/pooltogether/v4-periphery/blob/0e94c54774a6fce29daf9cb23353208f80de63eb/contracts/TwabRewards.sol#L331-L336
https://github.com/pooltogether/v4-periphery/blob/0e94c54774a6fce29daf9cb23353208f80de63eb/contracts/TwabRewards.sol#L276-L279
Recommendation
Consider checking if
block.timestamp > _promotionEndTimestamp
ingetRemainingRewards()
and return0
for ended promotions.