SNARKeling Treasure Hunt

First Flight #59
Beginner FriendlyGameFiFoundry
100 EXP
View results
Submission Details
Severity: low
Valid

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

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

Lead Judging Commences

s3mvl4d Lead Judge 18 days ago
Submission Judgement Published
Validated
Assigned finding tags:

no zero-address check in updateVerifier()

The issue is that `updateVerifier()` allows the owner to replace the verifier with an arbitrary address, including `address(0)`, even though the constructor explicitly treats a zero verifier as invalid and reverts with `InvalidVerifier()` during initial deployment. In other words, the contract establishes at deployment time that a null verifier address is not an acceptable configuration, but then fails to preserve that same invariant when the verifier is later updated through the admin recovery path.

Support

FAQs

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

Give us feedback!