SNARKeling Treasure Hunt

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

Verifier Update Without Proof Freshness Allows Replay / Control

Author Revealed upon completion

Root + Impact

Description

  • Normal behavior: The verifier is a trusted component that binds proof validity. Changing the verifier mid-hunt should be restricted and should not allow old proofs to validate new claims after update.

The owner can update the verifier while the contract is paused, but proof freshness is not tied to contract state or update epoch, allowing previously valid proofs for one verifier to be replayed after an update.

// Root cause in TreasureHunt.sol
// @> Contract uses verifier without freshness linkage
bool ok = verifier.verify(proof, publicInputs);

Risk

Likelihood:

  • Occurs when owner updates verifier after flawed proofs are generated.

Attackers with access to valid proof material can precompute and replay.

Impact:

  • Old proof data may validate against faulty/updated verifier logic.

Allows extraneous claims without recomputing proofs.

Proof of Concept

// Off-chain: pre-compute a valid proof for circuit 1
proof1 = generateProof(secret1)
// Owner updates verifier logic
treasureHunt.updateVerifier(newVerifier)
// Attacker replays proof1 with same public inputs
treasureHunt.claim(proof1, hash1, attacker)

Recommended Mitigation

  • Include a verifier epoch or version in the proof context, and invalidate old proofs after updates.

- remove this code
+ add this code
+uint256 public verifierEpoch;
+function updateVerifier(...) external onlyOwner {
+ verifierEpoch++;
+ verifier = newVerifier;
}
+function claim(...) external {
+ require(proof.epoch == verifierEpoch, "Stale proof");
// verify
}

Support

FAQs

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

Give us feedback!