# Eth trapped when sending incorrect msg.value hence user faces Eth losses
## Description
* The `buySnow()` function in the `Snow` contract allows users to purchase Snow tokens using either **ETH** or **WETH**, based on whether the exact ETH amount matches the fee calculation.
* However, when the user mistakenly sends an incorrect amount of ETH (i.e., not exactly equal to `s_buyFee * amount`), the contract silently falls back to expecting WETH via `safeTransferFrom(...)`. In this fallback path, **any ETH sent with the transaction remains trapped in the contract**, as it is not refunded or used.
```javascript
function buySnow(uint256 amount) external payable canFarmSnow {
if (msg.value == (s_buyFee * amount)) {
_mint(msg.sender, amount);
} else {
//@audit Mishandling of Eth, Eth trapped
@> i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
@> _mint(msg.sender, amount);
// s_earnTimer update...
}
}
```
## Risk
**Likelihood**:
* This will occur whenever a user sends the incorrect ETH amount — very common in DeFi protocols due to rounding errors, slippage miscalculations, or UI inconsistencies.
**Impact**:
* ETH is irreversibly locked in the contract without access control or withdrawal mechanism.
* User funds are silently lost with no error or refund, creating a poor UX and trust issue.
## Proof of Concept
The following proves that user's ETH is trapped when user sends slightly more or less ETH.
```javascript
// User sends slightly more or less ETH than expected
uint256 amount = 1e18;
uint256 fee = snow.s_buyFee() * amount;
// Send slightly more ETH than required
snow.buySnow{value: fee + 1}(amount);
// ETH is not used or refunded
assert(address(snow).balance == 1);
```
## Recommended Mitigation
- A recommended mitigation for the trapped ETH in buySnow() vulnerability is to reject transactions that send an incorrect ETH amount instead of silently falling back to WETH and trapping the ETH. This ensures users do not lose funds due to mistakes or UI errors. Stick to ETH only.
```diff
function buySnow(uint256 amount) external payable canFarmSnow {
- if (msg.value == (s_buyFee * amount)) {
- _mint(msg.sender, amount);
- } else {
- //@audit Mishandling of Eth, Eth trapped
- i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
- _mint(msg.sender, amount);
- // s_earnTimer update...
- }
+ if (msg.value == (s_buyFee * amount)) {
+ _mint(msg.sender, amount);
+ } else {
+ revert("Incorrect ETH amount sent");
+ }
}
```
Optionally, you may also add:
```javascript
// Add a refund mechanism if ETH is sent accidentally
if (msg.value > 0) {
(bool success, ) = msg.sender.call{value: msg.value}("");
require(success, "Refund failed");
}
```