SNARKeling Treasure Hunt

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

withdraw() Missing Access Control Anyone Can Trigger Post-Hunt Withdrawal

Author Revealed upon completion

Root + Impact

Description

  • The documented design states withdrawal of leftover funds is an owner-controlled admin flow.

  • withdraw() sends the entire contract balance to owner, which prevents direct theft, but the function lacks the onlyOwner modifier, allowing any external account to invoke it.

// Root cause in the codebase with @> mark// @> No onlyOwner modifier — any caller can trigger this
function withdraw() external {
require(claimsCount >= MAX_TREASURES, "HUNT_NOT_OVER");
uint256 balance = address(this).balance;
require(balance > 0, "NO_FUNDS_TO_WITHDRAW");
// @> Always sends to owner, so no theft — but caller is not authenticated
(bool sent, ) = owner.call{value: balance}("");
require(sent, "ETH_TRANSFER_FAILED");
emit Withdrawn(balance, address(this).balance);
}s to highlight the relevant section

Risk

Likelihood:

  • Any on-chain observer can call this function once claimsCount == MAX_TREASURES.

Bots routinely front-run state-change events to trigger permissionless functions.

Impact:

  • The owner loses control over the timing of their own withdrawal — a third party forces the transfer at any moment after the hunt ends.

  • Gas refund griefing: a malicious actor can repeatedly front-run the owner's own withdrawal transaction.

  • Violates the principle of least privilege and the protocol's documented access control model.

Proof of Concept

After all 10 treasures are claimed:

Attacker calls withdraw() before owner does.

hunt.withdraw(); // Succeeds — sends balance to owner despite attacker calling

Recommended Mitigation

Add the onlyOwner modifier:

- remove this function withdraw() external onlyOwner {
require(claimsCount >= MAX_TREASURES, "HUNT_NOT_OVER");
...
}

Support

FAQs

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

Give us feedback!