# ETH Sent Directly to Contract Is Trapped + Loss of User Funds
## Description
- Normally, any ETH sent to the contract should be recoverable or used in the game logic.
- The current implementation allows ETH to be sent directly to the contract via the receive() function, but this ETH is not accessible by any withdrawal function and is not added to the pot or platform fees.
```javascript
// Root cause in the codebase with @> marks to highlight the relevant section
//@audit: This function is used to receive ETH directly into the contract. Which traps any ETH sent to the contract address.
@> receive() external payable {}
```
## Risk
**Likelihood**:
- This will occur whenever a user mistakenly sends ETH directly to the contract address.
- Wallets and dApps may send ETH directly due to user error or UI bugs.
**Impact**:
- ETH is permanently trapped in the contract and cannot be withdrawn by anyone.
- Users lose funds, and the contract accumulates unusable ETH.
## Proof of Concept
- Send ETH directly to the contract and attempt to withdraw it via any contract function; the ETH remains trapped.
- This shows unusual increase in contract balance due to trapped ETH.
**Proof Of Code**
```javascript
function testEthTrappedProof() public {
uint256 sendAmount = 1 ether;
vm.startPrank(player1);
(bool sent,) = address(game).call{value: sendAmount}("");
require(sent, "Direct ETH send failed");
vm.stopPrank();
vm.startPrank(player2);
game.claimThrone{value: game.claimFee()}();
vm.warp(block.timestamp + GRACE_PERIOD + 1);
game.declareWinner();
game.withdrawWinnings();
vm.stopPrank();
vm.startPrank(deployer);
console2.log("Contract Balance:", game.getContractBalance());
game.withdrawPlatformFees();
console2.log("Contract Balance:", game.getContractBalance());
vm.stopPrank();
}
```
## Recommended Mitigation
- Either remove the receive() function or add logic to allow claimThrone on those funds.
```diff
- receive() external payable {}
+ receive() external payable {
+ claimThrone();
+ }
```
---