xanoutas/solidity-security-findings huggingface dataset:
Overstatement of Available Funds Due to Logic Error
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L262-L279


# Vulnerability details

## Impact
The `_computeAvailable` function in VaultBooster.sol could potentially overstate the available balance in certain situations. Two functions rely on `_computeAvailable` for determining the available funds, such as `liquidate`, `_accrue`. 
If the overstated balance from _computeAvailable is larger than _amountOut, the function would not revert as it should when there are insufficient real funds. This would lead to an inconsistent state where boost.available reflects a balance larger than the actual tokens available in the contract, 

## Proof of Concept
The vulnerability lies in the _computeAvailable function:
`return boost.available + deltaAmount;`
If deltaAmount is greater than the actual available balance, the function can return a value larger than the real balance of the contract. Thus impacting the normal functioning of functions that rely on _computeAvailable, such as `liquidate` and `_accrue`. 

## Tools Used

Manual review

## Recommended Mitigation Steps

To prevent this from happening, an additional check should be added in `_computeAvailable` function to ensure that the returned value does not exceed the contract's actual balance.
This could be implemented at the end of `computeAvailable`.
```
uint256 computedAvailable = boost.available + deltaAmount;
return computedAvailable <= availableBalance ? computedAvailable : availableBalance;
```



## Assessed type

Invalid Validation
Protocol won't work with tokens that can prevent transfers
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationRouter.sol#L69
https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L173
https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L193


# Vulnerability details

## Impact
There are various tokens  and token standards that can result in transfers being stopped, blocked, blacklisted, paused or disallowed. This entails protocols may function well with these tokens up until a time when any of above measures activated leading to inability to perform transfers into and out of the protocol

## Proof of Concept
Tokens such as ERC20Pausable, Pausable Tokens like WBTC,  ERC1400, Polymath like tokens; it implies the all instances mentioned in the links provided will not function for transfers. Whats worse is tokens with blacklisting capabilities may block contract addresses of protocol which renders them incapable to send and receive these tokens to function fully.

e.g in instances below
IERC20(collateralAsset).safeTransfer(ROEROUTER.treasury(), feeAmount);
// if collateralAsset is asset that can be paused for transfers then cant send fees to treasury

IERC20(_liquidationPair.tokenIn()).safeTransferFrom(...
// LiquidationPair.sol cant transfer in tokenIn from user 

_token.safeTransferFrom(msg.sender, address(this), _amount);
// users cant deposit token into VaultBooster.sol contract that is used to liquidate arbitrary tokens for a vaul

_token.transfer(msg.sender, _amount); 
// users cant withdraw the token from VaultBooster.sol 

...function liquidate(...) {
....IERC20(_tokenOut).safeTransfer(_account, _amountOut);
}
// users cant liquidate tokens 

etc

## Tools Used
Manual Analysis

## Recommended Mitigation Steps
It is recommended such tokens be disallowed from being used with the protocol
Consider a whitelist of allowed tokens


## Assessed type

Token-Transfer
[M-01] Denial of Service with failed call Dos
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/remote-owner/blob/285749ab51e98afc8ebb4e4049a4348d669a3e9d/src/RemoteOwner.sol#L67


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
External calls can fail accidentally or deliberately, which can cause a DoS condition in the contract. To minimize the damage caused by such failures, it is better to isolate each external call into its own transaction that can be initiated by the recipient of the call. This is especially relevant for payments, where it is better to let users withdraw funds rather than push funds to them automatically (this also reduces the chance of problems with the gas limit).

## Proof of Concept
Provide direct links to all referenced code in GitHub. 
```sol
https://github.com/GenerationSoftware/remote-owner/blob/285749ab51e98afc8ebb4e4049a4348d669a3e9d/src/RemoteOwner.sol#L67
    (bool success, bytes memory returnData) = target.call{ value: value }(data);
```
Add screenshots, logs, or any other relevant proof that illustrates the concept.
POC
```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { RemoteOwner } from "/Users/williamsmith/Documents/2023-08-pooltogether/remote-owner/src/RemoteOwner.sol";

contract AttackRemoteOwner {

    RemoteOwner public target;
 
  constructor(RemoteOwner _target) public
    {
        target = RemoteOwner(_target);
    }


  function attack(RemoteOwner _target) public payable {
  
            target.execute(address(target), 111 ether, "Ox20");  
        
        }

}
```

NB: Victim address in this test case is 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
Test Case
1. Deploy contract named AttackRemoteOwner.sol at victim address named RemoteOwner.sol.
2. Go to attack button and enter victim contract address.
3. Click attack button.
4. Dos occurs.

## Tools Used
VS Code

## Recommended Mitigation Steps
Avoid using the call function.
use require statement on call.


## Assessed type

DoS
swapExactAmountOut() no deadline protection
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationRouter.sol#L63


# Vulnerability details

## Impact
no deadline protection , users may suffer losses

## Proof of Concept
`LiquidationRouter.swapExactAmountOut()` use for swap `tokens`.
However, currently only `_amountInMax` slippage protection is provided, and not `deadline` protection like the common `AMMS` protection.

The role of the `deadline` protection is described below

```text
AMMs provide their users with an option to limit the execution of their pending actions, such as swaps or adding and removing liquidity. The most common solution is to include a deadline timestamp as a parameter (for example see Uniswap V2 and Uniswap V3). If such an option is not present, users can unknowingly perform bad trades:

Alice wants to swap 100 tokens for 1 ETH and later sell the 1 ETH for 1000 DAI.

The transaction is submitted to the mempool, however, Alice chose a transaction fee that is too low for miners to be interested in including her transaction in a block. The transaction stays pending in the mempool for extended periods, which could be hours, days, weeks, or even longer.

When the average gas fee dropped far enough for Alice's transaction to become interesting again for miners to include it, her swap will be executed. In the meantime, the price of ETH could have drastically changed. She will still get 1 ETH but the DAI value of that output might be significantly lower.

She has unknowingly performed a bad trade due to the pending transaction she forgot about.

An even worse way this issue can be maliciously exploited is through MEV:

The swap transaction is still pending in the mempool. Average fees are still too high for miners to be interested in it.

The price of tokens has gone up significantly since the transaction was signed, meaning Alice would receive a lot more ETH when the swap is executed. But that also means that her maximum slippage value (sqrtPriceLimitX96 and minOut in terms of the Spell contracts) is outdated and would allow for significant slippage.

A MEV bot detects the pending transaction. Since the outdated maximum slippage value now allows for high slippage, the bot sandwiches Alice, resulting in significant profit for the bot and significant loss for Alice.
```
```solidity
  function swapExactAmountOut(
    LiquidationPair _liquidationPair,
    address _receiver,
    uint256 _amountOut,
    uint256 _amountInMax
  ) external onlyTrustedLiquidationPair(_liquidationPair) returns (uint256) {
    IERC20(_liquidationPair.tokenIn()).safeTransferFrom(
      msg.sender,
      _liquidationPair.target(),
      _liquidationPair.computeExactAmountIn(_amountOut)
    );

    uint256 amountIn = _liquidationPair.swapExactAmountOut(_receiver, _amountOut, _amountInMax);

    emit SwappedExactAmountOut(_liquidationPair, _receiver, _amountOut, _amountInMax, amountIn);

    return amountIn;
  }
```



## T
RngRelayAuction.rngComplete() DOS attack
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L170


# Vulnerability details

## Impact
If the recipient maliciously enters the blacklist of `priceToken`, it may cause `rngComplete()` to fail to execute successfully

## Proof of Concept
The current implementation of `RngRelayAuction.rngComplete()` immediately transfers the `prizeToken` to the `recipient`

```solidity
  function rngComplete(
    uint256 _randomNumber,
    uint256 _rngCompletedAt,
    address _rewardRecipient,
    uint32 _sequenceId,
    AuctionResult calldata _rngAuctionResult
  ) external returns (bytes32) {
...
    for (uint8 i = 0; i < _rewards.length; i++) {
      uint104 _reward = uint104(_rewards[i]);
      if (_reward > 0) {
@>      prizePool.withdrawReserve(auctionResults[i].recipient, _reward);
        emit AuctionRewardDistributed(_sequenceId, auctionResults[i].recipient, i, _reward);
      }
    }  
..

```solidity
contract PrizePool is TieredLiquidityDistributor {
  function withdrawReserve(address _to, uint104 _amount) external onlyDrawManager {
    if (_amount > _reserve) {
      revert InsufficientReserve(_amount, _reserve);
    }
    _reserve -= _amount;
@>  _transfer(_to, _amount);
    emit WithdrawReserve(_to, _amount);
  }

  function _transfer(address _to, uint256 _amount) internal {
    _totalWithdrawn += _amount;
@>  prizeToken.safeTransfer(_to, _amount);
  }

```

There is a risk that if `prizeToken` is a `token` with a blacklisting mechanism, such as :`USDC`. 
then `recipient` can block `rngComplete()` by maliciously entering the `USDC` blacklist. 
Since `RngAuctionRelayer` supports `AddressRemapper`, users can more simply specify blacklisted addresses via `remapTo()`


## Tools Used

## Recommended Mitigation Steps

Add `claims` mechanism, `rngComplete()` only record `cliamable[token][user]+=rewards`
Users themselves go to `claims`


## Assessed type

Context
_computeAvailable() the calculations are wrong
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L277


# Vulnerability details

## Impact
`_computeAvailable()` incorrect calculations that result in a return value greater than the current balance, causing methods such as `liquidate` to fail

## Proof of Concept
`VaultBooster._computeAvailable()` used to count the number of `tokens` currently available
There are two conditions

1. `accrue` continuously according to time
2. the final cumulative value cannot be greater than the current contract balance

The code is as follows:
```solidity
  function _computeAvailable(IERC20 _tokenOut) internal view returns (uint256) {
    Boost memory boost = _boosts[_tokenOut];
    uint256 deltaTime = block.timestamp - boost.lastAccruedAt;
    uint256 deltaAmount;
    if (deltaTime == 0) {
      return boost.available;
    }
    if (boost.tokensPerSecond > 0) {
      deltaAmount = boost.tokensPerSecond * deltaTime;
    }
    if (boost.multiplierOfTotalSupplyPerSecond.unwrap() > 0) {
      uint256 totalSupply = twabController.getTotalSupplyTwabBetween(address(vault), uint32(boost.lastAccruedAt), uint32(block.timestamp));
      deltaAmount += convert(boost.multiplierOfTotalSupplyPerSecond.intoUD60x18().mul(convert(deltaTime)).mul(convert(totalSupply)));
    }
@>  uint256 availableBalance = _tokenOut.balanceOf(address(this));
@>  deltaAmount = availableBalance > deltaAmount ? deltaAmount : availableBalance;
    return boost.available + deltaAmount;
  }
```

The current implementation code, limiting the maximum value of `deltaAmount` is wrong, using the minimum value compared to the current balance `_tokenOut.balanceOf(address(this))`.
But the current balance includes the previously accumulated `boost.available`, so normally it should be compared to the difference between the current balance and `boost.available`.

so the value returned may be larger than the current balance, and `LiquidationPair.sol ` performs `source.liquidatableBalanceOf()` and `source.liquidate()` with too large a number, resulting in a failed transfer.

## Tools Used

## Recommended Mitigation Steps

The maximum value returned should not exceed the current balance


```solidity
  function _computeAvailable(IERC20 _tokenOut) internal view returns (uint256) {
    Boost memory boost = _boosts[_tokenOut];
    uint256 deltaTime = block.timestamp - boost.lastAccruedAt;
    uint256 deltaAmount;
    if (deltaTime == 0) {
      return boost.available;
    }
    if (boost.tokensPerSecond > 0) {
      deltaAmount = boost.tokensPerSecond * deltaTime;
    }
    if (boost.multiplierOfTotalSupplyPerSecond.unwrap() > 0) {
      uint256 totalSupply = twabController.getTotalSupplyTwabBetween(address(vault), uint32(boost.lastAccruedAt), uint32(block.timestamp));
      deltaAmount += convert(boost.multiplierOfTotalSupplyPerSecond.intoUD60x18().mul(convert(deltaTime)).mul(convert(totalSupply)));
    }
    uint256 availableBal
VaultBoosterFactory allows deployment of VaultBooster with phoney PrizePool
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBoosterFactory.sol#L29


# Vulnerability details

## Impact
A malicious `VaultBooster` can be deployed via `VaultBoosterFactory` contract. Users may lose funds while interacting with such `VaultBooster`.

```Solidity
File: src/VaultBoosterFactory.sol

    function createVaultBooster(PrizePool _prizePool, address _vault, address _owner) external returns (VaultBooster) {
        VaultBooster booster = new VaultBooster(_prizePool, _vault, _owner);

        emit CreatedVaultBooster(booster, _prizePool, _vault, _owner);

        return booster;
    }
```

createVaultBooster() function allows deploying `VaultBooster` contracts. `PrizePool` runs regular draws and distributes prizes among winners. Therefore, it is very critical that in every authentic VaultBooster contract, the implementations of PrizePool are also authentic and not Phoney. Otherwise, a malicious actor/hacker could deploy an authentic VaultBooster via VaultBoosterFactory and provide malicious `PrizePool` contracts. With current implementation, PrizePool can not be identified for being it Phoney or not. In addition, the function does not validate the passed inputs too. With current implementation, address(0) can be set in createVaultBooster() which can be seen in VaultBooster.sol [constructor](https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L118-L126). Prevent these parameters from being set zero address too.

## Proof of Concept
https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBoosterFactory.sol#L29

## Tools Used
Manual review

## Recommended Mitigation Steps
Consider implementing a `PrizePool` factory contracts. In the contracts, consider tracking the addresses of deployed `PrizePool` contracts. In `VaultBoosterFactory.createVaultBooster()` function, consider checking that the passed `_prizePool` address were deployed via the respective factory contracts.


## Assessed type

Other
Wrong Implementation of Continuous Gradual Dutch Auction
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/libraries/ContinuousGDA.sol#L39


# Vulnerability details

## Impact
Breaks the core functionality of the Liquidation Pair contract.  



Usage of wrong formula for calculation of Continuous Gradual Dutch Auction results in wrong calculation of purchase price which is basically used to find the `swapAmountIn` during liquidations .

## Proof of Concept
Statements from PoolTogether Code4rena docs: 





`The LiquidationPair prices yield liquidations using a periodic Continuous Gradual Dutch Auction. It's periodic in the sense that the auction runs in periods that will be aligned with the prize pool periods. At the beginning of each period, the CGDA adjusts the emissions rate and target price so that it adapts to changing market conditions.` 

PoolTogether implementation of Continuous Gradual Dutch Auction uses formula: 

```solidity 

(k/(r))*(e**((lambda)*q)/r)-1)/(e**((lambda)*T)) 

``` 

 at:
https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/libraries/ContinuousGDA.sol#L39 

The original formula of Continuous Gradual Dutch Auction: 
```solidity 


(k/(lambda))*(e**((lambda)*q)/r)-1)/(e**((lambda)*T)) 

``` 

First Term is ` k/(lambda)` not ` (k/(r)`. 

Reference : 

[Official Paradigm Article on CGDA’s which shows the correct formula](https://www.paradigm.xyz/2022/04/gda) 

[Official Github Link of Correct Implementaion of CGDA’s by Paradigm](https://github.com/FrankieIsLost/gradual-dutch-auction/blob/master/src/ContinuousGDA.sol#L82)
  
## Tools Used
Manual Review 
## Recommended Mitigation Steps
Reimplement the first term of Formula as ` k/(lambda)` that is `k.div(_decayConstant)`. 


## Assessed type

Error
Risk of silent overflow in `rngComplete` rewards cast
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L157-L168


# Vulnerability details

## Impact

The `rngComplete` function uses the `rewards` function from the `RewardLib` library to calculates the rewards that should be given, the `_rewards` returned by the `rewards` function  are of type `uint256` but before proceeding to the reward transfer (the call to `prizePool.withdrawReserve`), the reward amounts are down casted to type `uint104`.

The issue is that the casting is performed without first checking that the values being cast can fit into the lower type (`uint104`). As a result, there is a risk of a silent overflow occurring during the casting process.

## Proof of Concept

The issue occurs in the `rngComplete` function below :

```solidity
function rngComplete(
    uint256 _randomNumber,
    uint256 _rngCompletedAt,
    address _rewardRecipient, 
    uint32 _sequenceId,
    AuctionResult calldata _rngAuctionResult
) external returns (bytes32) {
    ...

    uint256 futureReserve = prizePool.reserve() + prizePool.reserveForOpenDraw();


    // @audit calculated rewards amounts of type uint256 
    uint256[] memory _rewards = RewardLib.rewards(auctionResults, futureReserve);

    emit RngSequenceCompleted(
        _sequenceId,
        drawId,
        _rewardRecipient,
        _auctionElapsedSeconds,
        rewardFraction
    );

    for (uint8 i = 0; i < _rewards.length; i++) {
        // @audit Casting without check if value fits in lower type
        uint104 _reward = uint104(_rewards[i]); 
        if (_reward > 0) {
            prizePool.withdrawReserve(auctionResults[i].recipient, _reward);
            emit AuctionRewardDistributed(_sequenceId, auctionResults[i].recipient, i, _reward);
        }
    }

    return bytes32(uint(drawId));
}
```

As we can see the `rngComplete` function calls `RewardLib.rawards` which returns an array of reward amounts of type `uint256`, the function uses a for loop to send all the rewards but before calling `prizePool.withdrawReserve` (which is responsible for transferring the rewards) the reward amount are casted into a lower type `uint104`, we can notice that the cast is done directly without checking if the casted amount fits in this lower type which can result in a silent overflow.

Because of this issue the reward recipient may receive less reward than what was intended by the protocol.

## Tools Used

Manual review

## Recommended Mitigation Steps

Use OZ `safeCast` when casting the reward amount to `uint104`.

```solidity
function rngComplete(
    uint256 _randomNumber,
    uint256 _rngCompletedAt,
    address _rewardRecipient, 
    uint32 _sequenceId,
    AuctionResult calldata _rngAuctionResult
) external returns (bytes32) {
    ...

    for (uint8 i = 0; i < _rewards.length; i++) {
        // @audit using OZ safeCast library
        uint104 _reward = _rewards[i].toUint104(); 
        if (_reward > 0) {