The claim() function is intended to prevent the same treasure from being claimed more than once through the claimed mapping. However, the current implementation checks claimed[_treasureHash] instead of claimed[treasureHash].
Since _treasureHash is declared as an immutable state variable but never initialized, the duplicate-claim check does not operate on the caller-supplied treasure identifier. As a result, the contract does not correctly enforce the one-claim-per-treasure invariant.
This issue directly affects the reward-distribution logic. A valid treasure may be claimed repeatedly, limited only by:
remaining contract balance
claimsCount < MAX_TREASURES
This can lead to repeated reward payouts for the same treasure.
An attack path is straightforward:
Obtain one valid proof for a legitimate treasureHash.
Call claim(proof, treasureHash, recipient) successfully.
The contract sets claimed[treasureHash] = true, but future calls still check claimed[_treasureHash].
Re-submit the same valid claim until the contract reaches MAX_TREASURES or runs out of funds.
The relevant flawed line is:
Update the duplicate-claim check so that it uses the function argument treasureHash, and remove the unused _treasureHash state variable.
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.