Company Simulator

First Flight #51
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: medium
Likelihood: medium

Sub-Share Deposits Are Accepted Without Minting Any Shares

Author Revealed upon completion

Root + Impact

Description

  • The funding flow is intended to mint msg.value // share_price shares so every wei contributed by a public investor is exchanged for an equivalent stake.

  • Contributions smaller than the computed share_price round new_shares down to zero, but the function still increases company_balance and emits SharesIssued, leaving the depositor with no shares.

@> new_shares: uint256 = msg.value // share_price
if new_shares > available:
new_shares = available
@> self.company_balance += msg.value

Risk

Likelihood:

  • Share price grows with each profitable cycle, so later investors often face valuations far above 1 wei and are likely to send dust tests or underpriced deposits.

  • Wallet UX frequently allows arbitrary amounts, including rounding errors from front-end conversions, making sub-price deposits common.

Impact:

  • Investors lose the entire contribution without receiving any shares.

  • The protocol accrues unbacked equity entries that damage trust and invite regulatory scrutiny.

Proof of Concept

  1. Ensure the share price is greater than the intended deposit (e.g., share_price = 1e15).

  2. Call fund_investor with a smaller value (e.g., msg.value = 5e11).

  3. new_shares evaluates to zero, the deposit is still credited to company_balance, and the sender's shares balance remains unchanged.

// Initial investor raises share price to 2e15 by doubling company net worth.
fund_investor{value: 2 ether}()
// Second investor sends 5e14 wei (< share price).
fund_investor{value: 5e14}()
// new_shares == 0, shares[investor] stays zero, yet company_balance increases by 5e14 wei.

Recommended Mitigation

  • Require msg.value >= share_price (or otherwise revert) so users must send at least enough to mint one share.

  • Alternatively, track each investor's remainder and only finalize the contribution once the accumulated value crosses the share price.

  • Immediately refund msg.value % share_price so callers automatically recover the excess portion of their payment.

- new_shares: uint256 = msg.value // share_price
+ new_shares: uint256 = msg.value // share_price
+ assert new_shares > 0, "Contribution below share price!!!"

Support

FAQs

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