Description
function register() public payable {
if (msg.value != entranceFee) {
revert ThePredicter__IncorrectEntranceFee();
}
if (block.timestamp > START_TIME - 14400) {
revert ThePredicter__RegistrationIsOver();
}
if (playersStatus[msg.sender] == Status.Pending) {
revert ThePredicter__CannotParticipateTwice();
}
playersStatus[msg.sender] = Status.Pending;
}
This function which allows users to make their registration only checks whether the status of their request is on pending, implying that whenever this status is moved from this state, the user would be able to reenter the function. The ThePredicter::approvePlayer
on the other hand changes the status in:
if (playersStatus[player] == Status.Pending) {
playersStatus[player] = Status.Approved;
players.push(player);
}
POC
function test_playerCanRegisterAgainAfterApproval() public {
vm.startPrank(stranger);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.prank(organizer);
thePredicter.approvePlayer(stranger);
vm.prank(stranger);
thePredicter.register{value: 0.04 ether}();
assertEq(stranger.balance, 0.92 ether);
}
Tools Used
Manual Review
Recommendations
The require check in ThePredicter::register
should also include whether it has been approved or not.
function register() public payable {
if (msg.value != entranceFee) {
revert ThePredicter__IncorrectEntranceFee();
}
if (block.timestamp > START_TIME - 14400) {
revert ThePredicter__RegistrationIsOver();
}
if (playersStatus[msg.sender] == Status.Pending || playersStatus[msg.sender] == Status.Approved ) {
revert ThePredicter__CannotParticipateTwice();
}
playersStatus[msg.sender] = Status.Pending;
}