EgisSecurity - StrategyPassiveManagerVelodrome.sol#setRewardPool() - When changing `rewardPool`, fees accumulated for the current `rewardPool` will go to the new `rewardPooll` #112
StrategyPassiveManagerVelodrome.sol#setRewardPool() - When changing rewardPool, fees accumulated for the current rewardPool will go to the new rewardPooll
Summary
StrategyPassiveManagerVelodrome.sol#setRewardPool() - When changing rewardPool, fees accumulated for the current rewardPool will go to the new rewardPooll
Vulnerability Detail
The protocol "harvests" the VELO fees, through harvest.
function _harvest(address _callFeeRecipient) private {
// Claim rewards from gauge
_claimEarnings();
// Charge fees for Beefy and send them to the appropriate addresses, charge fees to accrued state fee amounts.
(uint256 feeLeft) = _chargeFees(_callFeeRecipient, fees);
// Reset state fees to 0.
fees = 0;
// Notify rewards with our velo.
IRewardPool(rewardPool).notifyRewardAmount(output, feeLeft, 1 days);
// Log the last time we claimed fees.
lastHarvest = block.timestamp;
// Log the fees post Beefy fees.
emit Harvest(feeLeft);
}
We call notifyRewardAmount on the rewardPool which will then pull the output tokens out of the strategy.
It is possible to change the rewardPool, through setRewardPool.
You'll notice that the function only changes the rewardPool and nothing else. This will lead to the case, where there are already accumulated fees that are supposed to go the current rewardPool, but setRewardPool is changed, which means next time harvest is called, the fees will go to the new rewardPool, which technically hasn't earned them.
Example:
There are 100 output tokens that are ready to be harvested and are supposed to go to rewardPoolA.
setRewardPool is called and now the rewardPool is rewardPoolB.
When harvest is called, all the fees will go to rewardPoolB instead of rewardPoolA.
EgisSecurity
medium
StrategyPassiveManagerVelodrome.sol#setRewardPool() - When changing
rewardPool
, fees accumulated for the currentrewardPool
will go to the newrewardPooll
Summary
StrategyPassiveManagerVelodrome.sol#setRewardPool() - When changing
rewardPool
, fees accumulated for the currentrewardPool
will go to the newrewardPooll
Vulnerability Detail
The protocol "harvests" the VELO fees, through
harvest
.We call
notifyRewardAmount
on therewardPool
which will then pull theoutput
tokens out of the strategy.It is possible to change the
rewardPool
, throughsetRewardPool
.You'll notice that the function only changes the
rewardPool
and nothing else. This will lead to the case, where there are already accumulated fees that are supposed to go the currentrewardPool
, butsetRewardPool
is changed, which means next timeharvest
is called, the fees will go to the newrewardPool
, which technically hasn't earned them.Example:
output
tokens that are ready to be harvested and are supposed to go torewardPoolA
.setRewardPool
is called and now therewardPool
isrewardPoolB
.harvest
is called, all the fees will go torewardPoolB
instead ofrewardPoolA
.Impact
Fees won't be correctly distributed.
Code Snippet
https://github.com/sherlock-audit/2024-05-beefy-cowcentrated-liquidity-manager/blob/42ef5f0eac1bc954e888cf5bfb85cbf24c08ec76/cowcentrated-contracts/contracts/strategies/velodrome/StrategyPassiveManagerVelodrome.sol#L776-L779
Tool used
Manual Review
Recommendation
Call
harvest
insidesetRewardPool
prior to changing it.