withdraw() lacks access control, allowing any actor to trigger owner settlementEvery other administrative function in the contract (fund, pause, unpause, updateVerifier, emergencyWithdraw) is restricted to the owner. withdraw() is the only exception, containing no access control and callable by any external address once claimsCount >= MAX_TREASURES.
Funds always go to owner, so no direct theft is possible. However, any actor can front-run the owner's intended settlement transaction, causing the owner's tx to revert with NO_FUNDS_TO_WITHDRAW and forcing the owner to rely on third parties for execution of a semantically privileged lifecycle step.
Likelihood:
Any external address can call withdraw() once claimsCount >= MAX_TREASURES, meaning the condition for exploitation is met at the natural end of every hunt cycle without any special precondition.
A griefer monitoring the mempool can front-run the owner's settlement transaction on every withdrawal attempt, consistently forcing the owner's tx to revert with NO_FUNDS_TO_WITHDRAW.
Impact:
Inconsistent access control design, as withdraw() is the only admin function not restricted to the owner, undermining the contract's intended privileged lifecycle model.
Owner settlement can be griefed into a revert, forcing the owner to rely on third parties for execution of a semantically privileged lifecycle step.
Add an onlyOwner check, consistent with every other admin function in the contract, or use the existing onlyOwner modifier:
The `withdraw()` function is intended as an owner-only post-hunt recovery function, but the implementation does not actually enforce any ownership check before transferring the full remaining balance to owner. The function only requires that `claimsCount >= MAX_TREASURES` and that the contract balance is nonzero, after which it sends all ETH to the stored owner address regardless of who called the function. Therefore, the access control on the function itself is incomplete because any external account can trigger the withdrawal path once the hunt is considered over.
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.