Tapioca DAO - jaraxxus'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: 58/132

Findings: 2

Award: $499.76

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: GalloDaSballo

Also found by: jaraxxus

Labels

bug
2 (Med Risk)
satisfactory
duplicate-1276

Awards

349.0423 USDC - $349.04

External Links

Lines of code

https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/usd0/USDO.sol#L81-L105

Vulnerability details

Proof of Concept

In USDO.sol, users are able to call flashloan() to mint up to a max amount of USDO and pay a fee after using the flashloan.

function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external override notPaused returns (bool) { require(token == address(this), "USDO: token not valid"); require(maxFlashLoan(token) >= amount, "USDO: amount too big"); require(amount > 0, "USDO: amount not valid"); uint256 fee = flashFee(token, amount); //@audit --- fee is calculated here. Percentage set by owner _mint(address(receiver), amount); //@audit --- Flashloan caller will receive amount require( receiver.onFlashLoan(msg.sender, token, amount, fee, data) == FLASH_MINT_CALLBACK_SUCCESS, "USDO: failed" ); uint256 _allowance = allowance(address(receiver), address(this)); require(_allowance >= (amount + fee), "USDO: repay not approved"); _approve(address(receiver), address(this), _allowance - (amount + fee)); //@audit --- Flashloan caller repays flashloan by burning the amount + fee. _burn(address(receiver), amount + fee); return true; }

As noted by the audit comments above, the flashloan fee is burned instead of passing it on to the fee receiver.

  1. Bob intends to flashloan 1 million USDO for arbitrage use.
  2. Bob calls flashloan() and mints 1 million USDO.
  3. When he is done, Bob has to pay a 0.1% fee, so he has to pay 1000 USDO on top of burning 1 million USDO. This means that he has to have at least 1000 USDO in his wallet.
  4. The 1000 USDO fee is burned instead of passing to a fee receiver.

Impact

The fees are burned instead of being received by a designated fee receiver.

Tools Used

Manual Review

Recommend that the fee be passed to the fee receiver instead of being burned.

Assessed type

Token-Transfer

#0 - c4-pre-sort

2023-08-09T05:54:40Z

minhquanym marked the issue as duplicate of #1276

#1 - c4-judge

2023-09-30T14:29:47Z

dmvt marked the issue as satisfactory

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