# TOFT in (m)TapiocaOft contracts can be stolen by calling removeCollateral() with a malicious removeParams.market

BaseTOFTMarketModule.remove approves TOFT to an unvalidated user-supplied market address, letting a malicious market transferFrom all TOFT held by the (m)TapiocaOFT contract.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: 0x73696d616f
- Disclosed: 2023-11-16
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-07-tapioca-findings/issues/1695
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** BaseTOFTMarketModule.remove / BaseTOFT.removeCollateral (LayerZero cross-chain tOFT)
**Root cause:** remove() approves the caller-supplied removeParams.market for removeParams.share and calls removeCollateral on it without whitelisting or validating the market address.
**Steps:**
1. Attacker deploys MaliciousMarket whose removeCollateral(to,to,share) does IERC20(tapiocaOft).transferFrom(msg.sender, attacker, share).
2. Attacker calls tapiocaOft.removeCollateral(attacker, attacker, lzDstChainId, zro, withdrawParams, removeParams{share: balance, market: maliciousMarket}, approvals, adapterParams) paying LZ fees.
3. LZ endpoint delivers payload with PT_MARKET_REMOVE_COLLATERAL; lzReceive -> _nonBlockingLzReceive delegatecalls BaseTOFTMarketModule.remove.
4. remove approves maliciousMarket for share then calls its removeCollateral, which pulls the TOFT to the attacker.
5. Assert attacker balance equals all TOFT held by the contract.
**How found:** Code reading of the cross-chain remove flow: noticed remove() approves and calls an arbitrary user-supplied market address with no validation, then built a Foundry fork PoC with a malicious market to confirm theft.
**Exploitation:** Attacker funds LZ fees, submits removeCollateral with a malicious market and share equal to the contract's TOFT balance; the module's approve + external call lets the malicious market transferFrom the entire TOFT balance to the attacker.
**Insight:** In cross-chain delegatecall modules, any address taken from the user payload and used in approve/external call (market, adapter, receiver) is an arbitrary-call primitive; check every user-controlled address that receives an approval.
