xanoutas/solidity-security-findings huggingface dataset:
Index Out-of-Bounds in exchangeRewardsForCompoundingWithIncentive
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmController.sol#L62-L73


# Vulnerability details

## Vulnerability details 

there is a vulnerability arise in the function exchangeRewardsForCompoundingWithIncentive contains  from the lack of bounds checking this is  after obtaining an index with _findIndex, the function aims to exchange reward tokens for compounding, but fails to ensure that the provided reward token (_rewardToken) exists within the childInfo.rewardTokens array. Consequently, if an invalid _rewardToken is passed one not present in the array, the function might attempt to access an out-of-bounds index in childInfo.reservedForCompound, and this leading to undefined behavior or a revert. This vulnerability exposes the contract to potential manipulation, causing unintended reverts or even enabling attackers to exploit logic based on the faulty assumption of valid index retrieval here is the vulnerable part :
```python 
 CompoundStruct memory childInfo = pendleChildCompoundInfo[
            _pendleMarket
        ];

        uint256 index = _findIndex(
            childInfo.rewardTokens,
            _rewardToken
        );

        if (childInfo.reservedForCompound[index] < _rewardAmount) {
            revert NotEnoughCompound();
        }
```

## Impact

an attacker can exploit this vulnerability and could allow him to disrupt the normal operation of the contract by causing transactions to revert unexpectedly. 
and in a worst-case scenario, if the contract state is manipulated just right before such a call, it could potentially lead to logic errors elsewhere in the contract.

## Proof of Concept
 i fuzz with a scenario and as result i get this :
```solidity 
Attempting to exchange 500 of tokenA in market1
Transferred 500 of tokenA to pendleChild1 for compounding

Attempting to exchange 1500 of tokenA in market1
Not enough compound

Attempting to exchange 2500 of tokenA in market1
Not enough compound

Attempting to exchange 500 of tokenB in market1
Transferred 500 of tokenB to pendleChild1 for compounding

Attempting to exchange 1500 of tokenB in market1
Transferred 1500 of tokenB to pendleChild1 for compounding

Attempting to exchange 2500 of tokenB in market1
Not enough compound

Attempting to exchange 500 of tokenC in market1
Index out of bounds for tokenC in market1

Attempting to exchange 1500 of tokenC in market1
Index out of bounds for tokenC in market1

Attempting to exchange 2500 of tokenC in market1
Index out of bounds for tokenC in market1
```
- For tokenA and tokenB,  are present in the market1's reward token list, the function behaves as expected when there are enough reserves for compounding. and  it correctly identifies when there is "Not enough compound" for the requested amount, demonstrating proper handling of existing tokens within bounds.
- For tokenC, which does not exist in market1's rewa
Lack of slippage control in `PendlePowerFarmToken` and wrong projection of share prices due to missing sync in `preview` functions
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmToken.sol#L334-L345
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmToken.sol#L443-L492


# Vulnerability details

## Impact

`PendlePowerFarmToken` does not implement slippage control for the deposit/withdraw functions. Other projection functions related to those like `previewMintShares()` also lack a supply sync, which can mislead the depositor in the case where there was a prior reward distribution.

## Proof of Concept

`PendlePowerFarmToken` is vulnerable to griefing through slippage (either intentional or unintentional). There are functions that allow the vault share holder to project the outcome of deposit and withdraw interactions. Those are:

- `previewMintShares()`
- `previewAmountWithdrawShares()`
- `previewBurnShares()`

The problem is that none performs a supply sync, so the amount the user will get from those may not correspond to the amount they will get after calling: `depositExactAmount()`, `withdrawExactAmount()`, or `withdrawExactShares()`.

The vulnerability arises only when a reward distribution has happened before the victim's call. The supply sync is handled from the following function:

```solidity
function _syncSupply()
    private
{
    uint256 additonalAssets = previewDistribution();

    if (additonalAssets == 0) {
        return;
    }

    underlyingLpAssetsCurrent += additonalAssets;
    totalLpAssetsToDistribute -= additonalAssets;
}
```

This is handled properly for the interaction functions but not for the preview ones. The supply should be synced in both places so the user can be more certain of the projected amount.

Here's, for instance, how the `depositExactAmount()` function looks:

```solidity
function depositExactAmount(
    uint256 _underlyingLpAssetAmount
)
    external
    syncSupply
    returns (
        uint256,
        uint256
    )
{
    if (_underlyingLpAssetAmount == 0) {
        revert ZeroAmount();
    }

    uint256 shares = previewMintShares(
        _underlyingLpAssetAmount,
        underlyingLpAssetsCurrent
    );

    if (shares == 0) {
        revert NotEnoughLpAssetsTransferred();
    }

    uint256 reducedShares = _applyMintFee(
        shares
    );

    uint256 feeShares = shares
        - reducedShares;

    if (feeShares == 0) {
        revert ZeroFee();
    }

    if (reducedShares == feeShares) {
        revert TooMuchFee();
    }

    _mint(
        msg.sender,
        reducedShares
    );

    _mint(
        PENDLE_POWER_FARM_CONTROLLER,
        feeShares
    );

    underlyingLpAssetsCurrent += _underlyingLpAssetAmount;

    _safeTransferFrom(
        UNDERLYING_PENDLE_MARKET,
        msg.sender,
        PENDLE_POWER_FARM_CONTROLLER,
        _underlyingLpAssetAmount
    );

    return (
        reducedShares,
        feeShares
    );
}
```

The `syncSupply` modifier i
Risk of Funds Getting Stuck if User's Address is Blacklisted
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L710-L745


# Vulnerability details

## Impact
From the Audit overview, `Wiselending.sol` interacts with several tokens such as USDC, USDT, WETH, etc.
"ERC20 in scope: WETH, WBTC, LINK, DAI, WstETH, sDAI, USDC, USDT, WISE and may others in the future. (Also corresponding Aave tokens if existing)"

But USDC/USDT addresses can get blacklisted.

For more insight, Centre, the issuer of USDC, has the right to block the transfer of USDC under certain conditions, such as to comply with US court orders or to protect the USDC network.[Read here](https://decrypt.co/35166/why-blacklisting-stablecoins-could-undermine-defi)

Similarly, Tether (USDT) has been known to blacklist addresses holding millions of dollars on the Ethereum network since November 2017. [Read here](https://decrypt.co/35166/why-blacklisting-stablecoins-could-undermine-defi)

Therefore, since the `WiseLending` interacts with UDSC & USDT, a user's `address(msg.sender)` from which ERC20 assets were deposited into the WiseLending contract can get blacklisted by the USDC or USDT administrators AND their funds become inaccessible and stuck within the WiseLending contract when the user wants to withdraw. This can result in a loss of funds for the affected user.



## Proof of Concept
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L710-L745

```solidity
 function withdrawExactAmount(
        uint256 _nftId,
        address _poolToken,
        uint256 _withdrawAmount
    )
        external
        syncPool(_poolToken)
        healthStateCheck(_nftId)
        returns (uint256)
    {
        uint256 withdrawShares = _handleWithdrawAmount(
            {
                _caller: msg.sender,
                _nftId: _nftId,
                _poolToken: _poolToken,
                _amount: _withdrawAmount,
                _onBehalf: false
            }
        );

        _validateNonZero(
            withdrawShares
        );

        _safeTransfer(
            _poolToken,
            msg.sender,
            _withdrawAmount
        );

        return withdrawShares;
    }
```

Scenario:
Alice deposits USDC/USDT to WiseLending contract (At the time which she's depositing, her usdc/usdt address has not been blacklisted yet). After some days/weeks, her address gets blacklisted due to some issues/breaking of rules. After some time, she decides to withdraw her tokens by calling the withdraw function but finds out that she has been blacklisted. The function will revert and she won't be able to withdraw because the `withdrawExactAmount()` function is supposed to send the tokens to the `msg.sender` which is the same `msg.sender` who initiated the deposit. Therefore, her funds are stuck. This results in a total Denial of Service.



## Tools Used

Manual review
https://decrypt.co/35166/why-blacklistin
missing acces control on initialize function PendlepowerFarmToken.sol
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmToken.sol#L682


# Vulnerability details

The [initialize function](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmToken.sol#L682) in the PendlePowerFarmToken.sol is called by the factory when a token is created, this is a normal behavior for factories. The problem is that this initialize function is not protected by access control.

```Solidity
file:/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmTokenFactory.sol

    function _clone(
        address _underlyingPendleMarket,
        string memory _tokenName,
        string memory _symbolName,
        uint16 _maxCardinality
    )
        private
        returns (address pendlePowerFarmTokenAddress)
    {
        bytes32 salt = keccak256(
            abi.encodePacked(
                _underlyingPendleMarket
            )
        );

        bytes20 targetBytes = bytes20(
            IMPLEMENTATION_TARGET
        );

        assembly {

            let clone := mload(0x40)

            mstore(
                clone,
                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
            )

            mstore(
                add(clone, 0x14),
                targetBytes
            )

            mstore(
                add(clone, 0x28),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
            )

            pendlePowerFarmTokenAddress := create2(
                0,
                clone,
                0x37,
                salt
            )
        }

        PendlePowerFarmToken(pendlePowerFarmTokenAddress).initialize(   <------
            _underlyingPendleMarket,
            PENDLE_POWER_FARM_CONTROLLER,
            _tokenName,
            _symbolName,
            _maxCardinality
        );
    }
```
[Link](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmTokenFactory.sol#L102)

## Impact
Attacker can reinitialize the tokens changing importan variables like _underlyingPendleMarket, _pendleController, uint16 _maxCardinality breaking the correct function of the protocol.

## Proof of Concept

Analyzing the initialize function you can see that has no access control and not any conditional that revert the call if the msg.sender is not the factory:

```Solidity
file: contracts/PowerFarms/PendlePowerFarmController/PendlePowerFarmToken.sol
 function initialize(
        address _underlyingPendleMarket,
        address _pendleController,
        string memory _tokenName,
        string memory _symbolName,
        uint16 _maxCardinality
    )
        external
    {
        if (address(PENDLE_MARKET) != address(0)) {
            revert A
Funds could be lost due to failure to check for approval
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L939
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L1055


# Vulnerability details

## Impact
The functions **borrowOnBehalfExactAmount** and **withdrawOnBehalfExactShares** don't have a code logic that would check if the caller is approved to spend funds. A malicious user could front-run these function calls and would have tokens sent to themselves or anybody that manages to get **_nftId** of a holder could drain their funds as there's also no logic to check how much the **spender** is allocated
## Proof of Concept
![withdrawOnBehalfExactShares](C:\Users\USER\OneDrive\withdrawOnBehalf.jpg "withdrawOnBehalfExactShares")
In "withdrawOnBehalfExactShares" function above, the function allows an external user to borrow on behalf of a predetermined **_nftId** holder but there's no logic to ensure that the caller has been approved by the **_nftId holder**, the function thus calls an internal **_handleWithdrawShares** function (snapshot below), passing in **_caller** as **msg.sender** and setting the **_onbehalf** boolean to **true**
![_handleWithdrawtokens](C:\Users\USER\OneDrive\full _handleWithdrawtokens.jpg "_handleWithdrawtokens")
**_handleWithdrawtokens** above checks if **_onbehalf** is false, and since it was passed as **_true** from the **withdrawOnBehalfExactShares** function, the second function, **_coreWithdrawToken** is called. It's logic below

![_coreWithdrawToken](C:\Users\USER\OneDrive\_coreWithdrawToken1.jpg "_coreWithdrawToken")
![_coreWithdrawToken cont.](C:\Users\USER\OneDrive\_coreWithdrawToken2.jpg "_coreWithdrawToken cont.")

In the entire function that is **_coreWithdrawToken**, the only logic that would have been close was 

     if (_onBehalf == true) {
            emit FundsWithdrawnOnBehalf(
                _caller,
                _nftId,
                _poolToken,
                _amount,
                _shares,
                block.timestamp
            );
but it was only used to determine which event to emit.


The same goes for **borrowOnBehalfExactAmount**, except the withdraw logic is substituted for borrow logic, link below

[borrowOnBehalfExactAmount](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L1055)
[_handleBorrowExactAmount](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L1553")
[_coreBorrowToken](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseCore.sol#L349)



## Tools Used
 Manual Analysis
## Recommended Mitigation Steps
Incorporate a check to ensure that calls made to these functions have been approved by the owner of **_nftId** and an exact price that can be spent by **spender**
Slippage issues in `redeem()`/`addLiquiditySingleSy()`/`removeLiquiditySingleSy()` in `PendlePowerFarmLeverageLogic.sol`
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerFarmLeverageLogic.sol#L170
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerFarmLeverageLogic.sol#L183
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerFarmLeverageLogic.sol#L472


# Vulnerability details

## Impact
Pendle pools can be very volatile especially in extreme market scenarios, when performing leverage tactics in `PendlePowerFarmLeverageLogic.sol` it makes interactions with the Pendle pools the issue here is that on the call to:
- `addLiquiditySingleSy()`
- `redeem()`
- `removeLiquiditySingleSy()`

The contract accepts that the minimum amount of tokens it receives to a minimum of zero.
Sample :
```solidity
        uint256 tokenOutAmount = PENDLE_SY.redeem(
            {
                _receiver: address(this),
                _amountSharesToRedeem: netSyOut,
                _tokenOut: tokenOut,
                _minTokenOut: 0,
                _burnFromInternalBalance: false
            }
        );
```
Even this is specified in Pendle SDK.
https://api-v2.pendle.finance/sdk/#/

This is bad as an attacker can front-run the calls to cause the contracts to incur losses and backrun the tx to gain.
They require a slippage check to ensure the transactions do not end in loss to the caller.
This wouldn't revert the transaction and there loss of yield to the leverage strategy so I am labeling a high.
## Tools Used
Manual review.
## Recommended Mitigation Steps
As per the Docs use the underlying preview function to determine the supposed minimum amount out before performing the calls.




















## Assessed type

Other
Position NFT Id enumeration is incorrect
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PositionNFTs.sol#L130


# Vulnerability details

## Impact
Loss of user funds

## Proof of Concept
The `PositionNFT`s are vital for the protocol as the positions being held are represented by the ID of the `PositionNFT`.
The below list represents the summary of the functions that users can engage with their NFT id or the IDs assigned during the time of the call.

-----
There are 2 statuses of NFT ownership during system interactions:

Status 1: The user needs to possess the ownership of the NFT Id being passed into the function

Status 2: An NFT Id is being reserved for the user by this call or the reserved one is assigned

---

1. If a user wants to enter the system, they call:

[depositExactAmount](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L460) - Status 1

[depositExactAmountETH](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L388) - Status 1

[depositExactAmountETHMint](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L426) - Status 2

[depositExactAmountMint](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L442) - Status 2

[solelyDepositETH](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L508) - Status 1

[solelyDepositETHMint](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L493) - Status 2

[solelyDeposit](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L600) - Status 1

[solelyDepositMint](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseLending.sol#L581) - Status 2




2. And if the user wants to leverage their gains by entering Power Farms they call;

[enterFarm](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerManager.sol#L96) - The NFT id is assigned by calling [_getWiseLendingNFT](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerManager.sol#L185) that results in one of the Statuses.

[enterFarmETH](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerManager.sol#L142) - The NFT id is assigned by calling [_getWiseLendingNFT](https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowe
Liquidation is not possible in turbulent market situations
Audit: 2024-02-wise-lending-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L1306
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L1358
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseCore.sol#L638
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/WiseOracleHub.sol#L143-L168
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/WiseOracleHub.sol#L80-L82
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/OracleHelper.sol#L168-L170
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/OracleHelper.sol#L241-L242


# Vulnerability details

## Impact
Liquidators won't be able to liquidate the positions in case of turbulent market conditions due to use of double oracle. (Chainlink and TWAP.)

## Proof of Concept
There are two functions to liquidate the positions in `WiseLending.sol`
1. `liquidatePartiallyFromTokens()`
2. `coreLiquidationIsolationPools()`
Both the functions are calling `_coreLiquidation()` function internally, THe `_coreLiquidation()` function in `WiseCore.sol` is used for some security checks and internal maths,however while doing so it calculates the collateral percentage by calling `WISE_SECURITY.calculateWishPercentage` and passing the desired parameters for the above function, Now if you look closely at the parameters passed :

```solidity
uint256 collateralPercentage = WISE_SECURITY.calculateWishPercentage(
            _data.nftId,
            _data.tokenToRecieve,
            WISE_ORACLE.getTokensInETH(
                _data.tokenToPayback,
                _data.paybackAmount
            ),
            _data.maxFeeETH,
            _data.baseRewardLiquidation
        );
```
Look at the third parameter which is `WISE_ORACLE.getTokensInETH` which returns ETH value of a given token amount in order of 1E18 decimal precision.
The problem is in this function which takes the help of WiseOracle design to calculate the accurate price of a token in terms of ETH, The `getTokensInETH()` fuction is returning the amount with some calculation inside where `latestResolver(_tokenAddress)` is involved.
Now lets look closely at `latestResolver()` function and its trails

`latestResolver()`---> returns `_validateAnswer(_tokenAddress)` I'm providing a link to [_validateAnswer](https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracleHub/OracleHelper.sol#L131-L174) which calculates the price based on chainlink and also calculates the price based on TWAP price, and later it calculates the difference between the two and If the price difference between the two deviates by more than 2.5% the whole function just reverts with `OraclesDeviate()` error and doesn't return any valid price in that case. Check function [_compareDifference](https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseOracle