Beginner FriendlyGameFi
100 EXP
View results
Submission Details
Impact: low
Likelihood: medium
Invalid

Balance check not in the good function causing business logic flaws

Balance check not in the good function causing business logic flaws

Description

The function airdrop::claim_pizza_slice has an assert that checks if there is sufficiency balance to give the pizza lovers their slices.

public entry fun claim_pizza_slice(user: &signer) acquires ModuleData, State {
...
let amount = *table::borrow(&state.users_claimed_amount, user_addr);
// Check if contract has sufficient balance
assert!(state.balance >= amount, E_INSUFFICIENT_FUND);
...
}

The business logic flaw here is that the owner gives claim pizza that his/her doesn't have and when the pizza lovers want to take their parts, they will see that there is not sufficient funds they will need to call the owner for the explanation.

Risk

No money lost but a potentially bad user experience.

Proof of Concept

You can create the following scenario :

  1. Owner funded the pizza pool for 10000 APT.

  2. 50 users want to register

  3. the owners register 50 users

    1. The average claim is 300.

    2. 50 x 300 = 15000

  4. approximately 33 users will have their claim and the rest will have the message E_INSUFFICIENT_FUND

The owner will need to calculate the right amount of APT to refund the pool.

Recommended Mitigation

A better approach is to change the position of the check directly in the function airdrop::registers_pizza_lover, like below :

+ const MAX_REWARD: u64 = 500;
...
public entry fun register_pizza_lover(owner: &signer, user: address) acquires ModuleData, State {
let state = borrow_global_mut<State>(get_resource_address());
assert!(signer::address_of(owner) == state.owner, E_NOT_OWNER);
+ assert!(state.balance - MAX_REWARD > 0, E_INSUFFICIENT_FUND);
get_random_slice(user);
event::emit(PizzaLoverRegistered {
user: user,
});
}
...
public entry fun claim_pizza_slice(user: &signer) acquires ModuleData, State {
...
let amount = *table::borrow(&state.users_claimed_amount, user_addr);
// Check if contract has sufficient balance
- assert!(state.balance >= amount, E_INSUFFICIENT_FUND);
...
}

If the owner can't add another pizza lover because of the check, he will know at least how much he needs to refund the pool for this person to be registered.
With that the owner will know for sure that everyone registered will have their own slices.

Updates

Appeal created

bube Lead Judge 10 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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