collectPresent
function is callable by any address, but the call will succeed only if the user is registered as NICE
or EXTRA_NICE
in SantasList contract. In order to prevent users to collect presents multiple times, the following check is implemented:
Nevertheless, there is an issue with this check. Users could send their newly minted NFTs to another wallet, allowing them to pass that check as balanceOf(msg.sender)
will be 0
after transferring the NFT.
Let's imagine a scenario where an EXTRA_NICE
user wants to collect present when it is Christmas time. The user will call collectPresent
function and will get 1 NFT and 1e18
SantaTokens. This user could now call safetransferfrom
ERC-721 function in order to send the NFT to another wallet, while keeping SantaTokens on the same wallet (or send them as well, it doesn't matter). After that, it is possible to call collectPresent
function again as ``balanceOf(msg.sender)will be
0` again.
The impact of this vulnerability is HIGH as it allows any NICE
user to mint as much NFTs as wanted, and it also allows any EXTRA_NICE
user to mint as much NFTs and SantaTokens as desired.
The following tests shows that any NICE
or EXTRA_NICE
user is able to call collectPresent
function again after transferring the newly minted NFT to another wallet.
In the case of NICE
users, it will be possible to mint an infinity of NFTs, while transferring all of them in another wallet hold by the user.
In the case of EXTRA_NICE
users, it will be possible to mint an infinity of NFTs and an infinity of SantaTokens.
Foundry
SantasList should implement in its storage a mapping to keep track of addresses which already collected present through collectPresent
function.
We could declare as a state variable :
and then modify collectPresent
function as follows:
We just added a check that hasClaimed[msg.sender]
is false
to execute the rest of the function, while removing the check on balanceOf
. Once present is collected, either for NICE
or EXTRA_NICE
people, we update hasClaimed[msg.sender]
to true
. This will prevent user to call collectPresent
function.
If you run the previous test with this new implementation, it wail fail with the error user already collected present
.
Here is a new test that checks the new implementation works as desired:
Relying on balanceOf > 0 in collectPresent() allows the msg.sender to send their present to another address and then collect again.
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.