# burst() does not return eth when action fails

Magnetar.burst() with allowFailure=true leaves failed action's ETH stuck in contract, stealable by other users via value-bearing actions.

- Payout: Contest reward
- Severity: medium
- Program: Tapioca DAO
- Credited: bin2chen
- Disclosed: 2024-05-23
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-02-tapioca-findings/issues/114
- Library page: https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-16
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** Magnetar.burst() batch call executor
**Root cause:** _executeCall forwards _actionValue via call but on failure with _allowFailure=true it neither reverts nor refunds the value, leaving ETH in the contract.
**Steps:**
1. Call `Magnetar.burst{value: X}(calls)` with a call having `_actionValue > 0` and `allowFailure = true`.
2. Make that action revert so the call fails but does not revert the tx.
3. Observe the `_actionValue` ETH remains in Magnetar contract balance.
4. Another user calls burst with a value-bearing action (e.g. `depositRepayAndRemoveCollateralFromMarket` -> `_withdrawToChain` -> `_lzWithdraw` -> `sendPacket{value:...}`) to consume the stranded ETH.
**How found:** Code review of _executeCall failure path: noticed value is sent with the call but not refunded when allowFailure swallows the revert.
**Exploitation:** Attacker submits a burst() call whose action spends the contract's residual ETH (e.g. LayerZero sendPacket value) before owner calls rescueEth(), siphoning the stranded funds.
**Insight:** In batch/multicall executors, check that msg.value accounting refunds unused or failed-call value; any residual balance becomes claimable by the next caller whose action accepts ETH.
