Eggstravaganza

First Flight #37
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Invalid

Centralization Risk for trusted egg nft owners, which could disrupt game functionality and potentially cause a Denial of Service.

Description: the contract owner has the ability to mint NFTs to any address at will by changing the game contract address to addresses controlled by the nft owner.

function setGameContract(address _gameContract) external onlyOwner {
require(_gameContract != address(0), "Invalid game contract address");
gameContract = _gameContract;
}

This causes a mismatch in the game's tracking of the next tokenId to mint,
which can prevent other users from successfully minting their NFTs.

Impact: the game functionality could be disrupted, leading to a Denial of Service (DoS) for players.

Proof of Concept: add the following test and run it

address nftOwner = makeAddr("nftOwner");
address vaultOwner = makeAddr("vaultOwner");
address gameOwner = makeAddr("gameOwner");
address alice = makeAddr("alice");
address bob = makeAddr("bob");
uint256 constant GAME_DURATION = 100;
function setUp() public {
vm.prank(nftOwner);
nft = new EggstravaganzaNFT(NAME, SYMBOL);
vm.startPrank(vaultOwner);
vault = new EggVault();
vault.setEggNFT(address(nft));
vm.stopPrank();
vm.startPrank(gameOwner);
game = new EggHuntGame(address(nft), address(vault));
vm.stopPrank();
vm.prank(nftOwner);
nft.setGameContract(address(game));
}
...
function testNFTOwnerDoS() public {
uint256 eggId = 1;
// nft owner can mint egg to any address
vm.startPrank(nftOwner);
nft.setGameContract(nftOwner);
nft.mintEgg(nftOwner, eggId);
nft.setGameContract(address(game));
// deposit egg to vault
nft.approve(address(game), eggId);
game.depositEggToVault(eggId);
// check result
assertTrue(vault.isEggDeposited(eggId));
assertEq(vault.eggDepositors(eggId), nftOwner);
vm.stopPrank();
vm.startPrank(gameOwner);
game.startGame(GAME_DURATION);
game.setEggFindThreshold(100);
vm.stopPrank();
vm.startPrank(alice);
vm.expectRevert(abi.encodeWithSelector(IERC721Errors.ERC721InvalidSender.selector, address(0))); // denial of Service
game.searchForEgg();
vm.stopPrank();
}

Recommended Mitigation:
make gameContract unchangeable once set in EggstravaganzaNFT::setGameContract,

function setGameContract(address _gameContract) external onlyOwner {
+ require(gameContract == address(0), "Game contract already set");
require(_gameContract != address(0), "Invalid game contract address");
gameContract = _gameContract;
}
Updates

Lead Judging Commences

m3dython Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

Trusted Owner

Owner is trusted and is not expected to interact in ways that would compromise security

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!