# Pending allowances can be exploited

TOFT cross-chain receiver modules don't check msg.sender, so anyone can front-run a user's pending allowance to TOFT and redirect removed collateral or borrowed funds to themselves.

- Payout: Contest reward
- Severity: high
- Program: Tapioca
- Credited: GiuseppeDeLaZara
- Disclosed: 2024-02-14
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-02-tapioca-judging/issues/140
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AH-14
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** TOFT cross-chain receiver modules (marketRemoveCollateralReceiver, marketBorrowReceiver, exerciseOptionsReceiver, depositLendAndSendForLockingReceiver)
**Root cause:** Receiver functions like marketRemoveCollateralReceiver execute market actions using msg_.user as `from` without verifying msg.sender, relying only on a pre-existing allowance the user granted to the TOFT contract; the in-function approve() is useless since msg.sender is the lzEndpoint.
**Steps:**
1. Alice calls `Singularity.approveBorrow(TOFT, 10)` and `Pearlmit.approve(yieldBox, collateralId, TOFT, 10, expiry)` in separate txs.
2. Alice submits `TOFTMarketReceiverModule::marketRemoveCollateralReceiver` with from=Alice, withdrawParams.to=Alice.
3. Bob front-runs with same call but sets `MagnetarWithdrawData.LzSendParams.SendParam.to = Bob`.
4. Market.removeCollateral runs with msg.sender=TOFT, from=Alice, to=Magnetar; _allowedBorrow passes via Alice's allowance.
5. yieldBox.transfer sends collateral to Magnetar, which withdraws to Bob's address.
**How found:** Code review of the receiver modules' allowance flow: noticed the in-function approve() is a no-op because msg.sender is the lzEndpoint, that users must pre-approve TOFT separately, and that the receiver never checks msg.sender, making any pending allowance hijackable.
**Exploitation:** Attacker front-runs the victim's cross-chain receiver transaction, reusing the victim's pre-granted allowanceBorrow and Pearlmit allowance to the TOFT contract, and sets the withdraw destination to their own address to extract the collateral/borrowed amount.
**Escalation:** Same unchecked-msg.sender pattern appears in marketBorrowReceiver, mintLendXChainSGLXChainLockAndParticipateReceiver, exerciseOptionsReceiver (_internalTransferWithAllowance), and USDO::depositLendAndSendForLockingReceiver, broadening the drain surface.
**Insight:** In cross-chain receiver/executor modules where msg.sender is the bridge endpoint, any allowance the user grants to the module is effectively public; check whether the module authenticates the original user (e.g. via the cross-chain sender) before spending that allowance.
