# TOFT exerciseOption can be used to steal all underlying erc20 tokens

Unvalidated tapOftAddress in TOFT exerciseOption lets attacker pass the TOFT's underlying ERC20 as the transfer target, draining the contract's full balance.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: windhustler
- Disclosed: 2023-11-16
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-07-tapioca-findings/issues/1307
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-11
- 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:** BaseTOFT cross-chain exerciseOption / BaseTOFTOptionsModule
**Root cause:** exerciseInternal trusts attacker-supplied tapSendData.tapOftAddress and tapAmount, transferring that token from the TOFT (msg.sender) to the attacker when withdrawOnAnotherChain is false.
**Steps:**
1. Identify a TapiocaOFT/mTapiocaOFT whose underlying ERC20 is held in the contract; read it via `erc20()`.
2. Call `exerciseOption` on the source chain with minimal `optionsData.paymentTokenAmount` (burned).
3. Craft the LayerZero payload so `tapSendData.withdrawOnAnotherChain = false`, `tapSendData.tapOftAddress = <underlying ERC20>`, `tapAmount = <TOFT's ERC20 balance>`, `from = attacker`, `approvals = []`.
4. On the remote chain `exerciseInternal` runs: approvals skipped, `ITapiocaOptionsBroker(target).exerciseOption(...)` called on a no-op target, then `IERC20(tapOftAddress).safeTransfer(from, tapAmount)` executes with msg.sender = TOFT.
5. Attacker receives the entire underlying ERC20 balance of the TOFT.
**How found:** Code reading of exerciseInternal: noticed tapOftAddress and tapAmount are never validated against the expected TapOFT, and that msg.sender is the TOFT itself which custodies the underlying ERC20.
**Exploitation:** Attacker sends a cross-chain exerciseOption message with attacker-controlled tapSendData; the receiving TOFT executes safeTransfer of its own underlying ERC20 balance to the attacker for only the small burned paymentTokenAmount.
**Insight:** In cross-chain message handlers, any address/amount field in the payload that is later used as a transfer target or amount must be validated against protocol-owned constants; the receiving contract's own balance is the prize when msg.sender is the vault.
