Snow::collectFee uses an unchecked i_weth.transfer, ignoring the return value despite importing SafeERC20Snow imports and using SafeERC20 for IERC20, indicating safe transfer semantics are intended.
collectFee calls the raw i_weth.transfer(...) and ignores its boolean return. A token implementation that returns false instead of reverting on failure would silently fail to move the fees.
Likelihood: Low
Low for canonical WETH, but the contract is written generically against an IERC20 and the safe pattern is already available, so the unchecked call is an avoidable latent bug.
Impact: Low
A failed-but-non-reverting transfer would leave fees stuck in the contract while the function reports success.
The ERC20 standard permits an implementation to signal failure by returning false instead of reverting. collectFee discards that return value, so against such a token the call appears to succeed while the fees never move.
This PoC deploys Snow with a standards-compliant WETH whose transfer returns false (no revert, no movement), accumulates fees via the WETH buy path, then calls collectFee and shows it does not revert and the balance is unchanged:
Run: forge test --mt test_L2_collectFeeSilentlyFailsOnFalseTransfer -vv
Result:
The contract already declares using SafeERC20 for IERC20, so the safe wrapper is one keyword away. safeTransfer checks the boolean return (and tolerates non-standard tokens that return no data), reverting on failure instead of silently continuing.
Additional hardening for the same function:
The native-ETH sweep uses a low-level call whose success is checked (require(collected, ...)) — good. Consider replacing the bare-string require with a custom error for consistency with the rest of the contract and lower gas, e.g. if (!collected) revert S__FeeCollectionFailed();.
collectFee reads i_weth.balanceOf(address(this)) then transfers it; with the SafeERC20 fix this becomes a single safe, all-or-nothing transfer, removing the silent-loss path entirely. No further accounting changes are required.
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.