As per the protocol/doc "buyPresent(address presentReceiver)" in "SantasList" contract should burn the santa tokens of the msg.sender and give an NFT present to the given presentReceiver.
But it burns the tokens of the presentReceiver and gives the newly minted NFT to the msg.sender
If you add these tests to the SantaListTest.t.sol they will pass, but they shouldn't:
function testBuyPresentForSomeoneElse_whenReceiverHasTokens_receiversTokensAreBurntAndThepresentGoesToTheSender() public {
address presentReceiver = makeAddr("presentReceiver");
vm.startPrank(santa);
santasList.checkList(user, SantasList.Status.EXTRA_NICE);
santasList.checkTwice(user, SantasList.Status.EXTRA_NICE);
santasList.checkList(presentReceiver, SantasList.Status.EXTRA_NICE);
santasList.checkTwice(presentReceiver, SantasList.Status.EXTRA_NICE);
vm.stopPrank();
vm.warp(santasList.CHRISTMAS_2023_BLOCK_TIME() + 1);
vm.startPrank(presentReceiver);
santasList.collectPresent();
assertEq(santaToken.balanceOf(presentReceiver), 1e18);
vm.startPrank(user);
santasList.collectPresent();
assertEq(santasList.balanceOf(user), 1);
assertEq(santaToken.balanceOf(user), 1e18);
santasList.buyPresent(presentReceiver);
assertEq(santasList.balanceOf(user), 2);
assertEq(santaToken.balanceOf(user), 1e18);
assertEq(santaToken.balanceOf(presentReceiver), 0);
vm.stopPrank();
}
function testBuyPresentForSomeoneElse_revertsWithArithmeticOverflow() public {
address presentReceiver = makeAddr("presentReceiver");
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.expectRevert();
santasList.buyPresent(presentReceiver);
vm.stopPrank();
}
Anyone can burn others tokens to get NFTs for themselves.
Add a new function to _mintAndIncrement nfts for a given address, you can actually modify the already existing one
in the way given below, you would just have to call it with mintFor = msg.sender wheny you want to mint for the sender,
just give the flexibility to _mintAndIncrement to mint for the provided address instead of only to the msg.sender
Make the following or similar changes to the "buyPresent" function in "SantasList" contract:
function buyPresent(address presentReceiver) external {
i_santaToken.burn(msg.sender);
_mintAndIncrement(presentReceiver);
}
function _mintAndIncrement(address mintFor) private {
_safeMint(mintFor, s_tokenCounter++);
}