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

Weak Randomness Implementation

Root + Impact

Description

The contract uses timestamp-based randomness to determine slice amounts, which is predictable and can be manipulated by validators or sophisticated attackers. The randomness is generated using timestamp::now_microseconds() % 401 + 100.

#[randomness]
entry fun get_random_slice(user_addr: address) acquires ModuleData, State {
let state = borrow_global_mut<State>(get_resource_address());
let time = timestamp::now_microseconds(); // @> Predictable randomness source
let random_val = time % 401; // @> Simple modulo operation
let random_amount = 100 + random_val; // @> Results in 100-500 range
table::add(&mut state.users_claimed_amount, user_addr, random_amount);
}

Risk

Likelihood:

  • Validators can manipulate transaction timing to influence randomness outcomes

  • Attackers can predict slice amounts by observing timestamp patterns

  • MEV (Maximum Extractable Value) opportunities exist for sophisticated actors

Impact:

  • Unfair distribution of rewards favoring certain participants

  • Loss of randomness guarantees breaks the intended game mechanics

  • Potential for systematic exploitation reducing available funds

Proof of Concept

// Attacker can predict the outcome by timing their registration
// If current timestamp is X, the slice will be (X % 401) + 100
// Validators can delay/accelerate block production to manipulate this

Recommended Mitigation

- #[randomness]
- entry fun get_random_slice(user_addr: address) acquires ModuleData, State {
- let state = borrow_global_mut<State>(get_resource_address());
- let time = timestamp::now_microseconds();
- let random_val = time % 401;
- let random_amount = 100 + random_val;
- table::add(&mut state.users_claimed_amount, user_addr, random_amount);
- }
+ #[randomness]
+ entry fun get_random_slice(user_addr: address) acquires ModuleData, State {
+ let state = borrow_global_mut<State>(get_resource_address());
+ // Use Aptos randomness API for secure randomness
+ use aptos_framework::randomness;
+ let random_bytes = randomness::bytes(32);
+ let random_val = randomness::u64_range(100, 501); // 100-500 inclusive
+ table::add(&mut state.users_claimed_amount, user_addr, random_val);
+ }
Updates

Appeal created

bube Lead Judge 10 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.