buyPresent charges 1 SantaToken despite a declared 2 SantaToken costMedium
SantasList defines the cost of a purchased present as 2e18 SantaToken:
However, buyPresent() never uses this constant. It calls SantaToken.burn(), and SantaToken.burn() always burns exactly 1e18:
Affected code:
src/SantasList.sol:87-88
src/SantasList.sol:172-175
src/SantaToken.sol:28-33
Purchased presents are minted for half of the declared price. This breaks the protocol's token accounting and allows additional NFTs to be minted with fewer SantaTokens than intended.
The issue is especially visible for EXTRA_NICE users: they receive 1e18 SantaToken from collectPresent(), but the documented purchase price is 2e18. Despite not having enough tokens to pay the declared cost, they can still buy another present.
Medium.
The protocol mints purchased NFTs for less than the configured price. This weakens the intended scarcity and accounting model around SantaToken, because a user with only half the declared cost can still receive an additional NFT.
High.
Every buyPresent() call uses SantaToken.burn(), and that burn function always burns 1e18. The declared PURCHASED_PRESENT_COST of 2e18 is never enforced.
The exploit is covered by test_BuyPresentOnlyBurnsOneTokenDespiteTwoTokenCost in test/unit/SantasListTest.t.sol.
Run:
Result:
The user starts with only 1e18 SantaToken, while PURCHASED_PRESENT_COST is 2e18. The purchase still succeeds and mints an additional NFT.
Use the declared purchase cost when burning SantaToken:
Update SantaToken.burn() to accept the burn amount:
Add a regression test proving that a caller with only 1e18 SantaToken cannot buy a present when the declared cost is 2e18.
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.