@> function collectFee() external {
@> if (msg.sender != i_feeCollector) {
@> revert S__NotAllowed();
@> }
@> uint256 wethBalance = i_weth.balanceOf(address(this));
@> if (wethBalance > 0) {
@> i_weth.transfer(i_feeCollector, wethBalance);
@> }
@> (bool success,) = i_feeCollector.call{value: address(this).balance}("");
@> if (!success) {
@> revert S__TransferFailed();
@> }
@> }
i_weth.transfer() returns a bool that is never checked. If the WETH token returns false instead of reverting (as some tokens do), collectFee() completes successfully while the WETH fees stay in the contract, and the collector has no way of knowing the collection failed. Note the asymmetry inside the same function: the ETH leg is checked and reverts with S__TransferFailed, but the WETH leg is not. The contract already imports SafeERC20 and uses safeTransferFrom() in buySnow(), so this is also inconsistent with its own pattern. The standard WETH9 and the project's MockWETH return true, so this is a robustness issue rather than an observed loss - hence Low.
Explanation: use the SafeERC20 wrapper the contract already imports, matching buySnow().
- i_weth.transfer(i_feeCollector, wethBalance);
+ i_weth.safeTransfer(i_feeCollector, wethBalance);
SafeERC20 is already imported and used for safeTransferFrom in buySnow(), so this is a one-line change.