Company Simulator

First Flight #51
Beginner FriendlyDeFi
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Excessive Owner Privileges Leading to Share Dilution

Root + Impact

Description

  • The owner deploys the contract and uses privileged functions to adjust the share cap, produce inventory items, and handle debt repayments, simulating executive decisions in a virtual company. Investors receive shares proportional to their funding contributions, expecting fair governance.

  • The lack of checks or balances on the owner's increase_share_cap function allows them to inflate the total share supply indefinitely, issuing new shares to themselves or favored parties, which directly reduces the value and voting power of existing shares without recourse. This centralization risk undermines the decentralized ethos and exposes investors to rug-pull scenarios.

// Root cause in the codebase with @> marks to highlight the relevant section
@external
def increase_share_cap(new_cap: uint256):
# @> No validation on new_cap exceeding current cap or requiring justification
# @> Owner-only access without events or governance hooks
assert msg.sender == self.owner, "Only owner"
self.share_cap = max(self.share_cap, new_cap)
log ShareCapIncreased(new_cap)

Risk

Likelihood: High

  • Owner can call this function repeatedly during low-activity periods when investors are not monitoring

  • No cooldown, quorum, or timelock mechanisms to prevent abuse

Impact: High

  • Existing investors' proportional ownership is diluted, leading to loss of control over company decisions like production rates or debt management

  • Enables insider trading or self-funding loops where owner funds via new shares and extracts value through production sales

Proof of Concept

This PoC simulates a step-by-step attack sequence using pseudo-code (not executable Vyper, but illustrative of contract interactions). It demonstrates how an attacker (the owner) exploits the increase_share_cap and invest functions to dilute shares.

# Simulate deployment and exploitation
# Assume initial share_cap = 1000, investor A buys 500 shares for 500 ETH
# Owner calls increase_share_cap(2000)
# Owner then "invests" 0 ETH to claim 1000 new shares (if issuance logic allows minimal contribution)
# Result: Investor A's stake drops from 50% to 25%, while owner gains majority control

Recommended Mitigation

This diff shows targeted additions to increase_share_cap to add safeguards. + lines are new; - is unchanged for context. It introduces state variables like self.last_cap_increase (uint256 timestamp).

- remove this code
+ add this code
@external
def increase_share_cap(new_cap: uint256):
- assert msg.sender == self.owner, "Only owner"
+ assert msg.sender == self.owner, "Only owner"
+ assert new_cap <= self.share_cap * 2, "Cap increase limited to 2x" # Prevent extreme dilution
+ assert block.timestamp >= self.last_cap_increase + 30 days, "Cooldown period required" # Timelock for transparency
self.share_cap = max(self.share_cap, new_cap)
log ShareCapIncreased(new_cap)
+ self.last_cap_increase = block.timestamp
Updates

Lead Judging Commences

0xshaedyw Lead Judge
10 days ago
0xshaedyw Lead Judge 8 days ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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