The contract defines a private immutable variable _treasureHash which is never initialized in the constructor. In solidity, uninitialized bytes32 variables default to 0x0.
In a standard smart contract design, the claim function should verify that the specific treasure being submitted hasn't been previously claimed by checking its unique hash against the claimed mapping. This ensures that each of the ten individual reward can be distributed to ten different successful participants, while preventing any single treasure from being claimed multiple times.
The specific issue is that the contract checks a private, uninitialized state variable(_treasureHash) instead of the user-provided treasureHash parameter to determine if a reward has been claimed. Because uninitialized bytes32 variables default to 0x0, the contract tracks every single claim againts this same empty value, causing the logic to fail after the first successful transaction.
Likelihood:
Reason 1 - The private immutable variable _treasureHash defaults to 0x0 due to a lack of initialization in the constructor.
Reason 2 - The claim function logic points specifically to this uninitialized variable instead of the function parameter, ensuring the error triggers during every execution.
Impact:
Impact 1 - The contract permanently locks all remaining rewards after the first successful claim, as the claimed[0x0] state becomes true for all subsequent calls.
Impact 2 - Nine out of ten treasures (90 ETH) become fundamently unclaimable, resulting in a near-total loss of protocol functionality.
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.