The normal behavior is to have 10 distinct secrets mapped to 10 distinct allowed Pedersen hashes.
The issue is that ALLOWED_TREASURE_HASHES contains the same value at index 8 and 9. This collapses two intended treasure slots into one cryptographic identity. Under intended one-claim-per-hash semantics, only one of those two slots can be redeemed independently.
Likelihood:
The duplicate constant is deterministic and always active for all proofs.
At least one legitimate participant eventually hits the colliding slot in normal operation.
Impact:
One treasure reward becomes permanently uncollectable once per-hash replay protection is enforced as intended.
Protocol promise of 10 unique claimable treasures is violated.
Standalone reproduction in Noir:
Compute pedersen_hash([9]) which equals -4417726114039171734934559783368726413190541565291523767661452385022043124552.
Check membership against current ALLOWED_TREASURE_HASHES.
Observe membership is false because the array duplicates hash #10 instead of including hash #9.
A proof for treasure 9 cannot satisfy is_allowed(treasure_hash).
Written exploit flow:
The duplicated hash allows only one of the two intended physical treasure slots to be represented as a unique on-chain claim key.
Once that shared hash is claimed once (with a correct claimed[treasureHash] guard), the second participant mapped to the same hash cannot claim independently.
Use the global constant ALLOWED_TREASURE_HASHES in circuits/src/main.nr.
After updating the circuit constant, regenerate proving artifacts and contracts/src/Verifier.sol from the new circuit.
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.
The contest is complete and the rewards are being distributed.