The Snow contract imports SafeERC20 and applies using SafeERC20 for IERC20, and uses safeTransferFrom in buySnow.
However, in collectFee(), the WETH transfer uses the raw i_weth.transfer() instead of i_weth.safeTransfer(). The return value of transfer is not checked.
If the WETH token returns false on failure (as per ERC20 spec), the function will silently continue and proceed to send native ETH, giving the collector a false impression that all fees were collected.
Likelihood:
Standard WETH (Wrapped Ether) reverts on failure rather than returning false, so this is less likely with canonical WETH.
However, the contract is designed to work with any IERC20 WETH-like token, and non-standard tokens may return false.
Impact:
WETH fees accumulated in the contract could be permanently locked if transfer silently fails.
The collector believes fees are collected (no revert), but WETH remains stuck in the contract.
The Snow contract already recognizes the importance of safe ERC20 interactions — it imports SafeERC20, applies using SafeERC20 for IERC20, and uses safeTransferFrom in the buySnow function. However, in collectFee, the raw transfer is used instead of safeTransfer. According to the ERC20 standard, transfer returns a bool indicating success or failure. Tokens that return false on failure (instead of reverting) will cause a silent failure where no WETH is actually sent but execution continues.
Step-by-step scenario:
Users buy Snow tokens using WETH. The WETH accumulates in the Snow contract.
Users also buy Snow tokens using native ETH. The ETH accumulates in the Snow contract.
The collector calls collectFee() to withdraw accumulated fees.
i_weth.transfer(s_collector, collection) is called. If the WETH token returns false (e.g., due to a non-standard ERC20 implementation or a token pause), the return value is not checked.
Execution continues to the ETH transfer via .call{value: ...}(""), which succeeds.
The collector receives the ETH but not the WETH. The function does not revert, so the collector believes all fees were collected.
The WETH remains stuck in the contract with no mechanism to retry the failed transfer.
Replace the raw i_weth.transfer() call with i_weth.safeTransfer() from OpenZeppelin's SafeERC20 library, which is already imported and applied in this contract via using SafeERC20 for IERC20. The safeTransfer wrapper checks the return value and reverts if the transfer returns false or doesn't return data, ensuring that fee collection either fully succeeds or fully reverts.
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.