Description
Normal Behavior: The fund_investor function allows users to invest ETH to receive company shares. It calculates the current share_price by dividing the company's net worth (company_balance - holding_debt) by the total issued_shares.
Specific Issue: If the company's holding_debt grows larger than its company_balance, the net_worth can become extremely low. When this low net_worth is divided by a large issued_shares number, integer division can cause the share_price to become 0.
Root Cause:
Code snippet
Likelihood: Medium
Reason 1: This scenario occurs when the _apply_holding_cost function is not called for an extended period, which happens when no one triggers sell_to_customer.
Reason 2: When sell_to_customer is finally called, the large, accumulated holding_debt is applied all at once, which can drop the company's net_worth to a value less than issued_shares.
Impact:
Impact 1: This creates a Denial of Service (DoS) vulnerability, as any new call to fund_investor will permanently fail with a "division by zero" error.
Impact 2: The contract's primary method for raising capital is "bricked," preventing any new investors from funding the company and effectively freezing its growth.
A few investors call fund_investor to buy shares, so issued_shares is greater than zero.
All users (or an attacker) wait for a long period (e.g., several days) without calling trigger_demand on the CustomerEngine contract.
During this time, a large holding_debt accumulates in the Cyfrin_Hub contract.
A user finally calls trigger_demand, which executes sell_to_customer.
This triggers _apply_holding_cost, applying the massive debt and causing the company's net_worth to become very low (e.g., net_worth = 500 wei, while issued_shares = 1,000,000).
A new, legitimate investor calls fund_investor with 1 ETH.
The contract calculates share_price = 500 // 1_000_000, which results in share_price = 0.
The contract then attempts to execute new_shares = (1 ETH) // 0, which reverts the transaction.
All future attempts to call fund_investor will also revert, as the share_price will remain 0.
Code snippet
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.
The contest is complete and the rewards are being distributed.