The claim() function is intended to mark a treasure as claimed after a valid proof is submitted, preventing the same proof from being used again. The replay guard checks claimed[_treasureHash], where _treasureHash is a private immutable that is never assigned and defaults to bytes32(0). However, the claim is recorded using the function parameter claimed[treasureHash]. Since these keys differ, the check and the write operate on different storage slots, causing the replay protection to never trigger.
Likelihood:
Any participant who finds a treasure has a valid proof with their address as recipient
Replaying requires no additional capital — same calldata submitted multiple times
No special access or timing required — works any time the contract is unpaused and funded
Impact:
Full contract drain of up to MAX_TREASURES × REWARD using a single valid proof
claimsCount hits MAX_TREASURES via replay, permanently locking out all legitimate finders with AllTreasuresClaimed
Contract state corrupted — remaining treasure hashes appear unclaimed via isClaimed() but can never be claimed
In `claim()`, the guard uses `claimed[_treasureHash]`, where `_treasureHash` is an immutable state variable that is never initialized to the caller-supplied treasure identifier, while the contract later marks `claimed[treasureHash] = true` using the function argument instead. As a result, the duplicate-claim check and the state update are performed against different keys, which means a previously claimed treasure is not actually blocked from being claimed again with the same valid proof and `treasureHash`. This breaks a core invariant of the protocol described in the README, namely, that each treasure can only be redeemed once, and allows one valid treasure/proof pair to be reused to drain rewards repeatedly until either the `MAX_TREASURES` cap or the contract balance is exhausted.
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.