Closed code423n4 closed 2 years ago
The warden has identified a way for reward tokens to consistently be stuck in the contract.
Anytime the balance of tokens in the contract is less than the balance of the previous _calcRewardIntegral
the operation uint256 d_reward = bal - reward.remaining;
will underflow causing a revert.
This consistently will prevent users from claiming rewards until the contracts balance is greater than reward.remaining
With the information that I have I believe this will consistently happen after the first claim as the new balance of the contract will always be lower than the reward.remaining
(the previous balance of the contract)
Because the issue is consistent, and effectively breaks the contract, I believe High Severity to be appropriate
Dup of #199
Handle
kirk-baird
Vulnerability details
Impact
Incorrect accounting in
_calcRewardIntegral()
causes the rewards to be locked and will create an overflow that reverts for future calls.The impact is a significant loss in each rewards token in terms of value and
_calcRewardIntegral()
cannot be called again until we have transferred sufficient balance of each rewards token toConvexStakingWrapper
to account for the rewards already claimed.Proof of Concept
_calcRewardIntegral()
The core of this bug stems from setting the remaining rewards to the initial contract balance i.e.
reward.remaining = uint128(bal);
even after we have transferred the rewards to theclaimContract
.Example
Say we have
reward.token = tokenA
,tokenA.balanceOf(ConvexStakingWrapper) = 100
andrewards[pid][tokena]remaining = 0
then we do an event that calls_calcRewardIntegral()
:bal = 100
d_reward = 100 - 0 = 100
IERC20(reward.token).transfer(address(claimContract), d_reward);
occurs making thetokenA.balanceOf(ConvexStakingWrapper) = 0
reward.remaining = bal = 100
Now say the contract accrues 50 of
tokenA
as rewards sotokenA.balanceOf(ConvexStakingWrapper) = 50
and an event happens so do_calcRewardIntegral()
:bal = 50
uint256 d_reward = bal - reward.remaining;
is50 - 100 = -50
this is an overflow and revertsThus, we are unable to make future calls to this contract with this
pid
until the balance oftokenA
is greater than 100.Recommended Mitigation Steps
Consider, removing
reward.remaining
entirely. This will prevent future calls from overflowing when there are not sufficient rewards. However, this will no longer track the individual reward amounts for each (pid
,index
) pair.