Snow mint paths — protocol economically non-functionalSnow inherits OpenZeppelin's ERC20 with the default decimals() = 18. To mint "1 whole Snow" the code must call _mint(account, 1 * 10**decimals()) = _mint(account, 1e18). The contract does NOT apply this scaling in either of its mint paths:
The fundamental mismatch: s_buyFee is in wei units (scaled), but _mint's value argument receives the unscaled amount. With _buyFee = 1 at deployment, paying 1 ETH yields 1 wei of Snow. To buy 1 whole Snow (1e18 raw units), a user would have to pay s_buyFee * 1e18 = 10^36 wei = 10^18 ETH — economically impossible.
Downstream, SnowmanAirdrop.claimSnowman reads Snow.balanceOf(receiver) to determine NFT amount. With balances stuck at single-digit wei, claimers receive 0–1 NFTs each, and the airdrop is non-functional for the intended user base.
Likelihood: High — the bug fires on every call to buySnow or earnSnow; no special preconditions required.
Impact: High — the protocol's free-earn pathway is useless (1 wei per week), the paid pathway is unaffordable (10^18 ETH per Snow), and the entire downstream airdrop is non-functional because Snow balances never reach usable amounts.
Risk = Likelihood × Impact = High
The "earn for free once a week" feature mints 0.000000000000000001 S per call — economically zero. After 100 weeks of earning, a user holds 100 wei = 0.0000000000000001 S. The "buy Snow with ETH/WETH" feature charges 1 ETH per 1 wei of Snow — anyone who pays receives a balance that, displayed in standard 18-decimal wallet UI, rounds to zero. Because claimSnowman derives NFT count from Snow.balanceOf, no eligible user can receive a meaningful number of Snowman NFTs through legitimate means. The protocol cannot operate as documented.
Full PoC at .audit/poc/PoC_H-02.t.sol. The key test function:
Test passes inside hardened audit container (forge exit 0). Buyer pays 1 ETH and receives exactly 1 wei of Snow — a 10^18-fold shortfall vs. the intended whole-token mint.
Apply decimals scaling at mint time in both paths — keep the amount parameter user-friendly (whole tokens) and multiply by PRECISION when minting:
After this fix, buySnow(1) {value: 1 ether} mints 1 whole Snow (1e18 raw units), and earnSnow() mints 1 whole Snow per week — restoring the documented economic model.
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.