# withdrawForETH could be used to drain the WETH in RubiconRouter.sol

withdrawForETH trusts any caller-supplied targetPool implementing IBathToken, letting an attacker fake balanceOf/withdraw to drain the router's WETH as ETH.

- Payout: Contest reward
- Severity: medium
- Program: Rubicon
- Credited: dipp
- Disclosed: 2022-08-01
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-05-rubicon-findings/issues/356
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-rubicon%3AM-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** RubiconRouter.sol withdrawForETH
**Root cause:** withdrawForETH accepts an arbitrary targetPool address and trusts its IBathToken return values (underlyingToken, balanceOf, withdraw) without verifying it is a legitimate pool or that WETH was actually received.
**Steps:**
1. Deploy malicious contract implementing IBathToken: underlyingToken() returns wethAddress, balanceOf() returns type(uint256).max, transferFrom() no-ops, withdraw(shares) returns the router's WETH balance.
2. Call `withdrawForETH(shares, maliciousPool)` with shares equal to the router's WETH balance.
3. Router passes require checks, calls WETH9.withdraw(withdrawnWETH) burning its own WETH, and transfers the resulting ETH to msg.sender.
**How found:** Code review of withdrawForETH: noticed targetPool is fully caller-controlled and only checked via interface calls, so a fake implementation could satisfy all requires and return an arbitrary withdraw amount.
**Exploitation:** Attacker supplies a fake pool contract; router unwraps its own WETH balance to ETH and sends it to the attacker without receiving any shares or WETH in return.
**Insight:** When a router accepts a pool/token address from the caller, verify it against a registry or check the router's actual WETH balance delta rather than trusting interface return values.
