The Snow::buySnow() function allows users to purchase Snow tokens using either native ETH or WETH. The function uses an if/else pattern to determine the payment method based on msg.value:
The problem occurs when a user sends ETH (msg.value > 0) but the amount does not exactly match s_buyFee * amount. In this scenario:
The if condition fails because msg.value != s_buyFee * amount
Execution falls through to the else branch, which attempts a WETH safeTransferFrom
If the user has approved WETH, the WETH transfer succeeds and Snow tokens are minted
The ETH sent with msg.value remains trapped in the contract with no way to recover it
The user effectively pays twice: once in ETH (which is lost) and once in WETH. The Snow contract has no receive() or fallback() function for accepting ETH, and collectFee() only transfers the contract's ETH balance to the collector, meaning trapped user ETH goes to the protocol fee collector rather than being refunded.
Additionally, even when a user intends to pay with ETH and sends the exact correct amount, there is no require statement or explicit revert if the ETH branch is not taken. A slight rounding error or wrong amount parameter would silently fall through to WETH, trapping the ETH.
Likelihood: Medium
Users interacting directly with the contract (not through a well-designed front-end) can easily send a slightly wrong ETH amount
The s_buyFee is stored as _buyFee * PRECISION (1e18), making manual calculation error-prone
Wallet UIs may auto-suggest gas amounts that interfere with exact ETH matching
Impact: Medium
Users lose the ETH they sent, which is permanently trapped in the contract
Users are additionally charged WETH for the same transaction, resulting in double payment
There is no mechanism for users to recover their trapped ETH
The collectFee() function will sweep the trapped ETH to the collector, not back to the user
Use explicit checks instead of silent fallthrough. Either require exact ETH payment when ETH is sent, or explicitly handle the WETH-only case:
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.