xanoutas/solidity-security-findings huggingface dataset:
Missing _checkAmountWithBalance check in deposit functions
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L353-L380


# Vulnerability details

## Impact
When computing the input or output amount of a swap `_checkAmountWithBalance` is called to ensure that precision errors do not occur and that the pool does not lose any value. However, `_checkAmountWithBalance` is not called in `depositGivenInputAmount` and `depositGivenOutputAmount`. This opens two opportunities for a user: they deposit a small amount to cause precision errors or they can perform a malicious swap that is not validated by `_checkAmountWithBalance`. In order to perform that swap they can deposit an amount of x tokens and with the retrieved LP tokens withdraw an amount of y tokens. That way the amount of x tokens swapped for y tokens can be less than the required amount in `_checkAmountWithBalance` causing a small loss for the pool as stated in the dev comments.

## Proof of Concept
Below can be seen that there is no check for `_checkAmountWithBalance`:
   ``` 
function depositGivenInputAmount(
        uint256 xBalance,
        uint256 yBalance,
        uint256 totalSupply,
        uint256 depositedAmount,
        SpecifiedToken depositedToken
    ) external view returns (uint256 mintedAmount) {
        // deposit amount validations against the current balance
        require(
            depositedAmount < INT_MAX &&
                xBalance < INT_MAX &&
                yBalance < INT_MAX &&
                totalSupply < INT_MAX
        );

        int256 result = _reserveTokenSpecified(
            depositedToken,
            int256(depositedAmount),
            FEE_DOWN,
            int256(totalSupply),
            int256(xBalance),
            int256(yBalance)
        );

        // amount cannot be less than 0
        require(result > 0);
        mintedAmount = uint256(result);
    }
```
The dev comments, related to the issues with swapping small amounts of tokens:
`* @dev when we swap very small amounts against a very large pool,
     *  precision errors can cause the pool to lose a small amount of value.`

## Tools Used
Manual review
## Recommended Mitigation Steps
Include the `_checkAmountWithBalance` check in `depositGivenInputAmount` and `depositGivenOutputAmount`.


## Assessed type

Invalid Validation
Wrong check applied on certain function.
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L296


# Vulnerability details

## Impact
function which applied the require check for amount will always gets revert like swapGivenInputAmount , withdrawGivenOutputAmount , withdrawGivenInputAmount

## Proof of Concept
under function given above a wrong is made which always get revert when the amount to get check less than zero, since the require condition check for true statement and gets revert if it not matched..

```
 // amount cannot be less than 0
        require(result < 0);
```
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L296
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L451
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L488


## Tools Used

## Recommended Mitigation Steps
Make a proper validation check..


## Assessed type

Invalid Validation
ABDKMath64 performs multiplication on results of division
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L6


# Vulnerability details

## Impact
Solidity could truncate the results, performing multiplication before division will prevent rounding/truncation in solidity math.

## POC:
EvolvingProteus is using ABDKMath64x64 library which is doing performing multiplication before division this can rounding issue under function which is using particularly ```divu``` internal function of ABDKMath64x64 library to perform certain calculation.

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L90
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L701
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L259

## Recommended Mitigation Steps
Consider ordering multiplication first.


## Assessed type

Library
Liquidity concentration rate is reduced by the use of timestamp instead of block number
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L72-#L73
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L81


# Vulnerability details

## Impact
- Liquidity concentration rate is reduced by the use of timestamp instead of block number

## Proof of Concept
The document states that `This primitive can passively update liquidity concentration over time. You can think of it like a hybrid between a Balancer liquidity bootstrapping pool and Uniswap v3. The pool creator picks a starting liquidity concentration and an ending liquidity concentration. The creator also sets a starting timestamp and an ending timestamp during which liquidity concentration evolves. Every block, the primitive will update its concentration.`

The `liquidity concentrate` hence will be updated every block. However, library `LibConfig` all uses timestamp in calculations:
```solidity
    function elapsed(Config storage self) public view returns (uint256) {
        return block.timestamp - self.t_init;
    }
    function t(Config storage self) public view returns (int128) {
        return elapsed(self).divu(duration(self));
    }
    function p_min(Config storage self) public view returns (int128) {
        if (t(self) > ABDK_ONE) return self.px_final;
        else return self.px_init.mul(ABDK_ONE.sub(t(self))).add(self.px_final.mul(t(self)));
    }
    function p_max(Config storage self) public view returns (int128) {
        if (t(self) > ABDK_ONE) return self.py_final;
        else return self.py_init.mul(ABDK_ONE.sub(t(self))).add(self.py_final.mul(t(self)));
    }
```

These function `t`, `elapsed`, `p_min`, `p_max` is calculated using timestamp and they are used for computation in deposit, swap and withdraw.

According to this chart here https://arbiscan.io/chart/tx, the average block per second is 3 ~ 4. Therefore, the liquidity concentration rate will be slowed 3 -> 4 times and also if its change will not be reflected every block like described in documentation. 


## Tools Used
Manual review

## Recommended Mitigation Steps
I suggest using block as units in duration calculations.


## Assessed type

Library
Utility per LP token can decrease in some cases.
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L353


# Vulnerability details

## Impact
Utility per LP token can decrease in some cases.

## Proof of Concept
The documentation in contest repo states that `Within a timeslice (a single block), no set of transactions (swaps, deposits, withdrawals) should result in a decrease of the utility per LP token (utility / lp).`

However, I've found that utility per LP token can decrease in some cases. It's hard to mathematically generalize when this will happen, but through fuzzing method I found that when `totalSupply` (of LP token) is small compared to token X and Y's balances, the utility will decrease.

Below is a POC for such a case, I will make use of file `test/EvolvingProteusProperties.t.sol`, add console library using `import "forge-std/console2.sol";` (this is for logging utility). Place this test under contract `EvolvingProteusProperties` and run it using command:
`forge test --match-path src/test/EvolvingProteusProperties.t.sol --match-test test_deposit_minted_amount -vvvv`

In the test, we can see that the smaller total supply is, the greater the utility changes.
```solidity
    function test_deposit_minted_amount() public {

        uint256 yBalance = 2e18;
        uint256 xBalance = 1e18;
        uint256 specifiedAmount = 1e18;

        uint256[3] memory totalSupplies = [
                            uint256(1e15),
                            uint256(1e16),
                            uint256(1e17)];

        for (uint i=0;i< totalSupplies.length; i++) {
            uint256 totalSupply = totalSupplies[i];
            // Deposit specifiedAmount of X token
            uint256 mintedAmount = DUT.depositGivenInputAmount(
                yBalance,
                xBalance,
                totalSupply,
                specifiedAmount,
                SpecifiedToken.X
            );

            uint256 utilityBefore  = uint256(DUT.getUtility(int256(xBalance), int256(yBalance)));
            uint256 utilityAfter = uint256(DUT.getUtility(int256(xBalance + specifiedAmount), int256(yBalance)));

            uint256 utilityPerLpBefore = utilityBefore/totalSupply;
            uint256 utilityPerLpAfter = utilityAfter/(totalSupply + mintedAmount);

            console2.log("Utility per token before %s, after %s, difference %s", utilityPerLpBefore, utilityPerLpAfter,
            utilityPerLpBefore - utilityPerLpAfter);

            assertGt(utilityPerLpBefore, utilityPerLpAfter);
        }

    }
```
There are reasons for `totalSupply` will be small compared to token X and Y balances. For example, X and Y balance is increased though direct token transfer and not through `deposit` tokens in vaults. Another example is when a vault allows users to burn their shares but the tokens remains.


## Tools Used
Manual review

## Recommended Mitigation Steps
I think the best way to guard against these cases is to calculate `utility` before and after transfers (dep
The code uses block.timestamp for calculating the duration of the curve evolution which can be manipulated by miners
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L72C8-L73C40 #L72


# Vulnerability details

## Impact
block.timestamp is used to set the initial time (t_init) and the final time (t_final) for the curve's evolution - the duration over which these prices change (t_init, t_final). The potential issue here is that block.timestamp can be manipulated by miners to a certain degree.  

## Proof of Concept
https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L59C3-L75C6

## Tools Used
Manual review

## Recommended Mitigation Steps


## Assessed type

Other
Validating input parameters with the max value of uint
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L146


# Vulnerability details

## Impact
Validating input values with `uint256.max` will not revert in any condition as solidity v0.8.0 reverts on overflow and underflow. 
Detailed description of the impact of this finding.
Due to solidity v0.8.0 which reverts on overflow and underflow of integer types, there's no need of validating against the max value of uint as this check does not really do anything leading to input values not being validated properly. This can cause issues for the protocol as `inputAmount` is not validated against the balance of the pool
```solidity
function swapGivenOutputAmount(
        uint256 xBalance,
        uint256 yBalance,
        uint256 outputAmount,
        SpecifiedToken outputToken
    ) external view returns (uint256 inputAmount) {
        // output amount validations against the current balance
        require(
            outputAmount < INT_MAX && xBalance < INT_MAX && yBalance < INT_MAX
        );
         // More code...
```
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

## Tools Used
Manual review 
## Recommended Mitigation Steps
Consider Checking if `inputAmiunt` is less than the `tokenbalance`.


## Assessed type

Invalid Validation
Lack of slippage parameter in swap can cause losses for users
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L272
https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L312


# Vulnerability details

## Impact
Users can incure losses do to lack of slippage control.
Detailed description of the impact of this finding.
Slippage control helps to safeguard user funds against price falling below a certain threshold. This can be caused by`frontrunning` attack.
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Take for instance.
1• UserA tries to swap his xtoken for ytoken 
2• malicious user then on seeing this runs a `frontrun` attack which increases the  volume of xtoken in the pool, lowering it's price.
3• UserA transaction goes through but due to the reduced price of xtoken, it swaps for lesser number if ytokens than the user intended thereby leaging to losses for the user.
## Tools Used
Manual review
## Recommended Mitigation Steps
Add slippage parameter to the `swap` functions






## Assessed type

Invalid Validation
Invalid Error Reverts in Some Cases
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L786


# Vulnerability details

## Description:
While reviewing the code, I noticed that there is a potential issue with the error revert conditions in the _getPointGivenXandUtility and _getPointGivenYandUtility functions. The error handling mechanism in these functions might not be functioning as intended.

## Bug Location:
Within the _getPointGivenXandUtility and _getPointGivenYandUtility functions.

## Bug Explanation:
In both the _getPointGivenXandUtility and _getPointGivenYandUtility functions, there are checks to determine whether the calculated value y0 or x0 is negative. If the calculated value is negative, the functions revert with the CurveError error message. However, the condition for the revert check is not accurate because the calculated values y0 and x0 are int256 values that can be both positive and negative.

The error handling should be improved to ensure that the condition accurately captures the possibility of a negative value and responds accordingly.

## Proposed Fix:
Update the error handling conditions in both _getPointGivenXandUtility and _getPointGivenYandUtility functions to handle both negative and positive values correctly.

Example Fix for _getPointGivenXandUtility:


function _getPointGivenXandUtility(
    int256 x,
    int256 utility
) internal view returns (int256 x0, int256 y0) {
    int128 a = config.a();
    int128 b = config.b();

    int256 a_convert = a.muli(MULTIPLIER);
    int256 b_convert = b.muli(MULTIPLIER);
    x0 = x;

    int256 f_0 = (((x0 * MULTIPLIER) / utility) + a_convert);
    int256 f_1 = ((MULTIPLIER * MULTIPLIER) / f_0) - b_convert;
    int256 f_2 = (f_1 * utility) / MULTIPLIER;
    y0 = f_2;

    if (y0 < 0 || f_0 <= 0) revert CurveError(y0);
}

The similar fix should be applied to the _getPointGivenYandUtility function.


## Assessed type

Other
Rounding Issue and Inconsistent Fee Application 
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L548
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L551


# Vulnerability details

## Summary
There is a bug in the  _swap function. The bug can potentially cause incorrect balance checks and outputs when swapping. This issue arises due to improper usage of the _applyFeeByRounding function.

## Affected Function:
_swap

## Details:
In the _swap function, the roundedSpecifiedAmount is calculated using _applyFeeByRounding as follows:


roundedSpecifiedAmount = _applyFeeByRounding(specifiedAmount, feeDirection);

The _applyFeeByRounding function is used to apply a fee to an amount by rounding it. The fee can either be added or subtracted based on the value of feeDirection.

However, the issue arises because the roundedSpecifiedAmount is not correctly adjusted based on the specified token. In one branch of the function, x and y balances are correctly adjusted based on the value of roundedSpecifiedAmount, but in the other branch, the adjustment is based on roundedSpecifiedAmount regardless of whether the specified token is X or Y.

Since the calculation depends on the specified token and fee direction, it's essential to adjust x and y balances appropriately. This inconsistency could lead to incorrect balance checks and outputs when swapping.

##Solution:
To fix this issue, you need to adjust the x and y balances based on the specified token and fee direction in both branches of the _swap function.

Here's how you can adjust the affected lines of code:

- 1 .  Replace:


     computedAmount = _applyFeeByRounding(yf - yi, feeDirection);

- With:


     computedAmount = (specifiedToken == SpecifiedToken.Y) ? _applyFeeByRounding(yf - yi, feeDirection) : (yf - yi);
- 2 . Replace:


     computedAmount = _applyFeeByRounding(xf - xi, feeDirection);

- With:


computedAmount = (specifiedToken == SpecifiedToken.X) ? _applyFeeByRounding(xf - xi, feeDirection) : (xf - xi);

By making these adjustments, we can ensure that the x and y balances are correctly adjusted based on the specified token and fee direction in both branches of the _swap function. This should resolve the bug and ensure accurate balance checks and outputs during swapping operations.


## Assessed type

Error
Missing the amountOutMinimum parameter
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L272


# Vulnerability details

## Impact
Executing swapGivenInputAmount() without considering amountOutMinimum and without setting appropriate slippage values may make it vulnerable to MEV  manipulation.

## Proof of Concept
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L272

## Tools Used

## Recommended Mitigation Steps
Referencing the design of executing swaps in the Uniswap documentation, it is advisable to include the amountOutMinimum parameter when executing swapGivenInputAmount().

https://docs.uniswap.org/contracts/v3/guides/swaps/single-swaps


## Assessed type

MEV
Discriminant in utility function could be zero
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L1


# Vulnerability details

## Impact
The discriminant is calculated as (bQuad**2 - (aQuad.muli(cQuad)*4)). There's no check to see if this value is negative before taking the square root, which can cause an error.

## Proof of Concept
https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L1

## Tools Used
manual review

## Recommended Mitigation Steps
change code to

int256 discriminant = bQuad**2 - (aQuad.muli(cQuad)*4);
if (discriminant < 0) revert("Negative discriminant");
int256 disc = int256(Math.sqrt(uint256(discriminant)));



## Assessed type

Error
Error in Calculations in swapGivenInputAmount()
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L295


# Vulnerability details

## Impact
Contradiction in code

## Proof of Concept

According to the comments in the codebase it was the developers intent to make sure amount cannot be less than 0 but instead the check is  ```require(result < 0)```. With this above error, code greater than zero will revert. 
https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L295

Also in the next line of code https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L298C6-L299C41 
You can see the ```-result``` being casted to a ```uint``` (the casting method is also wrong) which means a 
positive number is expected as the ```outputAmount```  

Like I said earlier, the casting method is also wrong in https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L298C6-L299C41

## Tools Used
Manual Review + H20

## Recommended Mitigation Steps
It should be ```require(result > 0)``` 





## Assessed type

Error
Inconsistency with Specified Formula and Implementtion
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L697-L714


# Vulnerability details

## Impact
The entire functioning of the AMM engine is predicated upon Utility. However, inaccuracies in Utility Computation can lead to cascading errors that affect all other computations(_swap, _reserveTokenSpecified, _lpTokenSpecified) within the AMM engine.
 
## Proof of Concept
The calculation of Utility is derived from solving a quadratic equation: ```k(ab - 1)u**2 + (ay + bx)u + xy/k = 0```.
In this equation, the variables ```aQuad```, ```bQuad```, and ```cQuad``` correspond to the coefficients a, b, and c of the quadratic formula. Specifically, within this context, we have ```a = k(ab - 1)```, ```b = ay + bx```, and ```c = xy/k```.

According to the docs: "In qualitative terms, kappa (k) is an individual scale modifier that influences the degree that a curve segment scales at a given utility with respect to other curve segments."

However, during the calculation of variables a and c, variable k was not incorporated as specified in the natspec comment. This oversight results in incorrect computations for aQuad and cQuad. These miscalculated values are subsequently used in obtaining the value representing Utility.
```
 int128 aQuad = (a.mul(b).sub(one));
 int256 bQuad = (a.muli(y) + b.muli(x));
 int256 cQuad = x * y;
```

## Tools Used
Manual review.

## Recommended Mitigation Steps
As specified in the ntspec equation, incorperate k into the computation of aQuad and cQuad.
```
 int128 aQuad = k.mul(a.mul(b).sub(one));
 int256 bQuad = (a.muli(y) + b.muli(x));
 int256 cQuad = (x * y)/k;
```





## Assessed type

Math