As per the Yearn's documentation and the comments in the code, _harvestAndReport should return "A trusted and accurate account for the total amount of 'asset' the strategy currently holds including loose funds", but for all 3 strategies (mainnet, Op and Arb), the function returns the sum of all unexchanged tokens from the transmuter, the balance of asset for the strategy, and the balance of underlying for the strategy, corrupting the shares given to future depositors.
Code snippet from StrategyOp.sol
Note : I chose to pick the code from this strategy as it was the cleanest, but the other 2 strategies fundamentally implement the same logic.
_harvestAndReport is used when the keeper calls the report function to generate profit for vault's token holders. The profit calculation depends of the result value of _harvestAndReport (calculated at the beginning of the report function).
The code doesn't return only "'asset' the strategy currently holds", because while unexchanged + asset.balanceOf(address(this)) are the sum of withdrawable funds (alETH) in the transmuter + idle funds, underlyingBalance is the amount of idle WETH in the strategy, and the strategy withdrawable asset is only alETH.
If a user sends WETH to the strategy maliciously or by mistake, the accounting of profit will become wrong, because no WETH is ever withdrawable from the strategy.
Since the profit slowly unlocks over the maxProfitUnlockTime, a user who deposits straight after a report won't be impacted, but a user who deposits after the WETH is entirely accounted for profit will suffer the most disadvantage, as he receives less shares than other depositors for the same amount of alETH deposited, and will earn less yield for the future profits.
Also, while it isn't the root cause of the issue, the fact that WETH can't be removed from the strategy makes the issue worse than it could be, since the keeper can't withdraw the WETH before calling report, which would have been a possible mitigation of the problem.
Loss of yield profit for several users. Unfair advantage to users who deposit before the issue occurs.
Copy the following PoC in Operation.t.sol. Run with forge test --mt test_weth_harvest_report --fork-url $ETH_RPC_URL.
Have _harvestAndReport return only the sum of alETH available (like the availableWithdrawLimit does currently).
Also, adding a method to withdraw tokens in the strategy (except alETH) can be a good idea to avoid having WETH stuck here.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.