SNARKeling Treasure Hunt

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

Unsafe Deployment Assumption on Initial Funding Can Lead to Immediate Claim DoS

Author Revealed upon completion

Description

The deployment script assumes that the contract must always be funded with a fixed amount of 100 ether at deployment time:

uint256 constant DEFAULT_INITIAL_FUNDING = 100 ether;

However, this value is overrideable via an environment variable:

uint256 initialFunding = vm.envOr("INITIAL_FUNDING", DEFAULT_INITIAL_FUNDING);

This creates a critical mismatch between deployment assumptions and actual contract requirements.

The TreasureHunt contract relies on sufficient balance to process claims:

if (address(this).balance < REWARD) revert NotEnoughFunds();

Since each claim requires 10 ether, insufficient funding at deployment will immediately block user claims.

There is no on-chain enforcement ensuring that:

  • The contract is funded correctly

  • The funding matches MAX_TREASURES * REWARD

As a result, incorrect deployment configuration can permanently render the system unusable.


Risk

If the contract is deployed with insufficient funding (either accidentally or through misconfiguration of INITIAL_FUNDING), the system will immediately become partially or fully unusable.

Impact:

  • Users will be unable to claim rewards

  • Valid proofs will fail due to insufficient contract balance

  • The treasure hunt becomes economically non-functional

  • Requires redeployment to fix incorrect initialization

  • Breaks core protocol assumption that all treasures are claimable

Severity:

High

This is a funding-dependent denial of service at deployment time, caused by lack of enforced initialization invariants.


Proof of Concept

Step 1 — Deployment with incorrect funding

The script allows overriding funding:

uint256 initialFunding = vm.envOr("INITIAL_FUNDING", 100 ether);

An attacker or misconfigured deployer sets:

INITIAL_FUNDING=20 ether

Step 2 — Contract deployment succeeds

hunt = new TreasureHunt{value: initialFunding}(address(verifier));

Contract is deployed successfully with insufficient funds.


Step 3 — First claim execution fails

Each claim requires:

REWARD = 10 ether;

After 2 claims:

  • Balance becomes insufficient for remaining claims

  • Contract starts reverting:

revert NotEnoughFunds();

Step 4 — Result

  • Remaining users cannot claim rewards

  • Treasure hunt becomes partially unusable

  • System state is irreversibly broken without redeployment


Recommended Mitigation

Ensure deployment enforces correct funding invariants matching contract expectations.


✅ Fix 1 — Enforce correct funding in script

require(initialFunding == 100 ether, "INVALID_INITIAL_FUNDING");

✅ Fix 2 — Derive funding from contract constants

uint256 initialFunding = hunt.REWARD() * hunt.MAX_TREASURES();

✅ Fix 3 — Add runtime validation after deployment

require(
address(hunt).balance == hunt.REWARD() * hunt.MAX_TREASURES(),
"INVALID_CONTRACT_FUNDING"
);

Expected Outcome After Fix

  • Deployment always matches economic requirements

  • No risk of underfunded contract state

  • Claim system remains fully functional for all treasures

Support

FAQs

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

Give us feedback!