F-2025-0008·invariant-violation

Broken ticket index continuity leads to invalid winner selection and product.maxTickets invariant break

Acknowledgedrafflelotteryvrf
TL;DR

buySpecificTickets allows non-consecutive ticket indices but only increments ticketsSold by count, creating gaps that break maxTickets enforcement and enable winner selection on unowned indices.

Severity
HIGH
Impact
HIGH
Likelihood
MEDIUM
Method
MManual review
CAT.
Complexity
MEDIUM
Exploitability
MEDIUM
02Section · Description

Description

The contract assumes that ticket indices from 0 to round.ticketsSold - 1 are continuously owned. However, NexumManager::buySpecificTickets allows users to purchase any ticket numbers while only increasing round.ticketsSold by the number of tickets bought, not by the highest index used. This creates gaps in ticket ownership that violate the round internal accounting assumptions and also breaks the maxTickets check.

Vulnerable Scenario:

  • A round starts with round.ticketsSold = 0 and product.maxTickets = 1000.
  • A user buys tickets through buySpecificTickets, choosing not consecutive ticket numbers such as {10, 11, 12, 13, 14}.
  • At this point, round.ticketsSold == 5, but ticket indices like {0, 1, 2, 3, 4} have no owner.
  • Other users continue buying tickets through buyTickets, which increases round.ticketsSold sequentially, until round.ticketsSold reaches 1000.
  • When the protocol selects winners using randomness, it may select an index that has no owner.
  • If that index is chosen, the reward is sent to address(0) causing loss of funds.
03Section · Impact

Impact

  • Loss of rewards if a ticket with no owner becomes the winner.
  • Higher odds to win since the maxTickets check can be bypassed.
  • Loss of trust.
04Section · Recommendation

Recommendation

  • Apply the maxTickets checks present in buyTickets into buySpecificTickets.
  • Maintain a counter of valid ticket indices and use that structure for winner selection instead of assuming index continuity.
05Section · Resolution

Resolution

Nexalo: Fixed. Applied the maxTickets checks present in buyTickets into buySpecificTickets.

Zealynx: Partially fixed. We recommend to also maintain a counter of valid ticket indices and use that structure for winner selection instead of assuming index continuity.

F-2025-0008

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx