SNARKeling Treasure Hunt

First Flight #59
Beginner FriendlyGameFiFoundry
100 EXP
Submission Details
Impact: high
Likelihood: low

Verifier can be set to zero address

Author Revealed upon completion

Verifier can be set to zero address

Description

The constructor correctly validates that the verifier address is not the zero address, reverting with InvalidVerifier() if it is. This prevents the contract from being deployed with a broken state.

However, the updateVerifier function does not perform the same validation. The owner can set the verifier to address(0), which will cause every subsequent claim call to revert when it attempts to call verify on the zero address, effectively breaking the treasure hunt.

constructor(address _verifier) payable {
if (_verifier == address(0)) revert InvalidVerifier(); // validated here
// ...
}
function updateVerifier(IVerifier newVerifier) external {
require(paused, "THE_CONTRACT_MUST_BE_PAUSED");
require(msg.sender == owner, "ONLY_OWNER_CAN_UPDATE_VERIFIER");
@> // missing: if (address(newVerifier) == address(0)) revert InvalidVerifier();
verifier = newVerifier;
emit VerifierUpdated(address(newVerifier));
}

Risk

Likelihood: Low

The owner calls updateVerifier with address(0) by mistake.
The function accepts it silently.

Impact: High

All claim calls revert because verifier.verify(...) targets the zero address, which has no code. No participant can claim any treasure until the owner notices and calls updateVerifier again with a valid address.

Proof of Concept

function testUpdateVerifierToZeroAddress() public {
// Set verifier to zero address
vm.startPrank(owner);
hunt.pause();
hunt.updateVerifier(IVerifier(address(0)));
hunt.unpause();
vm.stopPrank();
// Participant tries to claim — reverts because verifier is address(0)
(bytes memory proof, bytes32 treasureHash, address payable recipient) = _loadFixture();
vm.prank(participant);
vm.expectRevert(); // call to address(0) reverts
hunt.claim(proof, treasureHash, recipient);
}

Recommended Mitigation

function updateVerifier(IVerifier newVerifier) external {
require(paused, "THE_CONTRACT_MUST_BE_PAUSED");
require(msg.sender == owner, "ONLY_OWNER_CAN_UPDATE_VERIFIER");
+ if (address(newVerifier) == address(0)) revert InvalidVerifier();
verifier = newVerifier;
emit VerifierUpdated(address(newVerifier));
}

Support

FAQs

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

Give us feedback!