# Missing the unwrapping of native token in RootBridgeAgent.sweep() causes fees to be stuck

RootBridgeAgent.sweep() transfers accumulatedFees as native ETH without unwrapping wrappedNativeToken, so fees are permanently stuck.

- Payout: Contest reward
- Severity: high
- Program: Maia DAO Ecosystem
- Credited: peakbolt
- Disclosed: 2023-09-18
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-05-maia-findings/issues/385
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-maia%3AH-21
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** RootBridgeAgent.sweep() in Maia DAO bridge
**Root cause:** sweep() calls SafeTransferLib.safeTransferETH() on accumulatedFees but the fees are held as wrappedNativeToken (WETH), not native ETH; no withdraw() is performed first.
**Steps:**
1. Deploy/use RootBridgeAgent with wrappedNativeToken set.
2. Trigger a bridge action that accrues fees (e.g. callOutSignedAndBridge with deposit) so accumulatedFees > 0 and WETH balance of the agent equals fees.
3. Call `multicallBridgeAgent.sweep()`; it attempts `safeTransferETH(accumulatedFees)` while the contract holds WETH, not ETH.
4. Transfer reverts (insufficient ETH balance), leaving fees permanently locked in the contract.
**How found:** Code review of sweep() noticed it transfers accumulatedFees via safeTransferETH without first calling wrappedNativeToken.withdraw(), while fees are accrued in WETH.
**Exploitation:** No attacker action needed; the flaw is a functional bug that permanently locks protocol fees. Any user can trigger fee accrual, after which sweep() always reverts because the contract holds WETH instead of native ETH.
**Insight:** When a contract holds both native and wrapped native tokens, audit every payout path for a matching unwrap step; fee-accrual functions that wrap on deposit must be paired with withdraw on sweep.
