xanoutas/solidity-security-findings huggingface dataset:
Controlled Delegatecall Vulnerability in Singularity, BaseUSDO, USDOLeverageModule, USDOMarketModule, and USDOOptionsModule
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/Singularity.sol#L618-L629
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/BaseUSDO.sol#L361-L373
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/modules/USDOLeverageModule.sol#L133-L188
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/modules/USDOMarketModule.sol#L134-L189
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/modules/USDOOptionsModule.sol#L138-L204


# Vulnerability details

## Impact
The Singularity, BaseUSDO, USDOLeverageModule, USDOMarketModule, and USDOOptionsModule contracts all use the delegatecall function to call a function in another contract. However, the function id of the function to be called is controlled by the caller. This means that an attacker could call the delegatecall function with a function id that they control, which could allow them to execute arbitrary code in the calling contract.


## Proof of Concept
If exploited, this vulnerability could allow an attacker to steal funds from the Singularity, BaseUSDO, USDOLeverageModule, USDOMarketModule, and USDOOptionsModule contracts. It could also allow the attacker to take control of the contracts or execute other malicious code.

The following is a proof of concept for the controlled delegatecall vulnerability in the Singularity, BaseUSDO, USDOLeverageModule, USDOMarketModule, and USDOOptionsModule contracts:

pragma solidity ^0.8.0;

import "contracts/markets/singularity/Singularity.sol";
import "contracts/usd0/BaseUSDO.sol";
import "contracts/usd0/modules/USDOLeverageModule.sol";
import "contracts/usd0/modules/USDOMarketModule.sol";
import "contracts/usd0/modules/USDOOptionsModule.sol";

contract Attacker {

function exploit() public {
    // Create a new Singularity contract.
    address singularity = address(new Singularity());

    // Call the _executeModule() function in the Singularity contract, passing in a function id that we control.
    (bool success, bytes memory returnData) = singularity.delegatecall(abi.encodeWithSelector(0x42, "controlledFunction"));

    // If the call was successful, then the attacker can execute arbitrary code in the Singularity contract.
    if (success) {
        // The attacker could steal funds from the Singularity contract, take control of the contract, or execute other malicious code.
    }
}
}


## Tools Used
VScode

## Recommended Mitigation Steps

The Singularity, BaseUSDO, USDOLeverageModule, USDOMarketModule, and USDOOptionsModule contracts should be updated to use the safecall function instead of the delegatecall function. The safecall function does not allow the caller to control the function id of the function to be called, which makes it more secure.

Recommendation:

The Singularity, BaseUSDO, USDOLeverageModule, USDOMarketModule, and USDOOptionsModule contracts should be updated to use the safecall fu
The USDOMarketModule contract's lend function allows for dangerous call delegation
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOMarketModule.sol#L134-L189


# Vulnerability details

## Impact

The [USDOMarketModule contract](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOMarketModule.sol#L21) is a module that is used by the [BaseUSDO contract](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L46) to facilitate functionality for market actions. The module functionality is invoked through the invocation of a [delegatecall](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L369) within the BaseUSDO contract's _executeModule function. Additionally, the BaseUSDO contract facilitates the functionality to execute a market 'lend' action on the USDOMarketModule contract of a [destination block chain](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L408-L422). The function [encodes](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L411) the selector for the USDOMarketModule contract's [lend function](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOMarketModule.sol#L134) as part of the call data so that the function is invoked once the message has been received by the BaseUSDO contract implementation on the destination block chain. However, the lend function's [delegatecall](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOMarketModule.sol#L168) is problematic because the function invokes a delegatecall on any address that is defined as the [module](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOMarketModule.sol#L135) parameter without restriction. Because this is also a public function, a malicious user can pass the address for a contract they have deployed that has functionality with-in it to manipulate the contract's state. For example, this module contract inherits from the [LzApp contract](https://github.com/Tapioca-DAO/tapioca-sdk/blob/f1ec0fdc944f2f6360c43cb8c95a08cb337b0b43/src/contracts/lzApp/LzApp.sol#L14) which inherits Open Zeppelin's Ownable contract. This means that a contract can be deployed that includes a function with the correct [signature](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOMarketModule.sol#L169-L175) with functionality that will update the owner to another address which will then be invoked when the respective contract's address is defined as the module param
Incorrect implementation of solvent() modifier
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/Market.sol#L122


# Vulnerability details

## Impact
In Market.sol, solvent() modifier is given as below,

```Solidity

    modifier solvent(address from) {
        updateExchangeRate();
        _accrue();

        _;

        require(_isSolvent(from, exchangeRate), "Market: insolvent");
    }
```

Here the modifier has used the _accrue() directly, however while the functions being used in modifer should be conditional like require() or if..etc. Here it is used directly which might not update the status. Therefore it should be wrapped in require(). _accrue() does not have any if..else statement which could be checked within function.

## Proof of Concept
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/Market.sol#L122

## Tools Used
Manual Review

## Recommended Mitigation Steps
```Solidity

    modifier solvent(address from) {
        updateExchangeRate();
-        _accrue();
+        require(_accrue(), "accrue failed");
        _;

        require(_isSolvent(from, exchangeRate), "Market: insolvent");
    }
```


## Assessed type

Other
The USDOLeverageModule contract's leverageUp function allows for dangerous call delegation
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOLeverageModule.sol#L133-L188


# Vulnerability details

## Impact

The [USDOLeverageModule contract](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOLeverageModule.sol#L19) is a module that is used by the [BaseUSDO  contract](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L46) to facilitate functionality for leverage actions. The module functionality is invoked through the invocation of a [delegatecall](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L369) within the BaseUSDO contract's _executeModule function. Additionally, the BaseUSDO contract facilitates the functionality to execute a market 'leverage up' action on the USDOLeverageModule contract of a [destination block chain](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L424-L438). The function [encodes](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/BaseUSDO.sol#L427) the selector for the USDOLeverageModule contract's [leverageUp function](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOLeverageModule.sol#L133) as part of the call data so that the function is invoked once the message has been received by the BaseUSDO contract implementation on the destination block chain. However, the leverageUp function's [delegatecall](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOLeverageModule.sol#L169) is problematic because the function invokes a delegatecall on any address that is defined as the [module](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOLeverageModule.sol#L134) parameter without restriction. Because this is also a public function, a malicious user can pass the address for a contract they have deployed that has functionality with-in it to manipulate the contract's state. For example, this module contract inherits from the [LzApp contract](https://github.com/Tapioca-DAO/tapioca-sdk/blob/f1ec0fdc944f2f6360c43cb8c95a08cb337b0b43/src/contracts/lzApp/LzApp.sol#L14) which inherits Open Zeppelin's Ownable contract. This means that a contract can be deployed that includes a function with the correct [signature](https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/modules/USDOLeverageModule.sol#L170-L177) with functionality that will update the owner to another address which will then be invoked when the respective contract'
In the BaseTOFT, removeCollateral(), any marketHelper can be specified, allowing all the ETH to be stolen from a mTapiocaOFT with ETH as erc
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapiocaz-audit/blob/bcf61f79464cfdc0484aa272f9f6e28d5de36a8f/contracts/tOFT/BaseTOFT.sol#L190
https://github.com/Tapioca-DAO/tapiocaz-audit/blob/bcf61f79464cfdc0484aa272f9f6e28d5de36a8f/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L44
https://github.com/Tapioca-DAO/tapiocaz-audit/blob/bcf61f79464cfdc0484aa272f9f6e28d5de36a8f/contracts/tOFT/BaseTOFT.sol#L512
https://github.com/Tapioca-DAO/tapiocaz-audit/blob/bcf61f79464cfdc0484aa272f9f6e28d5de36a8f/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L240


# Vulnerability details

## Impact
All the ETH in `(m)TapiocaOFT` can be stolen, which is relevant when the underlying asset `erc` is ETH.

## Proof of Concept
`(m)TapiocaOFT` allows removing collateral from `Singularity` through a cross chain call, but the address of the `MarketHelper` is not validated. 

To send a cross chain `removeCollateral()` transaction, users call `removeCollateral()` of `BaseTOFT` (which is inherited by `(m)TapiocaOFT`), and calls `_lzSend()` internally. 

Then, the LayerZero endpoint calls `lzReceive()` in the destination chain of `(m)TapiocaOFT`, which eventually reaches `_nonBlockingLzReceive()`. Here, the `packetType` is `PT_MARKET_REMOVE_COLLATERAL` and the function `remove()` from the `BaseOFTMarketModule` is called. 

Function `remove()` enables withdrawing from the market if the `withdrawParams.withdraw` flag is true. Then, it calls `withdrawToChain()` of address `removeParams.marketHelper`, without checking its validity, with a `msg.value` of `withdrawParams.withdrawLzFeeAmount`. Thus, a malicious market can be sent as `removeParams.marketHelper` and a `withdrawParams.withdrawLzFeeAmount` of the eth balance of the `(m)TapiocaOFT` contract. The vulnerable piece of code is in the function `remove()`, below:
```solidity
function remove(bytes memory _payload) public {
    ...
    IMagnetar(removeParams.marketHelper).withdrawToChain{ // arbitrary marketHelper
        value: withdrawParams.withdrawLzFeeAmount // arbitrary value
    }(
        ybAddress,
        to,
        assetId,
        withdrawParams.withdrawLzChainId,
        LzLib.addressToBytes32(to),
        IYieldBoxBase(ybAddress).toAmount(
            assetId,
            removeParams.share,
            false
        ),
        removeParams.share,
        withdrawParams.withdrawAdapterParams,
        payable(to),
        withdrawParams.withdrawLzFeeAmount
    );
}
```

The following POC shows an attacker stealing the balance of a `TapiocaOFT` contract with ETH as underlying asset:
```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import {Test, console} from "forge-std/Test.sol";

import {TapiocaOFT} from "contracts/tOFT/TapiocaOFT.sol";
import {BaseTOFTMarketModule} from "contracts/tOFT/modules/BaseTOFTMarketModule.sol";

import {IYieldBoxBase} from "tapioca-periph/contracts/interfaces/IYieldBoxBase.sol";
import {ISendFrom} from "tapioca-periph/contracts/interfaces/ISendFrom.sol";
im
Reentrancy vulnerability in SGLLendingCommon._removeCollateral
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLendingCommon.sol#L41-L55


# Vulnerability details

## Impact
This vulnerability could allow an attacker to withdraw collateral from the SGLLendingCommon contract without actually removing it. This could result in a loss of funds for the lender.

## Proof of Concept
The SGLLendingCommon._removeCollateral function is vulnerable to reentrancy attacks. Reentrancy occurs when a contract calls another contract, and the second contract calls back to the first contract before the first contract has finished executing. This can allow the first contract to be tricked into performing unintended actions.

In the case of SGLLendingCommon._removeCollateral, the function calls the yieldBox.transfer function. The yieldBox.transfer function can call back to the SGLLendingCommon contract if the user of the yieldBox has also deposited collateral in the SGLLendingCommon contract. This could allow the user to withdraw their collateral from the SGLLendingCommon contract without actually removing it, which would effectively double-spend their collateral.

The following is a proof of concept for the vulnerability:

The attacker deposits collateral into the SGLLendingCommon contract.
The attacker calls the SGLLendingCommon._removeCollateral function, passing in the address of the yieldBox contract.
The yieldBox.transfer function calls back to the SGLLendingCommon contract.
The attacker withdraws the collateral from the SGLLendingCommon contract.
The SGLLendingCommon contract does not remove the collateral from the attacker's account.

## Tools Used
VScode
## Recommended Mitigation Steps
The following are recommended mitigation steps for this vulnerability:

The yieldBox.transfer function should be modified to not allow callbacks to the SGLLendingCommon contract.
The SGLLendingCommon contract should implement a reentrancy guard.
The SGLLendingCommon contract could use a timelock.



## Assessed type

Reentrancy
Reentrancy vulnerability in SGLCommon._removeAsset
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLCommon.sol#L223-L251


# Vulnerability details

## Impact
The function SGLCommon._removeAsset is vulnerable to reentrancy attacks. Reentrancy occurs when a contract calls another contract, and the second contract calls back to the first contract before the first contract has finished executing. This can allow the first contract to be tricked into performing unintended actions.

In the case of SGLCommon._removeAsset, the function calls the yieldBox.transfer function. The yieldBox.transfer function can call back to the SGLCommon contract if the user of the yieldBox has also deposited collateral in the SGLCommon contract. This could allow the user to withdraw their collateral from the SGLCommon contract without actually removing it, which would effectively double-spend their collateral.

This vulnerability could allow an attacker to withdraw collateral from the SGLCommon contract without actually removing it. This could result in a loss of funds for the lender.

## Proof of Concept

The SGLCommon._removeAsset function is vulnerable to reentrancy attacks. Reentrancy occurs when a contract calls another contract, and the second contract calls back to the first contract before the first contract has finished executing. This can allow the first contract to be tricked into performing unintended actions.
In the case of SGLCommon._removeAsset, the function calls the yieldBox.transfer function. The yieldBox.transfer function can call back to the SGLCommon contract if the user of the yieldBox has also deposited collateral in the SGLCommon contract. This could allow the user to withdraw their collateral from the SGLCommon contract without actually removing it, which would effectively double-spend their collateral.

The following is a proof of concept for the vulnerability:
The attacker deposits collateral into the SGLCommon contract.
The attacker calls the SGLCommon._removeAsset function, passing in the address of the yieldBox contract.
The yieldBox.transfer function calls back to the SGLCommon contract.
The attacker withdraws the collateral from the SGLCommon contract.
The SGLCommon contract does not remove the collateral from the attacker's account.

## Tools Used
VScode

## Recommended Mitigation Steps
The following are some ways to mitigate the risk of reentrancy attacks in SGLCommon._removeAsset:

The yieldBox.transfer function could be modified to not allow callbacks to the SGLCommon contract.
The SGLCommon contract 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 SGLCommon contract could use a timelock. A timelock is a mechanism that prevents a contract fro
manipulate rate
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tapioca-yieldbox-strategies-audit/blob/05ba7108a83c66dada98bc5bc75cf18004f2a49b/contracts/balancer/BalancerStrategy.sol#L130
https://github.com/Tapioca-DAO/tapioca-sdk-audit/blob/90d1e8a16ebe278e86720bc9b69596f74320e749/src/contracts/YieldBox/contracts/YieldBox.sol#L102
https://github.com/Tapioca-DAO/tapioca-yieldbox-strategies-audit/blob/05ba7108a83c66dada98bc5bc75cf18004f2a49b/contracts/balancer/BalancerStrategy.sol#L271


# Vulnerability details

## Impact
using spot price as the exchange rate can be manipulated.

## Proof of Concept
1. attacker manipulates the balancer pool making eth very expensive 
2. By calling the updateCache function, the attacker updates the _cachedCalculatedAmount based on the manipulated pool price.
3. attacker deposit fund at the manipulated rate
4. attacker restores the Balancer pool to its normal price.
5. attacker calls the updateCache function again to update _cachedCalculatedAmount to reflect the normal pool price.
6. attacker withdraws the fund

## Recommended Mitigation Steps
- using oracle price


## Assessed type

Oracle
Broker Address can be Claim by a MEV Bot
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/options/oTAP.sol#L126
https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/options/oTAP.sol#L96


# Vulnerability details

## Impact
If the broker address is a malicious user, he can mint as many OTAP as he wants.

## Proof of Concept
- Protocol deploy the OTAP contract
- A Bot wait until the contract is deployed
- Then call the "brokerClaim()" straight away with his own address.
- He can then calls the "mint()" function as many time he wants.

## Tools Used
Manual Review

## Recommended Mitigation Steps
As the Broker Address can only be set once.
Set it in the constructor instead of an external function with Access Control.


## Assessed type

MEV
`exitPosition` in `TapiocaOptionBroker` may incorrectly inflate position weights
Audit: 2023-07-tapioca-findings
Severity: HIGH

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/options/TapiocaOptionBroker.sol#L316


# Vulnerability details

### Impact
Users who `participate()` and place stakes with large magnitudes may have their weight removed prematurely from `pool.cumulative`, hence causing the weight logic of participation to be wrong. `pool.cumulative` will have an incomplete image of the actual pool hence allowing future users to have divergent power when they should not. In particular, this occurs during the `exitPosition()` function.

### Proof of Concept 
This vulnerability stems from `exitPosition()` using the current `pool.AverageMagnitude` instead of the respective magnitudes of the user's weights to update `pool.cumulative` on line 316. Hence, when users call `exitPosition()`, the amount that `pool.cumulative` is updated but may not be representative of the weight of the user's input.

Imagine if we have three users, Alice, Bob, and Charlie who all decide to call `participate()`. Alice calls `participate()` with a smaller amount and a smaller time, hence having a weight of 10. Bob calls `participate()` with a larger amount and a larger time, hence having a weight of 50. Charlie calls `participate()` with a weight of 20.
#### Scenario 

+ Alice calls `participate()` first at time 0 with the aforementioned amount and time. The `pool.cumulative` is now 10 and the `pool.AverageMagnitude` is 10 as well. Alice's position will expire at time 10.
+ Bob calls `participate()` at time 5. The `pool.cumulative` is now 10 + 50 = 60 and the `pool.AverageMagnitude` is 50.
+ Alice calls `exitPosition()` at time 10. `pool.cumulative` is 60, but `pool.AverageMagnitude` is still 50. Hence, `pool.cumulative` will be decreased by 50, even though the weight of Alice's input is 10.
+ Charlie calls `participate` with weight 20. Charlie will have divergent power in the pool with both Bob and Charlie, since 20 > `pool.cumulative` (10).
...

If Alice does not participate at all, Charlie will not have divergent power in a pool with Bob and Charlie, since the `pool.cumulative` = Bob's weight = 50 > Charlie's weight (20).



We have provided a test to demonstrate the `pool.cumulative` inflation. Copy the following code into`tap-token-audit/test/oTAP/tOB.test.ts` as one of the tests.
```typescript=
it('POC', async () => {
        const {
            signer,
            tOLP,
            tOB,
            tapOFT,
            sglTokenMock,
            sglTokenMockAsset,
            yieldBox,
            oTAP,
        } = await loadFixture(setupFixture);

        // Setup tOB
        await tOB.oTAPBrokerClaim();
        await tapOFT.setMinter(tOB.address);

        // Setup - register a singularity, mint and deposit in YB, lock in tOLP
        const amount = 3e10;
        const lockDurationA = 10;
        const lockDurationB = 100;
        await tOLP.registerSingularity(
            sglTokenMock.address,
            sglToken