Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

NO UPPER BOUNDS ON DURATION AND REWARDS ON PERFORMANCES

Root + Impact

Description

  • Normally ,the Organizer creates performances with startTime, duration, and set rewards.

  • A malicious or careless Organizer could create infinite-durations or high-reward performances.

// Organizer creates a performance
function createPerformance(
uint256 startTime,
uint256 duration,
uint256 reward
) external onlyOrganizer returns (uint256) {
require(startTime > block.timestamp, "Start time must be in the future");
require(duration > 0, "Duration must be greater than 0");
// ❌ Missing: require(duration < MAX_DURATION)
// ❌ Missing: require(reward < MAX_REWARD)
// Set start/end times
performances[performanceCount] = Performance({
startTime: startTime,
endTime: startTime + duration,
baseReward: reward
});
emit PerformanceCreated(performanceCount, startTime, startTime + duration);
return performanceCount++;
}

Risk

Likelihood:

  • When Infinite or very long durations keep the performance active, allowing users to check in over and over again (abusing COOLDOWN reset).


  • Extremely high reward values could be used to mint absurd amounts of BEAT with just one check-in.


Impact:

  • Abuse of reward logic .the createPerformance function lacks upper bounds on duration and reward, which opens up a BEAT farming exploit risk,therefore a malicious attacker could do unlimited BEAT farming, resulting in beat token inflation ,theft ,fraud etc.

  • Infinite or very long durations keep the performance active, allowing users to check in over and over again (abusing COOLDOWN reset).This could result in disorder in the festival

Proof of Concept

// Infinite BEAT farmning
createPerformance(block.timestamp + 1, 9999999999, 1e20);

Recommended Mitigation

- function createPerformance(
uint256 startTime,
uint256 duration,
uint256 reward
) external onlyOrganizer returns (uint256) {
require(startTime > block.timestamp, "Start time must be in the future");
require(duration > 0, "Duration must be greater than 0");
// Set start/end times
performances[performanceCount] = Performance({
startTime: startTime,
endTime: startTime + duration,
baseReward: reward
});
emit PerformanceCreated(performanceCount, startTime, startTime + duration);
return performanceCount++;
}
+ //at the top of the contract ,add these
uint256 public constant MAX_PERFORMANCE_DURATION = 1 day; // or e.g 3 days if multi-day
uint256 public constant MAX_PERFORMANCE_REWARD = 100e18; // max 100 BEAT
//Update the function with additional require checks:
function createPerformance(
uint256 startTime,
uint256 duration,
uint256 reward
) external onlyOrganizer returns (uint256) {
require(startTime > block.timestamp, "Start time must be in the future");
require(duration > 0 && duration <= MAX_PERFORMANCE_DURATION, "Invalid duration");
require(reward > 0 && reward <= MAX_PERFORMANCE_REWARD, "Invalid reward");
performances[performanceCount] = Performance({
startTime: startTime,
endTime: startTime + duration,
baseReward: reward
});
emit PerformanceCreated(performanceCount, startTime, startTime + duration);
return performanceCount++;
}
//Then in createPerformance, check:
require(duration <= maxPerformanceDuration, "Exceeds max duration");
require(reward <= maxPerformanceReward, "Exceeds max reward");
Updates

Lead Judging Commences

inallhonesty Lead Judge 28 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.