Impact
The documentation clearly states that participating in performances grants a reward to users. However, the contract allows organizers to create performances with a reward value of zero. This breaks the expected incentive structure and may cause users to engage with performances under the false assumption that they will be rewarded. Additionally, the PerformanceCreated event emitted by the contract does not include the reward amount, which prevents front-end applications from easily displaying or verifying whether a performance actually offers a reward — further increasing the risk of user deception and reducing transparency
Description
The createPerformance function allows organizers to create a performance with a reward of zero. There is no validation to ensure that the reward is greater than zero, despite the system implying that performances should offer a reward to participants. This can lead to misleading or non-incentivized performances
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");
performances[performanceCount] = Performance({
startTime: startTime,
endTime: startTime + duration,
baseReward: reward
});
emit PerformanceCreated(performanceCount, startTime, startTime + duration);
return performanceCount++;
}
Risk
Likelihood:
This vulnerability is moderate to high depending on the organizer's behavior.
Proof of Concept
function test_ZeroRewardPerformance() public {
uint256 startTime = block.timestamp + 1 hours;
uint256 duration = 2 hours;
uint256 reward = 0;
vm.prank(organizer);
festivalPass.createPerformance(startTime, duration, reward);
vm.warp(block.timestamp + 1.5 hours);
vm.startPrank(user1);
festivalPass.buyPass{value : BACKSTAGE_PRICE}(3);
uint balanceBefore = beatToken.balanceOf(user1);
festivalPass.attendPerformance(0);
uint balanceAfter = beatToken.balanceOf(user1);
vm.stopPrank();
assertEq(balanceBefore,balanceAfter);
}
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");
+ require(reward > 0, "Reward must be greater than zero");
// Set start/end times
performances[performanceCount] = Performance({
startTime: startTime,
endTime: startTime + duration,
baseReward: reward
});
emit PerformanceCreated(performanceCount, startTime, startTime + duration);
return performanceCount++;
}