xanoutas/solidity-security-findings huggingface dataset:
REENTRANCY
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationRouter.sol#L63-L80
https://github.com/GenerationSoftware/remote-owner/blob/285749ab51e98afc8ebb4e4049a4348d669a3e9d/src/RemoteOwner.sol#L63-L75
https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L171-L176
https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L211-L237
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngAuction.sol#L170-L208
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngAuctionRelayerDirect.sol#L34-L45


# Vulnerability details

## Impact
In a Re-entrancy attack, a malicious contract calls back into the calling contract before the first invocation of the function is finished. This may cause the different invocations of the function to interact in undesirable ways, especially in cases where the function is updating state variables after the external calls.
This may lead to loss of funds, improper value updates, token loss, etc

## Proof of Concept
Below is an example of a simple smart contract that is vulnerable to reentrancy attacks:

```
mapping(address => uint) public balance;   

function deposit() public payable {
   balance[msg.sender] += msg.value;
}
function withdraw() public payable {
   require(balance[msg.sender] >= msg.value);
   payable(msg.sender).transfer(msg.value);
   balance[msg.sender] -= msg.value;
}
```

Explanation: In this contract, the deposit function allows users to deposit funds into their account and the withdraw function allows users to withdraw their deposited funds. However, the contract does not properly check for reentrancy, so an attacker could create a malicious contract that repeatedly calls the deposit function before calling the withdraw function, effectively stealing funds from the contract.

Below is an example of how the contract can be modified to prevent reentrancy attacks:

```
mapping(address => uint) public balance;
bool public reentrancyLock;

function deposit() public payable {
   require(!reentrancyLock);
   reentrancyLock = true;
   balance[msg.sender] += msg.value;
   reentrancyLock = false;
}
function withdraw() public payable{
   require(balance[msg.sender] >= msg.value);
   payable(msg.sender).transfer(msg.value);
   balance[msg.sender] -= msg.value;
}
```

Explanation: In this example, a reentrancyLock variable is added to the contract. The deposit function now checks if the reentrancyLock variable is true before allowing the deposit to occur. If the variable is true, the deposit will not occur and the attacker will not be able to steal funds. The reentrancyLock variable is set to true before the deposit and set back to false after, this way the contract can only be called once at a t
UNCHECKED TRANSFER
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
Some tokens do not revert the transaction when `transferFrom` fails and returns `False`. Hence we must check the return value after calling the transfer or transferFrom function.

## Proof of Concept
Check the last answer here:
https://ethereum.stackexchange.com/questions/136039/what-is-best-practice-for-transferfrom-out-of-these-two-ways
In short: 
Using `token.transferFrom(msg.sender, addr, amount);` is NOT enough. The risk is that you're assuming the transfer was successful when actually it wasn't. Example of tokens that don't revert: ZRX, HT, WOO.
The safest method is using this:

`(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'token transfer from sender failed');`
This is the one used by Openzeppelin's SafeERC20 library.

## Tools Used
Manual Report

## Recommended Mitigation Steps
Use OpenZeppelin SafeERC20's safetransfer and safetransferFrom functions.


## Assessed type

Token-Transfer
Wrong Type for Time Related Variable
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
uint8, uint16 was used as Type to declare Time Related Variable in the LiquidationPair.sol contract, this totally wrong as except otherwise stated, seconds is the standard time frame in solidity and the number of digits needed will be too large for uint8 and uint16 to handle causing overflow errors and denial of service.

## Proof of Concept
```solidity
69.   uint16 _period;
...
340. _period = uint16(__period);
```
these two line of code in the LiquidationPair.sol contract shows a time related variable being declared and assigned with uint16 which is totally wrong
## Tools Used
Solidity, manual review
## Recommended Mitigation Steps
uint64 is still a better option as 2^64-1 would be large enough to handle time values



## Assessed type

Math
removeFromAllTicks() withdraws all tick assets before deposit and withdraw re-deposit them  creates a reentrancy attacks.
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L313-L317
https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L330-L332


# Vulnerability details

## Impact
reentrancy attacks can result to stolen funds 

## Proof of Concept 
The key issue is that removeFromAllTicks() calls removeFromTick(index) in a loop, which calls lendingPool.withdraw() and tr.withdraw(). These external calls could trigger a reentrant call back into the contract before the loop finishes.

The lendingPool.withdraw() or tr.withdraw() calls could trigger a reentrant call back into deposit() or withdraw() before the loop finishes withdrawing from all ticks. This could lead to inconsistent state or enabling reentrancy attacks. 

Vulnerability arises because removeFromAllTicks() withdraws all tick assets before deposit and withdraw re-deposit them. This creates a reentrancy vulnerability - if deposit or withdraw is re-entered before re-depositing assets, the funds could be stolen:
- Attacker calls deposit or withdraw
- removeFromAllTicks() executes, draining all funds from the contract
- Before re-depositing funds, attacker makes a second call to deposit or withdraw
- Second call executes removeFromAllTicks() again before first call finishes re-depositing funds
- All funds are withdrawn a second time and sent to the attacker

## Tools Used 
Manual

## Recommended Mitigation Steps


## Assessed type

Reentrancy
The system is subjected to Cross-Contract Reentrancy due to Insufficient validation for tokens, source and liquidity Pairs
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
A malicious actor can gain control of the liquidation process which can manipulate the POOL token price

## Proof of Concept
Almost all the pieces of the protocol are open to everyone with no guard, and that can cause a serious problem.
consider the following scenario that the attacker can do:
1- create a fake token and mint a large enough amount of it.
2-  deploy a vault for that token
3- buy some POOL tokens
4- deploy a liquidationPair using liquidationPairFactory (to be registered)
5- deploy a swap source with both tokens and with the liquidate function I mentioned above he gains control of the flow and can do malicious actions to gain more prize


## Tools Used
manual review
## Recommended Mitigation Steps
add more strict validations and limit the allowed tokens to be used in vaults


## Assessed type

Context
Calculations like valueX8 and liquidity do not account for potential rounding errors
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L268
https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L277


# Vulnerability details

## Impact
- These small inaccuracies could accumulate and cause the total supply of liquidity tokens to not exactly match the vault holdings. 
- This could allow an attacker to potentially deposit tokens, get liquidity that is slightly higher than what they should based on the rounding error, and withdraw more assets than they deposited

## Proof of Concept
The rounding errors in calculations like valueX8 and liquidity can accumulate over time and lead to inaccuracies.

The key areas where rounding errors can occur are: 
1. valueX8 calculation - Here the amount is multiplied by the asset price (a uint) and then divided by the token decimals (a power of 10). This can lead to loss of precision :https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L268

2. liquidity calculation - Here valueX8 and vaultValueX8 are multiplied and divided, again potentially losing precision : https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L277 

Over many deposits and withdrawals, these small rounding errors can accumulate and lead to the total liquidity minted being inaccurate compared to the actual assets deposited.

## Tools Used 
Manual

## Recommended Mitigation Steps 
calculations involving division should aim to keep the intermediate values in the highest precision possible before dividing.


## Assessed type

Other
The treasury address can be updated by the contract owner to point to a malicious address after deployment
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L58
https://github.com/code-423n4/2023-08-goodentry/blob/71c0c0eca8af957202ccdbf5ce2f2a514ffe2e24/contracts/GeVault.sol#L108-L109


# Vulnerability details

## Impact
Any fees or funds sent to the treasury could potentially be stolen or manipulated

## Proof of Concept 
The treasury address can be updated by the contract owner to point to a malicious address after deployment. This presents a risk as the treasury receives all the deposit fees 

The setTreasury function allows the contract owner to update the treasury address. There are no restrictions on what address can be set.
A proof of concept exploit would be:
1. Deploy the contract with a trusted treasury address
2. Wait for users to deposit assets and fees to be collected by the treasury
3. The owner calls setTreasury and sets it to a malicious contract they control
4. When new fees are collected, they are sent to the malicious contract instead of the intended treasury


## Tools Used
Manual
## Recommended Mitigation Steps 
setTreasury could require a timelock so there is a delay between updating the address and when it takes effect


## Assessed type

Other
Too many rewards are distributed when a draw is closed
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L178-L184
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L154-L157
https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/26557afa439934afc080eca6165fe3ce5d4b63cd/src/PrizePool.sol#L366
https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/26557afa439934afc080eca6165fe3ce5d4b63cd/src/abstract/TieredLiquidityDistributor.sol#L374


# Vulnerability details

## Impact
A relayer completes a prize pool draw by calling `rngComplete` in `RngRelayAuction.sol`. This method closes the prize pool draw with the relayed random number and distributes the rewards to the RNG auction recipient and the RNG relay auction recipient. These rewards are calculated based on a fraction of the prize pool reserve rather than an actual value.

However, the current reward calculation mistakenly includes an extra `reserveForOpenDraw` amount just after the draw has been closed. Therefore the fraction over which the rewards are being calculated includes tokens that have not been added to the reserve and will actually only be added to the reserve when the next draw is finalised. As a result, the reward recipients are rewarded too many tokens. 

## Proof of Concept
Before deciding whether or not to relay an auction result, a bot can call `computeRewards` to calculate how many rewards they'll be getting based on the size of the reserve, the state of the auction and the reward fraction of the RNG auction recipient:

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

Here, the total reserve is calculated as the sum of the current reserve and and amount of new tokens that will be added to the reserve once the currently open draw is closed. This method is correct and correctly calculates how many rewards should be distributed when a draw is closed.

A bot can choose to close the draw by calling `rngComplete` (via a relayer), at which point the rewards are calculated and distributed. Below is the interesting part of this method:

```
    uint32 drawId = prizePool.closeDraw(_randomNumber);

    uint256 futureReserve = prizePool.reserve() + prizePool.reserveForOpenDraw();
    uint256[] memory _rewards = RewardLib.rewards(auctionResults, futureReserve);
```

As you can see, the draw is first closed and then the future reserve is used to calculate the rewards that should be distributed. However, when `closeDraw` is called on the pool, the `reserveForOpenDraw` for the previously open draw is added to the existing reserves. So `reserve()` is now equal to the `totalReserve` value in the earlier call to `computeRewards`. By including `reserveForOpenDraw()` w
Missing access control in RngRelayAuction::rngComplete()
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

For a draw auction to complete, a bot must relay a completed RNG result to the Prize Pool. This is done by calling rngComplete() and the data must originate from the relayer. However the rngComplete() function is missing a check that the msg.sender is the relayer so this allows anyone to call this function and pass in any data.

## Impact
The attacker has the ability to input their own data so he can input his own random number that he will benefit from and ensure that he will win. The attacker can also take advantage of the rewards that he will get and he can make them as big as possible to drain the reserves.

## Proof of Concept
https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngRelayAuction.sol#L77-L79

```solidity
77:   /// @notice The relayer that RNG results must originate from.
78:   /// @dev Note that this may be a Remote Owner if relayed over an ERC-5164 bridge.
79:   address public immutable rngAuctionRelayer;

```
As you can see here the rngAuctionRelayer is defined and the comments specify that only the relayer should have the privilege to call rngComplete().

However rngComplete() is missing this check:

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

```solidity

131: function rngComplete(
132:   uint256 _randomNumber,
133:   uint256 _rngCompletedAt,
134:   address _rewardRecipient,
135:   uint32 _sequenceId,
136:   AuctionResult calldata _rngAuctionResult
137: ) external returns (bytes32) {
138:   if (_sequenceHasCompleted(_sequenceId)) revert SequenceAlreadyCompleted();

```

The attacker can input his own data like the randomNumber,rewardFraction and etc. The only thing that he has to make sure is that he inputs the correct sequence id.

## Tools Used

Manual Review

## Recommended Mitigation Steps
Add a require statement that ensures that RngRelayAuction::rngComplete() is only callable by the auction relayer



## Assessed type

Access Control
rngComplete() function is vulnerable to an array out of bounds error
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
A malicious actor can manipulate the AuctionResult[] passed to RewardLib.rewards() to make it return a short _rewards array

## Proof of Concept
The issue is that there is no check that i stays within the bounds of _rewards. If _rewards is shorter than expected, this loop could try to access elements past the end of the array, causing an out of bounds error

## Tools Used
Manual
## Recommended Mitigation Steps 
bounds checking should be added


## Assessed type

Other
An attacker could manipulate the _rngAuctionResult to unfairly distribute more rewards to themselves
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
When the rewards are calculated using _computeRewards(), the attacker's inflated rewardFraction will be used, giving them a bigger share

## Proof of Concept
The _rngAuctionResult passed to rngComplete() is stored directly into the auctionResults array without any validation. An attacker could call rngComplete() with a manipulated _rngAuctionResult that has an inflated rewardFraction value. This would allow the attacker to receive a larger share of the rewards.

## Tools Used
Manual
## Recommended Mitigation Steps 
,_rngAuctionResult should be validated before using it. For example:
• Check that rewardFraction is within an expected range
• Ensure recipient is the address of the valid RNG relay contract
• Compare values to previously stored auction results to detect manipulation



## Assessed type

Other
The absence of proper Access Control in RngRelayAuction::rngComplete() enables anyone to prematurely conclude the Auction Process.
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

### Explanation
For the DrawAuction to be successfully completed, a specific sequence of actions must be followed, and each step holds significance. This demands a carefully designed execution flow that considers both the procedure's requirements and the authorized entities who can invoke these actions.

One pivotal function within this process is rngComplete(), which serves the purpose of finalizing the draw auction on the `toChain` and incorporating the generated random number into the prizePool. The code comments specify that only a relayer should have the privilege to call this function. Unfortunately, this crucial protocol was not adhered to, leading to an unintended vulnerability that allows anyone to execute the function as long as the sequence remains open.

### Impact
Given the ability for the caller to input their own random number instead of waiting for the one generated by the RNG, several advantages are available to the msg.sender who exploits this vulnerability. Among these advantages, the most significant is the potential for financial gain. By designating their address as the rewardRecipient, the individual can direct the rewards to themselves.
```solidity
    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);
      }
    }
```

### Recommendation
Add a require state that ensures that RngRelayAuction::rngComplete() is only callable by the auction relayer


## Assessed type

Access Control
integer underflow vulnerability in the _fractionalReward() function
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
It could cause an integer underflow when calculating the reward fraction, resulting in the attacker getting more rewards than intended. True or false, explain in details, show relevant code and explain proof of co
## Proof of Concept
The RewardLib.fractionalReward() takes _elapsedSeconds as one of its parameters. If an attacker provides a very large _elapsedSeconds value near UINT64_MAX, when it is subtracted from _auctionDurationSeconds, it could underflow and become a very small number.

## Tools Used
Manual
## Recommended Mitigation Steps
add a check to ensure _elapsedSeconds is less than _auctionDurationSeconds before calling RewardLib.fractionalReward():


## Assessed type

Under/Overflow
the _rngCompletedAt timestamp passed to rngComplete() can be manipulated by the caller to increase their reward
Audit: 2023-08-pooltogether-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
This will result in a larger reward fraction, allowing the caller to unfairly claim more of the rewards.

## Proof of Concept
The _rngCompletedAt timestamp is controlled by the caller. They can make _auctionElapsedSeconds smaller by providing a higher _rngCompletedAt to increase their reward fraction.
For example, if the real RNG completion time was 1 hour ago, they could pass a _rngCompletedAt of 30 mins ago. This makes the _auctionElapsedSeconds smaller, so the reward fraction will be higher


## Tools Used
Manual

## Recommended Mitigation Steps 
Use block.timestamp instead of relying on the passed _rngCompletedAt


## Assessed type

Other