The intended behavior is that users can buy Snow either by paying the exact ETH price or by paying with WETH through transferFrom. For ETH purchases, the amount of ETH sent should match the configured buy fee multiplied by the requested Snow amount.
The issue is that buySnow only treats the call as an ETH purchase when msg.value exactly equals s_buyFee * amount. Any other msg.value, including accidental overpayment, falls into the WETH branch. In that branch, the contract pulls WETH from the user but also keeps the ETH sent with the transaction.
Likelihood: Medium
Users commonly overpay ETH by mistake when interacting through scripts, custom frontends, or manual transactions.
Calls with non-exact msg.value are routed to the WETH branch instead of reverting.
Users with existing WETH approval lose WETH and also leave their sent ETH in the contract.
Impact: Medium
Users can be charged twice: once in WETH and once through the accidental ETH value.
Extra ETH remains in the contract until the collector withdraws it through collectFee.
Purchase behavior is surprising and can cause avoidable user fund loss.
The following PoC shows a user trying to buy 1 Snow while sending more ETH than required. Since the ETH amount is not exactly equal to FEE, the function enters the WETH branch. Because the user has approved WETH, the contract transfers WETH and also keeps the accidental ETH.
This demonstrates that an overpaid ETH purchase does not revert or refund. Instead, the buyer pays WETH while the ETH is retained by the contract.
Separate the ETH and WETH purchase paths explicitly. ETH purchases should require the exact ETH amount. WETH purchases should require 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.