Company Simulator

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

`Cyfrin_Hub::fund_investor` when an investor wants shares at the outset the function reverts because the company is insolvent

Cyfrin_Hub::fund_investor when an investor wants shares at the outset the function reverts because the company is insolvent

Description

  • The expected behavior is that fund_investor allows any investor to buy shares from the first block, using INITIAL_SHARE_PRICE while no shares have been issued and crediting the funds to company_balance.

  • What actually happens is the function reverts immediately because it checks self.company_balance > self.holding_debt, and the initial state (0 > 0) does not satisfy it; therefore, no public investment can start the round.

@payable
@internal
def fund_investor():
assert msg.value > 0, "Must send ETH!!!"
assert (
self.issued_shares <= self.public_shares_cap
), "Share cap reached!!!"
@> assert (self.company_balance > self.holding_debt), "Company is insolvent!!!"
// Calculate shares based on contribution
net_worth: uint256 = 0
if self.company_balance > self.holding_debt:
net_worth = self.company_balance - self.holding_debt
...

Risk

Likelihood: High

  • When the contract is deployed company_balance = 0 and holding_debt = 0. This causes all investments made after deployment to revert because company_balance is not greater than holding_debt.

Impact: High

  • Completely blocks public capital inflows, leaving the simulation without investment flows and preventing testing of the protocol's main paths.

Proof of Concept

The first inversor attempts to make a contribution, but the function reverts.

def test_initial_ivestors_revert(industry_contract):
with boa.env.prank(investor):
with boa.reverts("Company is insolvent!!!"):
industry_contract.fund_cyfrin(1, value=to_wei(10, "ether"))
tests/unit/test_company.py::test_initial_ivestors_revert PASSED

Recommended Mitigation

  • Require the owner to fund the contract during deployment so that fund_investor starts with a visible positive net worth.

def deploy_industry() -> VyperContract:
- cyfrin_industry: VyperContract = Cyfrin_Hub.deploy()
+ cyfrin_industry: VyperContract = Cyfrin_Hub.deploy(value=INITIAL_OWNER_FUND)
print(
f"Cyfrin Industry deployed at {cyfrin_industry.address} "
f"with initial balance {INITIAL_OWNER_FUND} wei"
)
return cyfrin_industry
@deploy
+ @payable
def __init__():
+ assert msg.value > 0, "Owner must fund initial capital!!!"
+ self.company_balance += msg.value
Updates

Lead Judging Commences

0xshaedyw Lead Judge
9 days ago
0xshaedyw Lead Judge 7 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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