xanoutas/solidity-security-findings huggingface dataset:
Reentrancy vulnerability in USDO.flashLoan() function
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/USDO.sol#L81-L104


# Vulnerability details

## Impact
The reentrancy vulnerability in the USDO contract could allow an attacker to withdraw funds from the contract even if the original contract has not yet approved the withdrawal.
This could result in a loss of funds for the USDO contract and its users.

## Proof of Concept
The flashLoan() function in the USDO contract has the potential for reentrancy.
The external call to receiver.onFlashLoan() is the call that has the potential to cause a reentrancy vulnerability.
The state variables _balances[account] and _totalSupply are both written after the call to receiver.onFlashLoan() function.
The ERC20._balances() function and ERC20._totalSupply() function can both be used in cross function reentrancies.

The proof of concept starts by creating a new contract that inherits from the USDO contract. The Attacker contract has a function called withdrawFunds() that withdraws funds from the USDO contract.

The withdrawFunds() function works by first calling the flashLoan() function in the USDO contract. The flashLoan() function borrows USDO tokens from the USDO contract and then calls the receiver.onFlashLoan() function. The receiver.onFlashLoan() function is a function that is defined by the contract that is receiving the flash loan.

In the proof of concept, the receiver.onFlashLoan() function is defined to call the withdrawFunds() function in the Attacker contract. This means that the withdrawFunds() function in the Attacker contract is called before the flashLoan() function in the USDO contract has finished executing.

This allows the withdrawFunds() function in the Attacker contract to withdraw funds from the USDO contract even if the original contract has not yet approved the withdrawal. This is because the withdrawFunds() function is called in the receiver.onFlashLoan() function, which is called by the flashLoan() function in the USDO contract.

The following is a diagram that illustrates the scenario:

USDO contract
    |- flashLoan()
        |- receiver.onFlashLoan()
            |- Attacker.withdrawFunds()
In this scenario, the attacker calls the flashLoan() function in the USDO contract. The flashLoan() function borrows USDO tokens from the USDO contract and then calls the receiver.onFlashLoan() function. The receiver.onFlashLoan() function is defined to call the withdrawFunds() function in the Attacker contract. This allows the withdrawFunds() function in the Attacker contract to withdraw funds from the USDO contract even if the original contract has not yet approved the withdrawal.

## Tools Used
VScode

## Recommended Mitigation Steps

The following mitigation steps can be taken to address the reentrancy vulnerability in the USDO contract:
Use the SafeERC20 library to prevent reentrancy vulnerabilities.
Update the USDO contract to use the SafeERC20 library.
The USDO team should also consider conducting
No slippage control while minting GLP
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-yieldbox-strategies-audit/blob/05ba7108a83c66dada98bc5bc75cf18004f2a49b/contracts/glp/GlpStrategy.sol#L166-L178


# Vulnerability details

## Impact
```
glpRewardRouter.mintAndStakeGlp(address(weth), wethAmount, 0, 0);
```
Here, minUSDG = 0 and minGlp = 0 means no slippage checks.

This can be sandwitched in certain conditions in which  delta between min and max glp price is higher due to following factors:
- delta between min and max price reported by gmx fast price feed
- delta between optimal weight of WETH (since WETH is used for minting) and current weight of WETH in GLP pool
- open interest imbalance

However, there is mint and burn fee of 0.1% on GLP and hence in usual conditions, it would be rare perform profitable sandwitch.

## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Add one of min output amount in mintAndStakeGlp (ref: https://github.com/RageTrade/delta-neutral-gmx-vaults/blob/main/contracts/libraries/DnGmxJuniorVaultManager.sol#L288-L300 )


## Assessed type

Oracle
_sendNative in tapiocaz::Balancer::rebalance() not sending ETH can break service
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapiocaz-audit/blob/bcf61f79464cfdc0484aa272f9f6e28d5de36a8f/contracts/Balancer.sol#L288


# Vulnerability details

## Impact
```solidity
    function _sendNative(
        address payable _oft,
        uint256 _amount,
        uint16 _dstChainId,
        uint256 _slippage
    ) private {
        if (address(this).balance < _amount) revert ExceedsBalance();

        routerETH.swapETH(
            _dstChainId,
            _oft, //refund
            abi.encodePacked(connectedOFTs[_oft][_dstChainId].dstOft),
            _amount,
            _computeMinAmount(_amount, _slippage)
        );
    }
```
It should check and send ETH during the `routerETH.swapETH` call but it's not sending. The router will revert leading to blocking rebalancing operation.

The tests didn't catch this because `StargateRouterETHMock` wasn't tested.

## Proof of Concept
```solidity
    function rebalance(
        address payable _srcOft,
        uint16 _dstChainId,
        uint256 _slippage,
        uint256 _amount,
        bytes memory _ercData
    )
        external
        payable
        onlyOwner
        onlyValidDestination(_srcOft, _dstChainId)
        onlyValidSlippage(_slippage)
    {
        ...

        //send
        bool _isNative = ITapiocaOFT(_srcOft).erc20() == address(0);
        if (_isNative) {
            if (msg.value <= _amount) revert FeeAmountNotSet();
            _sendNative(_srcOft, _amount, _dstChainId, _slippage);
        } else {
            if (msg.value == 0) revert FeeAmountNotSet();
            _sendToken(_srcOft, _amount, _dstChainId, _slippage, _ercData);
        }
```
1. Operator (owner) calls rebalance()
2. In `rebalance()`, if it's native asset, it checks `msg.value` against required amount and calls `_sendNative`
3. In `_sendNative()`, it checks contract balance against amount and calls `routerETH.swapETH` but without sending ETH.

The operation will revert and bubble up.

## Tools Used
Manual

## Recommended Mitigation Steps
Send ETH together using `{value: amount}`.





## Assessed type

call/delegatecall
Insufficient Authorization Checks in 'SGLLeverage' Contract Functions
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/singularity/SGLLeverage.sol#L21
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/singularity/SGLLeverage.sol#L58
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/singularity/SGLLeverage.sol#L97
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/singularity/SGLLeverage.sol#L147


# Vulnerability details

## Description
The 'SGLLeverage' contract contains critical vulnerabilities in multiple functions, including 'multiHopBuyCollateral,' 'multiHopSellCollateral,' 'sellCollateral,' and 'buyCollateral.' These functions lack proper authorization checks, allowing any user to impersonate others by setting an arbitrary 'from' address without adequate validation. Consequently, malicious actors can exploit these flaws to perform unauthorized actions on behalf of innocent users, leading to financial losses and compromising the security of the platform.

In the 'multiHopBuyCollateral' function, there is a missing verification mechanism for the 'from' address, which allows an attacker to impersonate another user during the buying process. Similarly, the 'multiHopSellCollateral' function, 'sellCollateral' function, and 'buyCollateral' function suffer from the same security flaw, enabling unauthorized users to perform actions on behalf of others without consent or proper validation.

Exploiting these vulnerabilities, attackers can manipulate the collateral transactions, perform unauthorized trades, or cause confusion and financial harm to innocent users. These unauthorized actions may also disrupt the platform's financial stability and undermine its trustworthiness.

## Impact && POC

1) Exploiting the Vulnerable Functions:
Call the 'multiHopBuyCollateral,' 'multiHopSellCollateral,' 'sellCollateral,' or 'buyCollateral' function with an arbitrary 'from' address belonging to another user.
Due to the absence of proper checks, the contract will allow unauthorized actions on behalf of the impersonated user.
2) Impact:
Unauthorized access to collateral and asset trades.
Unauthorized withdrawals or transfers of assets.

## Mitigation
To address these critical vulnerabilities, it is imperative to implement robust authorization checks in all affected functions. Validate that the 'msg.sender' matches the provided 'from' address to ensure that the caller has the necessary permissions to perform actions on behalf of the specified user. Utilize the 'require' statement to enforce these checks and prevent unauthorized access.


## Assessed type

Access Control
ARBTriCryptoOracle is prone to manipulation
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-periph-audit/blob/023751a4e987cf7c203ab25d3abba58f7344f213/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L117


# Vulnerability details

## Impact
ARBTriCryptoOracle is used to determine price of LP token of tricrypto (USDT, WBTC, WETH) on arbitrum. This pool is susceptible to re-entrancy due to bug in vyper 0.2.15.

and hence `get_virtual_price` can be manipulated which is used for pricing LP tokens.

## Proof of Concept
Arbitrum tricrypto allows to exchange/swap with native ETH as recepient

- Attacker implements fallback on their contract and calls exchange(..., use_eth=true) with flasloaned tokens on tricrypto
- It inflates `self.D` variable impacting calculation of `get_virtual_price` in rest of the call context
- Due to this, virtual_price can be decreased to very large extent
- If this price is used to calcuate slippage while swapping, adding liquidity or removing liquidity then it will lead to loss to the protocol

## Tools Used
Manual Review

## Recommended Mitigation Steps
Use latest crvUSD tricrypto pool and wait for curve team to release oracle for that or use offchain oracle


## Assessed type

Oracle
Reentrancy vulnerability in Singularity.execute
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/Singularity.sol#L181-L195


# Vulnerability details

## Impact

This vulnerability could allow an attacker to withdraw funds from the Singularity contract. This could result in a loss of funds for the user.

## Proof of Concept

The Singularity.execute function has external calls inside a loop. This could potentially lead to reentrancy attacks, as an attacker could call the function, then call back to the contract before the loop has finished executing. This could allow the attacker to withdraw funds from the contract without actually executing the function.

The attacker deposits funds into the Singularity contract.
The attacker calls the Singularity.execute function, passing in an array of data.
The attacker then calls back to the Singularity contract before the loop has finished executing.
The attacker withdraws the funds from the Singularity contract.
The Singularity contract does not execute the function, and the attacker keeps the funds.

## Tools Used
VScode
## Recommended Mitigation Steps

mitigation strategies that can be used to address the reentrancy vulnerabilities in these functions:

The functions could be modified to not allow callbacks to the contract. This would prevent the attacker from calling back to the contract before the loop has finished executing.
The contracts could implement a reentrancy guard. A reentrancy guard is a variable that is set to true when the contract is executing a function that is vulnerable to reentrancy attacks. The function will then check the reentrancy guard before it calls another contract. If the reentrancy guard is true, the function will not call the other contract.
The contracts could use a timelock. A timelock is a mechanism that prevents a contract from executing a function for a specified period of time. This would prevent the attacker from calling back to the contract before the reentrancy guard has had a chance to reset.
It is important to note that there is no foolproof way to prevent reentrancy attacks. However, by following the best practices outlined above, you can significantly reduce the risk of your contracts being vulnerable to these attacks




## Assessed type

Reentrancy
TapOFT.sol: Incorrect emission value due to division by higher decimal value
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/tokens/TapOFT.sol#L253-L255


# Vulnerability details

## Impact
Incorrect emission value which will be used in per week emission.

## Proof of Concept
`TapOFT.sol` has the [_computeEmission](https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/tokens/TapOFT.sol#L253-L255) function to calculate the emitted value. The output from this function is used in [emitForWeek](https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/tokens/TapOFT.sol#L197C14-L197C25).

when we look at the function `_computeEmission`

    function _computeEmission() internal view returns (uint256 result) {
        result = (dso_supply * decay_rate) / DECAY_RATE_DECIMAL;
    }

in above calculations, the precision value for each of the values are,

dso_supply  = 1e18

decay_rate = 8800000000000000 (1e16)

DECAY_RATE_DECIMAL = 1e18

The calculation is dividing extra by 2 more decimals. Hence the resulting output is lesser that actual value.


## Tools Used

## Recommended Mitigation Steps

Update the `_computeEmission` function as shown below.

    function _computeEmission() internal view returns (uint256 result) {
        result = (dso_supply * decay_rate * 100) / DECAY_RATE_DECIMAL;
    }


## Assessed type

Decimal
Reentrancy vulnerability in BigBang.execute
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/bigBang/BigBang.sol#L209-L223


# Vulnerability details

## Impact
This vulnerability could allow an attacker to withdraw funds from the BigBang contract. This could result in a loss of funds for the user.

## Proof of Concept

The BigBang.execute function has external calls inside a loop. This could potentially lead to reentrancy attacks, as an attacker could call the function, then call back to the contract before the loop has finished executing. This could allow the attacker to withdraw funds from the contract without actually executing the function.

The attacker deposits funds into the BigBang contract.
The attacker calls the BigBang.execute function, passing in an array of data.
The attacker then calls back to the BigBang contract before the loop has finished executing.
The attacker withdraws the funds from the BigBang contract.
The BigBang contract does not execute the function, and the attacker keeps the funds.


## Tools Used
VScode

## Recommended Mitigation Steps

mitigation strategies that can be used to address the reentrancy vulnerabilities in these functions:

The functions could be modified to not allow callbacks to the contract. This would prevent the attacker from calling back to the contract before the loop has finished executing.
The contracts could implement a reentrancy guard. A reentrancy guard is a variable that is set to true when the contract is executing a function that is vulnerable to reentrancy attacks. The function will then check the reentrancy guard before it calls another contract. If the reentrancy guard is true, the function will not call the other contract.
The contracts could use a timelock. A timelock is a mechanism that prevents a contract from executing a function for a specified period of time. This would prevent the attacker from calling back to the contract before the reentrancy guard has had a chance to reset.
It is important to note that there is no foolproof way to prevent reentrancy attacks. However, by following the best practices outlined above, you can significantly reduce the risk of your contracts being vulnerable to these attacks




## Assessed type

Reentrancy
Precision loss in TapiocaOptionBroker._getDiscountedPaymentAmount
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/options/TapiocaOptionBroker.sol#L538-L556
https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/option-airdrop/AirdropBroker.sol#L517-L537


# Vulnerability details


## Impact
> Note: This bug also occurs in the `AirdropBroker. _getDiscountedPaymentAmount()` function They are the exact same functions and therefore the bug also occurs in AirDropBroker. We will only be mentioning the `TapiocaOptionBroker. _getDiscountedPaymentAmount()` here for brevity's purpose.

TapiocaOptionBroker._getDiscountedPaymentAmount() does not correctly scale the rawPaymentAmount. This will cause precision loss when determining the raw payment amount.

`uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;`

As mentioned in the code comments for the _getDiscountedPaymentAmount function, both the _otcAmountInUSD and _paymentTokenValuation are scaled 1e18. This can result in precision loss due to how Solidity handles precision. 

This can in turn result in users receiving less TAP in the OTC deal.

## Proof of Concept

### Relevant code

```solidity
// From TapiocaOptionBroker.sol
//
/// @notice Computes the discounted payment amount for a given OTC amount in USD
/// @param _otcAmountInUSD The OTC amount in USD, 18 decimals
/// @param _paymentTokenValuation The payment token valuation in USD, 18 decimals
/// @param _discount The discount in BPS
/// @param _paymentTokenDecimals The payment token decimals
/// @return paymentAmount The discounted payment amount
function _getDiscountedPaymentAmount(
    uint256 _otcAmountInUSD, // AUDIT: this is mentioned to be 18 decimals in the code comments above
    uint256 _paymentTokenValuation, // AUDIT: this is mentioned to be 18 decimals in the code comments above
    uint256 _discount,
    uint256 _paymentTokenDecimals
) internal pure returns (uint256 paymentAmount) {
    // Calculate payment amount
    uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation; // AUDIT: this function should scale up the numerator because dividing 1e18 / 1e18 scaled values will result in precision loss
    paymentAmount =
        rawPaymentAmount -
        muldiv(rawPaymentAmount, _discount, 100e4); // 1e4 is discount decimals, 100 is discount percentage
    paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));
}
```

### Steps to Reproduce

1. Tapioca calculates the OTC deal where _otcAmountInUSD is 5e18 and _paymentTokenValuation is 8e17. rawPaymentAmount is calculated as 6 losing 0.25 due to precision loss. 

 
## Tools Used

Manual inspection

## Recommended Mitigation Steps

Tapioca should first scale up the numerator value before dividing. This will help maintain greater precision. Tapioca can then scale down accordingly at the end of the function when determining the paymentAmount.


## Assessed type

Math
Vulnerability in USDO Token Minting within baseUSDOStorage Contract
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDOStorage.sol#L78


# Vulnerability details

## Description
In the baseUSDOStorage contract, there is a vulnerability related to the minting of USDO tokens during its construction. Initially, the USDO token is created with 8 decimals. However, in the constructor of baseUSDOStorage, the tokens are minted with a quantity of 100k * 1e18, assuming it is equivalent to 100k. Due to this discrepancy in decimal points, an additional 10 zeros will be added to the minted token amount, resulting in unforeseen consequences and potential medium-level security risks.

## Example
Suppose the actual value of 100k is 100,000, with 8 decimals. However, due to the multiplication with 1e18 in the constructor, the tokens minted will be 100,000,000,000,000,000,000, which equals 100 trillion, instead of 100,000. This discrepancy can cause contract overflow issues, leading to misaligned user balances, incorrect financial calculations, and unexpected contract behaviors.

## Mitigation
To address this vulnerability, it is crucial to correct the token minting in the baseUSDOStorage constructor. The following measures can be taken to mitigate the problem:

Minting Correction: Ensure that in the baseUSDOStorage constructor, USDO tokens are minted with the correct quantity, taking into account the actual number of decimals for the token (8 in this specific case). Mint the token quantity equivalent to 100k with 8 decimals.


## Assessed type

Decimal
User can exit a position on behalf another user as soon as the stake duration expire
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/governance/twTAP.sol#L373
https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/governance/twTAP.sol#L522


# Vulnerability details

## Impact
An user might still want to hold the stake position of TAP even when the lock-time has been passed.
Another user can exit their positions and therefore decreased the amount of TAP tokens stake in the protocol.


## Proof of Concept
- Alice stake some TAP tokens, lock them for 2 weeks and mint an twTAP NFT token.
- Bob wait until the 2 weeks has passed and call the "releaseTap" function with Alice's token 
  Id and Alice's Address.
- Alice will have her TAP tokens back, but she might wanna hold her position longer.
- Fewer TAP tokens are being stake on the protocol.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Make sure that only the owner of the twTAP NFT can close his own position an nobody else.

Like so : 

```solidity
function releaseTap(uint256 _tokenId, address _to) external {
        require(msg.sender == ownerOf(_tokenId));
        _requireClaimPermission(_to, _tokenId);
        _releaseTap(_tokenId, _to);
    }
```



## Assessed type

Access Control