xanoutas/solidity-security-findings huggingface dataset:
Anyone can call the LiquidationPair.swapExactAmountOut directly to liquidate Vault shares without sending in POOL/tokenIn tokens.
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L211-L226


# Vulnerability details

## Impact
An attacker can directly call ```LiquidationPair.swapExactAmountOut``` to liquidate without transferring any ```tokenIn``` to the target address.


## Proof of Concept
According to the protocol design, users ought to interact with the ```LiquidationRouter.swapExactAmountOut``` https://media.discordapp.net/attachments/1136026908723777627/1136753836950814761/liquidation-flow.png?width=896&height=423 to perform liquidation, this is because the function first makes a transfer of tokenIn from the sender/user to the target address. 
```
 IERC20(_liquidationPair.tokenIn()).safeTransferFrom(
      msg.sender,
      _liquidationPair.target(),
      _liquidationPair.computeExactAmountIn(_amountOut)
```
before making a call to the ```_liquidationPair.swapExactAmountOut(_receiver, _amountOut, _amountInMax);```

However, this design can be breached when a malicious user interacts with the LiquidationPair.swapExactAmountOut directly and passes in a large amountInMax without transferring any tokenIn to the target address.
The checks below will be easily passed as an equivalent amountInMax will be passed since no token transfer is happening.

```
 uint swapAmountIn = _computeExactAmountIn(_amountOut);
    if (swapAmountIn > _amountInMax) {
      revert SwapExceedsMax(_amountInMax, swapAmountIn);
```

This attack is possible because LiquidationPair.swapExactAmountOut does not have an important check to assert that msg.sender is the address of the LiquidationRouter, so any address can interact with the function and abuse it.


## Tools Used
Manual review.

## Recommended Mitigation Steps
Consider having a check to confirm that only LiquidationRouter is calling the LiquidationPair.swapExactAmountOut 
```require(msg.sender == liquidationRouterAddress, "AccessDenied");```


## Assessed type

Invalid Validation
Relay Function Exploitation via Malicious RNG Contract
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
The relay function is vulnerable to potential malicious behavior when interacting with a contract implementing the IRngAuctionRelayListener interface.
 If the _rngAuctionRelayListener contract is malicious, it could return manipulated or false returnData to the relay function, leading to unintended consequences and potential security risks. The impact of this finding includes:
Economic Exploit: The malicious contract could set an unusually high reward amount, incentivizing users to execute the relay function repeatedly. This could lead to draining the contract's balance or causing a disruption in the reward distribution mechanism.
Manipulated RNG Results: The malicious contract might return manipulated or false random number generation (RNG) results to the relay function. This could compromise the integrity of the RNG process, resulting in unfair outcomes in auctions or any other system relying on the randomness.

## Proof of Concept

    function relay(
        IRngAuctionRelayListener _rngAuctionRelayListener,
        address _relayRewardRecipient
    ) external returns (bytes memory) {
        bytes memory data = encodeCalldata(_relayRewardRecipient);
        (bool success, bytes memory returnData) = address(_rngAuctionRelayListener).call(data);
        if (!success) {
            revert DirectRelayFailed(returnData);
        }
        emit DirectRelaySuccess(_relayRewardRecipient, returnData);
        return returnData;
    }

The malicious contract is designed to behave similarly to a valid implementation of IRngAuctionRelayListener. However, when called by the relay function, it internally manipulates the random number generation and sets an inflated reward amount.
The manipulated returnData is sent back to the relay function.
As the relay function does not validate the legitimacy of the returned data, it accepts the returnData as genuine.

## Tools Used
Manual review

## Recommended Mitigation Steps
Validate Return Data: Add checks and validations to verify the legitimacy of the returnData received from the IRngAuctionRelayListener contract. Ensure that the data aligns with the expected format and range.




## Assessed type

call/delegatecall
Potential Underflow Vulnerability in Rewards Calculation
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/libraries/RewardLib.sol#L67
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L235
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L183
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L191


# Vulnerability details

## Impact
The identified smart contract contains a potential underflow vulnerability in its reward calculation process. This vulnerability could lead to unintended reward distributions, loss of funds, halting of contract execution, and security vulnerabilities if exploited by malicious actors.

## Proof of Concept

    function rewards(
    AuctionResult[] memory _auctionResults,
    uint256 _reserve
    ) internal pure returns (uint256[] memory) {
    ..
      remainingReserve = remainingReserve - _rewards[i];
    }
     
it s called in here 

    function _computeRewards(AuctionResult[] calldata __auctionResults, uint256 _totalReserve) internal returns (uint256[] memory) {
    return RewardLib.rewards(__auctionResults, _totalReserve);
    }

_computeRewards is used in these functions

    function computeRewards(AuctionResult[] calldata __auctionResults) external returns (uint256[] memory) {
    uint256 totalReserve = prizePool.reserve() + prizePool.reserveForOpenDraw();
    return _computeRewards(__auctionResults, totalReserve);
    }


    function computeRewardsWithTotal(AuctionResult[] calldata __auctionResults, uint256 _totalReserve) external returns (uint256[] memory) {
    return _computeRewards(__auctionResults, _totalReserve);
    }

## Tools Used
Manual review

## Recommended Mitigation Steps
 Utilize safe arithmetic libraries like SafeMath or equivalent to handle arithmetic operations securely and prevent underflows.




## Assessed type

Under/Overflow
Owner can take all tokens via the execute function
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/remote-owner/blob/285749ab51e98afc8ebb4e4049a4348d669a3e9d/src/RemoteOwner.sol#L63C2-L75C4 #L63-L75


# Vulnerability details

## Impact
_originChainOwner can take all tokens considering the power the execute function gives the _originChainOwner.

## Proof of Concept
https://github.com/GenerationSoftware/remote-owner/blob/285749ab51e98afc8ebb4e4049a4348d669a3e9d/src/RemoteOwner.sol#L63C2-L75C4

## Tools Used
Manual review

## Recommended Mitigation Steps
I suggest the protocol should not allow _originChainOwner to perform arbitrary execution.


## Assessed type

ETH-Transfer
Only 256 rewards can be processed at max
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L131-L176
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L167-L173


# Vulnerability details

## Impact

In function rngComplete(), the "for loop" uses an iterator with datatype of uint8 (256 values).

    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);
      }
    }

This means if the [RewardLib.rewards(.....)](https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L157C5-L157C82) returns auction results with more than 256 values, anything above 256 will not be processed.

    uint256[] memory _rewards = RewardLib.rewards(auctionResults, futureReserve);


## Tools Used

Manual review + in-house tool

## Recommended Mitigation Steps

Document clearly how many auction results are to be processed (or maximum number of participants in an auction).


## Assessed type

Loop
RngRelayAuction.sol#rngComplete - no verification for caller
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
There is no check made to make sure the transaction is coming from the ``_rngAuctionRelayer`` address, which could lead to stealing rewards and possible emptying of prize pool reserves by crafting the function parameters.

## Proof of Concept
Even though it is intended for bots to use, all of the function are public
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L131-L137
By monitoring the mempool, a malicious actor can craft a certain set of parameters and just copy the sequence id he saw in the successful RNG request. 

## Tools Used
Manual Review

## Recommended Mitigation Steps
Add a simple require check to make sure that the ``msg.sender`` is the ``_rngAuctionRelayer``.


## Assessed type

Invalid Validation
The user can be front-runned when calling liquidate() in VaultBooster 
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact

VaultBooster contract allows anyone to deposit ERC20 token (such as USDC) and, after that, liquidate() the tokens by providing prize tokens to the prizePool. The user sets liquidationPair (most likely, his own deployed liquidationPair to liquidate his tokens in the VaultBooster), then transfers prize tokens to the prizePool inside of LiquidationRouter contract and gets his USDC back (and the boost for the particular vault) by calling liquidate() in VaultBooster.sol. The problem is that anybody can front-run the user by putting his liquidationPair address as the parameter inside of swapExactAmountOut() function in the LiquidationRouter. The only check for the liquidationPair that exists is to make sure that it's an actually deployed pair. This allows an adversary to contribute the prize pool tokens and get the USDC of the owner from the VaultBooster when calling liquidate(). This is an undesired behavior as the user's intention to exchange his USDC on prize tokens (and get the boost for the vault for this swap) but he can eventually lose his USDC. 

Note: inside of the VaultBooster, liquidationPair provided by the adversary will still be msg.sender so this check will also pass.

## Proof of Concept

_liquidationPair param inside of swapExactAmountOut() in LiquidationRouter:

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

the check whether this particular _liquidationPair exists:

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

So basically anybody can put other _liquidationPair address and all the checks will be bypassed and the user will be able to call liquidate() inside of other user's VaultBooster and get his tokens (USDC, in this example):

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

## Tools Used

Manual review.

## Recommended Mitigation Steps

Change the logic so that only the owner of the VaultBooster can swap his deposited tokens on prize tokens and boost the vault.


## Assessed type

Access Control
Everyone can call `rngComplete()` and therefore withdraw all reserves
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
`RngRelayAuction.rngComplete()` misses access control. It is supposed to be called by remote owner, however it doesn't check caller. As a result anyone can withdraw all reserves manipulating random numbers.


## Proof of Concept
There is no checks of msg.sender. He can manipulate all the data
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L131-L145
```solidity
  function rngComplete(
    uint256 _randomNumber,
    uint256 _rngCompletedAt,
    address _rewardRecipient,
    uint32 _sequenceId,
    AuctionResult calldata _rngAuctionResult
  ) external returns (bytes32) {
    if (_sequenceHasCompleted(_sequenceId)) revert SequenceAlreadyCompleted();
    uint64 _auctionElapsedSeconds = uint64(block.timestamp < _rngCompletedAt ? 0 : block.timestamp - _rngCompletedAt);
    if (_auctionElapsedSeconds > (_auctionDurationSeconds-1)) revert AuctionExpired();
    // Calculate the reward fraction and set the draw auction results
    UD2x18 rewardFraction = _fractionalReward(_auctionElapsedSeconds);
    _auctionResults.rewardFraction = rewardFraction;
    _auctionResults.recipient = _rewardRecipient;
    _lastSequenceId = _sequenceId;

    ...
  }
```


## Tools Used
Manual Review

## Recommended Mitigation Steps
As I understand, RemoteOwner must control RngRelayAuction.sol. So just add owner to RngRelayAuction.sol and check msg.sender





## Assessed type

Invalid Validation
RngRelayAuction.rngComplete can be called by anyone
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
RngRelayAuction.rngComplete can be called by anyone.

## Proof of Concept
`RngRelayAuction.rngComplete` function is very important as it should provide random number to the prize pool.
It is designed to be called [by `rngAuctionRelayer`](https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L79C28-L79C45), but this check is not implemented in the code.

Because of that anyone can provide random number, that he wishes and win prizes.
## Tools Used
VsCode
## Recommended Mitigation Steps
Add caller check.


## Assessed type

Error
Lack of check in `LiquidationPair.sol#_computePeriod()` can lead to DOS
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L377-L383


# Vulnerability details

## Impact
`_computePeriod()` will revert because lack of check input validation
## Proof of Concept
In `LiquidationPair.sol`, `_computePeriod()` is used to computes the current auction period: [see here](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L377-L383). It is called in functions like `getPeriodStart()` and `_checkUpdateAuction()`.

```
377:  function _computePeriod() internal view returns (uint256) {
378:    uint256 _timestamp = block.timestamp;
379:    if (_timestamp < periodOffset) {
380:      return 0;
381:    }
382:    return (_timestamp - periodOffset) / periodLength;
383:  }
```
In L382, `_computePeriod()` will  revert if  `periodLength == 0` lead to Dos
## Tools Used
Manual review
## Recommended Mitigation Steps
1. Add check `if (periodLength == 0) revert()`
2. In L379 change from `(_timestamp < periodOffset)` to `(_timestamp <= periodOffset)`





## Assessed type

Invalid Validation
Re-org attack in factory `LiquidationPairFactory.sol`
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPairFactory.sol#L65-L108


# Vulnerability details

## Impact
Allowing creation of new `LiquidationPairs` by `Re-org attack` may adversely affect pricing in `LiquidationPair.sol` contracts.
## Proof of Concept
The `LiquidationPairFactory.sol#createPair()` function deploys a new `LiquidationPair` using the `create`, where the address derivation depends only on the arguments passed.
At the same time, some of the chains like `Arbitrum` and `Polygon` are suspicious of the reorg attack.
[LiquidationPairFactory.sol#createPair()](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPairFactory.sol#L65-L108)
```
File: LiquidationPairFactory.sol
  function createPair(
    ILiquidationSource _source,
    address _tokenIn,
    address _tokenOut,
    uint32 _periodLength,
    uint32 _periodOffset,
    uint32 _targetFirstSaleTime,
    SD59x18 _decayConstant,
    uint112 _initialAmountIn,
    uint112 _initialAmountOut,
    uint256 _minimumAuctionAmount
  ) external returns (LiquidationPair) {
    LiquidationPair _liquidationPair = new LiquidationPair( // @audit-issue Reorg Attack
      _source,
      _tokenIn,
      _tokenOut,
      _periodLength,
      _periodOffset,
      _targetFirstSaleTime,
      _decayConstant,
      _initialAmountIn,
      _initialAmountOut,
      _minimumAuctionAmount
    );


    allPairs.push(_liquidationPair);
    deployedPairs[_liquidationPair] = true;


    emit PairCreated(
      _liquidationPair,
      _source,
      _tokenIn,
      _tokenOut,
      _periodLength,
      _periodOffset,
      _targetFirstSaleTime,
      _decayConstant,
      _initialAmountIn,
      _initialAmountOut,
      _minimumAuctionAmount
    );


    return _liquidationPair;
  }
```
Optimistic rollups (Optimism/Arbitrum) are also suspect to reorgs since if someone finds a fraud the blocks will be reverted, even though the user receives a confirmation.
Can refer this an issue [previously report here](https://code4rena.com/reports/2023-04-frankencoin#m-14-re-org-attack-in-factory) to have more understanding about it.
## Tools Used
Manual review and [previously report here](https://code4rena.com/reports/2023-04-frankencoin#m-14-re-org-attack-in-factory)
## Recommended Mitigation Steps
Deploy createPair() via `create2` with `salt`.


## Assessed type

Other
Incorrect Import Path Directories
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L4-L6


# Vulnerability details

## Impact
Wrong Import Path Directories of LiquidationPair.sol contract would affect the functionality of the contract as this contract relies of the implementation of this imports

## Proof of Concept
```solidity
4. import { ILiquidationSource } from "pt-v5-liquidator-interfaces/ILiquidationSource.sol";
5. import { ILiquidationPair } from "pt-v5-liquidator-interfaces/ILiquidationPair.sol";
6. import { SD59x18, uEXP_MAX_INPUT, wrap, convert, unwrap } from "prb-math/SD59x18.sol";
```
based on the context of the LiquidationPair.sol contract location in the code base, these imports seem to be wrong

## Tools Used
Solidity, Manual Review
## Recommended Mitigation Steps
The code base should be re-accessed and reorganized to ensure right import directories


## Assessed type

Access Control
Unchecked Call Return Value
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/remote-owner/blob/285749ab51e98afc8ebb4e4049a4348d669a3e9d/src/RemoteOwner.sol#L67
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngAuctionRelayerDirect.sol#L39


# Vulnerability details

## Impact
The functions do not check the return value of low-level calls. This can lock Ether in the contract if the call fails or may compromise the contract if the ownership is being changed.
The following calls were detected without return value validations - `call`

## Proof of Concept
Check both the links:
https://swcregistry.io/docs/SWC-104/
https://coinsbench.com/unchecked-return-value-in-smart-contracts-providing-an-attack-surface-dab2eed64251#:~:text=When%20the%20return%20value%20of,be%20executed%20causing%20unexpected%20behavior.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Ensure return value is checked using conditional statements for low-level calls. We should also ensure that we log failed calls using events.


## Assessed type

call/delegatecall
Wrong Accruing executed in VaultBooster.sol
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
Accounting error in accruing at `VaultBooster.sol` will cause unexpected problems in   VaultBooster.sol contract. 

## Proof of Concept
The `_accrue` function of `VaultBooster.sol` at : 



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

 does not check whether the return variable of `_computeAvailable(_tokenOut)` i.e., ` available` is greater than `_tokenOut.balanceOf(address(this))`.  

`One main problem that could occur is underflow error while withdrawing the boosted tokens` 

Let’s consider a case of emergency, where Owner is trying to withdraw all the boosted tokens from the contract at a time. He would call `getBoost` function to get information regarding available boosted tokens. Then he will try to withdraw all boosted tokens at a time . But it will cause problems as   

```solidity 

(available balance of boosted tokens) > (_tokenOut.balanceOf(address(this)) 

``` 

 And this line shown below which is present in withdraw function will cause an underflow error: 

```solidity 

uint256 remainingBalance = availableBalance - _amount; 

```  

Because the amount entered by Owner would be _boosts[_tokenOut].available which as we can see from above is less than (_tokenOut.balanceOf(address(this)). 
## Tools Used
Manual Review 

## Recommended Mitigation Steps
Add these modifications to _accrue() : 

```solidity 

  function _accrue(IERC20 _tokenOut) internal returns (uint256) { 

    uint256 available = _computeAvailable(_tokenOut);   

  +   uint256 total =  (available > (_tokenOut.balanceOf(address(this))) ? (_tokenOut.balanceOf(address(this)) : available; 

    _boosts[_tokenOut].available = total.toUint144(); 

    _boosts[_tokenOut].lastAccruedAt = uint48(block.timestamp); 

  

    emit BoostAccrued(_tokenOut, available); 

 +   return total; 

  } 


## Assessed type

Error