xanoutas/solidity-security-findings huggingface dataset:
AirdropBroker.sol#L442 :` _participatePhase3` - `PHASE_3_AMOUNT_PER_USER` should be multiplied by 1e18
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/option-airdrop/AirdropBroker.sol#L459


# Vulnerability details

## Impact
Incorrect `eligibleAmount` is minted to the user.

## Proof of Concept

An eligible user can call the [_participatePhase3](https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/option-airdrop/AirdropBroker.sol#L442-L462) function and mint the aToken to them.

    function _participatePhase3(
        bytes calldata _data
    ) internal returns (uint256 oTAPTokenID) {
        uint256 _tokenID = abi.decode(_data, (uint256));


        require(PCNFT.ownerOf(_tokenID) == msg.sender, "adb: Not eligible");
        address tokenIDToAddress = address(uint160(_tokenID));
        require(
            userParticipation[tokenIDToAddress][3] == false,
            "adb: Already participated"
        );
        // Close eligibility
        // To avoid a potential attack vector, we cast token ID to an address instead of using _to,
        // no conflict possible, tokenID goes from 0 ... 714.
        userParticipation[tokenIDToAddress][3] = true;


        uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch
        uint256 eligibleAmount = PHASE_3_AMOUNT_PER_USER; -------------->>>> audit find. should be multiplied by 1e18
        uint128 discount = uint128(PHASE_3_DISCOUNT);
        oTAPTokenID = aoTAP.mint(msg.sender, expiry, discount, eligibleAmount);
    }

As shown above, the eligibleAmount is incorrectly set. 

Note aoTAP has decimal value of 1e18.

## Tools Used

## Recommended Mitigation Steps

Update the [Line](https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/option-airdrop/AirdropBroker.sol#L459C2-L459C2) as shown below

uint256 eligibleAmount = PHASE_3_AMOUNT_PER_USER * 1e18;


## Assessed type

Decimal
ConvexTriCryptoStrategy might not compound all rewards
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-yieldbox-strategies-audit/blob/05ba7108a83c66dada98bc5bc75cf18004f2a49b/contracts/convex/ConvexTricryptoStrategy.sol#L246


# Vulnerability details

## Impact
When compounding in ConvexTriCryptoStrategy, the number of tokens that is swapped into wETH does not account for extraRewards and tokenRewards. This can cause a loss of yield and rewards to be lost.

## Proof of Concept
In `ConvexTriCryptoStrategy._executeClaim` function restricts the number of tokens to the number of rewardContracts that are claimed from:

```js
require(
    tempData.rewardContracts.length == tempData.tokens.length,
    "ConvexTricryptoStrategy: claim data not valid"
);
...
zap.claimRewards(
    tempData.rewardContracts,
    tempData.extraRewardContracts,
    tempData.tokenRewardContracts,
    tempData.tokenRewardTokens,
    extrasTempData.depositCrvMaxAmount,
    extrasTempData.minAmountOut,
    extrasTempData.depositCvxMaxAmount,
    extrasTempData.spendCvxAmount,
    extrasTempData.options
);

for (uint256 i = 0; i < tempData.tokens.length; i++) {
    finalBalances[i] = balancesAfter[i] - balancesBefore[i];
}

//WARDEN: this data is used in `compound` to swap and compound
return (finalBalances, tempData.tokens);
```

The call to `ClaimZap.claimRewards` [from Convex](https://github.com/convex-eth/platform/blob/main/contracts/contracts/ClaimZap.sol) will also claim extraRewards and tokenRewards if passed as input and if the strategy is eligible to any of those:

```js
    for(uint256 i = 0; i < extraRewardContracts.length; i++){
        IBasicRewards(extraRewardContracts[i]).getReward(msg.sender);
    }
    //claim from multi reward token contract
    for(uint256 i = 0; i < tokenRewardContracts.length; i++){
        IBasicRewards(tokenRewardContracts[i]).getReward(msg.sender,tokenRewardTokens[i]);
    }
```

These rewards are not considered in the return data of `_executeClaim` and hence also not handled in `compound`.

## Tools Used

Manual Review

## Recommended Mitigation Steps

Dont restrict the token number to the number of rewardContracts (since most BaseRewardPools pay in the same token CRV, this check does not seem to be correct to begin with). Validate the correctness of the token list differently if necessary.


## Assessed type

Other
Lack of slippage checks on public withdraw fees function
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/Penrose.sol#L232-L248


# Vulnerability details

## Impact
```
    function withdrawAllMarketFees(
        IMarket[] calldata markets_,
        ISwapper[] calldata swappers_,
        IPenrose.SwapData[] calldata swapData_
    ) public notPaused {
        require(
            markets_.length == swappers_.length &&
                swappers_.length == swapData_.length,
            "Penrose: length mismatch"
        );
        require(address(swappers_[0]) != address(0), "Penrose: zero address");
        require(address(markets_[0]) != address(0), "Penrose: zero address");

        _withdrawAllProtocolFees(swappers_, swapData_, markets_);

        emit ProtocolWithdrawal(markets_, block.timestamp);
    }
```
Here, protocol checks for valid allowed swappers down in call context with

```
        require(swappers[swapper], "Penrose: Invalid swapper");
```
but does not have checks for `_swapData`, a malicious user can sandiwtch by calling `withdrawAllMarketFees` with zero slippage swap data

## Proof of Concept
N/A (covered in above section)

## Tools Used
Manual Review

## Recommended Mitigation Steps
Use fixed slippage threshold or make it gated function


## Assessed type

Access Control
BigBang liquidations causes YieldBox-tokens to be locked in contract
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/bigBang/BigBang.sol#L616-L626


# Vulnerability details

## Impact

When a position gets liquidated in BigBang the contract will receive YieldBox-assetId-tokens of which some are sent to the liquidator and penrose-fee-receiver. The rest will get stuck in the contract and cannot be claimed as fees in `refreshPenroseFees`. Also, the supply of USDO will not decrease, even though the liquidation reduces the total debt.

## Proof of Concept
At the end of a liquidation the BigBang contract will hold yieldbox-assetId-tokens which it can no handle. Looking at what happens in `BigBang._liquidateUser` (note the comments for explanation):

```js
// do some validation and change accounting of user
...
//transfer yieldbox-collateralId-tokens to swapper
yieldBox.transfer(
    address(this),
    address(swapper),
    collateralId,
    collateralShare
);
...
//swapper will redeem yieldbox-tokens for collateral, then
//swap it to asset (USDO) and put it into yieldBox. Then transfers
//the yieldbox-assetId-tokens to this contract
ISwapper.SwapData memory swapData = swapper.buildSwapData(
    collateralId,
    assetId,
    0,
    collateralShare,
    true,
    true // `depositToYb` this wraps USDO into YB-tokens
);
swapper.swap(swapData, minAssetMount, address(this), "");
...
(uint256 feeShare, uint256 callerShare) = _extractLiquidationFees(
    returnedShare,
    borrowShare,
    callerReward
);
```

Looking into `_extractLiquidationFees`:

```js
uint256 extraShare = returnedShare - borrowShare;
feeShare = (extraShare * protocolFee) / FEE_PRECISION; // x% of profit goes to fee.
callerShare = (extraShare * callerReward) / FEE_PRECISION; //  y%  of profit goes to caller.

yieldBox.transfer(address(this), penrose.feeTo(), assetId, feeShare);
yieldBox.transfer(address(this), msg.sender, assetId, callerShare);
```

So some of the YieldBox-assetId-tokens are sent to liquidator and penrose-feeTo. The rest however remains stuck in the BigBang contract, as YieldBox tokens with assetId that are held by BigBang are not handled anywhere else. All other state changing occurrences of assetId for reference:

```js
// buyCollateral -> transfer from `from` to swapper
yieldBox.transfer(from, address(swapper), assetId, supplyShare);

// refreshPenroseFees -> deposits USDO (not yieldbox tokens) into yieldbox and mints to msg.sender/owner
yieldBox.depositAsset(
    assetId,
    address(this),
    msg.sender,
    totalFees,
    0
);

// _repay -> redeem yieldbox-assetId-tokens from `from` for USDO and burn
uint256 toBurn = amount - toWithdraw; 
yieldBox.withdraw(assetId, from, address(this), amount, 0);
if (toBurn > 0) {
    IUSDOBase(address(asset)).burn(address(this), toBurn);
}

// _borrow -> mints and deposits USDO into yieldbox. yieldbox-assetId-tokens are minted to `to`
IUSDOBase(address(asset)).mint(address(this), amount);
asset.approve(address(yieldB
Missing validation checks on sending non blocking LZ payload
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/tokens/BaseTapOFT.sol#L88


# Vulnerability details

## Impact
In OFTCoreV2 (provided as example by LayerZero)
```
    function _send(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) internal virtual returns (uint amount) {
        _checkAdapterParams(_dstChainId, PT_SEND, _adapterParams, NO_EXTRA_GAS);

        (amount,) = _removeDust(_amount);
        amount = _debitFrom(_from, _dstChainId, _toAddress, amount); // amount returned should not have dust
        require(amount > 0, "OFTCore: amount too small");

        bytes memory lzPayload = _encodeSendPayload(_toAddress, _ld2sd(amount));
        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);

        emit SendToChain(_dstChainId, _from, _toAddress, amount);
    }
```
- It calls `_checkAdapterParams` to validate gas, chainId and package
- `(amount,) = _removeDust(_amount);` ensures there is no dust on receiving chain while converting between long and short decimals

While,

```
    function lockTwTapPosition(
        address to,
        uint256 amount, // Amount to add
        uint256 duration, // Duration of the position.
        uint16 lzDstChainId,
        address zroPaymentAddress,
        bytes calldata adapterParams
    ) external payable {
        bytes memory lzPayload = abi.encode(
            PT_LOCK_TWTAP, // packet type
            msg.sender,
            to,
            amount,
            duration
        );

        require(duration > 0, "TapOFT: Small duration");
        bytes32 senderBytes = LzLib.addressToBytes32(msg.sender);
        _debitFrom(msg.sender, lzEndpoint.getChainId(), senderBytes, amount);

        _lzSend(
            lzDstChainId,
            lzPayload,
            payable(msg.sender),
            zroPaymentAddress,
            adapterParams,
            msg.value
        );

        emit SendToChain(
            lzDstChainId,
            msg.sender,
            LzLib.addressToBytes32(to),
            0
        );
    }
```
does not have those checks, Since user can pass these params as input, it can lead to bad decimal conversion if dst chain is SD chain and gas greifing / DOS  on relayer of tapioca because of no checks on adapter params.

## Proof of Concept
N/A (covered in above section)

## Tools Used
Manual 
## Recommended Mitigation Steps


## Assessed type

Invalid Validation
Incorrect Interest Accrual Calculation in 'SGLCommon' Contract
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/singularity/SGLCommon.sol#L103


# Vulnerability details

## Description
The 'SGLCommon' contract contains a critical vulnerability in the interest accrual calculation, particularly in the computation of the 'extraAmount' used for accruing interest. The flaw arises from always dividing by 1e18, disregarding the number of decimals the token possesses. This approach introduces significant precision errors, resulting in incorrect interest accrual calculations and potential financial discrepancies for users.

The 'extraAmount' is a crucial factor in determining the interest rates and amounts applied to user holdings. However, by consistently dividing by 1e18 without considering the token's specific decimal precision, the contract produces erroneous results. Tokens with different decimal places require adjusted division factors to maintain accurate interest calculations.

## Proof of concept and Impact
Exploiting this vulnerability, attackers can manipulate the interest accrual mechanism, causing incorrect interest rates or misleading users regarding their actual interest earnings or debt.

1) Exploiting the Vulnerability:
Trigger the interest accrual process for tokens with various decimal places.
Observe the 'extraAmount' calculation during the accrual phase, always dividing by 1e18.
Note that the 'extraAmount' will be incorrect for tokens with decimals other than 18.
2) Impact:
Incorrect interest rates and amounts for tokens with decimal places different from 18.
Misleading interest accrual information for users.

## Mitigation
To address this vulnerability, modify the interest accrual calculation within the 'SGLCommon' contract to dynamically adjust the division factor based on the token's decimal precision. Consider implementing a function to fetch the token's decimal places and use it in the calculation to ensure accurate and precise interest accrual.



## Assessed type

Decimal
Reentrancy vulnerability in BaseUSDO._executeModule() function
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/BaseUSDO.sol#L365
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/BaseUSDO.sol#L366
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/usd0/BaseUSDO.sol#L369


# Vulnerability details

## Impact
the success variable in the _executeModule() function in the BaseUSDO contract is written in both line 366 and line 369. This could potentially lead to a reentrancy vulnerability.

In line 366, the success variable is set to true. In line 369, the success variable is set to the result of the delegatecall() function. This means that the value of the success variable could be changed after it has been first written.

This could be exploited by an attacker to withdraw funds from the BaseUSDO contract even if the original contract has not yet approved the withdrawal. This is because the attacker could call the _executeModule() function, and then immediately call the delegatecall() function. The delegatecall() function would change the value of the success variable, and the attacker could then withdraw funds from the BaseUSDO contract even if the original contract has not yet approved the withdrawal.

The following is a diagram that illustrates the scenario:

BaseUSDO contract
    |- _executeModule()
        |- success = true (contracts/usd0/BaseUSDO.sol#366)
        |- (success,returnData) = module.delegatecall(_data) (contracts/usd0/BaseUSDO.sol#369)
In this scenario, the attacker calls the _executeModule() function in the BaseUSDO contract. The _executeModule() function sets the success variable to true. The attacker then immediately calls the delegatecall() function. The delegatecall() function changes the value of the success variable to false, and the attacker withdraw funds from the BaseUSDO contract even if the original contract has not yet approved the withdrawal.

The reentrancy vulnerability in the BaseUSDO._executeModule() function could allow an attacker to withdraw funds from the BaseUSDO contract even if the original contract has not yet approved the withdrawal.
This could result in a loss of funds for the BaseUSDO contract and its users.
Mitigation:

The reentrancy vulnerability in the BaseUSDO._executeModule() function can be mitigated by using the SafeMath library. The SafeMath library provides a function called safeSet() that can be used to set the value of a variable without overwriting it.
Here is an example of how to use the SafeMath library to mitigate the vulnerability:
import "contracts/libs/SafeMath.sol";

contract BaseUSDO is SafeMath {

    function _executeModule(BaseUSDO.Module module, bytes _data) public {
        bool success;
        (success, _) = module.delegatecall(_data);
        success = safeSet(success, true);
    }

}
Recommendation:

The BaseUSDO team should update the BaseUSDO contract to use the SafeMath library to mitigate the reentrancy vulnerability.
The BaseUSDO team should
Signature Validation Bypass in 'permit' Function of MarketERC20.sol
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Description
The 'MarketERC20.sol' contract contains a critical vulnerability in the 'permit' function, where insufficient signature validation allows for bypassing the authentication process. This loophole enables attackers to manipulate the function by providing an invalid signature, causing the 'ECDSA.recover' method in line 276 to return 'address(0)' (zero address). If the attacker sets 'owner' as 'address(0)' in the input, they gain unauthorized access to all Zombie tokens held by 'address(0)', essentially taking ownership of these tokens or borrowing them without any restrictions.

The 'permit' function is designed to provide an owner with the ability to approve third-party addresses to spend tokens on their behalf. However, due to the flawed signature validation process, attackers can exploit this function to impersonate the zero address ('address(0)'), giving them control over Zombie tokens meant to be locked or reserved for specific purposes.

The impact of this vulnerability is severe, as it allows attackers to gain control over valuable assets and disrupt the intended financial operations within the 'MarketERC20' contract. It jeopardizes the security of the platform and undermines the trust of users.
## Proof of concept and Impact
1) Exploiting the Vulnerability:
Call the 'permit' function with an invalid signature that leads to the 'ECDSA.recover' method returning 'address(0)'.
Set 'owner' as 'address(0)' in the input parameters.
As a result, the attacker gains unauthorized access to Zombie tokens held by 'address(0)'.
2) Impact:
Unauthorized control over Zombie tokens meant for specific purposes.
Unauthorized borrowing or transfers of Zombie tokens.

## Mitigation
Require(owner!=signer); after taking the signer value from recover
As suggested in the ERC-2612 standard: https://eips.ethereum.org/EIPS/eip-2612


## Assessed type

Invalid Validation
_sendToken in tapiocaz::Balancer::rebalance() not sending native fee will lead to revert
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact
```solidity
    function _sendToken(
        address payable _oft,
        uint256 _amount,
        uint16 _dstChainId,
        uint256 _slippage,
        bytes memory _data
    ) private {
        IERC20Metadata erc20 = IERC20Metadata(ITapiocaOFT(_oft).erc20());
        if (erc20.balanceOf(address(this)) < _amount) revert ExceedsBalance();

        (uint256 _srcPoolId, uint256 _dstPoolId) = abi.decode(
            _data,
            (uint256, uint256)
        );

        IStargateRouter.lzTxObj memory _lzTxParams = IStargateRouterBase
            .lzTxObj({
                dstGasForCall: 0,
                dstNativeAmount: msg.value,
                dstNativeAddr: abi.encode(
                    connectedOFTs[_oft][_dstChainId].dstOft
                )
            });

        erc20.approve(address(router), _amount);
        router.swap(
            _dstChainId,
            _srcPoolId,
            _dstPoolId,
            _oft, //refund,
            _amount,
            _computeMinAmount(_amount, _slippage),
            _lzTxParams,
            _lzTxParams.dstNativeAddr,
            "0x"
        );
    }
```
When calling `router.swap`, it should send native fee (ETH). Not sending fee will lead to revert rebalancing operation.

The tests didn't catch this because in `StargateRouterMock`, receiving fee wasn't tested.


## Proof of Concept
1. Operator (owner) calls rebalance()
2. In `rebalance()`, if it's non-native asset, it ensures `msg.value > 0` and calls `_sendToken`
3. In `_sendToken()`, it checks token balance of contract against amount and calls `router.swap` but without sending ETH.

Without fee, router will revert.

Stargate Router example:
https://stargateprotocol.gitbook.io/stargate/composability-stargateswap.sol#swap

## Tools Used
Manual

## Recommended Mitigation Steps
Calculate and send fee during `router.swap` call.








## Assessed type

call/delegatecall
Calc token amount can be manipulated
Audit: 2023-07-tapioca-findings
Severity: MEDIUM

# Lines of code

https://github.com/Tapioca-DAO/tapioca-yieldbox-strategies-audit/blob/05ba7108a83c66dada98bc5bc75cf18004f2a49b/contracts/curve/TricryptoLPGetter.sol#L200-L203


# Vulnerability details

## Impact
```
    function _calcDepositInOneCoin(
        uint256[3] memory arr
    ) private view returns (uint256) {
        return liquidityPool.calc_token_amount(arr, true);
    }
```

This function is being used to calculate slippage, return value `calc_token_amount` can be manipulated (as described in POC section), liquidity addition and removal can bypass slippage check and sandwitched.


## Proof of Concept
Here `calc_token_amount` relies on `virtual_price` of the pool which can be heavily manipulated by re-entering after changing `virtial_price` and withdrawing in native ETH (via fallback function) due to imbalance using flashloan (read-only re-entrancy)

## Tools Used
Manual Review

## Recommended Mitigation Steps
Use offchain oracles to mark slippage checks


## Assessed type

Oracle