buySnow branches on an exact equality: only if msg.value == s_buyFee * amount does it treat the call as an ETH purchase. Any other value, including a nonzero ETH amount that is slightly more or less than the fee, falls into the WETH branch, which pulls the full fee in WETH via safeTransferFrom while the ETH that accompanied the call simply stays in the contract. The buyer thus pays the full price in WETH plus whatever ETH they sent, and the stray ETH is later swept to the fee collector by collectFee, who receives it as if it were fee revenue. There is no refund path and no error: a user who misjudges the exact wei amount (easy, since the fee scales with PRECISION and the amount) silently loses the entire ETH portion of their payment.
Likelihood: Medium - requires a buyer to attach a nonzero but inexact ETH amount, a realistic mistake for a payable function whose price is computed from stored parameters; nothing warns or reverts when it happens.
Impact: Medium - direct loss of the full ETH amount the user sent (up to nearly the whole purchase price), on top of the full WETH charge; the funds end up with the collector rather than being refunded or credited.
Verified with Foundry (test passes). Dave buys 1 Snow (fee = 1 ether worth) attaching 0.5 ether, half the fee, intending a partial ETH payment. The contract keeps his 0.5 ether AND pulls the full 1e18 WETH fee from him, minting 1 Snow.
Make the payment method explicit and safe: if msg.value > 0, require it to cover the fee and refund any excess (or revert unless it matches exactly), and only fall back to WETH when msg.value == 0.
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.