Snow correctly uses SafeERC20.safeTransferFrom() when pulling WETH from buyers in buySnow(), but switches to the
raw IERC20.transfer() call — without checking its return value — when sweeping accumulated fees in collectFee().
Tokens that signal failure by returning false rather than reverting (e.g. USDT, BNB, and other non-compliant
ERC20s) would silently fail: the transfer would appear to succeed, ETH would be sent to the collector, and the
WETH balance would remain locked in the contract with no recovery path.
While the contract currently hardcodes i_weth to MockWETH/canonical WETH (which reverts rather than returning
false), the inconsistency creates a latent risk: if i_weth is ever pointed at a different token, or this pattern
is replicated for another asset, fees silently disappear.
Risk
Likelihood:
When i_weth is set to any ERC20 token that returns false on failure rather than reverting
When the contract is reused or forked with a different token address substituted for WETH
When the collector calls collectFee() during any edge-case token state (e.g. paused USDT)
Impact:
Accumulated WETH fees silently remain in the contract with no user-facing revert
ETH is sent to the collector (via the call below) while WETH transfer failure goes unnoticed
Fees are permanently locked — collectFee() has no retry logic and i_weth has no admin withdrawal fallback
Static confirmation — the pattern is directly visible at Snow.sol:103. The SafeERC20 wrapper is imported and
active at line 19 (using SafeERC20 for IERC20) but not applied to this call site. Slither flags this as
unchecked-transfer.
To demonstrate the silent-failure path with a non-compliant token:
Replace the raw transfer() call with the safeTransfer() wrapper already imported via SafeERC20. This wraps the
call in a check that reverts if the return value is false or if the call reverts — matching the pattern already
used in buySnow().
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.