Participants who have obtained eggs through the game's search mechanism can transfer their NFT eggs directly to the vault using standard ERC721 transfer methods. However, these directly transferred eggs cannot be withdrawn as they aren't properly registered in the vault's storage. This results in eggs becoming permanently locked in the vault with no possibility of retrieval.
When users transfer their egg NFTs directly to the vault using transferFrom()
instead of using the game's depositEggToVault()
function, the eggs arrive at the vault contract but the critical registration step is bypassed. The vault keeps track of deposited eggs using the storedEggs
mapping and records the original depositor in the eggDepositors
mapping. Direct transfers skip this registration process.
Since the withdrawal function requires that eggs be properly registered through the storedEggs
mapping (require(storedEggs[tokenId], "Egg not in vault")
), directly transferred eggs cannot be withdrawn, despite physically being in the vault's possession.
This vulnerability leads to permanent asset loss for users who inadvertently transfer their eggs directly to the vault. There is no recovery mechanism for these assets, and they become locked in the vault contract forever, reducing the total supply of active egg NFTs and causing financial loss to affected users.
Manual code review
Foundry testing framework to validate the vulnerability
Implement the onERC721Received
hook to properly register eggs that are transferred directly to the vault:
Then add a rescue function that allows contract administrators to help users recover accidentally transferred eggs:
Users can transfer NFTs directly to the vault using standard ERC721 transferFrom(), bypassing the registration
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.