The TreasureHunt protocol is designed with fixed parameters: REWARD = 10 ETH and MAX_TREASURES = 10. To function correctly and honor all 10
potential claims, the contract must be funded with at least 100 ETH upon deployment
The issue lies in the Deploy.s.sol script, which retrieves the INITIAL_FUNDING amount from an environment variable but fails to validate if
this amount is sufficient to cover the protocol's total liabilities. If the operator misconfigures the .env file or passes a lower value during
deployment, the contract will be successfully deployed but will be insolvent before the hunt is completed
Likelihood:
This is a realistic scenario involving operator error during deployment to a live network (e.g., Mainnet or Sepolia).
Foundry scripts often rely on environment variables that can be easily mistyped or misconfigured in high-pressure deployment environments
Impact:
Protocol Insolvency: If the contract is underfunded (e.g., only 50 ETH), the last 5 participants who find physical treasures will be unable to
claim their rewards. Their claim() transactions will revert with NotEnoughFunds(), leading to a breakdown in trust and financial loss for the
finders
If the script is executed with the following command:
INITIAL_FUNDING=10000000000000000000 forge script Deploy.s.sol ... (which is only 10 ETH)
The script will execute successfully without any warnings.
The TreasureHunt contract goes live with a balance of only 10 ETH.
The first successful claimant receives the 10 ETH.
All subsequent 9 claimants (2nd to 10th) will have their valid proofs rejected by the contract due to insufficient balance, even though they
found the physical treasures
It is recommended to add a strict validation check within the run() function of the deployment script. The script should verify that the
initialFunding is at least equal to the total reward liability of the hunt (MAX_TREASURES * REWARD).
The liquidity-enforcement issue arises because the protocol assumes the hunt will be funded with enough ETH to cover all rewards, but the contract itself does not actively enforce that invariant at deployment time. The constructor accepts arbitrary `msg.value` and only validates the verifier address, even though the contract hardcodes a reward of 10 ether and a maximum of 10 treasures, implying an expected full funding target of 100 ether; the README likewise states that the contract is expected to be funded with enough ETH to cover all rewards and notes that the default deployment flow uses 100 ether. Although the deployment script sets `DEFAULT_INITIAL_FUNDING = 100 ether`, it also allows that amount to be overridden via `vm.envOr("INITIAL_FUNDING", DEFAULT_INITIAL_FUNDING)`, and the only post-deployment balance check is that the contract balance equals the chosen `initialFunding`, not that the chosen amount is actually sufficient to fund the full hunt. As a result, the system can be deployed in an underfunded state after which otherwise valid claims will begin reverting with `NotEnoughFunds()` once the balance drops below a single reward payment.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.