The _harvestAndReport
function in the strategy contract fails to include the claimable WETH balance from the transmuter in its total assets calculation, leading to an undervaluation of the strategy's total assets during the period between token conversion and claim.
In the _harvestAndReport function, the total assets are calculated as:
However, this calculation misses the claimableBalance
from the transmuter, which represents WETH
that has been converted from alETH
but not yet claimed. This leads to underreporting of total assets during the conversion process.
The issue manifests in the following sequence:
When alETH
is deposited into the transmuter, it's counted in unexchangedBalance
When the transmuter converts alETH
to WETH
:
The alETH
is removed from unexchangedBalance
The WETH
appears in claimableBalance
Until claimed, this WETH is not counted in underlyingBalance
During this intermediate period, the converted WETH
exists only in claimableBalance
but is not included in _totalAssets
When tokens are converted, they leave unexchangedBalance
They don't appear in underlyingBalance
until claimed
During this intermediate period, they exist only in claimableBalance
By not including claimableBalance
, we're missing these converted but unclaimed tokens
Step-by-Step Analysis
Initial State:
Deposited Amount: The strategy deposits 100 alETH into the transmuter.
State in the transmuter:
unexchangedBalance = 100 alETH
claimableBalance = 0 WETH
Total Assets:
_totalAssets = unexchangedBalance + asset.balanceOf(address(this)) + underlyingBalance
Since no alETH or WETH is loose, we have:
_totalAssets = 100 alETH
Post Conversion by the Transmuter:
The transmuter converts 50 alETH into 50 WETH.
State in the transmuter:
unexchangedBalance = 50 alETH
claimableBalance = 50 WETH
Important Observation:
The conversion doesn’t change the total value held in the transmuter. The 50 alETH converted into WETH is still part of the strategy's assets, just in a different form.
If We Add claimableBalance:
New _totalAssets calculation:
_totalAssets = unexchangedBalance + claimableBalance + asset.balanceOf(address(this)) + underlyingBalance
Substituting values:
_totalAssets = 50 alETH + 50 WETH + 0 + 0 = 100 units
This Is Correct: Adding claimableBalance in this case reflects the actual total assets accurately.
If We Omit claimableBalance:
_totalAssets = unexchangedBalance + asset.balanceOf(address(this)) + underlyingBalance
Substituting values:
_totalAssets = 50 alETH + 0 + 0 = 50 units
This Is Incorrect: Omitting claimableBalance would underestimate the total assets held by the strategy because it ignores the WETH balance claimable from the transmuter.
Wrong _totalAssets
calculation. Undervaluation of the strategy's total assets between conversion and claim events
Manual Review
Update the _harvestAndReport
function to include the claimable balance in the total assets calculation:
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.