xanoutas/solidity-security-findings huggingface dataset:
If an isolated borrower/bidder is blacklisted by the debt token, risk of DOS liquidation / auction of the corresponding loan
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/IsolateLogic.sol#L262
https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/IsolateLogic.sol#L444


# Vulnerability details

## Impact
If an isolated borrower/bidder is blacklisted by the debt token, of DOS liquidation/auction of the corresponding loan.

## Proof of Concept
If a debt asset has a blacklisting feature (e.g. USDC), and an isolated borrower/bidder is blacklisted by the asset token, isolated liquidation /auction of the corresponding loan can be DOSsed.

When a user is blacklisted by an erc20 token, the asset cannot be transferred in or out of the blacklisted user’s account.

(1) A bidder is blacklisted after they placed the bid for an isolated loan auction through IsolateLogic::executeIsolateAuction.

When the next bidder outbids by calling IsolateLogic::executeIsolateAuction, the previous bidder’s bid amount is returned. Because previous bidder is blacklisted after placing the bid, `VaultLogic.erc20TransferOutBidAmount(debtAssetData, vars.oldLastBidder, vars.oldBidAmount)` will revert the auction tx. At this point, no one can bid on the loan.
```solidity
//src/libraries/logic/IsolateLogic.sol

  function executeIsolateAuction(InputTypes.ExecuteIsolateAuctionParams memory params) internal {
...
      // transfer last bid amount to previous bidder from escrow
      if ((vars.oldLastBidder != address(0)) && (vars.oldBidAmount > 0)) {
        VaultLogic.erc20TransferOutBidAmount(debtAssetData, vars.oldLastBidder, vars.oldBidAmount);
      }
...
```
(https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/IsolateLogic.sol#L262)

(2) The borrower is blacklisted by the debt token.

After the auction ends, when the liquidator calls `executeIsolateLiquidate()`, if the last bid amount is greater than total debt, the extra amount (last bid amount - total debt) has to be transferred to the borrower in the current implementation.
```solidity
//src/libraries/logic/IsolateLogic.sol

  function executeIsolateLiquidate(InputTypes.ExecuteIsolateLiquidateParams memory params) internal {
...
      // transfer remain amount to borrower
      if (vars.remainBidAmounts[vars.nidx] > 0) {
        VaultLogic.erc20TransferOutBidAmount(debtAssetData, tokenData.owner, vars.remainBidAmounts[vars.nidx]);
      }
...
```
(https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/IsolateLogic.sol#L444)

However, `VaultLogic.erc20TransferOutBidAmount(debtAssetData, tokenData.owner, vars.remainBidAmounts[vars.nidx])` will revert due to the original borrower (tokenData.owner) is blacklisted.

## Tools Used

Manual

## Recommended Mitigation Steps
In the isolate auction or liquidation flow, consider using try-catch block to handle `VaultLogic.erc20TransferOutBidAmount`.


## Ass
Unhandled request invalidation by the owner of Etherfi will lead to stuck debt
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/etherfi-protocol/smart-contracts/blob/master/src/WithdrawRequestNFT.sol#L182


# Vulnerability details

## Impact

The `owner` of Etherfi has the ability to invalidate withdrawal requests, which will DoS `YieldEthStakingEtherfi::protocolClaimWithdraw()` without ever repaying the debt. Additionally, Etherfi has a mechanism to manually claim the invalidated withdrawal, which will leave the withdraw request in a DoSed state in `YieldEthStakingEtherfi`.

## Proof of Concept

`WithdrawRequestNFT::claimWithdraw()` from Etherfi [checks](https://github.com/etherfi-protocol/smart-contracts/blob/master/src/WithdrawRequestNFT.sol#L94) that the request is valid. The owner of `WithdrawRequestNFT` may [invalidate](https://github.com/etherfi-protocol/smart-contracts/blob/master/src/WithdrawRequestNFT.sol#L174) the request at any time and claim it for [itself](https://github.com/etherfi-protocol/smart-contracts/blob/master/src/WithdrawRequestNFT.sol#L135).

Thus, as withdrawals in `YieldEthStakingEtherfi` can not be canceled and there is no way to handle invalidated withdrawals, the debt from the nft will never be repaid if the owner claims the nft for itself. If the owner validates the request later, there will still be a period of unknown duration during which it's not possible to repay the debt.

## Tools Used

Vscode

Foundry

## Recommended Mitigation Steps

Create a mechanism to handle invalidated withdrawals or withdrawals that have been claimed by the owner.


## Assessed type

Other
totalUnstakeFine collected will be locked in the staking contract due to no methods of fine transfer
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/yield/YieldStakingBase.sol#L336


# Vulnerability details

## Impact
`totalUnstakeFine` collected will be locked in the staking contract due to no methods of fine transfer.

## Proof of Concept
When the user’s health factor exceeds the threshold when unstaked, ustakeFine will be charged and recorded in both `sd.unstakeFine` and `totalUnstakeFine` denominated in the underlying asset. When the user `repay`, they will have to cover the debt amount plus sd.unstakeFine.

The issue is there are currently no methods to transfer or withdraw the accumulated unstakeFine in the staking contract, resulting in totalUnstakedFine locked.
```solidity
//src/yield/YieldStakingBase.sol

  function _unstake(uint32 poolId, address nft, uint256 tokenId, uint256 unstakeFine) internal virtual {
...
    // sender must be bot or nft owner
    if (msg.sender == botAdmin) {
      require(unstakeFine <= nc.maxUnstakeFine, Errors.YIELD_ETH_EXCEED_MAX_FINE);

      uint256 hf = calculateHealthFactor(nft, nc, sd);
      require(hf < nc.unstakeHeathFactor, Errors.YIELD_ETH_HEATH_FACTOR_TOO_HIGH);

      sd.unstakeFine = unstakeFine;
|>    totalUnstakeFine += unstakeFine;
    }
...
```
(https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/yield/YieldStakingBase.sol#L336)

Note that so far there is only `emergenEtherTransfer` method in child contracts(e.g. YieldEthStakingEtherFi.sol) to rescue ETH if sent by mistake. 

## Tools Used

Manual

## Recommended Mitigation Steps

Add a poolAdmin method to transfer out totalUnstakeFine.


## Assessed type

Other
Unstake fine in `YieldStakingBase` is stuck
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/main/src/yield/YieldStakingBase.sol#L335-L336
https://github.com/code-423n4/2024-07-benddao/blob/main/src/yield/YieldStakingBase.sol#L407-L426


# Vulnerability details

## Impact
Stuck unstake fine in `YieldStakingBase` that can not be retrieved.

## Proof of Concept

In `YieldStakingBase::unstake()` an unstake fine is [charged](https://github.com/code-423n4/2024-07-benddao/blob/main/src/yield/YieldStakingBase.sol#L335-L336) if the call is performed by the `botAdmin` and the health factor is below the minimum.

In `YieldStakingBase::repay()`, the funds are withdrawn from the external integration, the debt is repaid to the `pool` and any excess or leftover amount is pulled/pushed to the `nftOwner`. However, the unstake fine is never dealt with and stays in the `YieldStakingBase` contract forever.

## Tools Used

Vscode

Foundry

## Recommended Mitigation Steps

Handle the unstake fines by adding a function to claim them.


## Assessed type

Other
`YieldStakingBase::repay()` only allows the nft owner to repay, leading to forever accruing debt
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/main/src/yield/YieldStakingBase.sol#L417-L419


# Vulnerability details

## Impact

The yield borrowed from the protocol's `pool` may never be returned in case the `owner` of the nft never repays the debt via `YieldStakingBase::repay()`. This will keep accumulating yield debt in the pool without ever repaying it.

## Proof of Concept

In `YieldStakingBase::repay()`, in case the `vars.claimedYield` exceeds the `vars.nftDebtWithFine`, it transfers from the `nftOwner` the necessary assets. However, the owner of the nft may never call this function, so the debt will still forever borrowed, which could be harmful for BendDAO. Although the owner is incentivized to call it and recover the nft (as long as the value of the nft exceeds the yield excess required), it may still not do it for some reason (high gas prices or similar). In these cases it should be possible for a `bot` to seize the nft and repay the debt of the pool so that debt stops accruing.

## Tools Used

Vscode

Foundry

## Recommended Mitigation Steps

Allow the nft to be seized below a certain threshold, for example by starting an auction.


## Assessed type

Other
crossLiquidateERC721() specified debtAsset, borrower may not have any borrowing, resulting in a worse debt situation for borrower
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/LiquidationLogic.sol#L164


# Vulnerability details

## Vulnerability details

When executing `crossLiquidateERC721()` we can arbitrarily specify `debtAsset`.
This method does not restrict this `debtAsset` to whether the `borrower` is currently borrowing or not

`remainDebtToLiquidate == actualDebtToLiquidate` does not reduce any debt, but can be executed successfully.
```solidity
  function executeCrossLiquidateERC721(
    InputTypes.ExecuteCrossLiquidateERC721Params memory params
  ) internal returns (uint256, uint256) {
...
    vars.remainDebtToLiquidate = _repayUserERC20Debt(
      poolData,
      debtAssetData,
      params.borrower,
      vars.actualDebtToLiquidate
    );
@>   //@audit remainDebtToLiquidate == actualDebtToLiquidate can success , Debt has not been reduced
    if (vars.remainDebtToLiquidate > 0) {
```


Example:
1. bob deposit nft_1 and borrow btc 100
   - assest[btc].userScaledCrossBorrow[bob]=100
3. when bob can be liquidated
4. alice call crossLiquidateERC721(NFT_1, debtAsset = dogecoin)
   - remainDebtToLiquidate = _repayUserERC20Debt(dogecoin) == 100
   - assest[btc].userScaledCrossBorrow[bob]=100   ======>  (debt not change)
   - assest[dogecoin].userScaledCrossSupply[bob]  = 100   =======>(new supply)


In this case, the bob's debt is not reduced, but because `dogecoin` has a lower `liquidationThreshold`, it may result in the bob's debt being less healthy, leading to another liquidation

## Impact

Maliciously lowering a user's `healthFactor`, leading to secondary liquidation

Or the newly added collateral is not the `token` that the user wants to borrow, increasing additional risk

## Recommended Mitigation

Check that `debtAsset` reduce is not zero.

```diff
  function executeCrossLiquidateERC721(
    InputTypes.ExecuteCrossLiquidateERC721Params memory params
  ) internal returns (uint256, uint256) {
...
    vars.remainDebtToLiquidate = _repayUserERC20Debt(
      poolData,
      debtAssetData,
      params.borrower,
      vars.actualDebtToLiquidate
    );
+   require(vars.remainDebtToLiquidate < vars.actualDebtToLiquidate , "debtAsset invalid");
```


## Assessed type

Context
_calculateDebtAmountFromERC721Collateral() collateralPrice miscalculation
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/LiquidationLogic.sol#L489


# Vulnerability details

## Vulnerability details

When executing `crossLiquidateERC721()`, we will calculate the value of NFT `collateralPrice` by `_calculateDebtAmountFromERC721Collateral()`

`crossLiquidateERC721()` -> `_calculateDebtAmountFromERC721Collateral()`
```solidity
  function _calculateDebtAmountFromERC721Collateral(
    DataTypes.AssetData storage collateralAssetData,
    DataTypes.AssetData storage debtAssetData,
    InputTypes.ExecuteCrossLiquidateERC721Params memory params,
    LiquidateERC721LocalVars memory liqVars,
    IPriceOracleGetter oracle
  ) internal view returns (uint256, uint256) {
    CalculateDebtAmountFromERC721CollateralLocalVars memory vars;

    // in this function, all prices are in base currency

    vars.collateralPrice = oracle.getAssetPrice(params.collateralAsset);
@>  vars.collateralBonusPrice = vars.collateralPrice.percentMul(
      PercentageMath.PERCENTAGE_FACTOR - collateralAssetData.liquidationBonus
    );

    vars.debtAssetUnit = 10 ** debtAssetData.underlyingDecimals;
    vars.debtAssetPrice = oracle.getAssetPrice(params.debtAsset);
..

```

Currently the formula `collateralBonusPrice = collateralPrice * ( 1 - liquidationBonus)` is used.
This is not correct, it should be: `collateralBonusPrice = collateralPrice / ( 1 + liquidationBonus)`.

Similar calculation, `_calculateAvailableERC20CollateralToLiquidate()`.
```solidity
  function _calculateAvailableERC20CollateralToLiquidate(
...
    if (vars.maxCollateralToLiquidate > userCollateralBalance) {
      vars.collateralAmount = userCollateralBalance;
      vars.debtAmountNeeded = ((vars.collateralAmount * vars.collateralPrice * vars.debtAssetUnit) /
        (vars.collateralAssetUnit * vars.debtAssetPrice)).percentDiv(
@>        PercentageMath.PERCENTAGE_FACTOR + collateralAssetData.liquidationBonus
        );

```
 
This ensures that `debtValue * (1 + liquidationBonus) = collateralValue`.

Example:
1000000 * (1 - 0.01) = 990000
1000000 / (1 + 0.01) = 990099

These two formulas are not equal

 ## Impact
collateralPrice miscalculation，Valuation may be too low

## Recommended Mitigation

```diff
  function _calculateDebtAmountFromERC721Collateral(
    DataTypes.AssetData storage collateralAssetData,
    DataTypes.AssetData storage debtAssetData,
    InputTypes.ExecuteCrossLiquidateERC721Params memory params,
    LiquidateERC721LocalVars memory liqVars,
    IPriceOracleGetter oracle
  ) internal view returns (uint256, uint256) {
    CalculateDebtAmountFromERC721CollateralLocalVars memory vars;

    // in this function, all prices are in base currency

    vars.collateralPrice = oracle.getAssetPrice(params.collateralAsset);


-   vars.collateralBonusPrice = vars.collateralPrice.percentMul(
-     PercentageMath.PERCENTAGE_FACTOR - collateralAssetData.liquidationBonus
+   vars.collateralBonusPrice = var
wrapNativeTokenInWallet() always reverts on Arbitrum
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/VaultLogic.sol#L789


# Vulnerability details

## Vulnerability details
`VaultLogic.wrapNativeTokenInWallet()` is used in a number of places
It's mainly used to store `msg.value` into `WETH` and then transfer it to `msg.sender`.
```solidity
  function wrapNativeTokenInWallet(address wrappedNativeToken, address user, uint256 amount) internal {
    require(amount > 0, Errors.INVALID_AMOUNT);

    IWETH(wrappedNativeToken).deposit{value: amount}();

@>  bool success = IWETH(wrappedNativeToken).transferFrom(address(this), user, amount);
    require(success, Errors.TOKEN_TRANSFER_FAILED);
  }
```

The token transfer is done using the transferFrom method. This works fine on most chains (Ethereum, Optimism, Polygon, BSC) which use the standard WETH9 contract that handles the case src == msg.sender:

```solidity
WETH9.sol
if (src != msg.sender && allowance[src][msg.sender] != uint(- 1)) {
            require(allowance[src][msg.sender] >= wad);
            allowance[src][msg.sender] -= wad;
        }
```

The problem is that the WETH implementation on Arbitrum uses [a different contract](https://arbiscan.io/address/0x8b194beae1d3e0788a1a35173978001acdfba668#code), and does not have this src == msg.sender handling.

c4  similar issue: https://github.com/code-423n4/2023-05-chainlink-findings/issues/593

## Impact

`wrapNativeTokenInWallet()` revert , `BVault/CrossLending... `Contracts that use this method don't execute correctly.

## Recommended Mitigation

```diff
  function wrapNativeTokenInWallet(address wrappedNativeToken, address user, uint256 amount) internal {
    require(amount > 0, Errors.INVALID_AMOUNT);

    IWETH(wrappedNativeToken).deposit{value: amount}();

-   bool success = IWETH(wrappedNativeToken).transferFrom(address(this), user, amount);
+   bool success = IWETH(wrappedNativeToken).transfer(user, amount);
    require(success, Errors.TOKEN_TRANSFER_FAILED);
  }
```


## Assessed type

Context
totalUnstakeFine can't be taken away
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/yield/YieldStakingBase.sol#L71


# Vulnerability details

## Vulnerability details
in `YieldStakingBase.sol`

`botAdmin` can perform `unstake(unstakeFine)` for forced liquidation
In this case, the user pays `unstakeFine` and is credited with `totalUnstakeFine`.
```solidity
  function _unstake(uint32 poolId, address nft, uint256 tokenId, uint256 unstakeFine) internal virtual {
...
    if (msg.sender == botAdmin) {
      require(unstakeFine <= nc.maxUnstakeFine, Errors.YIELD_ETH_EXCEED_MAX_FINE);

      uint256 hf = calculateHealthFactor(nft, nc, sd);
      require(hf < nc.unstakeHeathFactor, Errors.YIELD_ETH_HEATH_FACTOR_TOO_HIGH);

      sd.unstakeFine = unstakeFine;
@>    totalUnstakeFine += unstakeFine;
    }

  function _repay(uint32 poolId, address nft, uint256 tokenId) internal virtual {
...
    vars.nftDebt = _getNftDebtInUnderlyingAsset(sd);
@>  vars.nftDebtWithFine = vars.nftDebt + sd.unstakeFine;

    // compute repay value
    if (vars.claimedYield >= vars.nftDebtWithFine) {
      vars.remainAmount = vars.claimedYield - vars.nftDebtWithFine;
    } else {
      vars.extraAmount = vars.nftDebtWithFine - vars.claimedYield;
    }

    // transfer eth from sender
    if (vars.extraAmount > 0) {
      underlyingAsset.safeTransferFrom(vars.nftOwner, address(this), vars.extraAmount);
    }
```

But the contract doesn't provide a way to take away the `totalUnstakeFine`.
So this part of the `token` will be left in the contract

## Impact
The `totalUnstakeFine` token will be locked in the contract.

## Recommended Mitigation

Add a way to take away the `totalUnstakeFine`.


## Assessed type

Context
YieldEthStakingLido lacks a limit on the max stake amount, which may result in the unstake exceeding MAX_STETH_WITHDRAWAL_AMOUNT, resulting in the token not being retrieved.
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/yield/lido/YieldEthStakingLido.sol#L81


# Vulnerability details

## Vulnerability details
in `YieldEthStakingLido` 

The main processes are as follows:
1. stake() -> stEth balnace increase
2. unstake () -> unstETH.requestWithdrawals(allShares)
3. repay() -> unstETH.claimWithdrawal()

The issue is the second step, `unstETH` is with a maximum withdrawal limit: `MAX_STETH_WITHDRAWAL_AMOUNT`
```solidity
contract YieldEthStakingLido is YieldStakingBase {
...
  function protocolRequestWithdrawal(YieldStakeData storage sd) internal virtual override {
    IYieldAccount yieldAccount = IYieldAccount(yieldAccounts[msg.sender]);

    uint256[] memory requestAmounts = new uint256[](1);
    requestAmounts[0] = sd.withdrawAmount;
    bytes memory result = yieldAccount.execute(
      address(unstETH),
@>    abi.encodeWithSelector(IUnstETH.requestWithdrawals.selector, requestAmounts, address(yieldAccount))
    );
    uint256[] memory withdrawReqIds = abi.decode(result, (uint256[]));
    require(withdrawReqIds.length > 0 && withdrawReqIds[0] > 0, Errors.YIELD_ETH_WITHDRAW_FAILED);
    sd.withdrawReqId = withdrawReqIds[0];
  }
```

https://docs.lido.fi/contracts/withdrawal-queue-erc721/#requestwithdrawals
>each amount in _amounts must be greater than or equal to MIN_STETH_WITHDRAWAL_AMOUNT and lower than or equal to MAX_STETH_WITHDRAWAL_AMOUNT

current configuration:
https://github.com/lidofinance/lido-dao/blob/master/contracts/0.8.9/WithdrawalQueue.sol#L57
```solidity
    /// @notice maximum amount of stETH that is possible to withdraw by a single request
    /// Prevents accumulating too much funds per single request fulfillment in the future.
    /// @dev To withdraw larger amounts, it's recommended to split it to several requests
    uint256 public constant MAX_STETH_WITHDRAWAL_AMOUNT = 1000 * 1e18;
```

`lido` suggests that if it exceeds this value, it needs to be taken in batches, but `YieldEthStakingLido.sol` can only be taken at once!

So if the stake amount exceeds this value, it will not be possible to `unstake()` and the `token` will be locked in the contract

Assumption.
`leverageFactor = 50000 , eth price = $2500`.

Then as long as the value of the nft is greater than: `1000 * $2500 / 5 = $500,000` it will be possible to `stake()` more than `MAX_STETH_WITHDRAWAL_AMOUNT`.
After that, when the user performs an `unstake()` it will fail, causing the token to be locked.

## Impact

Excessive amount of stake will result in failure to `unstake()`.

## Recommended Mitigation

`YieldStakingBase` add  method `checkStakeAmount`
Each sub contract override implements its own maximum amount limit, `YieldEthStakingLido` suggests a maximum of `MAX_STETH_WITHDRAWAL_AMOUNT / 2`.


## Assessed type

Context
executeYieldBorrowERC20() checking yieldCap wrong
Audit: 2024-07-benddao-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-07-benddao/blob/117ef61967d4b318fc65170061c9577e674fffa1/src/libraries/logic/YieldLogic.sol#L51


# Vulnerability details

## Vulnerability details
in `executeYieldBorrowERC20()`
We will check whether `stakerAddr` exceeds `yieldCap`
```solidity
  function executeYieldBorrowERC20(InputTypes.ExecuteYieldBorrowERC20Params memory params) internal {
...
    ValidateLogic.validateYieldBorrowERC20(params, poolData, assetData, groupData);

@>  vars.totalSupply = VaultLogic.erc20GetTotalCrossSupply(assetData, groupData.borrowIndex);

    // check asset level yield cap limit
    vars.totalBorrow = VaultLogic.erc20GetTotalCrossBorrowInGroup(groupData, groupData.borrowIndex);
    require(
      (vars.totalBorrow + params.amount) <= vars.totalSupply.percentMul(assetData.yieldCap),
      Errors.YIELD_EXCEED_ASSET_CAP_LIMIT
    );

    // check staker level yield cap limit
    vars.stakerBorrow = VaultLogic.erc20GetUserCrossBorrowInGroup(groupData, vars.stakerAddr, groupData.borrowIndex);
    require(
      (vars.stakerBorrow + params.amount) <= vars.totalSupply.percentMul(ymData.yieldCap),
      Errors.YIELD_EXCEED_STAKER_CAP_LIMIT
    );
```

The code above, calculating `totalSupply` using `totalSupply = totalScaledCrossSupply * groupData.borrowIndex` to calculate `supply` is wrong!

The correct way to calculate `supply` is to use: `assetData.supplyIndex`.

## Impact

With an incorrect value for `totalSupply`, the check for `yieldCap` will be inaccurate, leading to a security risk

## Recommended Mitigation
```diff
  function executeYieldBorrowERC20(InputTypes.ExecuteYieldBorrowERC20Params memory params) internal {
...
    ValidateLogic.validateYieldBorrowERC20(params, poolData, assetData, groupData);

-   vars.totalSupply = VaultLogic.erc20GetTotalCrossSupply(assetData, groupData.borrowIndex);
+   vars.totalSupply = VaultLogic.erc20GetTotalCrossSupply(assetData, assetData.supplyIndex);

    // check asset level yield cap limit
    vars.totalBorrow = VaultLogic.erc20GetTotalCrossBorrowInGroup(groupData, groupData.borrowIndex);
```


## Assessed type

Context