contracts/src/TreasureHunt.sol -> claimed[_treasureHash] checks the immutable constructor value instead of the caller-supplied treasureHash parameterThe contract maintains a claimed mapping to prevent the same treasure from being claimed twice. Each claim should check and mark the caller-supplied treasureHash parameter.
The duplicate-claim guard reads from claimed[_treasureHash] where _treasureHash is a separate immutable set at constructor time, but writes to claimed[treasureHash] where treasureHash is the caller-supplied parameter. These are two different storage slots, so the guard never blocks replay for any treasure hash other than the one that happens to match the constructor value.
Likelihood:
Any attacker who obtains a valid proof including a legitimate finder, immediately notices the same proof works again on the second call.
The exploit requires only a working proof and a loop, executable in a single script with no advanced knowledge
Impact:
A single valid proof is replayed indefinitely until the contract balance drops below 10 ETH, draining up to 100 ETH
claimsCount increments on every successful replay, corrupting the hunt state and potentially blocking legitimate claimants
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.