# Staking ETH incorrectly assumes revert bubbling

BadgerDAO's EbtcLeverageZapRouter ignores the return value of a low-level call to Lido stETH, so a paused/limited staking deposit silently fails and user ETH is lost.

- Payout: Audit contest
- Severity: medium
- Program: BadgerDAO
- Found by: 0xBinChook
- Disclosed: 2024-08-05
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-06-badger#m-02
- Library page: https://bugbountylibrary.com/r/c4%3A2024-06-badger%3AM-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** EbtcLeverageZapRouter / ZapRouterBase ETH-to-stETH deposit flow
**Root cause:** ZapRouterBase::_depositRawEthIntoLido uses a low-level `payable(address(stEth)).call{value: _initialETH}("")` without checking the success bool, so a Lido revert (staking paused or stake limit exceeded) is swallowed and the flow continues.
**Steps:**
1. Mock Lido stETH (CollateralTokenTester) with a `pauseDeposits()` that makes `deposit()` revert `STAKING_PAUSED`.
2. Call `leverageZapRouter.adjustCdpWithEth{value: marginIncrease}(cdpId, params, permit, tradeData)` on a healthy CDP with debt increase + margin increase.
3. Observe the low-level call to stETH reverts but is ignored; `_deposit` returns 0.
4. Flow continues through flash loan, CDP init, eBTC mint; only later ERC20 transfer reverts `ERC20: transfer amount exceeds balance`.
5. In adjust path, the operation can complete leaving the router holding the user's ETH (funds lost).
**How found:** Code reading of ZapRouterBase::_depositRawEthIntoLido spotted a low-level `.call` whose success bool is unchecked, combined with knowledge that Lido's `_submit` reverts on `STAKING_PAUSED` or `STAKE_LIMIT`.
**Exploitation:** Precondition: Lido staking paused or per-block stake limit exceeded. Attacker/user calls openCdpWithEth or adjustCdpWithEth; the ETH sent is not staked, the low-level call's failure is ignored, and the transaction either reverts late (open) or completes with the margin unprocessed, leaving ETH stuck in the router.
**Insight:** When a zap/router stakes ETH via a low-level `.call` to a liquid-staking token, check the success bool or use `submit{value:}`; a swallowed revert yields a zero balance delta that later steps may not catch, especially in adjust flows where slippage checks don't cover the unprocessed margin.
