Normal behavior:
All ETH that the company uses for operations is expected to flow through the contract’s payable entrypoints (fund_cyfrin, pay_holding_debt, etc.) and be tracked in the company_balance state variable. Other code paths (withdrawals, payouts) rely on this internal accounting variable for correctness.
Specific issue:
The contract rejects direct ETH transfers in the __default__() fallback (it raises), but the EVM allows ETH to be force-sent via SELFDESTRUCT (or other low-level mechanisms) which bypasses __default__ and increases the contract's actual balance (address(this).balance) without updating company_balance. The contract uses the stored company_balance for all logic (net worth, share price, payouts, bankruptcy checks), so a mismatch between the actual ETH held and the tracked company_balance can break invariants, allow griefing, and produce surprising behavior.
Likelihood:
This occurs when any external contract performs selfdestruct(target) pointing at the company contract (no permission required).
It can be done deliberately by an attacker (to force funds) or accidentally by a third party.
Impact:
1.Accounting mismatch: address(this).balance (real ETH) may be greater than company_balance (tracked ETH), breaking assumptions used by payout functions or share-price logic.
2.Unexpected behavior: functions that rely on company_balance (e.g., get_share_price, withdraw_shares, _is_bankrupt) may behave incorrectly relative to the real ETH stored. This can lead to denial-of-service for withdrawals or confusing audits.
3.Griefing: an attacker can force the contract to hold ETH that the contract logic does not consider available (or, conversely, can affect the economics in ways the accounting does not reflect). In some flows, this could be used to cause financial inconsistencies or to block recovery flows that check company_balance instead of real balance.
Explanation (brief)
Don’t assume all ETH in the contract must pass through controlled functions — either (A) make the contract resilient by using the actual contract balance (self.balance / address(this).balance) for safety-critical checks, or (B) accept direct deposits by implementing a payable receive() / __default__ that records any incoming ETH into company_balance and emits an event. Option (A) is safest for critical invariants; Option (B) keeps your existing bookkeeping but requires that every incoming ETH path increments company_balance.
Explanation
make the contract resilient by using the actual contract balance (self.balance / address(this).balance) for safety-critical checks
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.