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

Miscalculation of _totalAsset in the _harvestAndReport function due to omission of exchanged balance

Summary

The _totalAssets calculated and returned by the _harvestAndReport internal function is flawed because the unexchanged balance returned by the transmuter only represents the assets not yet converted by the transmuter, ignoring the already converted assets. This leads to an underestimation of the strategy’s total assets.

Vulnerability Details

The _harvestAndReport internal function calculates the total amount of assets the strategy's contract has both idle(not invested) and not idle assets and returns _totalAssets which should be "A trusted and accurate account for the total amount of 'asset' the strategy currently holds including idle funds.". It is calculated by the summing the total assets held in the strategy contract, the total underlying asset held in the strategy contract and the amount of unexchanged balance the strategy contract has in the transmuter contract.

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 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;

The transmuter.getUnexchangedBalance() function only reflects the portion of assets still pending conversion by the transmuter contract. It does not include the value of assets that the transmuter has already converted into their underlying token or any rewards earned through its operations. Consequently, the _totalAssets value calculated by _harvestAndReport omits a significant portion of the strategy’s holdings, resulting in an inaccurate report of the strategy’s total assets.

Impact

The value returned by the _harvestAndReport internal function is used to update the total assets of the strategy, which directly influences the calculation of the strategy’s PricePerShare (PPS). Due to the underestimation of total assets (excluding converted assets in the transmuter), the calculated PPS is lower than it should be. This discrepancy leads to financial losses for users, as it undervalues their share of the strategy during deposits or withdrawals.

Tools Used

Manual Review

Recommendations

Add the amount of exchanged assets and the rewards gotten from the transmuter to the calculation of the _totalAssets.
This can be done by adding either the transmuter.getExchangedBalance or the transmuter.getClaimableBalance(converted to asset(alETH)) to the calculation.

uint256 unexchanged = transmuter.getUnexchangedBalance(address(this));
+ uint256 unexchanged = transmuter.getExchangedBalance(address(this)); //this includes the exchanged assets and reward gotten
// NOTE : possible some dormant WETH that isn't swapped yet
uint256 underlyingBalance = underlying.balanceOf(address(this));
_totalAssets = unexchanged + asset.balanceOf(address(this)) + underlyingBalance;
Updates

Appeal created

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
_frolic Submitter
10 months ago
inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect accounting in `_harvestAndReport` claimable should be included

Support

FAQs

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