The constructor mixes two different ownership initialization styles Ownable(msg.sender) and transferOwnership(msg.sender) even though OpenZeppelin’s Ownable already sets the deployer as the owner.
Because of this redundancy, depending on inheritance order and compiler behavior, ownership can be set to the zero address or assigned to an unintended account, allowing a potential unauthorized contract takeover or permanent loss of control.
Likelihood:
Occurs during deployment or upgrade if wrong constructor version is used.
Can leave ownership uninitialized (owner = address(0)).
Impact:
If ownership is address(0), onlyOwner functions become permanently locked (denial of control).
If misassigned, an attacker or external deployer could take over all privileged actions (e.g., setting fees, event winners, rescuing funds).
Explanation:
If the OpenZeppelin Ownable base constructor already sets the deployer as the owner,
adding Ownable(msg.sender) again may pass a zero or unintended address depending on inheritance order.
This can result in owner() returning the wrong value — enabling unauthorized users to execute privileged actions or permanently locking out legitimate control.
Summary: Removing both Ownable(msg.sender) and transferOwnership(msg.sender) prevents ownership confusion, aligns with OpenZeppelin standards, and ensures the deployer remains the legitimate contract owner.
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.