SNARKeling Treasure Hunt

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

[L-02] `updateVerifier()` accepts zero address and can brick claims when unpaused

Author Revealed upon completion

Root + Impact

Description

The normal behavior is that verifier updates keep claim() operational.

The issue is that updateVerifier() does not validate newVerifier != address(0). If owner sets zero verifier and later unpauses, claim() attempts to call verify on address zero and fails for all claims until verifier is changed again.

// contracts/src/TreasureHunt.sol
function updateVerifier(IVerifier newVerifier) external {
require(paused, "THE_CONTRACT_MUST_BE_PAUSED");
require(msg.sender == owner, "ONLY_OWNER_CAN_UPDATE_VERIFIER");
verifier = newVerifier; // @> zero address allowed
}

Risk

Likelihood:

  • Owner can call updateVerifier(address(0)) while paused; no guard prevents it.

  • Existing test demonstrates this assignment succeeds.

Impact:

  • Claim path can be unavailable after unpause due to invalid verifier target.

  • Protocol availability depends on a follow-up admin correction.

Proof of Concept

Written reproduction flow:

  1. Owner pauses contract.

  2. Owner sets verifier to address(0).

  3. Owner unpauses.

  4. Any user calling claim() hits failed external verifier call path and cannot claim.

function test_B4_UpdateVerifierToZeroAddress() public {
vm.startPrank(OWNER);
hunt.pause();
hunt.updateVerifier(IVerifier(address(0))); // succeeds (bug)
hunt.unpause();
vm.stopPrank();
assertEq(hunt.getVerifier(), address(0));
vm.prank(PARTICIPANT);
vm.expectRevert(); // call/decode failure when verifier is address(0)
hunt.claim(DUMMY_PROOF, HASH_1, payable(address(0x1234)));
}

Recommended Mitigation

Add a guard in updateVerifier(IVerifier newVerifier).

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;
}

Support

FAQs

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

Give us feedback!