Platform: Code4rena
Start Date: 27/04/2023
Pot Size: $90,500 USDC
Total HM: 4
Participants: 43
Period: 7 days
Judge: GalloDaSballo
Id: 233
League: ETH
Rank: 29/43
Findings: 1
Award: $267.39
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: ABA
Also found by: 0xWaitress, 8olidity, ABA, MiloTruck, ToonVH, bughunter007, bytes032, juancito, rvierdiiev
267.3946 USDC - $267.39
slashQueuedWithdrawal
does not judge whether the withdraw
function of strategie
is suspended, but if the withdraw
is suspended, the code will stop when it runs to the bottom.
queuedWithdrawal.strategies[i].withdraw(recipient, tokens[i], queuedWithdrawal.shares[i]);
Because withdraw will judge whether to pause
function withdraw(address depositor, IERC20 token, uint256 amountShares) external virtual override onlyWhenNotPaused(PAUSED_WITHDRAWALS) onlyStrategyManager { require(token == underlyingToken, "StrategyBase.withdraw: Can only withdraw the strategy token"); // copy `totalShares` value to memory, prior to any decrease uint256 priorTotalShares = totalShares; require( amountShares <= priorTotalShares, "StrategyBase.withdraw: amountShares must be less than or equal to totalShares" ); // Calculate the value that `totalShares` will decrease to as a result of the withdrawal uint256 updatedTotalShares = priorTotalShares - amountShares; // check to avoid edge case where share rate can be massively inflated as a 'griefing' sort of attack require(updatedTotalShares >= MIN_NONZERO_TOTAL_SHARES || updatedTotalShares == 0, "StrategyBase.withdraw: updated totalShares amount would be nonzero but below MIN_NONZERO_TOTAL_SHARES"); // Actually decrease the `totalShares` value totalShares = updatedTotalShares; /** * @notice calculation of amountToSend *mirrors* `sharesToUnderlying(amountShares)`, but is different since the `totalShares` has already * been decremented. Specifically, notice how we use `priorTotalShares` here instead of `totalShares`. */ uint256 amountToSend; if (priorTotalShares == amountShares) { amountToSend = _tokenBalance(); } else { amountToSend = (_tokenBalance() * amountShares) / priorTotalShares; } underlyingToken.safeTransfer(depositor, amountToSend); }
function withdraw(address depositor, IERC20 token, uint256 amountShares) external virtual override onlyWhenNotPaused(PAUSED_WITHDRAWALS) onlyStrategyManager { require(token == underlyingToken, "StrategyBase.withdraw: Can only withdraw the strategy token"); // copy `totalShares` value to memory, prior to any decrease uint256 priorTotalShares = totalShares; require( amountShares <= priorTotalShares, "StrategyBase.withdraw: amountShares must be less than or equal to totalShares" ); // Calculate the value that `totalShares` will decrease to as a result of the withdrawal uint256 updatedTotalShares = priorTotalShares - amountShares; // check to avoid edge case where share rate can be massively inflated as a 'griefing' sort of attack require(updatedTotalShares >= MIN_NONZERO_TOTAL_SHARES || updatedTotalShares == 0, "StrategyBase.withdraw: updated totalShares amount would be nonzero but below MIN_NONZERO_TOTAL_SHARES"); // Actually decrease the `totalShares` value totalShares = updatedTotalShares; /** * @notice calculation of amountToSend *mirrors* `sharesToUnderlying(amountShares)`, but is different since the `totalShares` has already * been decremented. Specifically, notice how we use `priorTotalShares` here instead of `totalShares`. */ uint256 amountToSend; if (priorTotalShares == amountShares) { amountToSend = _tokenBalance(); } else { amountToSend = (_tokenBalance() * amountShares) / priorTotalShares; } underlyingToken.safeTransfer(depositor, amountToSend); }
vscode
Determine the withdraw state of the strategie
#0 - c4-pre-sort
2023-05-09T13:38:54Z
0xSorryNotSorry marked the issue as duplicate of #132
#1 - c4-judge
2023-05-31T18:41:07Z
GalloDaSballo marked the issue as partial-50
#2 - GalloDaSballo
2023-05-31T18:41:20Z
Valid, but report looks off in terms of explanation and POC