shutdownPool marks shutdown successful even if it's not (i.e. withdrawAll() call reverted). As withdrawing logic expect that the pool in shutdown has already provided the funds, and make no additional attempts to retrieve them, user funds will be frozen until shutdown state be turned off for the pool.
Proof of Concept
In the case of unsuccessful withdrawAll the pool nevertheless will be marked as shutdown:
//pull from gauge if not shutdown
// if shutdown tokens will be in this contract
if (!pool.shutdown) {
IStaker(staker).withdraw(lptoken,gauge, _amount);
}
//some gauges claim rewards when withdrawing, stash them in a seperate contract until next claim
//do not call if shutdown since stashes wont have access
address stash = pool.stash;
if(stash != address(0) && !isShutdown && !pool.shutdown){
IStash(stash).stashRewards();
}
//return lp tokens
IERC20(lptoken).safeTransfer(_to, _amount);
This way user funds will be frozen as the system will not attempt to withdraw from the pool, while there will be no funds to transfer to user and _withdraw() will be reverting on L476 transfer call.
Lines of code
https://github.com/code-423n4/2022-05-aura/blob/4989a2077546a5394e3650bf3c224669a0f7e690/convex-platform/contracts/contracts/Booster.sol#L360-L365
Vulnerability details
shutdownPool marks shutdown successful even if it's not (i.e. withdrawAll() call reverted). As withdrawing logic expect that the pool in shutdown has already provided the funds, and make no additional attempts to retrieve them, user funds will be frozen until shutdown state be turned off for the pool.
Proof of Concept
In the case of unsuccessful withdrawAll the pool nevertheless will be marked as shutdown:
https://github.com/code-423n4/2022-05-aura/blob/4989a2077546a5394e3650bf3c224669a0f7e690/convex-platform/contracts/contracts/Booster.sol#L360-L365
It will block the withdrawals as there will be not enough funds to fulfill the claim:
https://github.com/code-423n4/2022-05-aura/blob/4989a2077546a5394e3650bf3c224669a0f7e690/convex-platform/contracts/contracts/Booster.sol#L462-L476
This way user funds will be frozen as the system will not attempt to withdraw from the pool, while there will be no funds to transfer to user and _withdraw() will be reverting on L476 transfer call.
Recommended Mitigation Steps
The shutdownPool logic can to be updated:
https://github.com/code-423n4/2022-05-aura/blob/4989a2077546a5394e3650bf3c224669a0f7e690/convex-platform/contracts/contracts/Booster.sol#L356-L369
Consider unifying the logic with shutdownSystem() and marking the pool shutdown only if withdraw was successful, for example: