Tapioca DAO - 0xnev's results

The first ever Omnichain money market, powered by LayerZero.

General Information

Platform: Code4rena

Start Date: 05/07/2023

Pot Size: $390,000 USDC

Total HM: 136

Participants: 132

Period: about 1 month

Judge: LSDan

Total Solo HM: 56

Id: 261

League: ETH

Tapioca DAO

Findings Distribution

Researcher Performance

Rank: 32/132

Findings: 6

Award: $1,887.10

🌟 Selected for report: 1

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: unsafesol

Also found by: 0xRobocop, 0xnev, peakbolt, rvierdiiev

Labels

bug
3 (High Risk)
satisfactory
sponsor disputed
duplicate-1355

Awards

339.2691 USDC - $339.27

External Links

Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/bigBang/BigBang.sol#L721-L739 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLendingCommon.sol#L83-L98

Vulnerability details

Impact and Details

In _liquidateUser()/_orderBookLiquidation(), the internal _repay() function is never called, hence indicating that liquidator USDO balance is not burnt to repay borrower's CDP positions.

While it is true they only receive liquidation incentive based on current exchange rates, it essentially means that the liquidation mechanism is free of charge, since liquidator's do not risk their own CDP positions.

Depending on collateral type, this can cause the Tapioca's BigBang/Singularity markets to incur huge losses in the form of paying profits for liquidator's for free.

  • Liquidator's USDO balance is not updated (burned) based on current exchange rate, allowing liquidator's to arbritrage, by choosing exchange rates that favor them to liquidate, they can drain collateral in the form of rewards paid by Tapioca protocol due to liquidation bonuses
  • This allows liquidators to always keep a healthy CDP position by redepositing earned rewards and borrow more USDO
  • This also opens up for malicious borrowers to liquidate their own positions to get liquidation bonus and then redeposit, allowing them to permanently prevent positions from liquidation and incur bad debt for Singularity and BigBang markets due to payment of liquidation bonuses.

Tools Used

Manual Analysis

Recommendation

Call the internal _repay() function when liquidator's liquidate borrower's CDP position under maximum LTV ratio via liquidate() function. This forces liquidators to burn their EUSD (signifying loss)

Assessed type

Context

#0 - c4-pre-sort

2023-08-07T07:49:18Z

minhquanym marked the issue as primary issue

#1 - 0xRektora

2023-08-18T17:28:47Z

Out of scope. We mentioned that LiquidationQueue will not be audited.

#2 - c4-sponsor

2023-08-18T17:29:07Z

0xRektora marked the issue as sponsor disputed

#3 - c4-judge

2023-09-20T16:25:31Z

dmvt marked the issue as unsatisfactory: Out of scope

#4 - nevillehuang

2023-10-02T19:39:51Z

While _orderBookLiquidation() is out of scope, _liquidateUser() is. Noticed that this could be a duplicate of #1355.

#5 - dmvt

2023-10-05T14:25:38Z

Agreed. Thanks for raising the issue!

#6 - c4-judge

2023-10-05T14:25:54Z

dmvt removed the grade

#7 - c4-judge

2023-10-05T14:26:16Z

dmvt marked the issue as duplicate of #1355

#8 - c4-judge

2023-10-09T21:29:01Z

dmvt marked the issue as satisfactory

Findings Information

🌟 Selected for report: Sathish9098

Also found by: 0xSmartContract, 0xnev, Udsen, jasonxiale, rvierdiiev, tsvetanovv

Labels

bug
2 (Med Risk)
satisfactory
duplicate-1408

Awards

58.8874 USDC - $58.89

External Links

Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/bigBang/BigBang.sol#L604-L606 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLiquidation.sol#L350 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLeverage.sol#L21 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLeverage.sol#L58 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/bigBang/BigBang.sol#L336 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/bigBang/BigBang.sol#L384 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLeverage.sol#L147 https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/master/contracts/markets/singularity/SGLLeverage.sol#L97

Vulnerability details

Impact and Details

Functions lacking both slippage and deadline checks

  • BigBang._liquidateUser(): Link
  • Singularity._liquidateUser(): Link
  • SGLLeverage.multiHopBuyCollateral(): Link
  • SGLLeverage.multiHopSellCollateral(): Link

Functions lacking only deadline checks:

  • BigBang.buyCollateral(): Link
  • BigBang.sellCollateral(): Link
  • SGLLeverage.buyCollateral(): Link
  • SGLLeverage.sellCollateral(): Link

The BigBang/Singularity._liquidateUser() is called by _closedLiquidation() which is in turn called by liquidate() when liquidating CDP positions greater than maximum LTV ratios. One of the inputs is collateralToAssetSwapData calldata which allows user to input necessary swap information such as slippage.

During the liquidation process, while the data is successfully decoded, it is never checked against minimumAmount swapped out when swapping collateral to USDO, and thus liquidator slippage tolerance is never checked against amount of USDO swapped and transferred back to BigBang/Singularity.sol contract, similar to that performed in buyCollateral()/sellCollateral().

This issue also exist in LiquidationQueue.executeBids() which is called by SGLLiquidation._orderBookLiquidation(), where swapData is passed in as input but never decoded and checked.

In addition, all functions that involves a swap does not allow for the pass in of a deadline check for transaction expiration. This could mean being exposed to sandwich attacks due to being exposed to undesired slippage, and ultimately lead to lower liquidation incentives transferred to liquidators.

Tools Used

Manual Analysis

Recommendation

Ensure slippage check is performed in all functions involving a swap and consider adding an additional deadline check to prevent MEV/sandwich attacks.

Assessed type

Context

#0 - c4-pre-sort

2023-08-05T12:47:09Z

minhquanym marked the issue as duplicate of #1513

#1 - c4-judge

2023-09-29T21:47:37Z

dmvt marked the issue as satisfactory

Findings Information

🌟 Selected for report: 0xnev

Labels

bug
2 (Med Risk)
primary issue
selected for report
sponsor confirmed
M-61

Awards

1008.3444 USDC - $1,008.34

External Links

Lines of code

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

Vulnerability details

Impact and Details

In SGLCommon._getInterestRate(), the amount of fees that protocol accrue may be much lower than expected due to not converting feeAmount back to Asset amount.

feeAmount is in terms of USDO amount, and is multiplied by totalAsset.base / fullAssetAmount to essentially convert it back to base amount, that is the total asset to pay to protocol's fee receiver address.

However, this feeAmount should be multiplied by base borrowed positions represented by _totalBorrow.base instead of _totalAsset.base. This could potentially overestimate/underestimate protocol fees paid to protocol via Singularity.withdrawFeesEarned() since totalAssets used as collateral for lending USDO could be higher/lower than borrowed amount of USDO by lenders due to LTV ratio requirements.

SGLCommon.sol#L107

    function _getInterestRate()
        internal
        view
        returns (
            ISingularity.AccrueInfo memory _accrueInfo,
            Rebase memory _totalBorrow,
            Rebase memory _totalAsset,
            uint256 extraAmount,
            uint256 feeFraction,
            uint256 utilization,
            bool logStartingInterest
        )
    {
        ...
        ...
        extraAmount =
            (uint256(_totalBorrow.elastic) *
                _accrueInfo.interestPerSecond *
                elapsedTime) /
            1e18;
        _totalBorrow.elastic += uint128(extraAmount);

        uint256 feeAmount = (extraAmount * protocolFee) / FEE_PRECISION; // % of interest paid goes to fee
        /// @audit feeAmount should be multiplied by _totalBorrow.base
->      feeFraction = (feeAmount * _totalAsset.base) / fullAssetAmount;
        _accrueInfo.feesEarnedFraction += uint128(feeFraction);
        _totalAsset.base = _totalAsset.base + uint128(feeFraction);
        ...
        ...

Tools Used

Manual Analysis

Recommendation

    function _getInterestRate()
        internal
        view
        returns (
            ISingularity.AccrueInfo memory _accrueInfo,
            Rebase memory _totalBorrow,
            Rebase memory _totalAsset,
            uint256 extraAmount,
            uint256 feeFraction,
            uint256 utilization,
            bool logStartingInterest
        )
    {
        ...
        ...
        extraAmount =
            (uint256(_totalBorrow.elastic) *
                _accrueInfo.interestPerSecond *
                elapsedTime) /
            1e18;
        _totalBorrow.elastic += uint128(extraAmount);

        uint256 feeAmount = (extraAmount * protocolFee) / FEE_PRECISION; // % of interest paid goes to fee
        /// @audit feeAmount should be multiplied by _totalBorrow.base
--      feeFraction = (feeAmount * _totalAsset.base) / fullAssetAmount;
++      feeFraction = (feeAmount * _totalBorrow_.base) / fullAssetAmount;
        _accrueInfo.feesEarnedFraction += uint128(feeFraction);
        _totalAsset.base = _totalAsset.base + uint128(feeFraction);
        ...
        ...

Assessed type

Context

#0 - c4-pre-sort

2023-08-07T07:53:36Z

minhquanym marked the issue as low quality report

#1 - c4-pre-sort

2023-08-07T07:53:57Z

minhquanym marked the issue as remove high or low quality report

#2 - c4-pre-sort

2023-08-07T07:54:02Z

minhquanym marked the issue as primary issue

#3 - c4-sponsor

2023-08-22T14:29:22Z

0xRektora marked the issue as sponsor disputed

#4 - c4-sponsor

2023-08-22T14:38:44Z

0xRektora marked the issue as sponsor confirmed

#5 - c4-judge

2023-09-30T12:37:59Z

dmvt marked the issue as selected for report

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter