SNARKeling Treasure Hunt

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

M-02 Deployment Script Permits Underfunded Hunt Deployment

Author Revealed upon completion

Description

The deployment script accepts INITIAL_FUNDING from the environment and forwards it directly into the TreasureHunt constructor without validating that the amount is sufficient to fund all intended rewards.

Because the script does not enforce INITIAL_FUNDING >= REWARD * MAX_TREASURES, it can successfully deploy a hunt that is structurally underfunded from the first block.

Risk

An underfunded deployment can create an unusable or partially unusable hunt:

  • valid claims may revert with NotEnoughFunds

  • the deployed contract may violate the project’s intended economic assumptions

  • operators may believe deployment succeeded while the hunt is not actually solvent

This is primarily a deployment safety and operational integrity issue.

Proof of Concept

The script reads arbitrary funding input here:

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

and deploys the contract with that value here:

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

The only post-deployment balance check is:

require(hunt.getContractBalance() == initialFunding, "UNEXPECTED_BALANCE");

That check confirms only that the transfer occurred, not that the amount is economically sufficient.

For example, if INITIAL_FUNDING=5 ether, deployment would still proceed even though the contract’s reward logic expects:

REWARD = 10 ether
MAX_TREASURES = 10

As a result, the first valid claim would already be at risk of reverting due to insufficient funds.

Recommended Mitigation

Validate funding before broadcasting and fail fast unless the deployment is fully funded.

diff --git a/contracts/scripts/Deploy.s.sol b/contracts/scripts/Deploy.s.sol
--- a/contracts/scripts/Deploy.s.sol
+++ b/contracts/scripts/Deploy.s.sol
@@ -44,6 +44,9 @@ contract Deploy is Script {
uint256 deployerKey = vm.envUint("PRIVATE_KEY");
uint256 initialFunding = vm.envOr("INITIAL_FUNDING", DEFAULT_INITIAL_FUNDING);
+
+ require(initialFunding >= TreasureHunt.REWARD() * TreasureHunt.MAX_TREASURES(), "INSUFFICIENT_INITIAL_FUNDING");
address deployer = vm.addr(deployerKey);

Support

FAQs

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

Give us feedback!