xanoutas/solidity-security-findings huggingface dataset:
The auction purchase price can not be calculated correctly when vaults have large amounts of `liquidatableBalance`
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L221-L222
https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L334-L335
https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L347-L355
https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L309


# Vulnerability details

## Impact

The [swapExactAmountOut()](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L211) function helps to introduce prize tokens and get the correspondly underlying token amount.

The problem is the downcasting from `uint256` to `uint92` of [amountInForPeriod and amountOutForPeriod](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L221-L222) could be dangerous in vaults with have large amount of tokens. The [_amountInForPeriod and _amountOutForPeriod](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L221-L222) are assigned [here](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L334-L335) and those variables are used [to calculate the auction initial price](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L347-L355), then the initial price is used to [calculate the purchase price](https://github.com/GenerationSoftware/pt-v5-cgda-liquidator/blob/7f95bcacd4a566c2becb98d55c1886cadbaa8897/src/LiquidationPair.sol#L309) which is the amount of `input tokens` required to purchase the `output tokens`.

How the vaults can report ([liquidatableBalanceOf()](https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L201)) a large amount of `out tokens`?. A `VaultBooster` contract can be used by the `liquidationPair` then anyone can [transfer](https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L144) to the `VaultBooster` contract and [report a large available balance](https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L153). The `VaultBooster` doesn't have any restriction about using tokens with high decimals or limitation in the `token out` deposits. 

The auction purchase price is not calculated correctly when the vaults have large amount of tokens.

## Proof of Concept

Please see the next scenario:
1. `VaultBooster` is configured with a large amount of tokens us
`VaultBooster`: users tokens will be stuck if they deposited with unsupported boost tokens
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
- In `VaultBooster` contract : users can deposite their tokens to participate in boosting the chances of a vault winning.
- But in `deposit` function: users can deposit **any** ERC20 tokens without verifying if the token is supported or not (has a boost set to it; registered in `_boosts[_token]`).

- As there's no mechanism implemented in the contract for users to retreive their deposited tokens if these tokens are not supported; then they will lose them unless withdrawn by the `VaultBooster` owner; and then the owner transfers these tokens back to the users.
- If this behaviour is intended by design; then there must be a machanism to save unsupported deposited tokens with user address and amount; and another withdraw function accessible by the owner that enables transferring stuck tokens to their owners; or simply make `deposit` function reverts if the token is unsupported.

## Proof of Concept

- Code:

[Line 171-176](https://github.com/GenerationSoftware/pt-v5-vault-boost/blob/9d640051ab61a0fdbcc9500814b7f8242db9aec2/src/VaultBooster.sol#L171-L176)

```solidity
File: pt-v5-vault-boost/src/VaultBooster.sol
Line 171-176:
  function deposit(IERC20 _token, uint256 _amount) external {
    _accrue(_token);
    _token.safeTransferFrom(msg.sender, address(this), _amount);

    emit Deposited(_token, msg.sender, _amount);
  }
```

- Foundry PoC:

1. A `MockERC20.t.sol` contract is added to the test folder to simulate the user experience (miting/approving..),

```solidity
pragma solidity 0.8.19;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockERC20 is ERC20 {
  constructor() ERC20("MockToken", "MT") {}

  function mint(address account, uint256 amount) public returns (bool) {
    _mint(account, amount);
    return true;
  }
}
```

add remappings to the `foundry.toml`:  
 remappings = ["@openzeppelin/=lib/openzeppelin-contracts/"]

2.  This test is set in `VaultBooster.t.sol` file, where a user deposits unsuppotred token (basically no boosts were set),tries to liquidate but the call will revert, then the unsupported tokens can be withdrawn by the owner only (and not transferred to the original depositor):
    add this import line at the top of the test file:

```solidity
import "./MockERC20.t.sol";
```

add this test `testDepositWithUnsupportedToken()` to the `VaultBooster.t.sol` file:

```solidity
  function testDepositWithUnsupportedToken() public {
    //0- minting unsupportedToken to the user
    address user = address(0x2);
    uint256 userBalance = 1e18;
    MockERC20 unsupportedToken = new MockERC20();
    vm.startPrank(user);
    unsupportedToken.mint(user, userBalance);
    assertEq(unsupportedToken.balanceOf(user), userBalance);

    //1.the user deposits unsupported token (mainly there's no boosts set for any tokens):
    unsupportedToken
Use ``create2`` in factory contracts
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
After a brief discussion with one of the sponsors, we have come to the conclusion that there is a protocol risk in case of a chain re-org for the ``LiquidationPairFactory.sol``. The idea of the Vaults the protocol offers is that each vault would be linked to a single LPair. LPairs can be deployed by anybody via the factory and an owner of a vault may choose to switch his LPair due to certain parameters being more favorable for his vault. In the scenario he decides to create his own LPair a re-org might lead to him providing the wrong pair address, which if left unnoticed can lead to fund losses for him and his users, certain uncompatibilities with his vault, etc. The malicious LPair could potentially have arbitrary function bodies, since there is also no internal check to make sure they have been factory deployed.

## Proof of Concept
https://polygonscan.com/blocks_forked
As of the time of the report, there are common forks of 4-5 blocks, spiking up to 20 blocks every few hours.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Simply use the ``create2`` opcode and encode the many parameters needed to deploy a LPair to ensure uniqueness, not forgetting the salt and ``msg.sender`` to avoid front-running





## Assessed type

Other
Remote owner can't execute payable actions
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
RemoteOwner contract can't receive native asset, therefore can't execute payable actions

## Proof of Concept
There is no payable functions in this contract
```solidity
  function execute(address target, uint256 value, bytes calldata data) external returns (bytes memory) {
    ...

    (bool success, bytes memory returnData) = target.call{ value: value }(data);
    
    ...
  }
```

## Tools Used
Manual Review

## Recommended Mitigation Steps
Add payable function


## Assessed type

Governance
Result of transferFrom not checked 
Audit: 2023-08-pooltogether-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
A call to transferFrom is frequently done without checking the results . For certain ERC20 tokens, if insufficient tokens are present, no revert occurs but a result of false is returned .So, its important to check that if the tokens are not transfer from the caller to the contract then it will revert the complete function . 
## Proof of Concept
  https://github.com/GenerationSoftware/pt-v5-draw-auction/blob/f1c6d14a1772d6609de1870f8713fb79977d51c1/src/RngAuction.sol#L182
    
     IERC20(_feeToken).transferFrom(msg.sender, address(this), _requestFee);

## Tools Used
 Manual checking.
## Recommended Mitigation Steps
You can use safeTransferFrom for transferring the tokens.
  IERC20(_feeToken).safeTransferFrom(msg.sender, address(this), _requestFee);
                       Or
You can also write the code like this.
 (bool success ,) = IERC20(_feeToken).transferFrom(msg.sender, address(this), _requestFee);
   require(success, "transfer failed, couldn't send ETH");





## Assessed type

ETH-Transfer
Liquidation Router does not handle fee-on-transfer tokens
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
Because anyone can create a new pair with any tokens including fee-on-transfer tokens and deflation tokens.

When a user calls `LiquidationToken.swapExactAmountOut` with the argument `_liquidationPair.tokenIn()`, if the token is a fee-on-transfer token, the contract will receive less than the return value `amountIn`.


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

## Proof of Concept
likely these issues:
https://github.com/code-423n4/2021-05-88mph-findings/issues/16
https://github.com/code-423n4/2022-06-yieldy-findings/issues/234

## Tools Used
Manual review

## Recommended Mitigation Steps
Calculate after and before the balance of this contract to get the amount transferred to

example
```
uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));
    
IERC20(_token).safeTransferFrom(_from, address(this), _amount);
  
_actualAmountReceived = IERC20(_token).balanceOf(address(this)) - _balanceBefore;
```


## Assessed type

Token-Transfer
[H10] `MagnetarMintXChainModule.sol`:`mintBBLendXChainSGL` can be used to manipulate user positions by abusing whitelist privileges
Audit: 2024-02-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/modules/MagnetarAssetXChainModule.sol#L72


# Vulnerability details

## Impact

The Magnetar functions use `_checkSender` function to check if the caller should be allowed to perform operations on the account. The function allows operations if the caller is the owner, or if the caller is a whitelisted trusted address.

```solidity
function _checkSender(address _from) internal view {
    if (_from != msg.sender && !cluster.isWhitelisted(0, msg.sender)) {
        revert Magnetar_NotAuthorized(msg.sender, _from);
    }
}
```

However, this means that if a malicious user is able to make a whitelisted contract call magnetar functions with their own payload, they can steal tokens and wreak havoc on other user's accounts!

The function `depositYBLendSGLLockXchainTOLP` in the `MagnetarAssetXChainModule` contract uses a similar check. This function deposits and lends into markets, for the account passed in as `data.user`. Crucially, it also extracts tokens from `data.user` for these operations. So if a malicious user was able to get this function called by a whitelisted contract and pass in a malicious `data.user`, they can cause the target user to lose tokens and manipulate their market positions. This is a high severity issue and the path to attack is demonstrated below.

## Proof of Concept

The entry point is the `MagnetarMintXChainModule` contract's `mintBBLendXChainSGL` function for the attacker. This is a special function, in the sense that this sets up the system for multiple cross chain calls. This function calls the USDO function which then does an lzcompose call on another chain to the Magnetar contract again. This is a complex function and the attacker can use this to manipulate the system.

The flow of control of this function is shown below.

```mermaid
  flowchart LR
      Caller --mintBBLendXChainSGL--> MA["Magnetar\n(chain A)"];
      MA -- sendPacket() --> USDOA["USDO\n(chain A)"];
      USDOA -- lzSend --> EA["Endpoint\n(chain A)"];
      EB["Endpoint\n(chain B)"] -- lzReceive (1) --> USDOB["USDO\n(chain B)"];
      USDOB -- sendCompose (2) --> EB;
      EB -- lzcompose (3) --> USDOB;
      USDOB --depositYBLendSGLLockXchainTOLP--> MB["Magnetar\n(chain B)"];
      MB --> Markets["Markets\n(chain B)"];
```

As shown in the above diagram, the caller initiates the call to the Magnetar contract. The Magnetar contract then does a cross-chain call via the USDO contract. It also sends along a lzcompose message which will be executed on chain B. On chain B, the USDO contract receives the call and initiates the lzcompose execution. Due to how the system is desinged, this lzcompose message being executed by the USDO contract is actually a call to the Magnetar contract on chainB, specifically the `depositYBLendSGLLockXchainTOLP` function.

This can be shown by the fact that on chainA, the Magnetar encodes the lzcompose me
[H9] Missing check on helper contract allows arbitrary actions and theft of assets
Audit: 2024-02-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/modules/MagnetarOptionModule.sol#L173-L199


# Vulnerability details

## Impact

The `MagnetarOptionModule` contract implements the `exitPositionAndRemoveCollateral` function which allows users to do a series of operations which is irrelevant to the issue. The user passes in the variable `data`, and later, `data.externalData` is used to extract out relevant contract addresses. These are then checked against a whitelist.

```solidity
if (data.externalData.bigBang != address(0)) {
    if (!cluster.isWhitelisted(0, data.externalData.bigBang)) {
        revert Magnetar_TargetNotWhitelisted(data.externalData.bigBang);
    }
}
if (data.externalData.singularity != address(0)) {
    if (!cluster.isWhitelisted(0, data.externalData.singularity)) {
        revert Magnetar_TargetNotWhitelisted(data.externalData.singularity);
    }
}
```

The main issue is that the `data.externalData` also has a `marketHelper` field which is not checked against a whitelist and ends up being used.

```solidity
(Module[] memory modules, bytes[] memory calls) = IMarketHelper(data.externalData.marketHelper).repay(
    address(this), data.user, false, data.removeAndRepayData.repayAmount
);
(bool[] memory successes, bytes[] memory results) = bigBang_.execute(modules, calls, true);
```

The helper contracts are used to construct the calldata for market operations. In the above snippet, the helper contract is passed in some data, and it is expected to create a calldata out of the passed in data. The expected output is the repay module and a `call` value which when executed, will repay for the `data.user`'s account.

However, since the `marketHelper` contract is never checked against a whitelist, malicious user can pass in any address in that place. So the above call can return any data payload, and the `bigBang_.execute` will execute it without any checks. This means the malicious helper contract can return a `borrow` payload of some random user, and the contract will end up borrowing USDO against that user's position. The Magnetar contract is assumed to have approval for market operations, and thus the Magnetar's approval is essentially exploited by the attacker to perform arbitrary actions on any user's account.

This can be used by any user to steal collateral from other user's bigbang position, or borrow out usdo tokens on their position. Since this is direct theft, this is a high severity issue.

## Proof of Concept

The absence of checks is evident from the code snippet. Assuming `marketHelper` contract is malicious, we see that is used in 2 places to create payloads, which must also be deemed malicious.

```solidity
(Module[] memory modules, bytes[] memory calls) = IMarketHelper(data.externalData.marketHelper).repay(
    address(this), data.user, false, data.removeAndRepayData.repayAmount
);
```

```solidity
(Module[] memory modules, bytes[] memory ca
anyone can claim rewards for users with approval to `TapToken` or steal the whole position
Audit: 2024-02-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tap-token/blob/20a83b1d2d5577653610a6c3879dff9df4968345/contracts/tokens/TapTokenReceiver.sol#L176
https://github.com/Tapioca-DAO/tap-token/blob/20a83b1d2d5577653610a6c3879dff9df4968345/contracts/tokens/TapTokenReceiver.sol#L140-L141


# Vulnerability details

## Description
In `TapToken` there is a feature that you can interact with `TwTAP` cross chain, participate, claim rewards and exit a position.

The issue is that, in `TwTAP` to claim rewards and exit a position, the caller doing the actions needs to be approved by the owner, [`twTAP::_requireClaimPermission`](https://github.com/Tapioca-DAO/tap-token/blob/20a83b1d2d5577653610a6c3879dff9df4968345/contracts/governance/twTAP.sol#L547-L551):
```solidity
File: tap-token/contracts/governance/twTAP.sol

547:    function _requireClaimPermission(address _to, uint256 _tokenId) internal view {
548:        if (!_isApprovedOrOwner(_to, _tokenId) && !isERC721Approved(_ownerOf(_tokenId), _to, address(this), _tokenId)) {
549:            revert NotApproved(_tokenId, msg.sender);
550:        }
551:    }
```
In this case, the caller will be the TapOFT contract

Once the rewards are claimed by the TapOFT contract they are transferred back cross chain to an address provided by the caller, [`TapTokenReceiver::_claimTwpTapRewardsReceiver`](https://github.com/Tapioca-DAO/tap-token/blob/20a83b1d2d5577653610a6c3879dff9df4968345/contracts/tokens/TapTokenReceiver.sol#L176):
```solidity
File: tap-token/contracts/tokens/TapTokenReceiver.sol

176:            address sendTo_ = OFTMsgCodec.bytes32ToAddress(claimTwTapRewardsMsg_.sendParam[sendParamIndex].sendParam.to);
```
and the same for `exitPosition`, [`TapTokenReceiver::_unlockTwTapPositionReceiver`](https://github.com/Tapioca-DAO/tap-token/blob/20a83b1d2d5577653610a6c3879dff9df4968345/contracts/tokens/TapTokenReceiver.sol#L140-L141):
```solidity
File: tap-token/contracts/tokens/TapTokenReceiver.sol

140:        // Send TAP to the user address.
141:        uint256 tapAmount_ = twTap.exitPosition(unlockTwTapPositionMsg_.tokenId, unlockTwTapPositionMsg_.user);
```

Hence an attacker can spot a user that has an existing approval for their `TwTAP` position and steal their rewards or their whole position if it is expired.

## Impact
Any user that has an existing approval to `TwTAP` can have their rewards stolen by anyone or position stolen upon expiry.

Now, a user can mitigate this by grouping their claim/exit with a permit transaction, only granting the next call the allowance to transfer, then "unpermitting".

The issue is that, as shown by Trust Security here: https://www.trust-security.xyz/post/permission-denied this permit transaction can be forced to revert by executing it early.

Since the allowance is then there, the attacker can simply do their own cross chain claim/exit and that way steal the victims rewards/position.

## Proof of Concept
PoC showing how it works with `claimRewards` With just a few changes to the ex
anyone can take any whitelisted tokens approved to `Magnetar`
Audit: 2024-02-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/Magnetar.sol#L325-L333


# Vulnerability details

## Description
`Magnetar` has a call where you can interact with `OFT` contracts, [`Magnetar::_processOFTOperation`](https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/Magnetar.sol#L325-L333):
```solidity
File: tapioca-periph/contracts/Magnetar/Magnetar.sol

325:    function _processOFTOperation(
326:        address _target,
327:        bytes calldata _actionCalldata,
328:        uint256 _actionValue,
329:        bool _allowFailure
320:    ) private {
321:        if (!cluster.isWhitelisted(0, _target)) revert Magnetar_NotAuthorized(_target, _target);
322:        _executeCall(_target, _actionCalldata, _actionValue, _allowFailure);
323:    }
```

[`_executeCall`](https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/Magnetar.sol#L338-L353) simply does call on the target contract.

The issue here is that there is no validation other than that the `_target` is whitelisted.

A lot of functionality in `Magnetar` requires tokens, specifically `Singularity` tokens to be whitelisted. They also require the user to approve `Magnetar` to transfer these tokens as shown in [`MagnetarBaseModule::_extractTokens`](https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/modules/MagnetarBaseModule.sol#L100-L108). This is called on a singularity in [`MagnetarMintCommonModule::_lockOnTOB`](https://github.com/Tapioca-DAO/tapioca-periph/blob/032396f701be935b04a7e5cf3cb40a0136259dbc/contracts/Magnetar/modules/MagnetarMintCommonModule.sol#L115-L117).

Therefore, any user that has an existing approval to `Magnetar` for their singularity (or any other whitelisted token) can have their approved tokens stolen.

## Impact
Any user that has an approval for `Magnetar` for any token that is whitelisted in `Magnetar` can have their approved tokens stolen. Since some calls within `Magnetar` require this, it is likely this will affect users.

This also affects any whitelisted tokens held by the `Magnetar` contract, but as it is only a helper contract not designed to hold any tokens this isn't as impactful.

## Proof of Concept
Test in `tap-token/test/MagnetarApproval.t.sol`:
```solidity
    function testStealApprovalERC20() public {
        erc20.mint(address(ada),1e18);
        
        vm.prank(ada);
        erc20.approve(address(magnetar),1e18);

        MagnetarCall memory transfer = MagnetarCall({
            id: MagnetarAction.OFT,
            target: address(erc20),
            value: 0,
            allowFailure: false,
            call: abi.encodeWithSelector(IERC20.transferFrom.selector, address(ada), address(this), 1e18)
        });

        MagnetarCall[] memory calls = new MagnetarCall[](1);
        calls[0] = transfer;