StrategyPassiveManagerVelodrome::setRewardPool Does Not Remove ERC20 Token Allowances When rewardPool is Updated
Summary
StrategyPassiveManagerVelodrome provides ERC20 token allowances to the rewardPool, but these allowances are not removed when the rewardPool is updated.
Vulnerability Detail
When initialize is called, the rewardPool is assigned an address, and subsequently, the initialize function gives a maximum allowance to the rewardPool.
When the owner of the contract wants to update the rewardPool, the rewardPool has already been approved with the maximum value. This allows the contract to enter a state where the rewardPool is updated via setRewardPool, but the ERC20 token approvals given to the old rewardPool are not removed.
Allowances can only be removed by calling StrategyPassiveManagerVelodrome::panic. However, rewardPool can be changed at any time via the setRewardPool function.
function panic(uint256 _minAmount0, uint256 _minAmount1) public onlyManager {
_claimEarnings();
_removeLiquidity();
@>> _removeAllowances();
_pause();
(uint256 bal0, uint256 bal1) = balances();
if (bal0 < _minAmount0 || bal1 < _minAmount1) revert TooMuchSlippage();
}
Therefore, to remove the allowance, the entire protocol must be paused to remove the allowance from rewardPool.
This allows the contract to enter a state where rewardPool is updated via setRewardPool but the ERC20 token
approvals given to the old rewardPool are not removed.
Impact
The old rewardPool contract will continue to have ERC20 token approvals, allowing it to continue spending the protocol’s tokens when this is not intended, as the protocol has changed the rewardPool.
hunter_w3b
medium
StrategyPassiveManagerVelodrome::setRewardPool
Does Not Remove ERC20 Token Allowances When rewardPool is UpdatedSummary
StrategyPassiveManagerVelodrome provides ERC20 token allowances to the rewardPool, but these allowances are not removed when the rewardPool is updated.
Vulnerability Detail
When
initialize
is called, therewardPool
is assigned an address, and subsequently, the initialize function gives a maximum allowance to therewardPool
.When the owner of the contract wants to update the rewardPool, the rewardPool has already been approved with the maximum value. This allows the contract to enter a state where the rewardPool is updated via setRewardPool, but the ERC20 token approvals given to the old rewardPool are not removed.
Allowances can only be removed by calling
StrategyPassiveManagerVelodrome::panic
. However, rewardPool can be changed at any time via the setRewardPool function.Therefore, to remove the allowance, the entire protocol must be paused to remove the allowance from rewardPool.
This allows the contract to enter a state where rewardPool is updated via setRewardPool but the ERC20 token approvals given to the old rewardPool are not removed.
Impact
The old
rewardPool
contract will continue to have ERC20 token approvals, allowing it to continue spending the protocol’s tokens when this is not intended, as the protocol has changed the rewardPool.Code Snippet
https://github.com/sherlock-audit/2024-05-beefy-cowcentrated-liquidity-manager/blob/main/cowcentrated-contracts/contracts/strategies/velodrome/StrategyPassiveManagerVelodrome.sol#L776-L779
https://github.com/sherlock-audit/2024-05-beefy-cowcentrated-liquidity-manager/blob/main/cowcentrated-contracts/contracts/strategies/velodrome/StrategyPassiveManagerVelodrome.sol#L827C1-L832C6
https://github.com/sherlock-audit/2024-05-beefy-cowcentrated-liquidity-manager/blob/main/cowcentrated-contracts/contracts/strategies/velodrome/StrategyPassiveManagerVelodrome.sol#L173-L188
Tool used
Manual Review
Recommendation
This issue is correctly handled in the
setUnirouter
function.A similar approach should be implemented in the
setRewardPool
function.Duplicate of #3