# TOFTOptionsReceiverModule's and UsdoOptionReceiverModule's exerciseOptionsReceiver can lose the option payment provided

Rounding in TapiocaOptionBroker.exerciseOption can zero the payment amount, so exerciseOptionsReceiver's refund guard skips reimbursement, stranding user-supplied payment tokens stealable by back-runners.

- Payout: Contest reward
- Severity: medium
- Program: Tapioca
- Credited: hyh
- Disclosed: 2024-02-14
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-02-tapioca-judging/issues/147
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-35
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:precision-loss

**Target:** tOFT/USDO option receiver modules and TapiocaOptionBroker
**Root cause:** _getDiscountedPaymentAmount rounds paymentAmount down to zero, so bBefore==bAfter after exercise; the refund branch is gated on bBefore>bAfter, so the user's _options.paymentTokenAmount is never returned.
**Steps:**
1. Call exerciseOptionsReceiver with _options.paymentTokenAmount large and an exercise whose discountedPaymentAmount rounds to 0.
2. exerciseOption succeeds with zero payment; bBefore==bAfter in receiver.
3. Refund condition `if (bBefore > bAfter)` is false, so no transfer back to _options.from.
4. Back-runner calls exerciseOptionsReceiver with small paymentTokenAmount, spending the stranded balance for their own exercise.
**How found:** Code reading of the refund guard in exerciseOptionsReceiver against the rounding in _getDiscountedPaymentAmount; noticed bBefore==bAfter is a valid success state that the guard treats as 'no refund needed'.
**Exploitation:** Attacker back-runs the victim's exerciseOptionsReceiver transaction and exercises options using the contract's stranded payment-token balance, since the receiver does not verify that provided funds match the strike payment.
**Insight:** When auditing refund/remainder logic, check whether the 'nothing spent' case (zero amount after rounding) is handled by guards written as strict inequalities; zero-value success paths often bypass reimbursement.
