Beginner FriendlyGameFi
100 EXP
View results
Submission Details
Severity: medium
Valid

Predictable Randomness + Sybil Farm Drains PizzaCoin Treasury

Root + Impact
Root Cause

  • Predictable randomness source: Slice size is derived from easily knowable or manipulable values (e.g., block timestamp, transaction hash, user address). These inputs are not secure entropy.

  • Lack of Sybil resistance: The system enforces per-address limits only, allowing attackers to farm rewards with unlimited fresh accounts.

  • Unbounded treasury outflow: Claims do not check the remaining balance before payout, risking overdraws or premature pool exhaustion.

Impact

  • Treasury drained: An attacker can consistently claim near-max rewards (≈approximately 500 APT) across multiple accounts, rapidly depleting the pool.

  • Unfair distribution: Honest users are locked out, undermining the fairness of the “random surprise” element.

  • Reputation loss: PizzaCoin’s community campaign becomes associated with exploitation and broken promises.

Description

  • The PizzaCoin giveaway lets participants claim a “random slice” between 100–500 APT. Because randomness is generated from predictable inputs and there’s no Sybil resistance, attackers can simulate outcomes off-chain, submitting only high-value claims while discarding low-value ones. With unlimited accounts, they capture most of the rewards. This breaks the fairness model, ends the campaign early, and leaves honest participants with little or nothing.

// Root cause in the codebase with @> marks to highlight the relevant section

Risk

Likelihood:

  • Randomness is derived from block metadata (timestamp, height, txn hash), which are known before confirmation, allowing bots and validators to predict outcomes during the campaign.

  • Creating many Aptos accounts is cheap and fast, enabling Sybil farms to repeatedly exploit the predictable randomness mechanism within the 3d 4h campaign window.

Impact:

  • Giveaway treasury can be rapidly drained by an attacker who consistently claims near‑max rewards.

  • Honest users are denied fair distribution, leading to loss of trust and reputational damage for PizzaCoin.

Proof of Concept

// Simplified vulnerable claim function
public entry fun claim(account: &signer) acquires Treasury {
let treasury = borrow_global_mut<Treasury>(@pizzacoin);
@> let seed = hash64(block::timestamp_microseconds() | signer::address_of(account));
@> let slice = 100 + (seed % 401); // predictable randomness
coin::transfer(&mut treasury.funds, account, slice * OCTAS_PER_APT);
}
// Attacker script (off-chain pseudocode)
while true:
t = get_current_timestamp()
seed = hash64(t | attacker_addr)
payout = 100 + (seed % 401)
if payout >= 480:
submit_claim()
else:
skip

Recommended Mitigation

- // Insecure randomness based on block metadata and user address
- let seed = hash64(block::timestamp_microseconds() | signer::address_of(account));
- let slice = 100 + (seed % 401);
+ // Use unbiased randomness (VRF or commit-reveal scheme)
+ let random_bytes = aptos_std::randomness::random_bytes();
+ let random_num = u64::from_le_bytes(vector::sub_range(&random_bytes, 0, 8));
+ let slice = 100 + (random_num % 401);
+ // Cap payout by remaining balance
+ if (slice > treasury.funds.balance) {
+ slice = treasury.funds.balance;
+ }
+ // Enforce Sybil resistance (e.g., one claim per verified identity or require a small fee)
Updates

Appeal created

bube Lead Judge 11 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Predictable randomness

The `get_random_slice` function should only be called by the owner via the `register_pizza_lover` function. Also, the `owner` is trusted and will not choose a specific time for a new user to register. Therefore, I disagree with the claim of most reports in this group that an attacker can manipulate the random number of pizza slices. But I agree with the root cause of the reports in this group, that the random distribution is not completely random.

Support

FAQs

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