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

Incorrect calculation of totalAssets using _harvestAndReport() in StrategyMainnet.sol and Incomplete Implementaion of certain parts

Summary:

The issue arises because the _totalAssets calculation does not incorporate the claimable balance, leading to an incomplete representation of the strategy's total assets.

Additionally, the logic within the if blocks are commented and the logic inside the second if condition seems to be incomplete as it uses the function _swapUnderlyingToAsset(underlying.balanceOf(address(this))); which is nowhere to be found in StrategyMainnet.sol , further impacting the function's intended behavior.

Vulnerability Details:

The _harvestAndReport function is a critical internal function meant to harvest rewards, redeploy idle funds, and provide an accurate accounting of the total assets held by the strategy.

Additionally, the logic within the second if block appears to be incomplete, further impacting the function's intended behavior. This part is commented by the developer.

function _harvestAndReport()
internal
override
returns (uint256 _totalAssets)
{
@> uint256 claimable = transmuter.getClaimableBalance(address(this));
@> if (claimable > 0) {
@> // transmuter.claim(claimable, address(this));
}
@> // NOTE : we can do this in harvest or can do seperately in tend
@> // if (underlying.balanceOf(address(this)) > 0) {
@> // _swapUnderlyingToAsset(underlying.balanceOf(address(this)));
// }
uint256 unexchanged = transmuter.getUnexchangedBalance(address(this));
// NOTE : possible some dormant WETH that isn't swapped yet (although we can restrict to only claim & swap in one tx)
uint256 underlyingBalance = underlying.balanceOf(address(this));
_totalAssets = unexchanged + asset.balanceOf(address(this)) + underlyingBalance;
}

So, in the above function we can see that claimable is calculated using:

uint256 claimable = transmuter.getClaimableBalance(address(this));

This value represents the amount of the underlying asset (e.g., WETH) that can be claimed from the transmuter. Here comes the first issue the affects the calculation of _totalAssets, the subsequent logic to actually claim this balance is commented out, rendering the claimable balance calculation effectively useless:

@> if (claimable > 0) {
@> // transmuter.claim(claimable, address(this));
}

Following the claimable balance logic, the function checks the underlying balance and attempts to swap it to the asset (e.g., alETH). The swap logic is also commented out:

@> // NOTE : we can do this in harvest or can do seperately in tend
@> // if (underlying.balanceOf(address(this)) > 0) {
@> // _swapUnderlyingToAsset(underlying.balanceOf(address(this)));

NOTE: We can see the swap is happening using _swapUnderlyingToAsset(underlying.balanceOf(address(this))); . There no function in the whole StrategyMainnet.sol contract with this name. That's why I think either its not completely implemented or having broken logic.

If this logic had been enabled, the process would work as follows:

  • First, the transmuter.claim would have been executed, increasing the underlying asset (WETH) balance by the claimable amount.

  • Then, the swap function would convert any idle WETH into alETH, increasing the asset balance.

However, since both the claim and swap operations are commented out, the contract is not utilizing its claimable WETH nor converting idle WETH into the desired asset.

Next, unexchangedBalance is calculated using:

uint256 unexchanged = transmuter.getUnexchangedBalance(address(this));

This value represents the amount of synthetic asset (alETH) that has been deposited into the transmuter but has not been exchanged for the underlying asset (WETH).

Next, underlyingBalance is calculated using:

uint256 underlyingBalance = underlying.balanceOf(address(this));

Finally, its getting the _totalAssets

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

So, here we can see the _totalAssets are being calculated without taking claimable balance into account. As it stands, the function underrepresents the actual total assets by omitting any potential increase from the claimable assets.

Impact:

Incorrect calculation of the _totalAssets, The total assets value will be underreported since it does not reflect the full amount of assets held by the strategy, including any claimable balance.

Since the strategy relies on accurate total assets for profit and loss accounting, not including claimable funds means the strategy's performance is inaccurately reported. This can impact performance tracking, accounting, and the calculation of profits/losses.

Recommended Mitigations:

  • Define proper logic for calculating _totalAssets , by adding claimable balance also.

  • Write the appropriate logic inside the if blocks

Updates

Appeal created

inallhonesty Lead Judge 8 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.