Beatland Festival

AI First Flight #4
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

`getMultiplier()` Returns Highest Pass Multiplier When User Owns Multiple Passes

Root + Impact

Description

  • The `getMultiplier()` function returns the highest multiplier when a user owns multiple pass types (BACKSTAGE=3x > VIP=2x > GENERAL=1x). This allows users to purchase multiple passes and always receive the highest multiplier reward, potentially gaming the reward system and creating economic imbalances.

    The normal behavior might be expected to either restrict users to one pass type or apply multipliers differently. However, the current implementation prioritizes the highest tier pass owned.

    ```solidity

    function getMultiplier(address user) public view returns (uint256) {

    if (balanceOf(user, BACKSTAGE_PASS) > 0) {

    return 3; // @> Returns highest multiplier if multiple passes owned

    } else if (balanceOf(user, VIP_PASS) > 0) {

    return 2;

    } else if (balanceOf(user, GENERAL_PASS) > 0) {

    return 1;

    }

    return 0;

    }

    ```


Risk

Likelihood:

  • * Users can purchase multiple pass types

    * Function is called on every performance attendance

    * Highest multiplier is always returned regardless of other passes owned

    * No restriction prevents multiple pass ownership

Impact:

  • * Users can game the system by buying multiple passes

    * Economic imbalance - users get maximum rewards without using highest tier pass

    * Potential unintended reward inflation

    * May not align with intended design

Proof of Concept

```solidity
// User buys all three pass types
user.buyPass{value: GENERAL_PRICE}(GENERAL_PASS);
user.buyPass{value: VIP_PRICE}(VIP_PASS);
user.buyPass{value: BACKSTAGE_PRICE}(BACKSTAGE_PASS);
// User attends performance
festivalPass.attendPerformance(0);
// getMultiplier() returns 3x (BACKSTAGE) even though user owns all passes
// User receives maximum rewards without needing to use BACKSTAGE pass specifically
```

Recommended Mitigation

```diff
function getMultiplier(address user) public view returns (uint256) {
+ // Option 1: Return multiplier based on highest pass only (current behavior - document it)
+ // Option 2: Restrict to one pass type per user
+ // Option 3: Apply different logic (e.g., sum of multipliers, average, etc.)
if (balanceOf(user, BACKSTAGE_PASS) > 0) {
return 3;
} else if (balanceOf(user, VIP_PASS) > 0) {
return 2;
} else if (balanceOf(user, GENERAL_PASS) > 0) {
return 1;
}
return 0;
}
```
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 16 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!