The SantasList::collectPresent()
function exposes a vulnerability, enabling an attacker to reenter the function and mint multiple tokens
for a single address. Additionally, the SantasList::checkList
function lacks proper access control validations, allowing an attacker
to manipulate the status of their address in the s_theListCheckedOnce
mapping or modify the status of any user in the mapping.
The default enum value Status.NICE is returned for an address not present in the mapping, this opens up an exploitation opportunity
for an attacker.
The attacker can exploit the vulnerability to mint multiple tokens for their address by following these steps (this case assumes the address is not present in any of the mappings.)
Create a contract implementing the onERC721Received callaback.
Invoke SantasList::collectPresent() from this contract.
In the onERC721Received callback, transfer the NFT to a different address to bypass the control check limiting one NFT per address.
In the same callback, call SantasList::collectPresent() multiple times (limited by gas) to accumulate more NFTs.
This vulnerability allows an attacker to mint multiple tokens for the same address.
The testing scenario involves a contract implementing the IERC721Receiver callback and invoking SantasList::collectPresent().
Output
Foundry
Add the access control for the function SantasList::checkList
Add a new default value for the Status enum to represent undefined states.
Add a reentrancy safe guard to SantasList::collectPresent()
The function SantasList::collectPresent()
uses the users balance to check if the nft was already collected, this is not a good idea,
as the balance is a knob an attacker can use, the recomendation is to create a new State in the Status
struct, to COLLECTED
, and assign this status
to a user that already collected the nft.
Consider recommending Santa to take Patrick's Solidity course for additional insights and best practices.
In Solidity the first element of an enum is the default value. In Santa's List, the means each person is mapped by default to 'NICE'.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.