DeFiFoundrySolidity
16,653 OP
View results
Submission Details
Severity: medium
Valid

Incorrect Inclusion of Underlying Token Balance in totalAssets Calculation

Summary

When users deposit alETH into the strategy, all alETH is transferred to the transmuter. Similarly, when users withdraw, any idle alETH in the strategy is used first, and additional alETH is freed from the transmuter if needed and also the claimAndSwap swaps all the claimed WETH for alETH. Based on this flow, there should never be an underlying token (WETH) balance in the strategy. Any WETH remaining in the strategy would be inaccessible and effectively stuck. Therefore, including the WETH balance in the totalAssets calculation is incorrect and could lead to overestimation of the strategy’s actual holdings.

Vulnerability Details

The _harvestAndReport function adds the underlying token (WETH) balance in the strategy contract to the total assets:

Found in https://github.com/Cyfrin/2024-12-alchemix/blob/82798f4891e41959eef866bd1d4cb44fc1e26439/src/StrategyArb.sol#L170 , https://github.com/Cyfrin/2024-12-alchemix/blob/82798f4891e41959eef866bd1d4cb44fc1e26439/src/StrategyMainnet.sol#L191 , https://github.com/Cyfrin/2024-12-alchemix/blob/82798f4891e41959eef866bd1d4cb44fc1e26439/src/StrategyOp.sol#L173

uint256 underlyingBalance = underlying.balanceOf(address(this));
_totalAssets = unexchanged + asset.balanceOf(address(this)) + underlyingBalance;

However, since the strategy’s flow ensures that all deposited assets are either in the transmuter (alETH) or in idle alETH within the contract, and the claimAndSwap function immediately swaps any WETH claimed for alETH before reinvesting it in the transmuter any WETH in the contract would be inaccessible and cannot contribute to the strategy’s functional holdings.

Impact

The totalAssets of the vault can be artificially inflated if WETH is sent directly to the strategy contract. This misrepresents the strategy’s actual holdings by including inaccessible WETH in the asset calculation. As a result, the PricePerShare (PPS) is overstated, causing users to incur losses. Specifically, the reported assets may exceed the strategy’s real value, leaving insufficient funds to fully honor withdrawal requests.

i.e
total usable asset = unexchanged + asset.balanceOf(address(this));
total asset = unexchanged + asset.balanceOf(address(this)) + underlyingBalance; PPS will be calculated based on this

Tools Used

Manual Review

Recommendations

Remove the underlyingBalance component when calculating totalAssets in _harvestAndReport.

uint256 unexchanged = transmuter.getUnexchangedBalance(address(this));
// NOTE : possible some dormant WETH that isn't swapped yet
uint256 underlyingBalance = underlying.balanceOf(address(this));
- _totalAssets = unexchanged + asset.balanceOf(address(this)) + underlyingBalance;
+ _totalAssets = unexchanged + asset.balanceOf(address(this));
Updates

Appeal created

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

_harvestAndReport should not contain the underlying balance to prevent donations having an impact.

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Dormant WETH is not properly treated

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.