The CustomerEngine.trigger_demand() function rate-limits calls per user address using a cooldown mapping. This is intended to prevent spamming demand generation and to simulate realistic, throttled customer activity.
The cooldown is enforced only per address, so an adversary can rotate through unlimited new EOAs (or cheap contracts) to bypass the rate limit entirely. This is a classic Sybil vector: the system treats each address as a distinct “customer,” enabling high-frequency calls that the cooldown was designed to prevent.
Likelihood: High
The attack occurs whenever an adversary can create additional EOAs (cost ~0 off-chain, small on-chain for first tx) to alternate calls and evade the per-address timer.
It also occurs whenever bot operators or MEV searchers want to maximize reputation gains or revenue events by fanning out transactions across fresh addresses.
Impact: High
Spam demand / economic distortion — Attackers can generate near-continuous demand, manipulating inventory turnover and internal accounting in CompanyGame.sell_to_customer().
Reputation manipulation — Because successful sales increase the company’s reputation, an attacker can artificially inflate reputation by mass-calling via Sybil addresses (and further exploit other issues like missing msg.value validation in sell_to_customer() from a separate finding).
Copy below function to the test_Engine.py
Run command mox test -k test_Rate_Limit_Bypass_With_Sybil_Attack
Global rate limit + per-address limit
Introduce a global last-trigger timestamp and enforce a minimum inter-arrival time across all callers in addition to the per-address cooldown. This caps system-wide throughput.
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.