Last Man Standing

First Flight #45
Beginner FriendlyFoundrySolidity
100 EXP
View results
Submission Details
Impact: medium
Likelihood: low
Invalid

Improper `Ownable` Initialization May Break Ownership Logic

Root Cause + Impact

Description

The contract incorrectly attempts to initialize the OpenZeppelin Ownable contract by passing msg.sender as a constructor argument:

constructor(...) Ownable(msg.sender) { ... }

However, OpenZeppelin’s standard Ownable implementation does not accept constructor arguments — it automatically sets the owner to msg.sender inside its own constructor:

constructor() {
_owner = msg.sender;
}

This misuse leads to two possible outcomes:

  • Compiler error if using unmodified OpenZeppelin — the contract won’t compile.

  • Silent logic error if using a modified or custom Ownable, where the constructor argument is ignored or misused — leading to broken or misassigned ownership.

@> If owner is never set properly, all onlyOwner functions become inaccessible, potentially making the contract unmanageable after deployment.


Risk

Likelihood: Low

  • This is primarily a development-time issue.

  • It is caught at compile-time with unmodified OpenZeppelin.

Impact: Low → Medium (Contextual)

  • If deployed with a custom or altered Ownable, ownership logic may break.

  • Any onlyOwner functions (e.g. withdrawals, upgrades, admin control) will fail permanently if ownership is unset.

While the compiler catches this in most cases, it may indicate misunderstanding of inherited contract logic — which can lead to more severe logic bugs elsewhere.


Proof of Concept

Incorrect usage that causes compilation failure:

@> constructor(...) Ownable(msg.sender) {
// Error: Wrong argument count
}

Error: Wrong argument count for base constructor invocation (1 provided, 0 expected).

Correct usage (OpenZeppelin v4+):

+ constructor(...) Ownable() {
// Safe: msg.sender is automatically set as owner
}

Recommended Mitigation

Replace:

constructor(...) Ownable(msg.sender) {
// Incorrect
}

With:

constructor(...) Ownable() {
// Correct - OpenZeppelin sets msg.sender as owner internally
}

Additional Guidance:

  • If using a custom Ownable contract, clearly define and document the expected constructor behavior.

  • Consider unit tests to validate that owner() is correctly set after deployment.


Updates

Appeal created

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.