Description:
EggVault::depositEgg
is a public function, allowing users to deposit their eggs directly into the EggVault
contract instead of doing this through the EggHuntGame
. The function only checks if the egg has been transferred to the EggVault
contract. So whoever calls the function first will claim the egg after the real owner deposited it. A malicious user might watch for the ERC721::Transfer
event and call the EggVault::depositEgg
function before the real owner does and steal the egg. You can read more about listening to events.
Impact:
Real EggstravaganzaNFT
egg owners will get their NFT stolen.
Proof of Concept:
Users finds and mints an egg NFT.
User transfers their egg NFT to the vault contract directly.
A hacker watches for the transfer event and deposits the egg himself before the real owner does.
User tries to deposit the egg, but can't and finds out it was already deposited and stolen.
Proof of Code:
Place the following test inside the EggGameTest
:
Recommended Mitigation:
You can change the EggVault::depositEgg
function to include the egg transfer as well so the transfer and deposit will happen in one transaction like the EggHuntGame::depositEggToVault
function does. Of course, now the user will approve the EggVault
instead of the EggHuntGame
to transfer the NFT.
If you want to keep the original EggHuntGame::depositEggToVault
functionality, you can still use mitigation #1 as a separate function to allow direct deposits and have the EggVault::depositEgg
function only be callable from an approved mapping of EggHuntGame
s inside the EggVault
or use openzeppelin's access control.
Front-running depositEgg allows deposit ownership hijacking.
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.