Company Simulator

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

Inconsistent Price Between CustomerEngine and Cyfrin_Hub Causes Accounting Mismatch

Description

The CustomerEngine contract defines ITEM_PRICE = 2 * 10**16 (0.02 ETH) which customers must pay when triggering demand. However, the Cyfrin_Hub contract defines SALE_PRICE = 2 * 10**16 (0.02 ETH) as the revenue per item sold.

While these values currently match, they are defined independently in two separate contracts. If either value is changed during an upgrade or modification, it will cause an accounting mismatch where either:

  1. The company receives more ETH than credited (if ITEM_PRICE > SALE_PRICE)

  2. The company credits more than received (if SALE_PRICE > ITEM_PRICE, causing underflow)

Additionally, since finding C-1 shows that msg.value should be credited instead of calculated revenue, this inconsistency highlights a deeper architectural issue.

// In CustomerEngine.vy:
ITEM_PRICE: constant(uint256) = 2 * 10**16 # Line 25
// In Cyfrin_Hub.vy:
SALE_PRICE: constant(uint256) = 2 * 10**16 # Line 76

Risk

Likelihood:

  • This is currently not exploitable as both values match

  • Future contract modifications or upgrades could introduce mismatch

  • Contract maintainers may not realize these must stay synchronized

Impact:

  • If ITEM_PRICE > SALE_PRICE: Excess customer payments trapped in contract

  • If SALE_PRICE > ITEM_PRICE: Contract attempts to credit more than received, causing accounting errors

  • Breaks the economic model and trust in the system

Recommended Mitigation

# Option 1: Use msg.value directly (recommended, also fixes C-1)
@external
@payable
def sell_to_customer(requested: uint256):
assert msg.sender == self.CUSTOMER_ENGINE, "Not the customer engine!!!"
assert not self._is_bankrupt(), "Company is bankrupt!!!"
self._apply_holding_cost()
if self.inventory >= requested:
self.inventory -= requested
- revenue: uint256 = requested * SALE_PRICE
- self.company_balance += revenue
+ self.company_balance += msg.value
if self.reputation < 100:
self.reputation = min(self.reputation + REPUTATION_REWARD, 100)
else:
self.reputation = 100
- log Sold(amount=requested, revenue=revenue)
+ log Sold(amount=requested, revenue=msg.value)
# Option 2: Define price in a shared interface/constant that both contracts import
Updates

Lead Judging Commences

0xshaedyw Lead Judge
9 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.