xanoutas/solidity-security-findings huggingface dataset:
Swapping lacks deadline check
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-L304


# Vulnerability details

## Impact

There is no deadline when swapping tokens using EvolvingProteus. Swaps that are done through low gas transactions may be stuck in the mempool for a long time, resulting in unfavourable swap.

## Proof of Concept

Evolving prometeus seems like an upgrade to uniswapv3 and its primarily for dutch auctions and dynamic pools. This means that they have a swap feature as well, but the swap feature doesn't have a deadline check attached. When transactions are performed using the shell protocol, if there is a huge inflow of transactions in the blockchain, the transaction might stay dormant in the mempool for awhile, and will result in unfavourable swap.

```
    function swapGivenInputAmount(
        uint256 xBalance,
        uint256 yBalance,
        uint256 inputAmount,
        SpecifiedToken inputToken
    ) external view returns (uint256 outputAmount) {
//@audit there is no instance of checking the deadline here
        // input amount validations against the current balance
        require(
            inputAmount < INT_MAX && xBalance < INT_MAX && yBalance < INT_MAX
        );


        _checkAmountWithBalance(
            (inputToken == SpecifiedToken.X) ? xBalance : yBalance,
            inputAmount
        );


        int256 result = _swap(
            FEE_DOWN,
            int256(inputAmount),
            int256(xBalance),
            int256(yBalance),
            inputToken
        );
        // amount cannot be less than 0
        require(result < 0);


        // output amount validations against the current balance
        outputAmount = uint256(-result);
        _checkAmountWithBalance(
            (inputToken == SpecifiedToken.X) ? yBalance : xBalance,
            outputAmount
        );
    }
```

## Tools Used

Manual Review

## Recommended Mitigation Steps

UniswapV3 has the checkDeadline function to make sure that transactions will auto revert after passing a certain deadline to prevent unfavourable swaps.

```
 function exactInputSingle(ExactInputSingleParams calldata params)
        external
        payable
        override
->      checkDeadline(params.deadline)
        returns (uint256 amountOut)
    {
```

https://etherscan.io/address/0xe592427a0aece92de3edee1f18e0157c05861564#code


## Assessed type

Timing
MIN_PRICE_VALUE is incorrect
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

**`The MIN_PRICE_VALUE`** variable is being calculated based on 10^10 instead of the intended 10^12. As a result, the **`MIN_PRICE_VALUE`** will be lower than expected with 2 decimal places precision, potentially allowing **`px_init`** and **`px_final`** to be set lower than the **`MIN_PRICE_VALUE`**.

## Proof of Concept

*A code PoC demonstrates the issue by calculating **`MIN_PRICE_VALUE`** with both 10^10 and 10^12:*

```solidity
function testMinPriceValueWith10() public returns (int256) {
    int256 MIN_P_V = ABDKMath64x64.divu(10**10, 1e18);
    return MIN_P_V; // 184467440737
}

function testMinPriceValueWith12() public returns (int256) {
    int256 MIN_P_V = ABDKMath64x64.divu(10**12, 1e18);
    return MIN_P_V; // 18446744073709
}
```

The expected result for the second function should be **`18446744073709 (10^12 in wei)`**, but the current code implementation results in **`184467440737 (10^10 in wei)`**.

```solidity
    /** 
     @notice 
     The minimum price value calculated with abdk library equivalent to 10^12(wei)
    */ 
    int256 constant MIN_PRICE_VALUE = 184467440737;
```

## Tools Used

## Recommended Mitigation Steps

We recommend updating the variable as follows:

```solidity
int256 constant MIN_PRICE_VALUE = 18446744073709;
```


## Assessed type

Error
No deadline check when swapping tokens in `swapGivenInputAmount()` and `swapGivenOutputAmount`
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

Missing deadline checks allow pending transactions to be maliciously executed in the future. Without deadline parameters, as a consequence, users can have their operations executed at unexpected times, when the market conditions are unfavorable.
## Proof of Concept

The problem occurs  in `swapGivenInputAmount()`

```solidity
function swapGivenInputAmount(
        uint256 xBalance,
        uint256 yBalance,
        uint256 inputAmount,
        SpecifiedToken inputToken
    ) external view returns (uint256 outputAmount) {
        // input amount validations against the current balance
        require(
            inputAmount < INT_MAX && xBalance < INT_MAX && yBalance < INT_MAX
        );

        _checkAmountWithBalance(
            (inputToken == SpecifiedToken.X) ? xBalance : yBalance,
            inputAmount
        );
  
        int256 result = _swap(
            FEE_DOWN,
            int256(inputAmount),
            int256(xBalance),
            int256(yBalance),
            inputToken
        ); 
        // amount cannot be less than 0
        require(result < 0);

        // output amount validations against the current balance
        outputAmount = uint256(-result);
        _checkAmountWithBalance(
            (inputToken == SpecifiedToken.X) ? yBalance : xBalance,
            outputAmount
        );
    }
```

 and `swapGivenOutputAmount`:

```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
        );
        _checkAmountWithBalance(
            outputToken == SpecifiedToken.X ? xBalance : yBalance,
            outputAmount
        );

        int256 result = _swap(
            FEE_UP,
            -int256(outputAmount),
            int256(xBalance),
            int256(yBalance),
            outputToken
        );

        // amount cannot be less than 0
        require(result > 0);
        inputAmount = uint256(result);
  
        // input amount validations against the current balance
        _checkAmountWithBalance(
            outputToken == SpecifiedToken.X ? yBalance : xBalance,
            inputAmount
        );

    }
```

The deadline check ensures that the transaction can be executed on time and the expired transaction reverted.
## Tools Used

Visual Studio Code

## Recommended Mitigation Steps

Introduce a `deadline` parameter in these functions.


## Assessed type

MEV
Division before multiplication incurs larger precision loss 
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L717
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L718
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L751
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L752
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L782
https://github.com/code-423n4/2023-08-shell/blob/main/src/proteus/EvolvingProteus.sol#L783


# Vulnerability details

## Impact
There are couple of instance of using result of a division for multiplication while can cause larger precision loss.


## Proof of Concept
In contract EvolvingProteus.sol, value of int128 two at line 709 is calculated by using ABDKMath64x64.divu function.

The resultant is then multiplied further and divided in line#717 & 718.

Same pattern is followed in calculating y0 at line#753 and x0 at line#784 for _getPointGivenXandUtility() and _getPointGivenYandUtility() respectively.

This will result in larger Loss of precision.


## Tools Used
Manual code review

## Recommended Mitigation Steps
First multiply all the numerators and then divide it by the product of all denominator.




## Assessed type

Math
Potential pools unavailable
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-08-shell/blob/8ed551004f470489e070c1dd617d67eb4bf114e6/src/proteus/EvolvingProteus.sol#L751


# Vulnerability details

## Impact
The function `_getPointGivenXandUtility()` may always rollback and report an error `CurveError`.

## Proof of Concept
According to the formula `y = (k^2 u^2)/(aku + x) - bku`, it is possible to find the other coordinates of a point on the curve when given a `u` and a combined curve `(a, b, k)`, and the coordinates of that point.

where `u` (utility) can be calculated from the following equation: `k(ab - 1)u^2 + (ay + bx)u + xy/k = 0`

where `a, b`  can be calculated from:

`a = sqrt(1/p_max_current)` // `p_max_current`: the maximum price (at the x asymptote) at the current block

`b = sqrt(p_min_current)` // `p_min_current`: the minimum price (at the x asymptote) at the current block

`k` is a constant equal to 1.

The function `_getPointGivenXandUtility()` uses the above formula when given a certain number of input tokens, to calculate the number of output tokens. In lines 750 and 751 of the function, when the pool token x or y reserve is close to or less than `utility`, then the variable `f_1` is always negative. The function `_getPointGivenXandUtility()` may always rollback and report an error `CurveError`.
```solidity=750
        int256 f_0 = ((( x0  * MULTIPLIER ) / utility) + a_convert);
        int256 f_1 = ((MULTIPLIER * MULTIPLIER / f_0) -  b_convert);
        int256 f_2 = (f_1 * utility) / MULTIPLIER; 
```

#### Testing code

```solidity

    function setUp() public {
       py_init_val = 6951000000000000;
       px_init_val = 69510000000000;
       py_final_val = 695100000000000000;
       px_final_val = 69510000000000;

       py_init = ABDKMath64x64.divu(py_init_val, 1e18);
       px_init = ABDKMath64x64.divu(px_init_val, 1e18);
       py_final = ABDKMath64x64.divu(py_final_val, 1e18);
       px_final = ABDKMath64x64.divu(px_final_val, 1e18);

       duration = T_DURATION;

       DUT = new EvolvingInstrumentedProteus(py_init, px_init, py_final, px_final, duration);
    }

```

```solidity
    function testSwapInput(uint256 inputAmount, bool token) public {
        uint256 x0 = 18_000_000 * 10 ** 18;
        uint256 y0 = 100_000_000 * 10 ** 9;
        vm.assume(x0 >= MIN_BALANCE);
        vm.assume(y0 >= MIN_BALANCE);
        vm.assume(inputAmount >= MIN_OPERATING_AMOUNT);
        vm.assume(y0/x0 <= MAX_BALANCE_AMOUNT_RATIO);
        vm.assume(x0/y0 <= MAX_BALANCE_AMOUNT_RATIO);
        SpecifiedToken inputToken = token ? SpecifiedToken.X : SpecifiedToken.Y;
        DUT.swapGivenInputAmount(x0, y0, inputAmount, inputToken);
    }

```


## Tools Used
vscode

## Recommended Mitigation Steps
Ensure the correct setup for the initial price and final price.


## Assessed type

DoS
Lack of events in EvolvingProteus contract
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
There is no event emitted in the whole contract, even after executing sensitive actions like swaps between assets or at the constructor. That is bad because many automatic tools that monitors the contracts deployed rely on them. For example, see the `swap` function in `UniswapV3Pool#L786`

[https://github.com/Uniswap/v3-core/blob/d8b1c635c275d2a9450bd6a78f3fa2484fef73eb/contracts/UniswapV3Pool.sol#L786](https://github.com/Uniswap/v3-core/blob/d8b1c635c275d2a9450bd6a78f3fa2484fef73eb/contracts/UniswapV3Pool.sol#L786)

```
        emit Swap(msg.sender, recipient, amount0, amount1, state.sqrtPriceX96, state.liquidity, state.tick);
```

## Proof of Concept
Just `Ctrl+f` and look for `emit` in the whole file in scope

[https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L137-L853](https://github.com/code-423n4/2023-08-shell/blob/c61cf0e01bada04c3d6055acb81f61955ed600aa/src/proteus/EvolvingProteus.sol#L137-L853)

## Tools Used
Manual analysis

## Recommended Mitigation Steps
Consider emitting events after sensitive changes take place (including in the constructor), to facilitate tracking and notify off-chain clients following the contracts’ activity.

NOTE -> Medium severity as [here](https://solodit.xyz/issues/lack-of-event-emission-after-sensitive-actions-openzeppelin-uma-optimistic-governor-audit-markdown), [here](https://solodit.xyz/issues/lack-of-event-emission-openzeppelin-origin-governance-audit-markdown) and [here](https://solodit.xyz/issues/lack-of-event-emission-after-sensitive-actions-openzeppelin-forta-protocol-audit-markdown). For C4 ones, go to Solodit and put as keyword `emits` and there are plenty of them as a medium





## Assessed type

Other
UNSAFE CASTING CAN LEAD TO ERRORNEOUS `utility` VALUE CALCULATION
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

The `EvolvingProteus._getUtility` function is used to calculate the `utility` value of the pool at the time of the function call. The `utilitiy` is calculated using a quadratic formula which is shown below:

    k(ab - 1)u**2 + (ay + bx)u + xy/k = 0

Above quadratic equation when solved gives us two solutions which differ based on the sign of the `discriminant`. The `discriminant` is calculated in the function as shown below: 

    int256 disc = int256(Math.sqrt(uint256((bQuad**2 - (aQuad.muli(cQuad)*4)))));

This issue here is with the `uint256((bQuad**2 - (aQuad.muli(cQuad)*4)))` phrase. Since we are taking the square root of the result of the above phrase we are casting its result into `uint256`. 

Now consider the following scenario:

1. The `(bQuad**2 - (aQuad.muli(cQuad)*4))` phrase results in a `negative value`.
2. This is possible when `aQuad.muli(cQuad)*4) > bQuad**2`.
3. When we cast this negative value to `uint256` it will result in a large positive value (since negative int256 is represented in two's complement format).
4. But when `aQuad.muli(cQuad)*4) > bQuad**2` this condition occurred the transaction should have reverted.
5. But instead we are getting a large positive value as the answer which will be used to calculate the `utility` value thus providing a wrong `utility` value.

## Proof of Concept

```solidity
        // FIXED_FEE * 2 because we will possibly deduct the FIXED_FEE from
        // this amount, and we don't want the final amount to be less than
        // the FIXED_FEE.
        if (absoluteValue < FIXED_FEE * 2) revert AmountError();
```

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

```solidity
        int256 disc = int256(Math.sqrt(uint256((bQuad**2 - (aQuad.muli(cQuad)*4)))));
```

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

## Tools Used
VSCode and Manual Review

## Recommended Mitigation Steps

Hence it is recommended to revert the transaction when `aQuad.muli(cQuad)*4) > bQuad**2` occurs. This can be done by implementing a `require` statement (before `int256 disc` value is calculated) as shown below:

    require(aQuad.muli(cQuad)*4) <= bQuad**2, "Wrong Discriminant");


## Assessed type

Under/Overflow
Condition will not revert when block.timestamp is == to the compared variable
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Medium Issues


| |Issue|Instances|
|-|:-|:-:|
| [M-1](#M-1) | Condition will not revert when block.timestamp is == to the compared variable | 1 |
### <a name="M-1"></a>[M-1] Condition will not revert when block.timestamp is == to the compared variable
The condition does not revert when block.timestamp is equal to the compared > or < variable. For example, if there is a check for block.timestamp > proposerSignature.expirationTimestamp then there should be a check for cases where block.timestamp is == to proposerSignature.expirationTimestamp

*Instances (1)*:
```solidity
File: example/1.sol

73:             block.timestamp + _duration

```


## Assessed type

Other
```swapGivenInputAmount()``` will always revert
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
```swapGivenInputAmount(...)``` will always revert leading to a Denial of service.

## Proof of Concept
A call to ```swapGivenInputAmount(...)``` will always revert owing to the logic implementation in the function.
```
    function swapGivenInputAmount(
        uint256 xBalance,
        uint256 yBalance,
        uint256 inputAmount,
        SpecifiedToken inputToken
    ) external view returns (uint256 outputAmount) {
        ...

        int256 result = _swap(
            FEE_DOWN,
            int256(inputAmount),
            int256(xBalance),
            int256(yBalance),
            inputToken
        );
        // amount cannot be less than 0
        require(result < 0);

        ...
    }
```
The ``` _swap(...)``` function returns a positive signed integer value cached in ```result```. However, the function requires that ```result``` must be negative for this reason the check will not pass and this will lead to the function reverting.


## Tools Used
Manual review.


## Recommended Mitigation Steps
Change the less than sign to greater than as shown below

```
    function swapGivenInputAmount(
        uint256 xBalance,
        uint256 yBalance,
        uint256 inputAmount,
        SpecifiedToken inputToken
    ) external view returns (uint256 outputAmount) {
        ...

        int256 result = _swap(
            FEE_DOWN,
            int256(inputAmount),
            int256(xBalance),
            int256(yBalance),
            inputToken
        );
        // amount cannot be less than 0
        require(result > 0);

        ...
    }
```


## Assessed type

DoS
Existing checks with `INT_MAX` are insufficient such that the contract becomes dysfunctional after initial deployment of some large balance(s)
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

### Impact
`EvolvingProteus.sol` contains a variety of functions which detail the price in tokens to be paid in swaps, withdraws, and deposits. In external functions such as `depositGivenInputAmount()`, as well as internal functions such as `_check_Balances()`, there exists a large number of checks to ensure proper functionality of the contract (during initial deployment and normal operations). For example, most of the external functions check that the amounts of each tokens are smaller than `int256 MAX`, while `_checkBalances()` checks that the reserve tokens satisfy a balance ratio range. The coverage is substantial. However, there is one case where overflow may still be possible such that an initial depositer may not be able to get their funds back.

Users who provide an initial deposit large enough balance of one or two of the reserve tokens may be unable to withdraw those tokens (thus being locked in the contract) due to arithmatic overflow (not during initial deployment but rather in subsequent operations).


### POC
`EvolvingProteus.sol` supports 3 different functionalities: swap, deposit, and withdraw, each with two functions. Additionally, all of these functions call `_getUtility()` at some point in their execution.

Currently, the checks placed on the input parameters of the functions only determine whether or not the parameters are less than the max `uint256` value. However, during `_getUtility()`, many of these parameters are multiplied together, hence potentially exceeding the max `uint256` value even if the previous checks were satisfied.

This becomes a problem under the assumption that `EvolvingProteus.sol` will be used as an oracle for a smart contract that handles monetary currency. In the event that an initial deposit (i.e. the deployer) contains large enough values such that multiplying the currencies in subsequent operations exceeds the max value, the withdraw oracles will always revert, causing the currency to be locked within the contract.

To demonstrate, we provide a runnable test case. Copy the following code into the `EvolvingProteus.t.sol` file within the `test` directory and call `forge test` or ` forge test --match-contract EvolvingProteusProperties --match-test testBadInput` to run.

#### Code:
```solidity=
function testBadInput() public{
        uint256 MAX_INT = 10**64;
        uint256 x0 = MAX_INT - 1;
        uint256 y0 = MAX_INT - 1;

        uint256 s0 = 10**10;


        uint256 withdrawnAmount = x0/100 * 5;
        SpecifiedToken withdrawnToken = SpecifiedToken.X;

        DUT.withdrawGivenOutputAmount(
                x0,
                y0,
                s0,
                withdrawnAmount,
                withdrawnToken
            );
    }
```

#### Expected output and explanation
The test, which simulates a withdraw from the scenario
Swap Tokens with Fee Consideration and Balance Checks
Audit: 2023-08-shell-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
Detailed description of the impact of this finding.

In the `_swap()` function, the discrepancy lies in the usage of the variable `specifiedAmount` instead of `roundedSpecifiedAmount` when checking the final balance in the `_swap()` function.

```solidity=547
        if (specifiedToken == SpecifiedToken.X) {
            computedAmount = _applyFeeByRounding(yf - yi, feeDirection);
            _checkBalances(xi + specifiedAmount, yi + computedAmount);
        } else {
            computedAmount = _applyFeeByRounding(xf - xi, feeDirection);
            _checkBalances(xi + computedAmount, yi + specifiedAmount);
        }
```

In the code snippet, when `specifiedToken == SpecifiedToken.X`, the correct calculation for the final X balance should be `xi + roundedSpecifiedAmount`. However, the code uses `xi + specifiedAmount` instead.
Similarly, if `specifiedToken == SpecifiedToken.Y`, it uses `yi + specifiedAmount`.

## 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

## Recommended Mitigation Steps
Recommend to use `roundedSpecifiedAmount` instead of `specifiedAmount` in `_checkBalances()` call. 
For example:
```solidity=547
        if (specifiedToken == SpecifiedToken.X) {
            computedAmount = _applyFeeByRounding(yf - yi, feeDirection);
            _checkBalances(xi + roundedSpecifiedAmount, yi + computedAmount);
        } else {
            computedAmount = _applyFeeByRounding(xf - xi, feeDirection);
            _checkBalances(xi + computedAmount, yi + roundedSpecifiedAmount);
        }
```


## Assessed type

Invalid Validation