Normal behavior: Documentation states the proof binds to a specific recipient EVM address; the circuit should constrain the public recipient input accordingly.
Problem: main declares recipient: pub Field but no assertion uses it. There is no 160-bit range check or decomposition in Noir. Whether full field public inputs versus uint160 packing on chain fully bind the payout address needs verifier-transcript analysis. Project tests already reject wrong recipient with the same proof bytes, so this may be informational.
Likelihood:
Exploitability depends on a concrete mismatch between field semantics and on-chain uint160 packing.
Low without a demonstrated transcript ambiguity.
Impact:
Ranges from informational (Honk hashing sufficient) to medium if an encoding gap existed.
Explanation: The Noir entrypoint never constrains recipient in-circuit; binding may come entirely from the Honk verifier and public-input transcript. The repo’s own tests show claim reverts if recipient does not match the proof’s public inputs.
Supporting code — run wrong-recipient tests:
Supporting code — TreasureHunt.t.sol (wrong recipient reverts verifier; excerpt):
Supporting code — circuit (recipient unused in constraints):
Conclusion for triage: Executable tests indicate recipient is enforced by the verifier, not by explicit Noir assertions; treat as informational unless a concrete encoding or transcript bug is demonstrated. Attach forge test output when submitting.
Explanation: If the security model requires an explicit statement “this proof pays exactly this 160-bit address,” add constraints in Noir (for example range-check recipient as an Ethereum address). If Honk public inputs and the verifier already bind recipient (as project tests suggest), document that design and ensure Solidity publicInputs encoding matches the verifier’s expected layout so reviewers do not assume recipient is unconstrained.
The claim that the proof system is broken because the recipient is not explicitly constrained in the Noir circuit reflects a misunderstanding of how zero-knowledge proofs bind public inputs. Although the circuit does not impose algebraic constraints on recipient, the value is still included in the public input vector, which is cryptographically committed to during proof generation. As a result, the proof is only valid for the exact tuple of public inputs it was created with. Any attempt by an attacker to front-run and substitute a different recipient would alter this tuple, causing the verifier’s check to fail because the proof no longer matches the provided public inputs. Therefore, while unconstrained public inputs do not enforce logical relationships within the circuit, they remain inseparably bound to the proof itself, and this binding is sufficient to prevent tampering or replay with modified values. Run the unit tests 'testClaimInvalidProofFails', 'testFrontRunningClaimFails'.
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.