The EggVault contract’s depositEgg function lacks proper access control, allowing anyone to call it and assign ownership of an NFT to an arbitrary address after transferring it to the Vault. This vulnerability enables attackers to steal ownership of deposited NFTs, bypassing the intended game mechanics.
The depositEgg function in EggVault is defined as public without caller restrictions:
Key issues:
No Caller Restriction: Any address can call depositEgg and set depositor to themselves or another address, as long as the NFT is already in the Vault.
Interaction with EggHuntGame: While EggHuntGame.depositEggToVault calls this function correctly, an attacker can bypass it by:
Transferring an NFT to the Vault via eggNFT.transferFrom.
Calling depositEgg directly with their own address as depositor.
An attacker can:
Transfer an NFT to the Vault independently.
Register it under their address, effectively claiming ownership.
Later call withdrawEgg to retrieve it.
This vulnerability disrupts the system:
NFT Theft: Attackers can claim ownership of NFTs deposited by others, stealing assets.
Game Integrity: Bypasses the intended deposit flow through EggHuntGame, breaking gameplay rules.
Economic Loss: Stolen NFTs reduce trust and value in the ecosystem.
Player Frustration: Legitimate players lose control over their assets, potentially abandoning the game.
Manual code review
Solidity compiler analysis (version ^0.8.23)
Scenario testing with hypothetical attack contracts
Restrict Caller Access:
Limit depositEgg to only be callable by the EggHuntGame contract.
Validate Depositor:
Ensure depositor matches the actual sender or NFT owner at transfer time (though current design relies on EggHuntGame).
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.