Users can potentially receive tokens without proper payment validation due to flawed payment logic in Snow::buySnow
Description: The payment validation logic in buySnow
uses an equality check for ETH payments but falls through to WETH transfer without proper validation if the ETH amount doesn't match exactly. This creates a potential for users to receive tokens without proper payment.
function buySnow(uint256 amount) external payable canFarmSnow {
if (msg.value == (s_buyFee * amount)) {
_mint(msg.sender, amount);
} else {
i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
_mint(msg.sender, amount);
}
}
The logic flaw allows scenarios where:
User sends wrong ETH amount (triggers else branch)
WETH transfer fails but tokens are still minted
No explicit validation of payment success
Impact: Users can potentially receive tokens without paying, breaking the economic model.
Proof of Concept:
function test_PaymentLogicFlaw() public {
uint256 initialBalance = snow.balanceOf(attacker);
uint256 correctFee = getBuyFee();
try snow.buySnow{value: 1 wei}(1) {
uint256 newBalance = snow.balanceOf(attacker);
if (newBalance > initialBalance) {
}
} catch {
}
}
Recommended Mitigation: Implement explicit payment path validation:
error S__InvalidPayment();
function buySnow(uint256 amount) external payable canFarmSnow {
if (amount == 0) revert S__ZeroValue();
uint256 totalCost = s_buyFee * amount;
if (msg.value > 0) {
if (msg.value != totalCost) {
revert S__InvalidPayment();
}
_mint(msg.sender, amount);
} else {
i_weth.safeTransferFrom(msg.sender, address(this), totalCost);
_mint(msg.sender, amount);
}
emit SnowBought(msg.sender, amount);
}