# Accumulated ETH fees of InfinityExchange cannot be retrieved

InfinityExchange's rescueETH sends msg.value instead of contract balance, permanently trapping ETH protocol fees accrued from every ETH-denominated trade.

- Payout: Audit contest
- Severity: high
- Program: Infinity NFT Marketplace
- Found by: hyh
- Disclosed: 2022-08-16
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-06-infinity-findings/issues/296
- Library page: https://bugbountylibrary.com/r/c4%3A2022-06-infinity%3AH-04
- Tags: area:web3 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:** Solidity exchange contract fee-withdrawal function
**Root cause:** rescueETH forwards msg.value (ETH attached to the call) rather than address(this).balance, so the contract's own accumulated ETH fee balance is never reachable.
**Steps:**
1. Call takeOrders() or takeMultipleOneOrders() with ETH as currency; _transferFees keeps protocolFee in the contract.
2. Owner calls `rescueETH(destination)` with some msg.value; only that attached value is forwarded.
3. Contract ETH balance (accumulated fees) remains stuck; no other function withdraws native ETH.
**How found:** Code review of the fee transfer path: noticed ETH fees are retained in-contract by design, then audited the sole withdrawal function and saw it uses msg.value instead of address(this).balance.
**Insight:** When a contract intentionally retains native ETH for later withdrawal, verify the rescue/withdraw function references address(this).balance, not msg.value — a payable-onlyOwner rescue that forwards msg.value is a common trap.

