buySnow accepts payment either in native ETH (exact s_buyFee * amount) or in WETH (pulled via transferFrom). However, the rail selection is a strict equality check on msg.value, so any non-exact ETH amount silently falls into the WETH branch, which charges the full WETH fee and keeps the attached ETH — with no refund path.
A user who intends to pay in WETH but accidentally attaches ETH (a common wallet/UX mistake), or who overpays the ETH fee by even 1 wei, is charged on both rails: the contract pulls s_buyFee * amount WETH from them and retains every wei of the attached ETH, which collectFee later sweeps to the fee collector. There is no branch that refunds or credits the excess, so the overpayment is a permanent, unrecoverable loss for the buyer.
Likelihood:
Any buyer who attaches a non-exact msg.value while holding an active WETH approval — e.g. intending the WETH rail and leaving ETH on the call, or miscomputing the exact fee.
No attacker needed; ordinary user error triggers it.
Impact:
Direct, unrecoverable loss of all ETH attached to a non-exact-payment buy (demonstrated: 5 WETH charged plus 1 ETH kept for a single 1-wei purchase).
Lost funds accrue to the fee collector via collectFee — users fund the protocol's fee pot through the ambiguity.
Run: add the test to test/TestSnowmanAirdrop.t.sol (it imports MockWETH already), then forge test --match-test test_PoC_DoubleChargeEthAndWeth -vv
Output (actual run):
Make the rail choice explicit and reject mixed or incorrect payment.
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.