xanoutas/solidity-security-findings huggingface dataset:
Share price manipulation attack
Audit: 2024-05-bakerfi-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L225


# Vulnerability details

## Proof of Concept
In this variant of share price manipulation attack, an attacker will need to deploy a small amount of assets, like 1 wei, just to mint 1 wei of shares and then donate aave collateral tokens directly to the contract, to increase share price to make its price to be e18 for example.

Then all next depositors may lose some value to the attacker and this value depends on the amount they deposited. There is [no 0 shares check](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L225), which means that depositor can receive nothing at all after deposit.

## Impact
User lose deposited assets.

## Tools Used
VsCode

## Recommended Mitigation Steps
Make sure first depositor mints big amount of shares.


## Assessed type

Error
Missing slippage in the call to `exactInputSingle()` inside `UseSwapper::_swap()`
Audit: 2024-05-bakerfi-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/hooks/UseSwapper.sol#L72


# Vulnerability details

## Description
The [exactInputSingle() inside _swap()](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/hooks/UseSwapper.sol#L72) function uses a `amountOutMinimum` param with a value of zero. Thus it offers no slippage protection to the caller and can result in sandwich attacks or even under the normal flow of events a bad price for which the caller was not ready.

## Tools Used
Manual review

## Recommended Mitigation Steps
Set it to a user provided param by specifying `amountOutMinimum: params.amountOutMinimum` inside `ExactInputSingleParams`.



## Assessed type

Other
An attacker can extract someone else's `ShareReward`
Audit: 2024-05-bakerfi-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/59b1f70cbf170871f9604e73e7fe70b70981ab43/contracts/core/Vault.sol#L224
https://github.com/code-423n4/2024-05-bakerfi/blob/59b1f70cbf170871f9604e73e7fe70b70981ab43/contracts/core/Vault.sol#L254


# Vulnerability details

## Impact
An attacker can extract someone else's `ShareReward`

## Proof of Concept

1. Vault#deposit:
    shares = amount *  totalSupply / _totalAssets

```solidity
    function deposit(address receiver) ....{
        .....
        uint256 amount = abi.decode(result, (uint256));
        // shares = amount *  totalSupply / _totalAssets
        shares = total.toBase(amount, false);
        _mint(receiver, shares);
        emit Deposit(msg.sender, receiver, msg.value, shares);
    }

```

_totalAssets = totalCollateralInEth - totalDebtInEth 

```solidity
    function deployed(uint256 priceMaxAge) public view returns (uint256 totalOwnedAssets) {
        (uint256 totalCollateralInEth, uint256 totalDebtInEth) = _getPosition(priceMaxAge);
        totalOwnedAssets = totalCollateralInEth > totalDebtInEth
            ? (totalCollateralInEth - totalDebtInEth) : 0;
    }
```

2. withdrawAmount = share * totalAssets() / totalSupply()

3. When totalAssets > 0, the attacker can `deposit` and `withdraw` again and again, and the attacker will always get `share` until totalAssets = 0.


## Tools Used
vscode, manual

## Recommended Mitigation Steps
Modify the way rewards are distributed.



## Assessed type

Error
Hardcoded uniswap fee tier may cause dos of harvest functionality
Audit: 2024-05-bakerfi-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L545-L547


# Vulnerability details

## Proof of Concept
When `StrategyLeverage.harvest` is called and current LTV is bigger than max LTV, then function adjusts LTV of position and then [flashloan is taken](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L346-L350) with `FlashLoanAction.PAY_DEBT` action, which means that `_payDebt` function [will handle callback](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L307). 

The function tries to understand what amount of collateral it needs to withdraw to repay flashloan and fee.
```solidity
        (uint256 amountIn, , , ) = uniQuoter().quoteExactOutputSingle(
            IQuoterV2.QuoteExactOutputSingleParams(ierc20A(), wETHA(), debtAmount + fee, 500, 0)
        );    
```

As you can see it puts `500` as uniswap fee tier.
But later during the swap it uses `_swapFeeTier` to get correct pool.
```solidity
        uint256 output = _swap(
            ISwapHandler.SwapParams(
                ierc20A(),
                wETHA(),
                ISwapHandler.SwapType.EXACT_OUTPUT,
                amountIn,
                debtAmount + fee,
                _swapFeeTier,
                bytes("")
            )
        );
```

As result, in case if `_swapFeeTier` is not `500` this means that functionality may work incorrectly. For example it's possible that there is no 500 fee tier, or `_swapFeeTier` is higher, which means that swap will revert as not enough funds will be allowed to swap.

## Impact
Harvest functionality may now work.

## Tools Used
VsCode

## Recommended Mitigation Steps
Use `_swapFeeTier` variable to get quote.

```solidity
        (uint256 amountIn, , , ) = uniQuoter().quoteExactOutputSingle(
            IQuoterV2.QuoteExactOutputSingleParams(ierc20A(), wETHA(), debtAmount + fee, _swapFeeTier, 0)
        );    
```





## Assessed type

Error
Attacker can DoS deposits to a new Vault
Audit: 2024-05-bakerfi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L204-L209


# Vulnerability details

## Impact
Attackers can DoS deposits on New Vaults, rendering the vault completely unusable.

## Proof of Concept
When doing a deposit on a Vault, [there are some checks that analyze the state of the Rebase values](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L204-L209). Deposits are allowed only when `(total.elastic == 0 && total.base == 0)` || `(total.base > 0 && total.elastic > 0)`, any other combination of those two values will cause the deposit to revert.

```
function deposit(
    address receiver
)
    ...
{
    ...

    Rebase memory total = Rebase(_totalAssets(maxPriceAge), totalSupply());
    if (
        // Or the Rebase is unititialized
        !((total.elastic == 0 && total.base == 0) ||
            // Or Both are positive
            (total.base > 0 && total.elastic > 0))
    ) revert InvalidAssetsState();
    ...
}
```

The `total.elastic` represents the [assets controlled by the Vault in the associated Strategy](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L289-L291).
- The assets controlled by the Vault is the difference between the value in ETH of the aCollateralTokens owned by the Strategy and the total WETH debt of the Strategy.

The `total.base` represents all the vault shares that have been minted (totalSupply())

An attacker can donate (do a direct transfer) 1 wei of the aCollateralToken to the Strategy. This will make the `total.elastic` to be equals to 1 wei, while the `total.base` is 0 because any deposits on the Vault have been made.
- `total.elastic > 0 && total.base == 0` is a combination of values that will cause a deposit to revert with the error `InvalidAssetsState`

## Tools Used
Manual Audit

## Recommended Mitigation Steps
Remove those if conditionals from the deposit(). Design a different mechanism to validate the state of the Rebase that can't be affected by direct donations of aCollateralTokens




## Assessed type

Context
Incorrect integration with UniswapRouter causes all swaps to revert.
Audit: 2024-05-bakerfi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/hooks/UseSwapper.sol#L67-L76
https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/hooks/UseSwapper.sol#L84-L93


# Vulnerability details

## Impact
Core functions on the Strategy contract are impacted because the Strategy won't be able to do swaps caused an incorrect integration with the UniswapRouter.
- The deploy(), undeploy() and harvest() will revert when swapping the flashloaned borrowed WETH for collateral.


## Proof of Concept
The [`UseSwapper._swap() function`](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/hooks/UseSwapper.sol#L57-L101) makes use of the UniswapRouter when executing swaps. The problem is that the parameters that are passed to the UniswapRouter are [missing the `deadline` parameter](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/hooks/UseSwapper.sol#L67-L76), on both types of swaps (EXACT_INPUT && EXACT_OUTPUT).
- Not passing the deadline parameter to the UniswapRouter will cause the tx to be reverted because when the Router tries to read that parameter it won't find it. This throws an `EvmError: Revert`, which ultimately ends up reverting the whole tx.

```
> UseSwapper.sol

function _swap(
    ISwapHandler.SwapParams memory params
) internal override returns (uint256 amountOut) {
    ...

    // Exact Input
    if (params.mode == ISwapHandler.SwapType.EXACT_INPUT) {
        amountOut = _uniRouter.exactInputSingle(
          //@audit-issue => Not passing the deadline parameter
            IV3SwapRouter.ExactInputSingleParams({
                tokenIn: params.underlyingIn,
                tokenOut: params.underlyingOut,
                amountIn: params.amountIn,
                amountOutMinimum: 0,
                fee: fee,
                recipient: address(this),
                sqrtPriceLimitX96: 0
            })
        );
        if (amountOut == 0) {
            revert SwapFailed();
        }
        emit Swap(params.underlyingIn, params.underlyingOut, params.amountIn, amountOut);
        // Exact Output
    } else if (params.mode == ISwapHandler.SwapType.EXACT_OUTPUT) {
        uint256 amountIn = _uniRouter.exactOutputSingle(
          //@audit-issue => Not passing the deadline parameter
            IV3SwapRouter.ExactOutputSingleParams({
                tokenIn: params.underlyingIn,
                tokenOut: params.underlyingOut,
                fee: fee,
                recipient: address(this),
                amountOut: params.amountOut,
                amountInMaximum: params.amountIn,
                sqrtPriceLimitX96: 0
            })
        );
        ...
    }
}
```

If we take a look at the code of the SwapRouter, we can notice that the `deadline` is a parameter that must be sent as part of the params when calling the [exactInputSingle()](https://github.com/Uniswap/v3-periphery/blob/main/contracts/SwapRouter.sol#L119) or [exactOutputSingle()](https://gi
All supplied WETH to Aave as a deposit by a Strategy will be irrecoverable.
Audit: 2024-05-bakerfi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L562-L566


# Vulnerability details

## Impact
WETH supplied to Aave will be lost.

## Proof of Concept
When a strategy pays debt on Aave it does a swap of the withdrawn collateral from Aave in exchange for WETH. After the swap is completed, it checks [if there are any weth leftovers after the swap, if so, it deposits them back](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L562-L566). The problem with this approach is that the strategy doesn't have any means to pull WETH out of Aave, the strategy is only capable of withdrawing the collateral from Aave, but not WETH.

```
function _payDebt(uint256 debtAmount, uint256 fee) internal {
  ...

  //@audit-info => output represents the received amount of WETH for the swap
  uint256 output = _swap(
      ISwapHandler.SwapParams(
          ierc20A(),
          wETHA(),
          ISwapHandler.SwapType.EXACT_OUTPUT,
          amountIn,
          debtAmount + fee,
          _swapFeeTier,
          bytes("")
      )
  );

  //@audit-info => Checks if there are any WETH leftovers
  // When there are leftovers from the swap, deposit then back
  uint256 wethLefts = output > (debtAmount + fee) ? output - (debtAmount + fee) : 0;

  //@audit-issue => If any leftover WETH, it deposits them onto Aave!
  //@audit-issue => Once the WETH is deposited in Aave, the Strategy won't be able to pull it out.
  if (wethLefts > 0) {
      _supply(wETHA(), wethLefts);
  }
  emit StrategyUndeploy(msg.sender, debtAmount);
}
```

The strategy uses the [`StrategyAAVEv3._withdraw() function`](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyAAVEv3.sol#L126-L129) to withdraw an asset from Aave, but, in the places where this function is called, the only assets requested to be withdrawn is the Collateral.
- in the [`StrategyLeverage._payDebt()`](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L549)
- in the [`StrategyLeverage._repayAndWithdraw()`](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L701)


## Tools Used
Manual Audit

## Recommended Mitigation Steps
Instead of supplying the `wethLefts`, use the excess WETH to repay more WETH debt on Aave, in this way, those extra WETHs won't be lost on Aave because the strategy doesn't have any means to withdraw them.
- By using the extra WETH to repay more debt, the loan to value is brought down even to a healtier level.


```
function _payDebt(uint256 debtAmount, uint256 fee) internal {
  ...
  ...
  ...

  //@audit => Instead of supplying WETH to Aave, use it to repay more debt
  if (wethLefts > 0) {
-     _supply(wETHA(), wethLefts);
+     _repay(wETHA(), wethLefts);
  }
  emit StrategyUndeploy(msg.sender, debtAmount);
}
```


## Assessed type

Context
Incorrect formula to compute tokenPerETH rate renders unnusable the max deposit feature.
Audit: 2024-05-bakerfi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L339


# Vulnerability details

## Impact
The tokenPerETH rate is computed incorrectly, which will cause problems with the max deposit feature. (Will provide some examples of the calculations in the Proof of Concept section)
- If the totalAssets > totalSupply, the rate will be computed lower than what it really is, thus, users will be able to deposit more than what they are allowed to.
- If the totalSupply > totalAssets, the rate will be computed bigger, thus, users will be able to deposit less than what they are allowed to. 

## Proof of Concept
When making a deposit in a Vault, if the maxDeposit feature is enabled, the execution will validate if the depositor should be allowed to deposit the requested amount. To determine if the depositor should be allowed or not, the function will compute the afterDeposit value of the user deposits including the deposit being made.
- To determine the afterDeposit vaule, the function first computes the current depositor's value by calculating the tokenPerETH rate and then it multiplies the current rate by the total shares owned by the depositor. And finally, the afterDeposit value is the sum of the current depositor's value + the amount being deposited. If the afterDeposit value exceeds the maxDeposit, the execution is reverted because the depositor would exceed the maximum allowed amount to be deposited.

```
function deposit(
    address receiver
)
    ...
{
    ...

    // Verify if the Deposit Value exceeds the maximum per wallet
    uint256 maxDeposit = settings().getMaxDepositInETH();
    if (maxDeposit > 0) {
        uint256 afterDeposit = msg.value +
        //@audit-info => Current existing deposited amount of the depositor
            ((balanceOf(msg.sender) * _tokenPerETH(maxPriceAge)) / 1e18);
        if (afterDeposit > maxDeposit) revert MaxDepositReached();
    }

    ...
}

//@audit-info => Computes the amount of ETH that each share can claim!
function _tokenPerETH(uint256 priceMaxAge) internal view returns (uint256) {
    uint256 position = _totalAssets(priceMaxAge);
    if (totalSupply() == 0 || position == 0) {
        return 1 ether;
    }

    //@audit-issue => Incorrect formula causes the tokenPerETH rate to be computed wrong
    return (totalSupply() * 1 ether) / position;
}
```

[There is a problem in the formula to determine the current tokenPerETH rate](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/Vault.sol#L339). The formula that is used to determine the rate is incorrectly computing the rate, the current formula is `(totalSupply() * 1 ether) / position;`. By doing some math using the current formula we can see the problem with it.
**Example 1: totalAssets > totalSupply**
- `totalSupply()` === 100e18 shares 
- `totalAssets()` === 1000e18 assets.
- `tokenPerETH rate` === 100e18 * 1e18 / 1000e18 ===> 100e36 / 1000e18 => 0.1e18
- Using the current formula, the tokenP
Vault can be DoS
Audit: 2024-05-bakerfi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/59b1f70cbf170871f9604e73e7fe70b70981ab43/contracts/libraries/RebaseLibrary.sol#L32


# Vulnerability details

## Impact
When totalSupply = 0, the attacker donates 1wei token, causing the number of shares to remain 0 at deposit time.


## Proof of Concept

The `toBase` function only determines whether `total.elastic(_totalAssets)` is 0, not whether `totalSupply` is 0.

```solidity
    function toBase(Rebase memory total, uint256 elastic,bool roundUp
    ) internal pure returns (uint256 base) {
@       if (total.elastic == 0) {
            base = elastic;
        } else {
            //total.base = totalSupply ; total.elastic = _totalAssets
            base = (elastic * total.base) / total.elastic;
            if (roundUp && (base * total.elastic) / total.base < elastic) {
                base++;
            }
        }
    }
```

When totalSupply=0, if _totalAssets > 0, `toBase` always returns 0.

An attacker can make a donation of _totalAssets > 0, the `toBase` function will then compute base through a branch in the else statement, since totalSupply=0
base = 0 * elastic / total.elastic = 0,

As a result, the number of deposit shares is always 0, and the protocol will not work.

```solidity
    function deposit(address receiver) ....{
        .....
        shares = total.toBase(amount, false);
        _mint(receiver, shares);
        emit Deposit(msg.sender, receiver, msg.value, shares);
    }
```

An attacker can send Collateral token to the `StrategyAAVEv3(address(this))` contract,

_totalAssets = collateralBalance - debtBalance

```solidity
    function _getMMPosition() internal virtual override view returns ( uint256 collateralBalance, uint256 debtBalance ) {
        DataTypes.ReserveData memory wethReserve = (aaveV3().getReserveData(wETHA()));
        DataTypes.ReserveData memory colleteralReserve = (aaveV3().getReserveData(ierc20A()));
        debtBalance = IERC20(wethReserve.variableDebtTokenAddress).balanceOf(address(this));
        collateralBalance = IERC20(colleteralReserve.aTokenAddress).balanceOf(address(this));
    }
```

## Tools Used
vscode, manual

## Recommended Mitigation Steps
```diff
    function toBase(Rebase memory total, uint256 elastic,bool roundUp
    ) internal pure returns (uint256 base) {
-        if (total.elastic == 0) {
+        if (total.elastic == 0 || total.base == 0) {
            base = elastic;
        } else {
            //total.base = totalSupply ; total.elastic = _totalAssets
            base = (elastic * total.base) / total.elastic;
            if (roundUp && (base * total.elastic) / total.base < elastic) {
                base++;
            }
        }
    }
```





## Assessed type

DoS
StrategyLeverage.harvest doesn't account flashloan fee
Audit: 2024-05-bakerfi-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L397-L399


# Vulnerability details

## Proof of Concept
`StrategyLeverage.harvest` function checks position state. In case if position LTV is bigger than max LTV, then [extra debt is repaid](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L395) to decrease LTV back to normal.

In order to repay part of debt, flashloan is taken and contract [should pay fee for it](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L342).
So overall after adjusting our debt is decreased with `deltaDebt` but our collateral is decreased with  `deltaDebt + fee`.

The problem is that this is not reflected in the [`newDeployedAmount` calculation](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L397-L399) as it thinks that both collateral and debt where decreased by `deltaDebt`.

As result of this `newDeployedAmount` is bigger than it is in reality(in reality it is `newDeployedAmount - fee`), which means that later when some profit accrued, protocol [may not receive it](https://github.com/code-423n4/2024-05-bakerfi/blob/main/contracts/core/strategies/StrategyLeverage.sol#L408-L416). For example if `profit is < fee`, then protocol won't receive it and if `profit is > fee`, then protocol will receive management fee based on `profit - fee` amount. 

## Impact
Protocol may receive smaller amount of fees.

## Tools Used
VsCode
## Recommended Mitigation Steps
Make `_adjustDebt` returns `fee` as well and use it to decrease collateral.


## Assessed type

Error